ReactNative【实战系列教程】我的小红书 8 -- 我(含左侧弹窗菜单,右下角图标等)

最终效果

在这里插入图片描述

点左上角菜单按钮,弹出左侧菜单后

在这里插入图片描述

代码实现

app/(tabs)/mine.tsx

import icon_add from "@/assets/icons/icon_add.png";
import mine_bg from "@/assets/images/mine_bg.png";
import Heart from "@/components/Heart";
import articleList from "@/mock/articleList";
import SideMenu, { SideMenuRef } from "@/modules/mine/components/SideMenu";
import Entypo from "@expo/vector-icons/Entypo";
import MaterialCommunityIcons from "@expo/vector-icons/MaterialCommunityIcons";
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
import { useRouter } from "expo-router";
import { useCallback, useRef, useState } from "react";
import {Dimensions,Image,LayoutChangeEvent,ScrollView,StyleSheet,Text,TouchableOpacity,View,
} from "react-native";
import icon_no_collection from "../../assets/icons/icon_no_collection.webp";
import icon_no_favorate from "../../assets/icons/icon_no_favorate.webp";
import icon_no_note from "../../assets/icons/icon_no_note.webp";
import Empty from "../../components/Empty";
const { width: SCREEN_WIDTH } = Dimensions.get("window");
const EMPTY_CONFIG = [{ icon: icon_no_note, tips: "快去发布今日的好心情吧~" },{ icon: icon_no_collection, tips: "快去收藏你喜欢的作品吧~" },{ icon: icon_no_favorate, tips: "喜欢点赞的人运气不会太差哦~" },
];
export default function MineScreen() {const sideMenuRef = useRef<SideMenuRef>(null);const router = useRouter();const [bgImgHeight, setBgImgHeight] = useState<number>(400);const [tabIndex, setTabIndex] = useState<number>(0);const onArticlePress = useCallback((article: ArticleSimple) => () => {router.push(`/articleDetail?id=${article.id}`);},[]);const renderTitle = () => {const styles = StyleSheet.create({titleLayout: {width: "100%",height: 48,flexDirection: "row",alignItems: "center",},menuButton: {height: "100%",paddingHorizontal: 16,justifyContent: "center",},menuImg: {width: 28,height: 28,resizeMode: "contain",},rightMenuImg: {marginRight: 14,},});return (<View style={styles.titleLayout}><TouchableOpacitystyle={styles.menuButton}onPress={() => {sideMenuRef.current?.show();}}><Entypo name="menu" size={24} color="white" /></TouchableOpacity><View style={{ flex: 1 }} /><Entypostyle={styles.rightMenuImg}name="shopping-cart"size={24}color="white"/><Entypostyle={styles.rightMenuImg}name="share"size={24}color="white"/></View>);};const renderInfo = () => {const userInfo = {avatar:"https://img0.baidu.com/it/u=919979501,2820948992&fm=253&app=120&f=JPEG?w=800&h=800",nickName: "清禾",redBookId: "635942",desc: "钟爱编程,偏前端开发,欢迎私信我加入EC尽享编程俱乐部共同学习,交流成长!",sex: "female",};const { avatar, nickName, redBookId, desc, sex } = userInfo;const styles = StyleSheet.create({avatarLayout: {width: "100%",flexDirection: "row",alignItems: "flex-end",padding: 16,},avatarImg: {width: 96,height: 96,resizeMode: "cover",borderRadius: 48,},addImg: {width: 28,height: 28,marginLeft: -28,marginBottom: 2,},nameLayout: {marginLeft: 20,},nameTxt: {fontSize: 22,color: "white",fontWeight: "bold",},idLayout: {flexDirection: "row",alignItems: "center",marginTop: 16,marginBottom: 20,},idTxt: {fontSize: 12,color: "#bbb",},qrcodeImg: {width: 12,height: 12,marginLeft: 6,tintColor: "#bbb",},descTxt: {fontSize: 14,color: "white",paddingHorizontal: 16,},sexLayout: {width: 32,height: 24,backgroundColor: "#ffffff50",borderRadius: 12,marginTop: 12,marginLeft: 16,justifyContent: "center",alignItems: "center",},sexImg: {width: 12,height: 12,resizeMode: "contain",},infoLayout: {width: "100%",paddingRight: 16,flexDirection: "row",alignItems: "center",marginTop: 20,marginBottom: 28,},infoItem: {alignItems: "center",paddingHorizontal: 12,},infoValue: {fontSize: 18,color: "white",},infoLabel: {fontSize: 12,color: "#ddd",marginTop: 6,},infoButton: {height: 32,paddingHorizontal: 16,borderWidth: 1,borderColor: "white",borderRadius: 16,justifyContent: "center",alignItems: "center",marginLeft: 16,},editTxt: {fontSize: 14,color: "#ffffff",},settingImg: {width: 20,height: 20,tintColor: "#ffffff",},});return (<ViewonLayout={(e: LayoutChangeEvent) => {const { height } = e.nativeEvent.layout;setBgImgHeight(height);}}><View style={styles.avatarLayout}><Image style={styles.avatarImg} source={{ uri: avatar }} /><Image style={styles.addImg} source={icon_add} /><View style={styles.nameLayout}><Text style={styles.nameTxt}>{nickName}</Text><View style={styles.idLayout}><Text style={styles.idTxt}>小红书号:{redBookId}</Text><MaterialCommunityIconsstyle={{marginLeft: 6,}}name="qrcode"size={12}color="white"/></View></View></View><Text style={styles.descTxt}>{desc}</Text><View style={styles.sexLayout}><MaterialCommunityIconsname={sex === "male" ? "gender-male" : "gender-female"}size={14}color="white"/></View><View style={styles.infoLayout}><View style={styles.infoItem}><Text style={styles.infoValue}>1</Text><Text style={styles.infoLabel}>关注</Text></View><View style={styles.infoItem}><Text style={styles.infoValue}>65</Text><Text style={styles.infoLabel}>粉丝</Text></View><View style={styles.infoItem}><Text style={styles.infoValue}>625</Text><Text style={styles.infoLabel}>获赞与收藏</Text></View><View style={{ flex: 1 }} /><TouchableOpacity style={styles.infoButton}><Text style={styles.editTxt}>编辑资料</Text></TouchableOpacity><TouchableOpacity style={styles.infoButton}><MaterialIcons name="settings" size={20} color="white" /></TouchableOpacity></View></View>);};const renderTabs = () => {const styles = StyleSheet.create({titleLayout: {width: "100%",height: 48,flexDirection: "row",alignItems: "center",justifyContent: "center",backgroundColor: "white",paddingHorizontal: 16,borderTopLeftRadius: 12,borderTopRightRadius: 12,borderBottomWidth: 1,borderBottomColor: "#eee",},icon: {width: 28,height: 28,},line: {width: 28,height: 2,backgroundColor: "#ff2442",borderRadius: 1,position: "absolute",bottom: 6,},tabButton: {height: "100%",flexDirection: "column",alignItems: "center",justifyContent: "center",paddingHorizontal: 14,},tabTxt: {fontSize: 17,color: "#999",},tabTxtSelected: {fontSize: 17,color: "#333",},});return (<View style={styles.titleLayout}><TouchableOpacitystyle={styles.tabButton}onPress={() => {setTabIndex(0);}}><Text style={tabIndex === 0 ? styles.tabTxtSelected : styles.tabTxt}>笔记</Text>{tabIndex === 0 && <View style={styles.line} />}</TouchableOpacity><TouchableOpacitystyle={styles.tabButton}onPress={() => {setTabIndex(1);}}><Text style={tabIndex === 1 ? styles.tabTxtSelected : styles.tabTxt}>收藏</Text>{tabIndex === 1 && <View style={styles.line} />}</TouchableOpacity><TouchableOpacitystyle={styles.tabButton}onPress={() => {setTabIndex(2);}}><Text style={tabIndex === 2 ? styles.tabTxtSelected : styles.tabTxt}>赞过</Text>{tabIndex === 2 && <View style={styles.line} />}</TouchableOpacity></View>);};const renderList = () => {const noteList: ArticleSimple[] = [];const collectionList: ArticleSimple[] = [];const favorateList: ArticleSimple[] = articleList.filter((item) => item.isFavorite);const currentList = [noteList, collectionList, favorateList][tabIndex];if (!currentList?.length) {const config = EMPTY_CONFIG[tabIndex];return <Empty icon={config.icon} tips={config.tips} />;}const styles = StyleSheet.create({listContainer: {width: "100%",flexDirection: "row",flexWrap: "wrap",backgroundColor: "white",},item: {width: (SCREEN_WIDTH - 18) >> 1,backgroundColor: "white",marginLeft: 6,marginBottom: 6,borderRadius: 8,overflow: "hidden",marginTop: 8,},titleTxt: {fontSize: 14,color: "#333",marginHorizontal: 10,marginVertical: 4,},nameLayout: {width: "100%",flexDirection: "row",alignItems: "center",paddingHorizontal: 10,marginBottom: 10,},avatarImg: {width: 20,height: 20,resizeMode: "cover",borderRadius: 10,},nameTxt: {fontSize: 12,color: "#999",marginLeft: 6,flex: 1,},heart: {width: 20,height: 20,resizeMode: "contain",},countTxt: {fontSize: 14,color: "#999",marginLeft: 4,},itemImg: {width: (SCREEN_WIDTH - 18) >> 1,height: 240,},});return (<View style={styles.listContainer}>{currentList.map((item, index) => {return (<TouchableOpacitykey={`${item.id}-${index}`}style={styles.item}onPress={onArticlePress(item)}><Image style={styles.itemImg} source={{ uri: item.image }} /><Text style={styles.titleTxt}>{item.title}</Text><View style={styles.nameLayout}><Imagestyle={styles.avatarImg}source={{ uri: item.avatarUrl }}/><Text style={styles.nameTxt}>{item.userName}</Text><Heartvalue={item.isFavorite}onValueChanged={(value: boolean) => {console.log(value);}}/><Text style={styles.countTxt}>{item.favoriteCount}</Text></View></TouchableOpacity>);})}</View>);};return (<View style={styles.page}><Imagestyle={[styles.bgImg, { height: bgImgHeight + 64 }]}source={mine_bg}/>{renderTitle()}<ScrollView style={styles.scrollView}>{renderInfo()}{renderTabs()}{renderList()}</ScrollView><SideMenu ref={sideMenuRef} /></View>);
}
const styles = StyleSheet.create({scrollView: {width: "100%",flex: 1,},page: {width: "100%",height: "100%",backgroundColor: "white",},bgImg: {position: "absolute",top: 0,width: "100%",height: 400,},
});

