UNIapp实现局域网内在线升级

首先是UNIapp 生成apk

用Hbuilder 进行打包云打包
可以从网站https://www.yunedit.com/reg?goto=cert 使用自有证书,目测比直接使用云证书要快一些。

发布apk 网站

发布内容用IIS发布即可
注意事项中记录如下内容

第一、需要在 iis 的MiMe 中添加apk 的格式,否则无法下载apk 文件到手持机中。 添加方式 打开MIME 点击添加
分别输入 apk application/vnd.android.package-archive 点击保存即可

第二、发布新的apk 的时候,需要修改应用版本号(往大了修改),同时版本号.json 文件中
newVersionCode对应的值,也要和新的应用版本号相同(方便检测更新) newVersionName 中保存的是当前PDA的版本名称
versionDesc 中可以添加修改的内容 appName 需要添加新发布的apk 名称(用于下载对应的文件)

第三、将对应的文件夹发布在iis中,同时要修改uniapp 中的http.js文件
uni.setStorageSync(‘loadVersion’, ‘http://127.0.0.1:8032/’); 修改内部的url

要在IIS中添加.apk文件的MIME类型,可以按照以下步骤操作:

打开IIS管理器,找到服务器,右键选择“属性”。
在打开的属性窗口中,选择“MIME类型”选项卡。
点击“MIME类型”按钮,打开MIME类型设置窗口。
选择“新建”来添加一个新的MIME类型。
在“扩展名”中填写“.apk”,在“MIME类型”中填写“.apk”的MIME类型“application/vnd.android.package-archive”。
点击“确定”保存设置。
重启IIS服务,以使更改生效。
完成以上步骤后,IIS就能够正确识别和处理.apk文件了

版本号.json中的内容为

{"newVersionCode":223,"newVersionName":"V1.2.0","versionDesc":"升级了部分功能","appName":"android_debug.apk"}

uniapp相关代码

结构
upgrade.vue中存在

<template>
	<view class="upgrade-popup">
		
		<view class="main">
			<view class="version">发现新版本{{versionName}}</view>
			<view class="content">
				<text class="title">更新内容</text>
				<view class="desc" v-html="versionDesc"></view>
			</view>
			<!--下载状态-进度条显示 -->
			<view class="footer" v-if="isStartDownload">
				<view class="progress-view" :class="{'active':!hasProgress}" @click="handleInstallApp">
					<!-- 进度条 -->
					<view v-if="hasProgress" style="height: 100%;">
						<view class="txt">{{percentText}}</view>
						<view class="progress" :style="setProStyle"></view>
					</view>
					<view v-else>
						<view class="btn upgrade force">{{ isDownloadFinish  ? '立即安装' :'下载中...'}}</view>
					</view>
				</view>
			</view>
			<!-- 强制更新 -->
			<view class="footer" v-else-if="isForceUpdate">
				<view class="btn upgrade force" @click="handleUpgrade">立即更新</view>
			</view>
			<!-- 可选择更新 -->
			<view class="footer" v-else>
				<view class="btn close" @click="handleClose">以后再说</view>
				<view class="btn upgrade" @click="handleUpgrade">立即更新</view>
			</view>
		</view>
	</view>
</template>
 
<script>
	import {
		downloadApp,
		installApp
	} from './upgrade.js'
	export default {
		data() {
			return {
				isForceUpdate: false, //是否强制更新
				versionName: '', //版本名称
				versionDesc: '', //更新说明
				downloadUrl: '', //APP下载链接
				isDownloadFinish: false, //是否下载完成
				hasProgress: false, //是否能显示进度条
				currentPercent: 0, //当前下载百分比
				isStartDownload: false, //是否开始下载
				fileName: '', //下载后app本地路径名称
			}
		},
		computed: {
			//设置进度条样式,实时更新进度位置
			setProStyle() {
				return {
					width: (510 * this.currentPercent / 100) + 'rpx' //510:按钮进度条宽度
				}
			},
			//百分比文字
			percentText() {
				let percent = this.currentPercent;
				if (typeof percent !== 'number' || isNaN(percent)) return '下载中...'
				if (percent < 100) return `下载中${percent}%`
				return '立即安装'
 
			}
		},
		onLoad(options) {
			this.init(options)
		},
		onBackPress(options) {
			// 禁用返回
			if (options.from == 'backbutton') {
				return true;
			}
 
		},
		methods: {
			//初始化获取最新APP版本信息
			init(options) {
				let randomNum = Math.random();
				//模拟接口获取最新版本号,版本号固定为整数
				const baseurl = uni.getStorageSync('loadVersion')+options.appName+'?V='+randomNum;;
				console.log('结果为')
				console.log((baseurl))
				//模拟接口获取
				setTimeout(() => {
                   //演示数据请根据实际修改
					this.versionName = options.versionName; //版本名称
					this.versionDesc = options.versionDesc; //更新说明
					this.downloadUrl = baseurl; //下载链接
					this.isForceUpdate = false; //是否强制更新
				}, 200)
			},
			//更新
			handleUpgrade() {
				console.log('Hello UniApp!-----------------------------------------------')
				uni.getStorage({
					key: 'loadVersion',
					success: function (res) {
						console.log(res.data);
					}
				});
			   //requestTask.abort();
				if (this.downloadUrl) {
					this.isStartDownload = true
					//开始下载App
					downloadApp(this.downloadUrl, current => {
						//下载进度监听
						this.hasProgress = true
						this.currentPercent = current
 
					}).then(fileName => {
						//下载完成
						this.isDownloadFinish = true
						this.fileName = fileName
						if (fileName) {
							//自动安装App
							this.handleInstallApp()
						}
					}).catch(e => {
						console.log(e, 'e')
					})
				} else {
					uni.showToast({
						title: '下载链接不存在',
						icon: 'none'
					})
				}
 
			},
			//安装app
			handleInstallApp() {
				//下载完成才能安装,防止下载过程中点击
				if (this.isDownloadFinish && this.fileName) {
					installApp(this.fileName, () => {
						//安装成功,关闭升级弹窗
						uni.navigateBack()
					})
				}
			},
			//关闭返回
			handleClose() {
				uni.navigateBack()
			},
		}
	}
</script>
 
<style>
	page {
		background: rgba(0, 0, 0, 0.5);/**设置窗口背景半透明*/
	}
</style>
<style lang="scss" scoped>
	.upgrade-popup {
		width: 580rpx;
		height: auto;
		position: fixed;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		background: #fff;
		border-radius: 20rpx;
		box-sizing: border-box;
		border: 1px solid #eee;
	}
 
	.header-bg {
		width: 100%;
		margin-top: -112rpx;
	}
 
	.main {
		padding: 10rpx 30rpx 30rpx;
		box-sizing: border-box;
		.version {
			font-size: 36rpx;
			color: #026DF7;
			font-weight: 700;
			width: 100%;
			text-align: center;
			overflow: hidden;
			text-overflow: ellipsis;
			white-space: nowrap;
			letter-spacing: 1px;
		}
 
		.content {
			margin-top: 60rpx;
 
			.title {
				font-size: 28rpx;
				font-weight: 700;
				color: #000000;
			}
 
			.desc {
				box-sizing: border-box;
				margin-top: 20rpx;
				font-size: 28rpx;
				color: #6A6A6A;
				max-height: 80vh;
				overflow-y: auto;
			}
		}
 
		.footer {
			width: 100%;
			display: flex;
			justify-content: center;
			align-items: center;
			position: relative;
			flex-shrink: 0;
			margin-top: 100rpx;
 
			.btn {
				width: 246rpx;
				display: flex;
				justify-content: center;
				align-items: center;
				position: relative;
				z-index: 999;
				height: 96rpx;
				box-sizing: border-box;
				font-size: 32rpx;
				border-radius: 10rpx;
				letter-spacing: 2rpx;
 
				&.force {
					width: 500rpx;
				}
 
				&.close {
					border: 1px solid #E0E0E0;
					margin-right: 25rpx;
					color: #000;
				}
 
				&.upgrade {
					background-color: #026DF7;
					color: white;
				}
			}
 
			.progress-view {
				width: 510rpx;
				height: 90rpx;
				display: flex;
				position: relative;
				align-items: center;
				border-radius: 6rpx;
				background-color: #dcdcdc;
				display: flex;
				justify-content: flex-start;
				padding: 0px;
				box-sizing: border-box;
				border: none;
				overflow: hidden;
 
				&.active {
					background-color: #026DF7;
				}
 
				.progress {
					height: 100%;
					background-color: #026DF7;
					padding: 0px;
					box-sizing: border-box;
					border: none;
					border-top-left-radius: 10rpx;
					border-bottom-left-radius: 10rpx;
 
				}
 
				.txt {
					font-size: 28rpx;
					position: absolute;
					top: 50%;
					left: 50%;
					transform: translate(-50%, -50%);
					color: #fff;
				}
			}
		}
	}
</style>

upgrade.js

/**
 * @description H5+下载App
 * @param downloadUrl:App下载链接
 * @param progressCallBack:下载进度回调
 */
export const downloadApp = (downloadUrl, progressCallBack = () => {}, ) => {
	return new Promise((resolve, reject) => {
		//创建下载任务
		const downloadTask = plus.downloader.createDownload(downloadUrl, {
			method: "GET"
		}, (task, status) => {
			console.log(status,'status')
			if (status == 200) { //下载成功
				resolve(task.filename)
 
			} else {
				reject('fail')
				uni.showToast({
					title: '下载失败',
					duration: 1500,
					icon: "none"
				});
			}
		})
		//监听下载过程
		downloadTask.addEventListener("statechanged", (task, status) => {
			switch (task.state) {
				case 1: // 开始  
					break;
				case 2: //已连接到服务器  
					break;
				case 3: // 已接收到数据  
					let hasProgress = task.totalSize && task.totalSize > 0 //是否能获取到App大小
					if (hasProgress) {
						let current = parseInt(100 * task.downloadedSize / task.totalSize); //获取下载进度百分比
						progressCallBack(current)
					}
					break;
				case 4: // 下载完成       
					break;
			}
		});
		//开始执行下载
		downloadTask.start();
	})
 
 
}
/**
 * @description H5+安装APP
 * @param fileName:app文件名
 * @param callBack:安装成功回调
 */
export const installApp = (fileName, callBack = () => {}) => {
	//注册广播监听app安装情况
	onInstallListening(callBack);
	//开始安装
	plus.runtime.install(plus.io.convertLocalFileSystemURL(fileName), {}, () => {
		//成功跳转到安装界面
	}, function(error) {
		uni.showToast({
			title: '安装失败',
			duration: 1500,
			icon: "none"
		});
	})
 
}
/**
 * @description 注册广播监听APP是否安装成功
 * @param callBack:安装成功回调函数
 */
const onInstallListening = (callBack = () => {}) => {
 
	let mainActivity = plus.android.runtimeMainActivity(); //获取activity
	//生成广播接收器
	let receiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {
		onReceive: (context, intent) => { //接收广播回调  
			plus.android.importClass(intent);
			mainActivity.unregisterReceiver(receiver); //取消监听
			callBack()
		}
	});
	let IntentFilter = plus.android.importClass('android.content.IntentFilter');
	let Intent = plus.android.importClass('android.content.Intent');
	let filter = new IntentFilter();
	filter.addAction(Intent.ACTION_PACKAGE_ADDED); //监听APP安装     
	filter.addDataScheme("package");
	mainActivity.registerReceiver(receiver, filter); //注册广播
 
}

