当前位置:网站首页>Imitation Netease cloud music applet
Imitation Netease cloud music applet
2022-07-03 21:19:00 【*neverGiveUp*】
One 、 Program description
Imitation Netease cloud music applet , Call Netease cloud API Real interface , Realize music playing , Music switching , Lyrics show , Search for music , Video playback , Functions such as user login and exit . Here is the effect display :
Imitation Netease cloud applet
Two 、 Code Introduction
(1) catalogue
(2) Search for Code explanation
Realize the idea :
- First display the static page of the search
- Call interface handle Hot search list The data of is changed to dynamic
- Realize the search according to the value of the input box
- Every time you search , The history will be recorded and stored locally , Then the life cycle of the applet onLoad To get historical records
The code is as follows :
--search.wxml
<view class="searchContainer">
<!-- Head search area -->
<view class="header">
<view class="searchInput">
<text class="iconfont icon-search1 searchIcon"></text>
<input type="text" value="{
{searchContent}}" placeholder="{
{placeholderData}}" placeholder-class="placeholder" bindinput="handleInputChange" />
<text class="clear" bindtap="clearSearchContent" hidden="{
{!searchContent}}">X</text>
</view>
<text class="cancel"> Cancel </text>
</view>
<block wx:if="{
{searchList.length}}">
<!-- Search content display -->
<view class="showSearchContent">
<view class="searchContent"> Search content :{
{
searchContent}}</view>
<view class="searchList">
<view class="searchItem" wx:for="{
{searchList}}" wx:key="id">
<text class="iconfont icon-search1"></text>
<text class="content" bindtap="toSongDeatil" id="{
{item.id}}">{
{
item.name}}</text>
</view>
</view>
</view>
</block>
<block wx:else>
<!-- Search history -->
<view class="history" wx:if="{
{historyList.length}}">
<view class="title"> history </view>
<view class="historyItem" wx:for="{
{historyList}}" wx:id="{
{item}}" bindtap="searchHistory" data-historyword="{
{item}}">{
{
item}}</view>
<!-- Delete -->
<text class="iconfont icon-shanchu delete" bindtap="deleteSearchHistory"></text>
</view>
<!-- Hot search list -->
<view class="hotContainer">
<view class="title"> Hot search list </view>
<!-- Hot search list -->
<view class="hotList">
<view class="hotItem" wx:for="{
{showList}}" wx:key="searchWord">
<text class="order">{
{
index+1}}</text>
<text bindtap="searchHotSong" data-hotwords="{
{item.searchWord}}">{
{
item.searchWord}}</text>
<image class="iconImg" wx:if="{
{item.iconUrl}}" src="{
{item.iconUrl}}"></image>
</view>
</view>
</view>
</block>
</view>
--search.js
import request from "../../utils/request"
let isSend = false
// pages/search/search.js
Page({
/** * Initial data of the page */
data: {
placeholderData: "", // The default value of the search box
showList: [],// Recommended songs on the hot search list
searchContent: "", // The value of the input box
searchList: [],// Search for matching data
historyList: [], // In history
},
/** * Life cycle function -- Monitor page loading */
onLoad: function (options) {
// call Get the default value of the search box
this.getPlaceholderData()
// Get history
this.getHistory()
},
// Get search history locally
getHistory() {
let historyList = wx.getStorageSync('searchHistory')
if (historyList) {
this.setData({
historyList
})
}
},
// Get the value of the default search box
async getPlaceholderData() {
let placeholderData = await request("/search/default")
let showMusic = await request("/search/hot/detail")
// modify state
this.setData({
placeholderData: placeholderData.data.showKeyword,
showList: showMusic.data
})
},
// Callback when the content of the form item changes
handleInputChange(event) {
// modify searchContent State data for
this.setData({
searchContent: event.detail.value.trim(),
})
if (isSend) {
return
}
isSend = true;
this.getSearchList();
// Function throttling
setTimeout(() => {
isSend = false;
}, 300)
},
// Function to obtain search data
async getSearchList() {
// If the search box has no value , We want to show song recommendations
if (!this.data.searchContent) {
this.setData({
searchList: []
})
return;
}
// Send a request to obtain keyword fuzzy matching data
let {
searchContent, historyList } = this.data
let searchList = await request("/search", {
keywords: searchContent, limit: 10 })
this.setData({
searchList: searchList.result.songs
})
if (historyList.indexOf(searchContent) != -1) {
// In historical records and there have been
historyList.splice(historyList.indexOf(searchContent), 1) // Delete in history
}
// Add search keywords to search history
historyList.unshift(searchContent)
this.setData({
historyList
})
wx.setStorageSync('searchHistory', historyList)
},
// Clear the search
clearSearchContent() {
this.setData({
searchContent: "",
searchList: [],
})
},
// Delete search history
deleteSearchHistory() {
wx.showModal({
content: ' Are you sure to delete ?',
success: (res) => {
if (res.confirm) {
// Click OK to delete
this.setData({
historyList: []
});
wx.removeStorageSync('searchHistory')
}
}
})
},
/* Jump to the song details page */
toSongDeatil(event) {
console.log(event)
wx.navigateTo({
url: '/pages/songDetail/songDetail?musicId=' + event.currentTarget.id,
})
},
/* Click the hot search list to search */
searchHotSong(event) {
console.log(event)
this.setData({
searchContent: event.currentTarget.dataset.hotwords
})
// Send a request to get the data matching the search
this.getSearchList()
}
})
--search.wxss
/* pages/search/search.wxss */
.searchContainer{
padding: 0 20rpx;
}
.header {
display: flex;
height: 60rpx;
line-height: 60rpx;
padding: 10rpx 0;
}
.searchInput {
position: relative;
flex: 1;
background: rgba(237,237,237,0.3);
border-radius: 30rpx;
}
.cancel {
width: 100rpx;
text-align: center;
}
.searchIcon{
position: absolute;
left: 15rpx;
}
.searchInput input{
margin-left: 50rpx;
height: 60rpx;
}
.placeholder{
font-size: 28rpx;
}
/* Hot search list */
.hotContainer {
margin-top: 30rpx;
}
.hotContainer .title{
font-size: 28rpx;
height: 80rpx;
line-height: 80rpx;
border-bottom: 1rpx solid #eee;
}
.hotList{
display: flex;
flex-wrap: wrap;
}
.hotItem {
width: 50%;
height: 80rpx;
line-height: 80rpx;
font-size: 26rpx;
}
.hotItem .order{
margin: 0 10rpx;
}
.hotItem .iconImg {
width: 35rpx;
height: 20rpx;
margin-left: 10rpx;
}
/* Search history */
.history {
position: relative;
display: flex;
flex-wrap: wrap;
line-height: 50rpx;
margin: 20rpx 0;
}
.history .title{
font-size: 28rpx;
height: 50rpx;
}
.history .historyItem {
height: 50rpx;
font-size: 26rpx;
background: #ededed;
margin-top: 5rpx;
margin-left: 20rpx;
padding: 0 30rpx;
border-radius: 20rpx;
}
.history .delete{
position: absolute;
bottom: 10rpx;
right: 15rpx;
font-size: 36rpx;
}
.clear{
position: absolute;
z-index: 10; /* priority */
right: 30rpx;
top:0;
font-size: 30rpx;
}
/* Search content display */
.searchContent {
color: #d43c33;
height: 80rpx;
line-height: 80rpx;
font-size: 24rpx;
border-bottom: 1rpx solid #d43c33;
}
.searchItem {
height: 80rpx;
line-height: 80rpx;
display: flex;
}
.searchItem .content {
flex: 1;
margin-left: 20rpx;
border-bottom: 1rpx solid #eee;
font-size: 26rpx;
}
(3) Daily recommendation Code explanation
Realize the idea :
- Write a static page
- The header date is changed to dynamic
- Call the interface to realize dynamic data
The code is as follows :
--recommendSong.wxml
<view class="recommendSongContainer">
<!-- Head -->
<view class="header">
<image src="/static/images/recommendSong/recommendSong.jpg"></image>
<view class="date">
<text class="day">{
{
month}} / </text>
<text class="month">{
{
day}}</text>
</view>
</view>
<!-- List area -->
<view class="ListContainer">
<view class="listHeader">
<text> Play all </text>
<text class="changeMore"> multi-select </text>
</view>
<!-- Content area -->
<scroll-view scroll-y class="listScroll">
<view class="scrollItem" wx:for="{
{recommentList}}" wx:key="id" bindtap="toSongDetail" data-index="{
{index}}" data-song="{
{item}}">
<image src="{
{item.album.picUrl}}"></image>
<view class="musicInfo">
<text class="musicName">{
{
item.name}}</text>
<text class="author">{
{
item.ar[0].name}}</text>
</view>
<text class="iconfont icon-gengduo"></text>
</view>
</scroll-view>
</view>
</view>
--recommendSong.js
import Pubsub from 'pubsub-js'
import request from '../../utils/request.js'
Page({
/** * Initial data of the page */
data: {
day: " ", // God
month: " ", // month
recommentList: [], // Store recommended songs
index:0,// Click the music subscript
},
/** * Life cycle function -- Monitor page loading */
onLoad: function (options) {
// Determine whether the user is logged in
let userLogin = wx.getStorageSync('userInfo')
if (!userLogin) {
// The user is not logged in , A message appears
wx.showToast({
title: ' Please log in first ',
icon:'none',
success: function () {
wx.reLaunch({
url: '/pages/login/login'
})
}
})
}
// Dynamically modify the date
this.setData({
/* date.getDay()// What day date.getDate()// What's the current number */
day: new Date().getDate(),
month: new Date().getMonth() + 1
})
// Call the recommended song interface
this.getRecommendList()
// Subscription from songDetail News published on the page
Pubsub.subscribe("switchType",(msg,type) =>{
// console.log(msg,type)
let {
recommentList,index} = this.data
if(type==='pre'){
// On a
// If it's the first song , That is, the subscript is 0, Will jump to the subscript of the last song
(index==0)&&(index=recommentList.length)
index-=1
}else{
// The following piece
// If it's the last song , That is, the subscript is length -1, Then the next song will be the first song
(index==recommentList.length-1)&&(index=-1)
index+=1
}
// Update subscript
this.setData({
index
})
// take musicId Send it back to songDetail page
Pubsub.publish('musicId',recommentList[index].id)
})
},
async getRecommendList() {
let result = await request('/recommend/songs')
// Update data
this.setData({
recommentList: result.data.dailySongs
})
},
/* Click the daily recommended song event */
toSongDetail(event){
// Get the click song id
let {
song,index} = event.currentTarget.dataset;
// Store subscripts of clicked songs
this.setData({
index
})
// Routing jump
wx.navigateTo({
url:"/pages/songDetail/songDetail?musicId="+song.id
})
}
--recommendSong.wxss
/* pages/recommendSong/recommendSong.wxss */
/* Head */
page{
height: 100%;
}
.recommendSongContainer .header {
position: relative;
width: 100%;
height: 300rpx;
}
.recommendSongContainer .header image {
width: 100%;
height: 100%;
}
.recommendSongContainer .header .date{
position: absolute;
left: 50%;
top:50%;
margin-left: -133rpx;
margin-top: -36rpx;
width: 300rpx;
height: 100rpx;
text-align: center;
line-height: 100rpx;
color: #fff;
}
.header .date .day {
font-size: 38rpx;
}
/* List area */
.ListContainer {
position: relative;
top:-20rpx;
padding: 0 20rpx;
border-radius: 30rpx;
background: #fff;
}
.listHeader {
height: 80rpx;
line-height: 80rpx;
}
.listHeader .changeMore {
float: right;
}
/* Content area */
.listScroll{
height: calc(100vh - 380rpx);
}
.scrollItem{
position: relative;
display: flex;
margin-bottom: 20rpx;
}
.scrollItem image{
width: 80rpx;
height: 80rpx;
border-radius:8rpx;
}
.musicInfo {
display: flex;
flex-direction: column;
margin-left: 20rpx;
}
.musicInfo text {
height: 40rpx;
line-height: 40rpx;
font-size: 24rpx;
max-width: 500rpx;
white-space: noweap;
overflow: hidden;
text-overflow: ellipsis;
}
.scrollItem .iconfont {
position: absolute;
right: 0;
width: 80rpx;
height: 80rpx;
line-height: 80rpx;
text-align: right;
}
(4) Music playing page Code explanation
Realize the idea :
- Write a static page
- Get music from the recommended song list page or daily recommendation page id, Music subscript index, Then send it to the music playing page , Realize the playback and switching of music
- Lyrics display and music playback progress
The code is as follows :
--songDetail.wxml
<view class="songDetailContainer">
<view class="author">{
{
songList.ar[0].name}}</view>
<view class="circle"></view>
<image class="needle {
{isPlay && 'needleRotate'}}" src="/static/images/song/needle.png"></image>
<view class="discContainer {
{isPlay && 'discAnimation'}}" >
<image class="disc" src="/static/images/song/disc.png"></image>
<image class="musicImg" src="{
{songList.al.picUrl}}"></image>
</view>
<!-- The lyrics -->
<view class="scrollLrc">
<text>{
{
currentLyric}}</text>
</view>
<!-- Progress bar control area -->
<view class="progressControl">
<text>{
{
currentTime}}</text>
<!-- Overall progress -->
<view class="barContril">
<!-- Real time progress bar -->
<view class="audio-currentime-Bar" style="width: {
{currentWidth + 'rpx'}}">
<!-- Little ball -->
<view class="audio-circle"></view>
</view>
</view>
<text>{
{
durationTime}}</text>
</view>
<!-- The bottom controls the playback area -->
<view class="musicControl">
<text class="iconfont icon-iconsMusicyemianbofangmoshiShuffle"></text>
<text class="iconfont icon-shangyishou" id="pre" bindtap="handleSwitch"></text>
<text class="iconfont {
{isPlay?'icon-zanting': 'icon-bofang'}} big" bindtap="handleMusicPlay"></text>
<text class="iconfont icon-next" id="next" bindtap="handleSwitch"></text>
<text class="iconfont icon-iconsMusicyemianbofangmoshiPlayList"></text>
</view>
</view>
--songDeatai.js
import Pubsub from 'pubsub-js'
import request from '../../utils/request.js'
import moment from 'moment'
// pages/songDetail/songDetail.js
Page({
/** * Initial data of the page */
data: {
isPlay: false, // Mark whether the music is played
songList: {
}, // Song details
musicId: "",// Store songs id
musicLink: "", // Store music links
currentTime: '00:00',// Real time
durationTime: '00:00', // Total duration
currentWidth: 0, // The width of the real-time progress bar
currentLyric: "",// Current lyrics object
lyric: [], // The lyrics
lyricTime: 0,// The time corresponding to the lyrics
},
/** * Life cycle function -- Monitor page loading */
onLoad: function (options) {
/* options Accept the value passed by the route */
let musicId = options.musicId
this.setData({
musicId,
})
// call Get song list details
this.getMusicInfo(musicId)
// call The lyrics
this.getLyric(musicId);
// Create an instance that controls music playback
this.backgroundAudioManager = wx.getBackgroundAudioManager();
// Monitor music playback / Pause
this.backgroundAudioManager.onPlay(() => {
this.getIsPlay(true)
});
this.backgroundAudioManager.onPause(() => {
this.getIsPlay(false)
});
this.backgroundAudioManager.onStop(() => {
this.getIsPlay(false)
})
// Monitor the progress of music playing in real time
this.backgroundAudioManager.onTimeUpdate(() => {
this.musicPlayTime()
})
// The listening music will end naturally
this.backgroundAudioManager.onEnded(() => {
console.log(" About to enter the next song ")
// Automatically switch to the next music , And automatically play
Pubsub.publish('switchType', 'next')
// Restore the length of the real-time progress bar to 0; Time reverts to 0;
this.setData({
currentWidth: 0,
currentTime: '00:00',
isPlay: false,
lyric: [],
currentLyric: "",
lyricTime: 0,// The time corresponding to the lyrics
})
Pubsub.subscribe('musicId', (msg, musicId) => {
// Get songs
this.getMusicInfo(musicId)
// Get the lyrics
this.getLyric(musicId)
// Automatically play the current music
this.musicControl(true, musicId)
Pubsub.unsubscribe('musicId')
})
})
// Let the music play as soon as you come in
this.musicControl(true, musicId)
},
// Observe the music playing progress
musicPlayTime() {
// Get the corresponding time of lyrics
let lyricTime = Math.ceil(this.backgroundAudioManager.currentTime)
// Format the real-time playback time
let currentTime = moment(this.backgroundAudioManager.currentTime * 1000).format("mm:ss")
let currentWidth = (this.backgroundAudioManager.currentTime / this.backgroundAudioManager.duration) * 450;
this.setData({
currentTime,
lyricTime,
currentWidth
})
// Get the current lyrics
this.getCurrentLyric()
},
// modify isPlay The state of
getIsPlay(isPlay) {
this.setData({
isPlay
})
},
// Get song details
async getMusicInfo(musicId) {
let result = await request("/song/detail", {
ids: musicId })
let durationTime = moment(result.songs[0].dt).format("mm:ss")
this.setData({
songList: result.songs[0],
durationTime
})
// Dynamically modify the window title
wx.setNavigationBarTitle({
title: this.data.songList.name
})
},
// Click play / Suspended callback
handleMusicPlay() {
let isPlay = !this.data.isPlay
// Modify data status
this.setData({
isPlay
})
let {
musicId, musicLink } = this.data;
this.musicControl(isPlay, musicId, musicLink)
},
// Control music playback / Suspended function
async musicControl(isPlay, musicId, musicLink) {
if (isPlay) {
// Music playing
if (!musicLink) {
// First request
let musicLinkData = await request('/song/url', {
id: musicId })
// Get music links
musicLink = musicLinkData.data[0].url;
// Update music links
this.setData({
musicLink
})
}
this.backgroundAudioManager.src = musicLink; // Audio data source
this.backgroundAudioManager.title = this.data.songList.name; // Audio title , Required
} else {
// Music pause
this.backgroundAudioManager.pause(); // Music suspended
}
},
// Click the callback of cutting song
handleSwitch(event) {
// Get the type of cut song
let type = event.currentTarget.id;
console.log(type)
// Close the currently playing music
this.backgroundAudioManager.stop();
// Publish message data to recommendSong page
Pubsub.publish("switchType", type)
Pubsub.subscribe('musicId', (msg, musicId) => {
console.log(musicId)
// Get music details
this.getMusicInfo(musicId);
// Get the lyrics of music
this.getLyric(musicId)
// Automatically play the current music
this.musicControl(true, musicId);
// Unsubscribe
Pubsub.unsubscribe('musicId')
})
},
// Get the lyrics
async getLyric(musicId) {
let lyricData = await request("/lyric", {
id: musicId });
let lyric = this.formatLyric(lyricData.lrc.lyric);
},
// Pass in the initial lyrics text text
formatLyric(text) {
let result = [];
let arr = text.split("\n"); // The original lyrics text has been changed, which is much more convenient , We go directly through the newline “\n” For cutting
let row = arr.length; // Get the number of lines of lyrics
for (let i = 0; i < row; i++) {
let temp_row = arr[i]; // Now the format of each line is roughly like this "[00:04.302][02:10.00]hello world";
let temp_arr = temp_row.split("]");// We can go through “]” Separate time and text
let text = temp_arr.pop(); // Remove the lyrics text from the array , Got the lyrics text !
// Then deal with the remaining lyrics
temp_arr.forEach(element => {
let obj = {
};
let time_arr = element.substr(1, element.length - 1).split(":");// First put the extra “[” Get rid of , Then separate out points 、 second
let s = parseInt(time_arr[0]) * 60 + Math.ceil(time_arr[1]); // Convert time into and currentTime The same type , Easy to scroll later
obj.time = s;
obj.text = text;
result.push(obj); // Each line of lyrics object is stored in the component lyric Lyrics attribute
});
}
result.sort(this.sortRule) // Because of the same lyrics at different times, we are lined up , So here we need to rearrange it in chronological order
this.setData({
lyric: result
})
},
// Control the lyrics
getCurrentLyric() {
let j;
for (j = 0; j < this.data.lyric.length - 1; j++) {
if (this.data.lyricTime == this.data.lyric[j].time) {
this.setData({
currentLyric: this.data.lyric[j].text
})
}
}
}
})
--songDeatil.wxss
page {
height: 100%;
}
.songDetailContainer{
height: 100%;
/* background: rgba(0,0,0,0.5); */
background-color: #696969;
display: flex;
flex-direction: column;
align-items: center;
}
/* base */
.circle{
position: relative;
z-index: 100;
width: 60rpx;
height: 60rpx;
border-radius: 50%;
background: #fff;
margin: 10rpx 0;
}
/* rocker */
.needle {
position: relative;
z-index: 99;
top: -40rpx;
left: 60rpx;
width: 192rpx;
height: 274rpx;
transform-origin: 40rpx 0; /* Rotate the center point ,x Axis y Axis */
transform: rotate(-20deg); /* rotate */
transition: transform 1s; /* transition */
}
.needleRotate {
transform: rotate(0deg);
}
/* disk */
.discContainer {
position: relative;
top: -170rpx;
width: 598rpx;
height: 598rpx;
}
.discAnimation {
animation: disc 4s linear infinite;/* infinite Infinite loop */
animation-delay: 1s; /* Animation delay 1s */
}
/* @keyframes: Set animation frame 1) from to - Use simple animation , Only start frame and end frame 2) percentage - Mostly used for complex animation , The animation is more than two frames */
@keyframes disc {
from{
transform: rotate(0deg);
}
to{
transform: rotate(360deg);
}
}
.disc {
width: 598rpx;
height: 598rpx;
}
.musicImg{
position: absolute;
top:0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
width: 370rpx;
height: 370rpx;
border-radius: 50%;
}
/* Lyrics show */
.scrollLrc {
position: absolute;
bottom: 280rpx;
width: 640rpx;
height: 120rpx;
line-height: 120rpx;
text-align: center;
}
/* Bottom control area */
.musicControl {
position: absolute;
bottom: 40rpx;
left: 0;
border-top: 1rpx solid #fff;
width: 100%;
display: flex;
}
.musicControl text {
width: 20%;
height: 120rpx;
line-height: 120rpx;
text-align: center;
color: #fff;
font-size: 50rpx;
}
.musicControl text.big{
font-size: 80rpx;
}
/* Progress bar control area */
.progressControl{
position: absolute;
bottom: 200rpx;
width: 640rpx;
height: 80rpx;
line-height: 80rpx;
display: flex;
}
.barContril{
position: relative;
width: 450rpx;
height: 4rpx;
background: rgba(0,0,0,0.4);
margin: auto;
}
.audio-currentime-Bar{
position: absolute;
top:0;
left: 0;
width: 100rpx;
z-index: 1;
height: 4rpx;
background: red;
}
/* Little ball */
.audio-circle{
position: absolute;
right: -12rpx;
top:-4rpx;
width: 12rpx;
height: 12rpx;
border-radius: 50%;
background: #fff;
}
(5)pubsub-js News publishing subscription
pubsub-js It is suitable for communication between any components
npm install pubsub-js // install
import Pubsub from ‘pubsub-js’ // Reference in filePubsub.subscribe ( “XXX” , (msg,type) => { } ) // subscribe
Pubsub.unsubscribe(“XXX”)// Unsubscribe
Pubsub.publish(“XXX”, value )// Release
Daily recommendation page and music playing page pubsub-js
3、 ... and 、 Related information
https://binaryify.github.io/NeteaseCloudMusicApi/#/?id=%e6%8e%a5%e5%8f%a3%e6%96%87%e6%a1%a3
https://download.csdn.net/download/qq_48701993/85877882
边栏推荐
- 全网都在疯传的《老板管理手册》(转)
- Summary of common operation and maintenance commands
- Study diary: February 14th, 2022
- 技术管理进阶——如何在面试中考察候选人并增大入职概率
- Transformation between yaml, Jason and Dict
- Preliminary understanding of C program design
- Solve the problem that openocd fails to burn STM32 and cannot connect through SWD
- Mysql - - Index
- Sort out several network request methods of JS -- get rid of callback hell
- Capturing and sorting out external articles -- autoresponder, composer, statistics [III]
猜你喜欢
一台服务器最大并发 tcp 连接数多少?65535?
treevalue——Master Nested Data Like Tensor
Summary of common operation and maintenance commands
Is it OK for fresh students to change careers to do software testing? The senior answered with his own experience
技术管理进阶——如何在面试中考察候选人并增大入职概率
【愚公系列】2022年7月 Go教学课程 002-Go语言环境安装
QT6 QML book/qt quick 3d/ Basics
《ActBERT》百度&悉尼科技大学提出ActBERT,学习全局局部视频文本表示,在五个视频-文本任务中有效!...
SQL injection - Fundamentals of SQL database operation
2022 low voltage electrician examination and low voltage electrician simulation examination question bank
随机推荐
Qualcomm platform WiFi update disconnect end open event
MySQL——JDBC
Gauss elimination solves linear equations (floating-point Gauss elimination template)
Inventory 2021 | yunyuansheng embracing the road
C 10 new feature [caller parameter expression] solves my confusion seven years ago
treevalue——Master Nested Data Like Tensor
Link aggregation based on team mechanism
MySQL——SQL注入问题
浅析 Ref-NeRF
Monkey/ auto traverse test, integrate screen recording requirements
Après 90 ans, j'ai démissionné pour démarrer une entreprise et j'ai dit que j'allais détruire la base de données Cloud.
17 websites for practicing automated testing. I'm sure you'll like them
Pengcheng cup Web_ WP
TLS environment construction and plaintext analysis
(5) Web security | penetration testing | network security operating system database third-party security, with basic use of nmap and masscan
C程序设计的初步认识
Last week's content review
Service discovery and load balancing mechanism -service
Apprentissage intensif - notes d'apprentissage 1 | concepts de base
抓包整理外篇——————autoResponder、composer 、statistics [ 三]