相关组件

modules/mine/components/SideMenu.tsx

左侧弹窗菜单

import icon_browse_histroy from "@/assets/icons/icon_browse_history.png";
import icon_community from "@/assets/icons/icon_community.png";
import icon_coupon from "@/assets/icons/icon_coupon.png";
import icon_create_center from "@/assets/icons/icon_create_center.png";
import icon_draft from "@/assets/icons/icon_draft.png";
import icon_exit from "@/assets/icons/icon_exit.png";
import icon_fid_user from "@/assets/icons/icon_find_user.png";
import icon_free_net from "@/assets/icons/icon_free_net.png";
import icon_nice_goods from "@/assets/icons/icon_nice_goods.png";
import icon_orders from "@/assets/icons/icon_orders.png";
import icon_packet from "@/assets/icons/icon_packet.png";
import icon_red_vip from "@/assets/icons/icon_red_vip.png";
import icon_scan from "@/assets/icons/icon_scan.png";
import icon_service from "@/assets/icons/icon_service.png";
import icon_setting from "@/assets/icons/icon_setting.png";
import icon_shop_car from "@/assets/icons/icon_shop_car.png";
import icon_wish from "@/assets/icons/icon_wish.png";
import { remove } from "@/utils/Storage";
import { useRouter } from "expo-router";
import React, {forwardRef,useCallback,useImperativeHandle,useState,
} from "react";
import {Dimensions,Image,LayoutAnimation,Modal,ScrollView,StyleSheet,Text,TouchableOpacity,View,
} from "react-native";
const MENUS = [[{ icon: icon_fid_user, name: "发现好友" }],[{ icon: icon_draft, name: "我的草稿" },{ icon: icon_create_center, name: "创作中心" },{ icon: icon_browse_histroy, name: "浏览记录" },{ icon: icon_packet, name: "钱包" },{ icon: icon_free_net, name: "免流量" },{ icon: icon_nice_goods, name: "好物体验" },],[{ icon: icon_orders, name: "订单" },{ icon: icon_shop_car, name: "购物车" },{ icon: icon_coupon, name: "卡券" },{ icon: icon_wish, name: "心愿单" },{ icon: icon_red_vip, name: "小红书会员" },],[{ icon: icon_community, name: "社区公约" },{ icon: icon_exit, name: "退出登陆" },],
];
const BOTTOM_MENUS = [{ icon: icon_setting, txt: "设置" },{ icon: icon_service, txt: "帮助与客服" },{ icon: icon_scan, txt: "扫一扫" },
];
export interface SideMenuRef {show: () => void;hide: () => void;
}
const { width: SCREEN_WIDTH } = Dimensions.get("window");
const ContentWidth = SCREEN_WIDTH * 0.75;
// eslint-disable-next-line react/display-name
export default forwardRef((props: any, ref) => {const [visible, setVisible] = useState<boolean>(false);const [open, setOpen] = useState<boolean>(false);const router = useRouter();const show = () => {setVisible(true);setTimeout(() => {LayoutAnimation.easeInEaseOut();setOpen(true);}, 100);};const hide = () => {LayoutAnimation.easeInEaseOut();setOpen(false);setTimeout(() => {setVisible(false);}, 300);};useImperativeHandle(ref, () => {return {show,hide,};});const onMenuItemPress = useCallback((item: any) => async () => {if (item.name === "退出登陆") {hide();await remove("userInfo");router.replace("/login");}},[]);const renderContent = () => {return (<View style={[styles.content, { marginLeft: open ? 0 : -ContentWidth }]}><ScrollViewstyle={styles.scrollView}contentContainerStyle={styles.container}showsVerticalScrollIndicator={false}>{MENUS.map((item, index) => {return (<View key={`${index}`}>{item.map((subItem, subIndex) => {return (<TouchableOpacitykey={`${index}-${subIndex}`}style={styles.menuItem}onPress={onMenuItemPress(subItem)}><Imagestyle={styles.menuItemIcon}source={subItem.icon}/><Text style={styles.menuItemTxt}>{subItem.name}</Text></TouchableOpacity>);})}{index !== MENUS.length - 1 && (<View style={styles.divideLine} />)}</View>);})}</ScrollView><View style={styles.bottomLayout}>{BOTTOM_MENUS.map((item) => {return (<TouchableOpacitykey={`${item.txt}`}style={styles.bottomMenuItem}><View style={styles.bottomMenuIconWrap}><Image style={styles.bottomMenuIcon} source={item.icon} /></View><Text style={styles.bottomMenuTxt}>{item.txt}</Text></TouchableOpacity>);})}</View></View>);};return (<Modaltransparent={true}visible={visible}statusBarTranslucent={false}animationType="fade"onRequestClose={hide}><TouchableOpacity style={styles.root} onPress={hide} activeOpacity={1}>{renderContent()}</TouchableOpacity></Modal>);
});
const styles = StyleSheet.create({root: {width: "100%",height: "100%",backgroundColor: "#000000C0",flexDirection: "row",},content: {height: "100%",width: ContentWidth,backgroundColor: "white",},scrollView: {width: "100%",flex: 1,},bottomLayout: {width: "100%",flexDirection: "row",paddingTop: 12,paddingBottom: 20,},bottomMenuItem: {flex: 1,alignItems: "center",},bottomMenuIconWrap: {width: 44,height: 44,backgroundColor: "#f0f0f0",borderRadius: 22,justifyContent: "center",alignItems: "center",},bottomMenuIcon: {width: 26,height: 26,},bottomMenuTxt: {fontSize: 13,color: "#666",marginTop: 8,},divideLine: {width: "100%",height: 1,backgroundColor: "#eee",},menuItem: {width: "100%",height: 64,flexDirection: "row",alignItems: "center",},menuItemIcon: {width: 32,height: 32,resizeMode: "contain",},menuItemTxt: {fontSize: 16,color: "#333",marginLeft: 14,},container: {paddingTop: 10,paddingHorizontal: 28,paddingBottom: 12,},
});