home.vue

<template>
	<view>
		<image style="width: 100%;" mode="widthFix" src="/static/swiper1.png"></image>
		<!-- 	<u-swiper height="360rpx" :list="swiperList" :radius="0"></u-swiper> -->
		<view class="home-content">
			<view class="app-name">WMS手持机系统</view>
			<view class="card-container">
				<view class="fn-title">基础功能</view>
				<u-grid :border="false" @click="gridClick" col="4">
					<u-grid-item v-for="(item,index) in fn" :key="index">
						<view :class="['grid-item-bg','grid-item-bg-'+(index+1)]">
							<u-icon :name='item.icon' :color="item.color" size="28"></u-icon>
						</view>

						<view class="grid-text">{{item.name}}</view>
					</u-grid-item>
				</u-grid>
			</view>
			<view style="padding:30rpx;padding-top:0;">
				<vol-alert type="primary">

				</vol-alert>
			</view>

		</view>


	</view>
</template>

<script>
	export default {
		data() {
			return {
				height: 0,
				swiperList: [
					'/static/swiper1.png',
					'/static/swiper2.png',
					'/static/swiper3.png'
				],
				fn: [{
						name: "有单据组盘1",
						icon: '/static/fc.png',
						path: "/pages/basics/T_In_ReceiptNoticeDetail/T_In_ReceiptNoticeDetail",
						color: '#EE0000',
						subPage: true //二级页面
					}, {
						name: "手动入库",
						icon: '/static/fc.png',
						path: "",
						color: '#EE0000',
						subPage: true //二级页面
					}, {
						name: "无单据组盘",
						icon: 'edit-pen-fill',
						color: '#8B8989',
						path: "/pages/createbyus/HaveOrderGroup/HaveOrderGroup",
						subPage: true //二级页面
					}, {
						name: "入库计划",
						icon: '/static/fc.png',
						path: "/pages/basics/T_In_ReceiptNotice/T_In_ReceiptNotice",
						color: '#EE0000',
						subPage: true //二级页面
					}, {
						name: "确认出库",
						icon: '/static/fc.png',
						path: "/pages/reportvshow/V_OutboundDetail/V_OutboundDetail",
						color: '#EE0000',
						subPage: true //二级页面
					}, {
						name: "托盘处理",
						icon: '/static/fc.png',
						path: "/pages/strategy/DealTrayCURD/DealTrayCURD",
						color: '#EE0000',
						subPage: true //二级页面
					}, {
						name: "盘点处理",
						icon: '/static/fc.png',
						path: "/pages/strategy/T_InventoryCheckDetail/T_InventoryCheckDetail",
						color: '#EE0000',
						subPage: true //二级页面
					}, {
						name: "出库计划",
						icon: '/static/flow.png',
						color: '#EE0000',
						path: "/pages/basics/T_Out_DeliveryNotice/T_Out_DeliveryNotice",
						subPage: true //二级页面
					},
					{
						name: "审批流程",
						icon: '/static/flow.png',
						color: '#EE0000',
						path: "/pages/flow/flow",
						subPage: false //二级页面
					}, {
						name: "表单示例",
						icon: '/static/form.png',
						color: '#EE0000',
						path: "/pages/form/form",
						subPage: true //二级页面
					},
					{
						name: "Table组件",
						icon: '/static/fc.png',
						color: '#EE0000',
						path: "/pages/form/form",
						subPage: true //二级页面
					},
					{
						name: "菜单列表",
						icon: '/static/table.png',
						color: '#EE0000',
						path: "/pages/menu/menu",
						subPage: false //二级页面
					},

					// {
					// 	name: "地图导航",
					// 	icon: '/static/fc.png',
					// 	color:'#EE0000',
					// 	path: "/pages/map/map",
					// 	subPage: true //二级页面
					// },
					// //待开发功能
					// {
					// 	name: "敬请期待",
					// 	icon: '/static/fc.png',
					// 	path: "pages/basics/T_In_ReceiptNotice/T_In_ReceiptNotice",
					// 	color:'#EE0000',
					// 	subPage: true //二级页面
					// },

					// {
					// 	name: "敬请期待",
					// 	icon: '/static/fc.png',
					// 	color:'#EE0000',
					// 	path: "",
					// }
				],
			}
		},
		onLoad() {

			var _this = this;
			// 获取手机状态栏高度
			uni.getSystemInfo({
				success: function(data) {
					// 将其赋值给this
					_this.height = data.statusBarHeight;
				}
			});
			
			_this.init();
		},
		onReady(){
			this.checkVersion(1)
		},
		onShow() {
			
		},
		methods: {
			//初始化
			init() {

				

			},
			//检查版本更新情况
			checkVersion(indexValue) {

	var _this = this;
				let index=0;
				setTimeout(() => {
					let randomNum = Math.random();
					//模拟接口获取最新版本号,版本号固定为整数
					const baseurl = uni.getStorageSync('loadVersion')+'版本号.json?V='+randomNum;
					console.log(baseurl)
					var requestTask = uni.request({
						url: baseurl, //仅为示例,并非真实接口地址。
						method:'GET',
						success: function(res) {
							index++;
								console.log(res.data);	
								const newVersionName =res.data.newVersionName //线上最新版本名
								const newVersionCode =res.data.newVersionCode; //线上最新版本号
								const selfVersionCode = Number(uni.getSystemInfoSync().appVersionCode) //当前App版本号
								console.log(index+'../index/upgrade?versionName='+newVersionName+'&versionDesc='+res.data.versionDesc)
								console.log(selfVersionCode)
								console.log(newVersionCode)
								//线上版本号高于当前,进行在线升级
								if (selfVersionCode < newVersionCode) {
									let platform = uni.getSystemInfoSync().platform //手机平台
								
									uni.navigateTo({
										url: '../index/upgrade?versionName='+newVersionName+'&versionDesc='+res.data.versionDesc+'&appName='+res.data.appName
									})
								}
								else
								{
									_this.clickUseInfo(indexValue);
								}
								
							},
							fail :function(res)
							{
								console.log(res);
							},
							complete: ()=> {}
					});
				
				}, 200)
				
			},

			getStyle(item) {
				return {
					paddingTop: 20 + 'rpx',
					background: item.color,
					padding: '50%',
					color: "#ffff",
					'border-radius': '50%',
					left: '-24rpx'
				}
			},
			gridClick(index) {
				
				this.checkVersion(index)
				
				
			
			
			},
			clickUseInfo(index)
			{
				const item = this.fn[index];
				console.log(index)
				if (!item.path) {
					this.$toast('开发中')
					return;
				}
				
			//注意下面的跳转方式,一级页面指pages.json中tabBar配置path
			//具体见uni页面跳转文档
			if (item.subPage) {
				//二级页面用navigateTo跳转
				uni.navigateTo({
					url: this.fn[index].path
				})
				return;
			}
			//一级页面
			uni.switchTab({
				url: this.fn[index].path
			})
			},
			swiperClick(index) {

			}
		}
	}
