uniapp 给画作生成画框

news/2024/9/16 18:49:32/ 标签: uni-app, javascript, 前端
javascript"><template><ax-page class="privateCustom"><gui-page :customHeader="true" ref="guipage"><template #gHeader><aHeader title="个性定制" :showTitle="true" back="2"></aHeader></template><template v-slot:gBody><view class="privateCustom-body"><form @submit="submit"><view class="gui-bg-white gui-dark-bg-level-3 gui-padding-x"><view class="gui-form-item gui-border-b"><text class="gui-form-label">{{ pageIndex == 0 ? '上传图片' : '已选画作' }} |</text><view class="rowContentDiv"><view v-if="pageIndex == 0"><view@tap="uploadImgClick"class="uploadDiv"v-if="!formData.image"><image class="addImg" :src="addPImg" mode="scaleToFill" /><text>图片</text></view><imagev-else:src="formData.image"class="uploadDiv"mode="aspectFit"@tap="uploadImgClick"></image></view><image:src="canvasSize.imgSrc || formData.image"class="posterImg"mode="aspectFit"@tap="previewImage(canvasSize.imgSrc || formData.image)"></image></view></view><!-- <view class="gui-form-item gui-border-b"><text class="gui-form-label">画作名称 |</text><view class="frame-box content"><inputtype="text"class="gui-form-input"v-model="formData.name"name="name"placeholder="请输入内容"/></view></view> --><view class="gui-form-item gui-border-b" v-if="pageIndex == 0"><text class="gui-form-label">画框选择 |</text><view class="frame-box content"><viewstyle="display: flex; align-items: center"v-for="(item, index) in selectFrame":key="index":class="['frame-item',{ 'frameImg-active': index == formData.frame }]"@tap="frameClick(index)"><image:src="$App.ossImage(item.url)"class="frameImg"mode="aspectFit"/><text>{{ item.name }}</text></view></view></view><view class="gui-form-item gui-border-b" v-if="pageIndex == 0"><text class="gui-form-label">选择画纸 |</text><view class="frame-box content"><viewstyle="display: flex; align-items: center"v-for="(item, index) in papers":key="index":class="['frame-item',{ 'frameImg-active': index == formData.paper }]"@tap="paperClick(index)"><image:src="$App.ossImage(item.url)"class="frameImg"mode="aspectFit"/><text>{{ item.name }}</text></view></view></view><view class="gui-form-item gui-border-b" v-if="pageIndex == 0"><text class="gui-form-label">画框尺寸 |</text><view class="frame-box content"><picker@change="selectSize":value="currentSize"range-key="key"v-if="selectSizeMenu.length > 0":range="selectSizeMenu"><view class="uni-input">{{selectSizeMenu[currentSize].key}}</view></picker></view></view><viewclass="gui-form-item gui-border-b"v-if="currentSize == selectSizeMenu.length - 1 && pageIndex == 0"><text class="gui-form-label">自定义尺寸</text><view class="frame-box content"><inputtype="number"class="gui-form-input"v-model="formData.size"name="size"placeholder="最小10"@blur="getImageSize":min="1"/></view></view><view class="gui-form-item gui-border-b" v-if="pageIndex == 0"><text class="gui-form-label">卡纸宽度 |</text><view class="frame-box content"><picker@change="selectWidths":value="formData.width"range-key="w"v-if="widths.length > 0":range="widths"><view class="uni-input">{{ widths[formData.width].w }}cm</view></picker></view></view><view class="gui-form-item gui-border-b" v-if="pageIndex == 0"><text class="gui-form-label">选择数量 |</text><view class="frame-box content"><gui-step-box:inputClass="['gui-step-box-input','gui-border-radius','gui-bg-gray','gui-dark-bg-level-2']"@change="stepChange":value="formData.num":minNum="1"></gui-step-box></view></view><view class="gui-form-item gui-border-b" v-if="pageIndex == 0"><text class="gui-form-label">指导价格 |</text><view class="price-box content"><image :src="pricePImg" class="pricePImg" /><text class="price-text">{{Utils.amountS(formData.price)}}</text></view></view><view class="gui-form-item gui-border-b" v-if="pageIndex == 1"><text class="gui-form-label">作品备注 |</text><view class="frame-box content"><inputtype="text"class="gui-form-input"v-model="formData.mark"name="mark"placeholder="请输入备注"/></view></view><view class="gui-form-item gui-border-b" v-if="pageIndex == 1"><text class="gui-form-label">收货地址 |</text><view class="frame-box content" @tap="goAddressList"><viewclass="left-part"v-if="Object.keys(formData.address).length > 0"><view class="name">{{ formData.address.recipient }}{{ formData.address.phone }}</view><view class="address-detail">{{`${formData.address.address}${formData.address.detail}`}}</view></view><view class="left-part" v-else><view class="name"> 请选择收货地址 </view></view><!-- <view class="right-part"><textclass="gui-list-arrow-right gui-icons gui-color-gray-light">&#xe601;</text></view> --></view></view><view class="gui-form-item gui-border-b" v-if="pageIndex == 1"><text class="gui-form-label">提示 |</text><view class="frame-box content" style="color: red">定制商品,非商品自身问题,暂不支持退换服务,请您在确认订单前仔细核对商品信息,如有任何疑问,请及时联系我们。感谢您的理解与支持!</view></view></view><buttonclass="gui-button gui-bg-primary gui-noborder submitBtn"formType="submit"><text class="gui-color-white gui-button-text">{{pageIndex == 0 ? '去下单' : '确认下单'}}</text></button><view style="height: 60rpx"></view></form><view class="canvas-in"><canvasv-if="canvasSize.heightIn > 0":style="{width: canvasSize.widthIn + 'px',height: canvasSize.heightIn + 'px',opacity: 0}"canvas-id="graceCanvas"class="grace-canvas"></canvas></view></view></template></gui-page></ax-page>
</template>
<script setup lang="ts">
import App from '@/script/module/App'
import PublicImg from '@/components/publicImage.vue'
import User from '@/script/module/User'
import { axj } from '@/script/sdk/ms-store'
import axConfig from '@/script/AxConfig'
import {onBackPress,onLoad,onPageScroll,onReachBottom,onShow,onUnload
} from '@dcloudio/uni-app'
import { computed, nextTick, onMounted, reactive, ref } from 'vue'
import Page from '@/script/module/Page'
import Utils from '@/script/util/Utils'
import Artist from '@/script/module/Artist'
import addPImg from '../images/addP.png'
import pricePImg from '../images/priceP.png'
import SdkActs from '@/script/module/SdkActs'const pageIndex = ref(0)
const selectSizeMenu = ref([])
const sizeList = ref([])
const selectFrame = ref([])
const papers = ref([])
const widths = ref([])const formData = reactive({name: '',mark: '',image: '',frame: 0,num: 1,price: <number | string>'',address: User.state.address,size: <any>10,width: 0,paper: 0
})
const currentSize = ref(0)
const customOrderCfg = ref(<axj.DtDCustomOrderCfg>undefined)
const imgInfo = ref({width: 0,height: 0,aspectRatio: 0
})const canvasSize = reactive({widthIn: 0, // 自动计算转换为 pxheightIn: 0, //  自动计算转换为 pxbgColor: '#ffffff', // 背景颜色bgImg: '',contentImg: '',imgSrc: '',multiple: 1, // 将画布放大 2.0 - 2.9 倍(支持小数,过大app端会出现无法渲染的问题),保存的图片更清晰bw: 0,iw: 0,ih: 0,w: 0,h: 0
})
const context = ref(<any>null)const imagesPath = ref(<any>[])// 选择图片
const uploadImgClick = () => {uni.chooseImage({count: 1,extension: ['jpeg', 'jpg', 'png'],success: (res) => {console.log('[  getImageInfo  ] >', res)formData.image = res.tempFilePaths[0]getImageInfo(res.tempFilePaths[0])formData.name = res?.tempFiles[0]?.name || ''}})
}// 获取图片信息
const getImageInfo = (tempFilePath) => {uni.getImageInfo({src: tempFilePath,success: (info) => {const width = info.widthconst height = info.height// 获取宽高比,用于自定义尺寸时候计算宽度const aspectRatio = width / heightimgInfo.value = {width: width,height: height,aspectRatio: aspectRatio}initSize()customOrder()}})
}// 自定义尺寸重绘画布
const getImageSize = () => {customOrder()initSize()
}// 上传图片
const uploadFun = (filePath,name: string = new Date().getTime() + 'image',back: () => any
) => {Artist.fileUpload(filePath, name, 'png', (url) => {uni.hideLoading()formData.image = urlif (back) {back()}})
}
// 选择画框
const frameClick = (index) => {formData.frame = indexinitSize()customOrder()
}const paperClick = (index) => {formData.paper = indexcustomOrder()
}// 定做数量
const stepChange = (e) => {if (e && e[0]) {formData.num = e[0]customOrder()}
}// 选择尺寸
const selectSize = (e) => {// console.log(e)currentSize.value = e.detail.valueif (currentSize.value == selectSizeMenu.value.length - 1) {formData.size = selectSizeMenu.value[0].w} else {formData.size = selectSizeMenu.value[e.detail.value].winitSize()customOrder()}
}// 选择卡纸宽度
const selectWidths = (e) => {formData.width = e.detail.valueinitSize()customOrder()
}// 选择地址
const goAddressList = () => {SdkActs.address(null, null, null)
}// 提交订单
const submit = (e) => {if (formData.image.length == 0) {App.toast('请上传图片')return}if (pageIndex.value == 1) {if (!formData.address) {App.toast('请选择收货地址')return}uni.showModal({title: '提示',content: '确认要提交订单吗?',success: (res) => {if (res.confirm) {// 上传图片后回调提交订单uploadFun(formData.image, formData.name, () => {customOrder(true)})} else if (res.cancel) {// 用户点击取消按钮console.log('用户点击取消')}}})} else {pageIndex.value = 1}
}/*** 自定义画框订单(包括预览逻辑)  confirm 	确认订单(下单)* 流程 : 提交订单-订单详情-支付*/
const customOrder = (confirm?: boolean) => {if (formData.image.length == 0) {App.toast('请上传图片')return}// if (!formData.name) {//   App.toast('请输入画作名称')//   return// }let sizes = selectSizeMenu.value[currentSize.value]let params = {image: formData?.image, //	  画芯// name: formData?.name, //		画作名称frameIdx: formData.frame, //		画框索引paperIdx: formData.paper, //		画纸索引widthIdx: formData.width, //		卡纸宽度索引// attName: selectFrame.value[formData.frame]?.name, //		画框名称w: sizes?.w, //		宽(cm)h: sizes?.h, //		高(cm)num: formData.num, //		数量mark: formData.mark, //		备注confirm: confirm || false, //		确认订单(下单)address: formData.address //		收货地址}App.client.store.Api_order.customOrder(1,[params],(err: any, res: axj.DtDOrderRep) => {console.log('[ customOrder ] >', err, res)formData.price = res.amountif (res?.orderId && confirm) {// uni.redirectTo({//   url: `/pagesShop/shop/cashierDesk?orderId=${res.orderId}`// })Page.navUri(`/pagesShop/order/orderDetail?orderId=${res.orderId}`)} else {// initSize()}})
}
// 获取初始化信息
const getCustomOrderCfg = () => {App.client.store.Api_order.customOrderCfg(1,[],(err: any, res: axj.DtDCustomOrderCfg) => {customOrderCfg.value = resif (res) {if (res.sizes) {// selectSizeMenu.value = ['其他']// 拼接尺寸显示内容for (let i = 0; i < res.sizes.length; i++) {const el = res.sizes[i]if (el.open) {el.key = el.w + 'cm*' + el.h + 'cm'// selectSizeMenu.value.unshift(size)}}selectSizeMenu.value = res.sizes// 增加自定义尺寸选项let obj = {name: '其他',w: res.sizes[0].w || 10,h: res.sizes[0].h || 10,open: true,key: '其他'}formData.size = obj.w//@ts-ignoreselectSizeMenu.value.push(obj)}if (res.frames) {selectFrame.value = res.frames}if (res.papers) {papers.value = res.papers}if (res.widths) {widths.value = res.widths}}})
}// 判断是否存在相同图片,存在则直接显示,不存在则生成
const checkNameExists = (back: (res: any) => any) => {let imgPath = imagesPath.valuelet name =selectSizeMenu.value[currentSize.value].key +'_' +selectSizeMenu.value[currentSize.value].w +'_' +formData.name +selectFrame.value[formData.frame].name +widths.value[formData.width].wconst existingImage = imgPath.find((image) => image.name === name)if (existingImage) {canvasSize.imgSrc = existingImage.urlback(existingImage)} else {back(null)}
}// w h 图片+画框的宽高  ,bw 画框尺寸 ,iw ih 图片宽高
const initSize = () => {if (!formData.image) {return}// 如果是自定义宽度,根据图片宽高比,计算高度if (currentSize.value == selectSizeMenu.value.length - 1) {formData.size = parseInt(formData.size)formData.size = Math.max(formData.size, 10)if (formData.size) {const width = formData.sizeconst height = width / (imgInfo.value.aspectRatio || 1)selectSizeMenu.value[selectSizeMenu.value.length - 1].w = width.toFixed(2)selectSizeMenu.value[selectSizeMenu.value.length - 1].h =height.toFixed(2)}}checkNameExists((res) => {if (!res) {let width = selectSizeMenu.value[currentSize.value].wlet height = selectSizeMenu.value[currentSize.value].hlet imgWidth = imgInfo.value.widthlet imgHeight = imgInfo.value.heightlet cardBoardWidth = widths.value[formData.width].wif (imgWidth >= imgHeight != width >= height) {// 画框方向和画面方向一致let swap = widthwidth = heightheight = swap}let imgW_H = imgWidth / imgHeightif (imgW_H >= width / height) {imgWidth = width - (cardBoardWidth + 2) * 2imgHeight = imgWidth / imgW_H} else {imgHeight = height - (cardBoardWidth + 2) * 2imgWidth = imgHeight * imgW_H}let w = widthlet h = heightlet bw = 2let iw = imgWidthlet ih = imgHeightconsole.log('[  initSize  ] >', w, h, iw, bw, ih)if (w >= h !== iw >= ih) {var t = ww = hh = t}var s = 750 / wif (!s) {return}canvasSize.w = 750canvasSize.h = h * scanvasSize.bw = bw * scanvasSize.iw = iw * scanvasSize.ih = ih * scanvasSize.widthIn = canvasSize.wcanvasSize.heightIn = canvasSize.hsetTimeout(() => {draw()}, 1000)}})
}// 绘制画框图
const draw = () => {uni.showLoading({ title: '正在生成画框图...' })step01()let img = selectFrame.value[formData.frame].urlif (formData.image != '') {drawBGIMG(App.ossImage(img), () => {step03()})} else {step03()}
}const step01 = () => {context.value.setFillStyle(canvasSize.bgColor)context.value.fillRect(0, 0, canvasSize.widthIn, canvasSize.heightIn)
}
// 绘制边框
const drawBGIMG = (img, callback) => {uni.downloadFile({url: img,success: (res) => {if (res.statusCode == 200) {// 绘制uni.getImageInfo({src: res.tempFilePath,success: (res2) => {var pattern = context.value.createPattern(res.tempFilePath,'repeat')context.value.fillStyle = patternvar scale = canvasSize.bw / res2.heightvar w_2 = canvasSize.w * 0.5var h_2 = canvasSize.h * 0.5// 顶部边框context.value.save()context.value.rotate(0)context.value.scale(scale, scale)context.value.fillRect(0,0,canvasSize.w / scale,canvasSize.bw / scale)context.value.restore()// 底部边框context.value.save()context.value.translate(w_2, h_2)context.value.rotate(Math.PI)context.value.translate(-w_2, -h_2)context.value.scale(scale, scale)context.value.fillRect(0,0,canvasSize.w / scale,canvasSize.bw / scale)context.value.restore()// 右侧边框context.value.save()context.value.translate(w_2, h_2)context.value.rotate(Math.PI * 0.5)context.value.translate(-h_2, -w_2)context.value.scale(scale, scale)// 开始绘制梯形路;context.value.beginPath()context.value.moveTo(0, 0)context.value.lineTo(canvasSize.h / scale, 0)context.value.lineTo(canvasSize.h / scale - canvasSize.bw / scale,canvasSize.bw / scale)context.value.lineTo(canvasSize.bw / scale, canvasSize.bw / scale)context.value.closePath()// 填充梯形区域context.value.fill()context.value.restore()// 左侧边框context.value.save()context.value.translate(w_2, h_2)context.value.rotate(-Math.PI * 0.5)context.value.translate(-h_2, -w_2)context.value.scale(scale, scale)// 开始绘制梯形路;context.value.beginPath()context.value.moveTo(0, 0)context.value.lineTo(canvasSize.h / scale, 0)context.value.lineTo(canvasSize.h / scale - canvasSize.bw / scale,canvasSize.bw / scale)context.value.lineTo(canvasSize.bw / scale, canvasSize.bw / scale)context.value.closePath()// 填充梯形区域context.value.fill()context.value.restore()callback()}})}},fail: function (e) {uni.hideLoading()console.log(e)}})
}
// 绘制图片
const step03 = () => {uni.downloadFile({url: formData.image.startsWith('tmp/')? App.ossImage(formData.image): formData.image,success: (res) => {if (res.statusCode === 200) {context.value.drawImage(res.tempFilePath,(canvasSize.w - canvasSize.iw) / 2,(canvasSize.h - canvasSize.ih) / 2,canvasSize.iw,canvasSize.ih)// 在最后一步执行 drawIt 完整最终的绘制drawIt()}},fail: function (e) {console.log(e)}})
}const drawIt = () => {context.value.draw(true, () => {setTimeout(() => {uni.canvasToTempFilePath({x: 0,y: 0,width: canvasSize.widthIn,height: canvasSize.heightIn,destWidth: canvasSize.widthIn,destHeight: canvasSize.heightIn,canvasId: 'graceCanvas',success: (res) => {// 在H5平台下,tempFilePath 为 base64canvasSize.imgSrc = res.tempFilePathlet name =selectSizeMenu.value[currentSize.value].key +'_' +selectSizeMenu.value[currentSize.value].w +'_' +formData.name +selectFrame.value[formData.frame].name +widths.value[formData.width].wcheckNameExists((res) => {if (!res) {imagesPath.value.push({name: name,url: canvasSize.imgSrc})}})uni.hideLoading()}})}, 1000)})
}
const previewImage = (url) => {;(url = url.startsWith('tmp/') ? App.ossImage(url) : url),uni.previewImage({urls: [url],current: 0})
}const kf = () => {Page.openHelp(JSON.stringify(data))
}onShow(() => {// 必须放在show防止登录后返回不触发getCustomOrderCfg()
})onLoad((option) => {if (!User.state?.logined) {Page.navLogin()}// 监听选择地址返回数据uni.$on('addressSelectBack', (res) => {formData.address = res})context.value = uni.createCanvasContext('graceCanvas')
})const goBack = () => {if (pageIndex.value == 1) {pageIndex.value = 0} else {// 物理返回nextTick(() => {Page.navBack()})}
}
onBackPress((e: any) => {if (e && e.from === 'backbutton') {goBack()return true}
})
onUnload(() => {uni.$off('addressSelectBack')
})
</script>
<style scoped lang="scss">
.privateCustom {background: #fbfbfb;position: relative;.privateCustom-body {position: relative;//   margin-top: 38rpx;}// .prvate-line {//   width: 2rpx;//   height: 20rpx;//   background: #000;//   margin-right: 44rpx;//   margin-left: 15rpx;//   margin-top: 6rpx;// }.content {width: 500rpx;}.rowContentDiv {display: flex;justify-content: space-around;width: 500rpx;}.posterImg {height: 200rpx;width: 200rpx;}.uploadDiv {height: 200rpx;width: 200rpx;display: flex;justify-content: center;align-items: center;flex-direction: column;font-weight: 400;font-size: 26rpx;color: #a1a1a1;border: 2rpx dashed black;.addImg {width: 46rpx;height: 46rpx;flex: none;}}:deep(.gui-form-label) {font-weight: 400;font-size: 24rpx;color: #323232;margin-right: 20rpx !important;// line-height: normal !important;}:deep(.gui-form-item) {// align-items: flex-start !important;height: auto !important;// line-height: normal !important;width: auto !important;// margin-top: 80rpx;// margin-top: 55rpx;margin-top: 15rpx;}.frame-box {flex-wrap: wrap;display: flex;.frame-item {border: 2rpx solid #fff;padding: 4rpx;display: flex;flex-direction: column;justify-content: center;align-items: center;margin-right: 4px;}.frameImg {width: 50rpx;height: 50rpx;margin-bottom: 18rpx;}// .frameImg:nth-child(2n - 1) {//   margin-right: 20rpx;// }.frameImg-active {border-color: #961912 !important;}}.price-box {display: flex;font-weight: 400;font-size: 37rpx;color: #ff0000;line-height: 37rpx;height: 48rpx;align-items: center;.pricePImg {width: 48rpx;height: 48rpx;}text {margin-left: 9rpx;}}
}.submitBtn {width: 702rpx;height: 90rpx;background-color: #e4a428 !important;font-weight: 400;font-size: 52rpx;color: #ffffff;line-height: 90rpx;margin-left: 24rpx !important;margin-top: 40rpx !important;
}
.canvas-in {width: 750rpx;overflow: hidden;position: absolute;z-index: 1;left: 0;top: -5000px;
}
</style>

customOrderCfg数据格式

javascript">[1,{"frames": [{"price": 1000,"name": "画框一","bName": "这两个是红色的画框","url": "ms-admin/2024/08/15/00i7ihmuzlxdh0mh.png","open": true,"bname": "这两个是红色的画框"},{"price": 1000,"name": "画框二","url": "ms-admin/2024/08/15/00u8ihmuzlrf8nzr.png","open": true},{"price": 1000,"name": "画框三","url": "ms-admin/2024/08/15/00x9ihmuzlj3ey2q.png","open": true}],"papers": [{"price": 10000,"name": "宣纸","url": "ms-admin/2024/08/15/00uxedxuzlba8ebp.png","open": true},{"price": 20000,"name": "油画纸","url": "ms-admin/2024/08/15/0040fdxuzlcxwifk.png","open": true}],"sizes": [{"name": "尺寸一","w": 43.0,"h": 77.0,"open": true},{"name": "尺寸二","w": 50.0,"h": 50.0,"open": true},{"name": "尺寸三","w": 36.0,"h": 96.0,"open": true},{"name": "尺寸四","w": 77.0,"h": 43.0,"open": true}],"widths": [{"name": "大框大画","w": 1.0,"open": true},{"name": "大框中画","w": 10.0,"open": true},{"name": "大框小画","w": 15.0,"open": true}]}
]

http://www.ppmy.cn/news/1522628.html

相关文章

深度学习与大模型第4课:使用多种模型在Pima印度糖尿病数据集上的分类效果评估

文章目录 技术博客&#xff1a;使用多种模型在Pima印度糖尿病数据集上的分类效果评估数据集介绍数据预处理模型一&#xff1a;逻辑斯谛回归&#xff08;Logistic Regression&#xff09;模型二&#xff1a;支持向量机&#xff08;SVM&#xff09;模型三&#xff1a;决策树&…

1、正则表达式

1、正则表达式是一种用于描述文本模式的工具。它是由字符和特殊符号组成的字符串&#xff0c;描述了模式的重复或者多个字符&#xff0c;于是就可以按照某种模式匹配一系列有相似特征的字符串。它主要的作用是将文本用某种可被计算机识别的模式表现出来&#xff0c;为高级的文本…

Helm Deploy Online Rancher v2.9.1

文章目录 准备安装查看下载 准备 $ kubectl get node NAME STATUS ROLES AGE VERSION kube-master01 Ready control-plane 19d v1.29.5 kube-node01 Ready <none> 19d v1.29.5 kube-node02 Ready <none&…

Tekton简介,安装和构建最简单ci/cd

简介 Tekton是一种基于k8的支持CI/CD的operator。 说到持续集成&#xff0c;我们比较熟悉的有jenkins&#xff0c;gitlab ci等&#xff0c;但只有Tekton是云原生的。 既然Tekton是一种operator&#xff0c;那就必须了解它的CRD&#xff0c;然后我们定义CR&#xff0c;让Tekt…

WebAPI (一)DOM树、DOM对象,操作元素样式(style className,classList)。表单元素属性。自定义属性。间歇函数定时器

文章目录 Web API基本认知一、 变量声明二、 DOM1. DOM 树2. DOM对象3. 获取DOM对象(1)、选择匹配的第一个元素(2)、选择匹配多个元素 三、 操作元素1. 操作元素内容2. 操作元素属性(1)、常用属性&#xff08;href之类的&#xff09;(2)、通过style属性操作CSS(3)、通过类名(cl…

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、…

golang hertz框架入门

两种模式新建项目 1、手动新建项目 2、使用hz工具新建项目 一、手动创建项目&#xff0c;并拉取框架 1、新建项目目录 hertz_demo_w 2、在项目跟目录新建main.go 文件 package mainimport ("context""github.com/cloudwego/hertz/pkg/app""github.…

API安全 | 发现API的5个小tips

在安全测试目标时&#xff0c;最有趣的测试部分是它的 API。API 是动态的&#xff0c;它们比应用程序的其他部分更新得更频繁&#xff0c;并且负责许多后端繁重的工作。在现代应用程序中&#xff0c;我们通常会看到 REST API&#xff0c;但也会看到其他形式&#xff0c;例如 Gr…

C# 使用国密SM4加密解密

首先需第三方Nuget包&#xff1a;Portable.BouncyCastle &#xff08;源码来自http://www.bouncycastle.org/csharp/&#xff09;&#xff0c;支持.NET 4,.NET Standard 2.0 目录 使用BouncyCastle指定填充方案 零填充&#xff08;Zero Padding&#xff09; PKCS7填充&…

MariaDB基本知识汇总

/* MariaDB 1、视图 2、临时表 3、自定义函数 4、存储过程 5、触发器 6、游标 7、变量声明与赋值 8、常用函数&#xff08;日期格式&#xff0c;Guid&#xff0c;判断&#xff0c;循环&#xff0c;XML格式操作&#xff09; 9、动态执行SQL 语句 10、开启执行计划 11、创建登录M…

AI智能分析/智慧安防EasyCVR视频汇聚平台新版本(V3.6.0)播放鉴权与播放限制时长的区别介绍

随着科技的飞速发展&#xff0c;视频技术已成为现代社会不可或缺的一部分&#xff0c;广泛应用于安防监控、娱乐传播、在线教育、电商直播等多个领域。EasyCVR视频汇聚平台作为视频技术的佼佼者&#xff0c;不断推陈出新&#xff0c;通过功能更新迭代&#xff0c;为用户提供更加…

什么是视频缓存服务器,它有哪些作用?

视频缓存服务器通常拥有大容量的存储空间和高速的读写能力&#xff0c;它通过缓存(即临时存储)用户经常访问的视频内容&#xff0c;来优化内容的分发过程。这种服务器通常部署在网络中的关键位置&#xff0c;如靠近用户接入点的位置&#xff0c;以降低用户访问视频内容时的网络…

rtsp服务器逻辑

定时器逻辑&#xff1a;比如H264文件是每隔40ms发送一帧数据。aac文件每隔23ms发送一个音频帧数据。 在sink的子类中有aac和h264的sink&#xff0c;在两个子类的构造函数中需要添加它们各自的触发时间。调用的函数时runEvery()&#xff0c;将这两个触发时间设置到了TimerManag…

【H2O2|全栈】关于HTML(1)认识HTML

HTML相关知识 目录 前言 准备工作 WEB前端是什么&#xff1f; HTML是什么&#xff1f; 如何运行HTML文件&#xff1f; 标签 概念 分类 双标签和单标签 行内标签和块标签 HTML文档结构 预告和回顾 UI设计相关 Markdown | Md文档相关 项目合作管理相关 后话 前…

数据结构之堆的创建

1、堆的概念及结构 1.1堆的概念 如果有一个关键码的集合K{k0,k1,k2,…,kn-1}&#xff0c;把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中&#xff0c;并满足ki<k2i1且ki<k2i2&#xff08;或满足ki>k2i1且ki>k2i2&#xff09;&#xff0c;其中i0…

Vue2项目搭建:Vue2.7+Vite4+Pinia+TailwindCSS+Prettier+ESLint

目前 create-vue 和 Vite 都不提供 Vue2 项目的搭建&#xff0c;不想用 Vue CLI 和 webpack&#xff0c;于是就打算从 0 搭建一个工程化项目&#xff0c;支持组合式 API (Composition API) 写法&#xff0c;没有使用 TypeScript&#xff0c;有朋友需要的话我可以再完善一下。 N…

结构体小知识

目录 前言1.结构体数组1.1结构体数组理解1.2结构体数组知识运用1.3 -> 操作符 2. 知识拓展 前言 本期blog是对上一期指针知识的知识补充&#xff0c;如果各位大佬感兴趣的话&#xff0c;可以结合起来一起看&#xff01; 1.结构体数组 1.1结构体数组理解 结构体数组在本…

pytorch torch.nn.functional.one_hot函数介绍

torch.nn.functional.one_hot 是 PyTorch 中用于生成独热编码&#xff08;one-hot encoding&#xff09;张量的函数。独热编码是一种常用的编码方式&#xff0c;特别适用于分类任务或对离散的类别标签进行处理。该函数将整数张量的每个元素转换为一个独热向量。 函数签名 tor…

notepad++软件介绍(含安装包)

Notepad 是一款开源的文本编辑器&#xff0c;主要用于编程和代码编辑。它是一个功能强大的替代品&#xff0c;常常被用来替代 Windows 系统自带的记事本。 Notepad win系统免费下载地址 以下是 Notepad 的一些主要特点和功能&#xff1a; 多语言支持&#xff1a;Notepad 支持多…

Kafka【八】如何保证消息发送的可靠性、重复性、有序性

【1】消息发送的可靠性保证 对于生产者发送的数据&#xff0c;我们有的时候是不关心数据是否已经发送成功的&#xff0c;我们只要发送就可以了。在这种场景中&#xff0c;消息可能会因为某些故障或问题导致丢失&#xff0c;我们将这种情况称之为消息不可靠。虽然消息数据可能会…