components/Heart.tsx

import AntDesign from "@expo/vector-icons/AntDesign";
import React, { useEffect, useRef, useState } from "react";
import { Animated, TouchableOpacity } from "react-native";
type Props = {value: boolean;onValueChanged?: (value: boolean) => void;size?: number;color?: string;
};
// eslint-disable-next-line react/display-name
export default (props: Props) => {const { value, onValueChanged, size = 20, color = "black" } = props;const [showState, setShowState] = useState<boolean>(false);const scale = useRef<Animated.Value>(new Animated.Value(0)).current;const alpha = useRef<Animated.Value>(new Animated.Value(0)).current;useEffect(() => {setShowState(value);}, [value]);const onHeartPress = () => {const newState = !showState;setShowState(newState);onValueChanged?.(newState);if (newState) {alpha.setValue(1);const scaleAnim = Animated.timing(scale, {toValue: 1.8,duration: 300,useNativeDriver: false,});const alphaAnim = Animated.timing(alpha, {toValue: 0,duration: 400,useNativeDriver: false,delay: 200,});Animated.parallel([scaleAnim, alphaAnim]).start();} else {scale.setValue(0);alpha.setValue(0);}};return (<TouchableOpacity onPress={onHeartPress}>{showState ? (<AntDesign name="heart" size={size} color="red" />) : (<AntDesign name="hearto" size={size} color={color} />)}<Animated.Viewstyle={{width: size,height: size,borderRadius: size / 2,borderWidth: size / 20,position: "absolute",borderColor: "#ff2442",transform: [{ scale: scale }],opacity: alpha,}}/></TouchableOpacity>);
};