</script>
<style lang="less" scoped>
	.home-content {
		z-index: 999;
		position: relative;
		margin-top: -220rpx;
	}

	.app-name {
		text-align: center;
		color: #ffff;
		font-weight: bolder;
		font-size: 60rpx;
		top: -40rpx;
		position: relative;
	}

	.card-container {

		box-shadow: 1px 1px 9px #b9b6b629;
		margin: 30rpx 30rpx 30rpx 30rpx;
		border: 1px solid #f1f1f1;
		border-radius: 10rpx;
		padding: 26rpx 10rpx 14rpx 10rpx;
		background: #ffff;


		.fn-title {
			font-family: 黑体;
			font-size: 30rpx;
			font-weight: bold;
			//color: #8f9ca2;
			padding: 4rpx 20rpx 30rpx 20rpx;
		}

		.grid-text {
			padding-top: 8rpx;
			font-size: 26rpx;
			color: #626262;
			padding-bottom: 20rpx;
		}

	}

	.grid-item-bg {
		border-radius: 50%;
		width: 86rpx;
		height: 86rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		box-shadow: 5px 3px 6px #e0ddddb0;
	}

	.grid-item-bg-1 {
		background-image: linear-gradient(to bottom right, #97caff, #47a1fe);
	}

	.grid-item-bg-2 {
		background-image: linear-gradient(to bottom right, #f8bcbc, #f07e7e);

	}

	.grid-item-bg-3 {
		background-image: linear-gradient(to bottom right, #afb5e6, #808cf0);
	}

	.grid-item-bg-4 {

		background-image: linear-gradient(to bottom right, #98e4e2, #56c3bf);
	}

	.grid-item-bg-5 {
		background-image: linear-gradient(to bottom right, #d1d1d1, #c878e7);
	}

	.grid-item-bg-6 {
		background-image: linear-gradient(to bottom right, #97caff, #47a1fe);
	}

	.grid-item-bg-7 {
		background-image: linear-gradient(to bottom right, #98e4e2, #56c3bf);

	}

	.grid-item-bg-8 {
		background-image: linear-gradient(to bottom right, #afb5e6, #808cf0);

	}
</style>

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

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

相关文章

STM32(15)USART编程

使用USART实现STM32与电脑之间的通信 中介&#xff1a;USB转TTL模块 闭合总开关&#xff0c;外部时钟才会传输到分频器 c8t6手册里面写了&#xff0c;usart最大支持4.5MHz&#xff0c;所以选10 重映射时记得开启AFIO的时钟

Android logcat系统

一 .logcat命令介绍 android log系统: logcat介绍 : logcat是android中的一个命令行工具&#xff0c;可以用于得到程序的log信息. 二.C/Clogcat访问接口 Android系统中的C/C日志接口是通过宏来使用的。在system/core/include/android/log.h定义了日志的级别&#xff1a; /…

opencart3 添加速卖通商品脚本

非爬虫&#xff0c;只能把速卖通商品信息拿下来解析插入到自己的项目里。 刚接触opencart3没多久&#xff0c;有一些新项目需要添加商品&#xff0c;每次手动从速卖通复制信息又很慢&#xff0c;就自己写了一个脚本。 思路&#xff1a;速卖通商品详情页有一段数据包含了几乎所…

Vue-02

开发者工具 安装插件&#xff0c;用于调试 Vue 应用。 https://chrome.zzzmh.cn/index 搜索 Vue &#xff0c;下载 Vue.js Devtools &#xff0c;此插件可以帮助更新信息&#xff0c;而不通过控制台更新&#xff0c;更方便调试。 注&#xff1a;安装插件后&#xff0c;记得在插…

Hello World!第一个labview程序

软件版本&#xff1a; labview myrio 2021英文版 因为没有找到中文版的&#xff0c;据说是myrio没有中文版本 实验内容&#xff1a; 文本显示&#xff0c;程序界面输入任意文本&#xff0c;然后运行程序 在前面板显示出输入的文本 以下为具体步骤&#xff1a; 第一步&…

no declaration can be found for element ‘rabbit:connection-factory‘

spring-mvc 配置 rabbitmq 出现问题。 我的解决方案如下&#xff1a; 1 找到配置文件 spring-rabbitmq.xml 我的配置文件叫&#xff1a;spring-rabbitmq.xml&#xff0c;你们按照自己的查找。 2 定位如下URI 接着 Ctrl鼠标左键 3 确定spring-rabbit-x.x.xsd 按照步骤2 &…

拿到年终奖马上离职,厚道吗?

拿到年终奖马上离职&#xff0c;厚道吗&#xff1f; 大家好&#xff0c;我是銘&#xff0c;全栈开发程序员。 今天在知乎上看到一个问题&#xff1a;拿到年终奖后马上辞职&#xff0c;厚道吗&#xff1f; image-20240229232132786 我的答案是&#xff1a;厚道&#xff0c;非常厚…

day03_Vue_Element

文章目录 01.Ajax1.1 Ajax 概述1.2 同步异步1.3 原生Ajax 2. Axios2.1 Axios的基本使用2.2 Axios快速入门2.3请求方法的别名2.4 案例 3 前后台分离开发3.1 前后台分离开发介绍 04 YAPI4.1 YAPI介绍4.2 接口文档管理 05 前端工程化5.1 前端工程化介绍5.2 前端工程化入门5.2.1 环…

吴恩达机器学习全课程笔记第七篇

目录 前言 P114-P120 推荐系统 协同过滤 均值归一化 协同过滤的tensorflow实现 查找相关项目 P121-P130 基于内容的过滤 强化学习 P131-P142 状态动作值函数定义 Bellman方程 随机环境 连续状态空间应用实例 前言 这是吴恩达机器学习笔记的第七篇&#xff0c;…

【C++】list模拟实现+反向迭代器

list模拟实现 list定义list用法list iterator的使用begin() end()rbegin()rend() reverse()sort()merge()unique()remove()splice() list模拟实现struct和class的区别list三个类模板默认成员函数构造函数拷贝构造函数赋值运算符重载析构函数 数据修改操作push_back()push_fron…

阿里云2核4G服务器支持多少人在线?多少钱?

阿里云2核4G服务器多少钱一年&#xff1f;2核4G5M带宽优惠价格199元一年&#xff0c;轻量应用服务器2核4G4M带宽165元一年&#xff0c;2核4G服务器30元3个月&#xff0c;可以在阿里云官方活动查看2核4G配置详细报价 https://t.aliyun.com/U/bLynLC 阿里云2核4G服务器价格 2核4G…

java 版本企业招标投标管理系统源码+功能描述+tbms+及时准确+全程电子化

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

cannot import name ‘Flask‘ from partially initialized module ‘flask‘

bug&#xff1a; ImportError: cannot import name Flask from partially initialized module flask (most likely due to a circular import) (G:\pythonProject6\flask.py) 这个是因为包的名字和文件的名字一样 修改文件名&#xff1a; 结果 &#x1f923;&#x1f923;&…

【QT】Qt Charts概述

目录 1 QtCharts模块 2 图表的主要组成部分 2.1 QChartView的功能 2.2 序列 2.3 坐标轴 2.4 图例 3 一个简单的QChart绘图程序 QtCharts是Qt提供的图表模块&#xff0c;在Qt5.7以前只有商业版才有Qt Charts&#xff0c;但是从Qt5.7开始&#xff0c;社区版本也包含了Qt C…

基于SpringBoot+Apache POI的前后端分离外卖项目-苍穹外卖(十九)

数据导出 1. 工作台1.1 需求分析和设计1.1.1 产品原型1.1.2 接口设计1.2.1 Controller层1.2.2 Service层接口1.2.3 Service层实现类1.2.4 Mapper层 1.3 功能测试 2. Apache POI2.1 介绍2.2 入门案例2.2.1 将数据写入Excel文件2.2.2 读取Excel文件中的数据 3. 导出运营数据Excel…

重学SpringBoot3-yaml文件配置

重学SpringBoot3-yaml文件配置 引言YAML 基本语法YAML 数据类型YAML 对象YAML 数组复合结构标量引用 YAML 文件结构Spring Boot 中的 YAML 配置注意事项总结参考 引言 YAML&#xff08;YAML Ain’t Markup Language&#xff09;是一种常用于配置文件的数据序列化格式&#xff…

LabVIEW起重机工作参数远程监测系统

LabVIEW起重机工作参数远程监测系统 随着起重机技术的持续发展&#xff0c;对其工作参数的实时监控需求日益增加。设计了一个基于LabVIEW和TBox的起重机工作参数远程监测系统&#xff0c;能够实现起重机工作参数的实时采集、传输、解析和显示&#xff0c;有效提升起重机的性能…

【Linux-shell系列】多脚本同时启动

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

基于51单片机风速仪风速测量台风预警数码管显示

基于51单片机风速仪风速测量报警数码管显示 1. 主要功能&#xff1a;2. 讲解视频&#xff1a;3. 仿真4. 程序代码5. 设计报告6. 设计资料内容清单&&下载链接资料下载链接&#xff1a; 基于51单片机风速仪风速测量报警数码管显示( proteus仿真程序设计报告讲解视频&…

Elasticsearch:使用 Streamlit、语义搜索和命名实体提取开发 Elastic Search 应用程序

作者&#xff1a;Camille Corti-Georgiou 介绍 一切都是一个搜索问题。 我在 Elastic 工作的第一周就听到有人说过这句话&#xff0c;从那时起&#xff0c;这句话就永久地印在了我的脑海中。 这篇博客的目的并不是我出色的同事对我所做的相关陈述进行分析&#xff0c;但我首先…