components/Empty.tsx

import React from "react";
import { Image, StyleSheet, Text, View } from "react-native";
type Props = {icon: number;tips: string;
};
// eslint-disable-next-line react/display-name
export default ({ icon, tips }: Props) => {return (<View style={styles.root}><Image style={styles.icon} source={icon} /><Text style={styles.tipsTxt}>{tips}</Text></View>);
};
const styles = StyleSheet.create({root: {alignItems: "center",paddingTop: 120,},icon: {width: 96,height: 96,resizeMode: "contain",},tipsTxt: {fontSize: 14,color: "#bbb",marginTop: 16,},
});

模拟数据

mock/articleList.ts

const articleList: ArticleSimple[] = [{id: 1,title: "让我抱抱,一起温暖,真的好治愈",userName: "小飞飞爱猫咪",avatarUrl:"https://img2.baidu.com/it/u=902203086,3868774028&fm=253&app=138&f=JPEG?w=500&h=500",image:"http://gips2.baidu.com/it/u=195724436,3554684702&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960",favoriteCount: 325,isFavorite: true,},{id: 2,title: "不愧是网友给的配方,真的香迷糊了",userName: "大厨师小飞象",avatarUrl:"https://pic.rmb.bdstatic.com/bjh/events/eeae3b71dabc9a372afd7f9e112287086428.jpeg@h_1280",image:"http://gips0.baidu.com/it/u=3602773692,1512483864&fm=3028&app=3028&f=JPEG&fmt=auto?w=960&h=1280",favoriteCount: 1098,isFavorite: true,},{id: 3,title: "一觉醒来,满树的柑橘爬上了我的窗",userName: "小小风筝",avatarUrl:"https://img1.baidu.com/it/u=1811602911,3261262340&fm=253&app=138&f=JPEG?w=500&h=500",image:"http://gips3.baidu.com/it/u=1537137094,335954266&fm=3028&app=3028&f=JPEG&fmt=auto?w=720&h=1280",favoriteCount: 18700,isFavorite: false,},{id: 4,title: "满床清梦压星河",userName: "失忆",avatarUrl:"https://img1.baidu.com/it/u=3505470809,2700212068&fm=253&app=138&f=JPEG?w=500&h=500",image:"https://gips3.baidu.com/it/u=1014935733,598223672&fm=3074&app=3074&f=PNG?w=1440&h=2560",favoriteCount: 8700,isFavorite: true,},{id: 5,title: "手机拍出来的星星,没想到那么多人喜欢",userName: "慢慢",avatarUrl:"https://img1.baidu.com/it/u=1924685292,2387273894&fm=253&app=138&f=JPEG?w=500&h=500",image:"https://img2.baidu.com/it/u=2585843050,3523947274&fm=253&app=138&f=JPEG?w=1422&h=800",favoriteCount: 2655,isFavorite: false,},{id: 6,title: "告白如同田野间的风在青春里轰然",userName: "潇潇",avatarUrl:"https://img1.baidu.com/it/u=3843254675,2187553494&fm=253&app=120&f=JPEG?w=800&h=800",image:"https://img1.baidu.com/it/u=1926713654,274347830&fm=253&app=138&f=JPEG?w=1422&h=800",favoriteCount: 2655,isFavorite: false,},
];
export default articleList;

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

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

相关文章

C++性能优化实战:从理论到落地的五大核心策略

在当今这个对计算效率要求极高的时代&#xff0c;C作为系统级编程语言的王者&#xff0c;其性能优化能力依然是无可替代的核心竞争力。本文将分享我在大型分布式系统开发中积累的C性能优化实战经验&#xff0c;这些经验帮助我们将关键组件的吞吐量提升了300%&#xff0c;延迟降…

字节 Seed 团队联合清华大学智能产业研究院开源 MemAgent: 基于多轮对话强化学习记忆代理的长文本大语言模型重构

&#x1f525; 最新动态!!! [2025/07] 我们提供了快速启动脚本&#xff0c;让使用MemAgent变得超级简单&#xff0c;详情请见下方"快速入门"部分。[2025/06] 我们发布了RL-MemAgent-14B和RL-MemAgent-7B模型&#xff0c;在350万token上下文任务中实现了近乎无损的性…

【unitrix】 4.20 类型级二进制数减法实现解析(sub.rs)

一、源码 这段代码实现了一个用于统计二进制补码整数位数的系统&#xff0c;支持多种自定义数值类型&#xff08;Z0、P1、N1、B0、B1&#xff09;。 use core::mem::size_of; use crate::number::{Z0, P1, N1, B0, B1, Var};/// 统计二进制位数的 trait pub trait BitLength {f…

手把手教你安全删除Anaconda虚拟环境(避坑指南)

文章目录一、删除前必看清单&#xff08;超级重要&#xff09;二、三种删除方法对比&#xff08;建议收藏&#xff09;方法1&#xff1a;官方推荐命令&#xff08;最安全&#xff09;方法2&#xff1a;暴力删除大法&#xff08;快速但需谨慎&#xff09;方法3&#xff1a;核弹级…

Effective Modern C++ 条款7:区分使用 `()` 和 `{}` 创建对象

在 C11 及以后的版本中&#xff0c;初始化对象的方式变得更加灵活&#xff0c;但也带来了选择上的困惑。() 和 {} 是两种常见的初始化语法&#xff0c;它们在语义、行为和适用场景上有显著差异。本文将通过具体示例&#xff0c;深入解析这两种初始化方式的区别&#xff0c;并探…

Java基础-String常用的方法

String常用的三种构造方法 public static void main(String[] args) {//1.使用常量字符串构造String s1 "1.Hello world";System.out.println(s1);//2.使用new关键字构造String s2 new String("2.Hello world");System.out.println(s2);//3。使用字符数组…

数学建模:多目标规划:ε约束法、 理想点法

一、ε约束法定义ε约束法通过将部分目标函数转化为约束条件&#xff0c;保留一个主要目标进行优化。1、选择一个主要目标 fk​(x) 进行优化。2、其他目标 fi​(x) 转化为约束 fi​(x)≤εi​&#xff0c;其中 εi​ 是决策者设定的容许阈值。​​原理​​​​目标选择​​&…

linux kernel struct regmap_config结构详解

在 Linux 内核中&#xff0c;struct regmap_config 是 ​Regmap 子系统的核心配置结构体&#xff0c;用于定义如何与底层硬件寄存器进行交互。Regmap&#xff08;Register Map&#xff09;子系统通过抽象不同总线&#xff08;如 I2C、SPI、MMIO 等&#xff09;的寄存器访问细节…

【Python3教程】Python3高级篇之CGI编程

博主介绍:✌全网粉丝23W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…

docker安装Consul笔记

安装过程 详细步骤如下&#xff1a; 首先拉取Consul的Docker镜像&#xff1a; docker pull hashicorp/consul:1.18.1创建Consul的配置文件和数据目录&#xff1a; mkdir -p /srv/docker/consul/data mkdir -p /srv/docker/consul/config在config目录下创建一个config.json配置文…

.net数据脱敏

.NET数据脱敏技术&#xff1a;保障数据安全的有效手段 在当今数字化时代&#xff0c;数据安全至关重要。尤其是涉及到用户的敏感信息&#xff0c;如密码、手机号码等&#xff0c;必须采取有效的措施进行保护。数据脱敏就是这样一种技术&#xff0c;它能够在不影响数据可用性的…

【openp2p】 学习2:源码阅读P2PNetwork和P2PTunnel

【openp2p】 学习1:P2PApp和优秀的go跨平台项目已经做了初步分析。阅读原版工程,感觉工程是一个暴露内网服务端口,让外部可以用的一个实现是一个完整的、跨平台的可商业化的应用。感谢作者需要学习作者的设计思路工程构建 F:\GolandProjects\openp2p\core\p2pnetwork.go通常…

网安学习NO.14

防火墙基础实验 传统防火墙配置实验拓扑图PC&#xff1a; ip 192.168.10.1 255.255.255.0 192.168.10.254 ip dns 114.114.114.114二层交换机 vl 10 ex int e0/0 sw mo ac sw ac vl 10 ex inr e0/1 sw tr en do sw mo tr三层交换机 vl 10 ex int g0/0 sw tr en do sw mo tr ex …

ESP32语音唤醒

两种唤醒方式AfeWakeWord与EspWakeWord对比 底层技术 AfeWakeWord&#xff1a;基于ESP-IDF的AFE框架&#xff08;esp_afe_sr_iface_t&#xff09;&#xff0c;高性能模式&#xff08;AFE_MODE_HIGH_PERF&#xff09;EspWakeWord&#xff1a;基于WakeNet接口&#xff08;esp_wn_…

借助 Wisdom SSH AI 助手,轻松安装 CentOS 8 LNMP 环境

打开Wisdom SSH软件&#xff0c;在AI对话区输入“在CentOS 8服务器安装LNMP环境”&#xff0c;AI助手会按以下步骤分析并执行安装&#xff1a; 安装Nginx 分析&#xff1a;CentOS 8默认软件源可能没有Nginx&#xff0c;所以要先启用Nginx官方软件源&#xff0c;然后才能安装Ngi…

WD0407 40V 7A 超级肖特基二极管,应用于开关汽车工业控制

WD0407 40V 7A 超级肖特基二极管说明​ 产品概述​ WD0407 是一款性能卓越的超级肖特基二极管&#xff0c;专为满足现代电子设备对高效、可靠电源管理的需求而设计。它采用先进的半导体制造工艺&#xff0c;在诸多关键性能指标上表现出色&#xff0c;能够为各类电路提供稳定、高…

卢比危机下的金融破局:科伦坡交易所技术升级作战图

&#x1f30f; 今日南亚风暴眼 印度双重上市机制加速落地&#xff1a;印度国家证券国际交易所&#xff08;NSE IX&#xff09;与科伦坡证券交易所&#xff08;CSE&#xff09;达成技术对接协议&#xff0c;斯企可通过印度GIFT City吸引美元资本&#xff0c;交易时段覆盖全球22小…

upload-labs靶场通关详解:第20关 /.绕过

一、分析源代码// 初始化上传状态标记&#xff0c;默认为false&#xff0c;即文件未上传 $is_upload false; // 初始化消息变量&#xff0c;用于存储错误信息 $msg null;// 检查是否通过POST方式提交了表单&#xff08;点击上传按钮&#xff09; if (isset($_POST[submit])) …

企业用云状态评估

云部署形态及其策略规划成熟度 单云部署&#xff1a; 主要业务负载运行在单一公有云或私有云上 多云/混合云部署 —有清晰战略规划与实施&#xff1a; 业务负载运行在多个云&#xff08;公有云或混合云&#xff09;上&#xff0c;并且企业拥有清晰的多云/混合云战略规划&#x…

STM32G473串口通信-USART/UART配置和清除串口寄存器状态的注意事项

USART和UART配置的区别 如果USART使用的是异步通信&#xff0c;那么UART与USART配置基本相同。 USART配置如下:UART配置如下&#xff1a;如果USART使用的是同步通信&#xff0c;那么UART配置就有差异。首先通信双方都是使用USART的同步通信&#xff0c;一个主机&#xff0c;一个…