基于Spring的Uniapp自动更新实现方法

news/2024/9/16 19:11:43/ 标签: uni-app

Uniapp自动更新

   本文介绍了基于rouyi-uniapp的更新包版本自动推送更新。结合minio和网址下载地址两种方式,计算版本号大小后,可选是否强制更新。

一、表结构和后端版本号检测设计

1、版本更新控制表结构

主要字段和设计思路:

fileUrl:直接下载地址,用于网址直接下载,uniapp可直接访问(isUrlDownload=”Y“)

filePath:minio下载地址, 存储minio文件管理系统表的关键字,uniapp走本地minio文件下载地址(isUrlDownload=”N“)

version:版本号3位,eg:4.0.1,与uniapp的manifest.Json的versionName对应。

versionValue:版本号值,类似于二进制值转化,在更新版本时,比价用户当前版本信息和发布的有效最高版本号,如果当前版本号低于发布的最高版本号,进行更新提示。

Eg:Version=4.0.1; versionValue = 1*Math.power(10,0)+0*Math.power(10,1)+1*Math.power(10,2)。平方基数值不得小于10,否则值计算的最终大小会不符合。

isUrlDownload:是否使用直接地址下载还是minio,更加灵活

Status:版本是否可用。‘Y’为可用,即使用户安装的是旧版本,也可以不更新。‘N’为版本停用,如果用户当前安装的版本状态为停用,则强制更新到最新版(状态为‘Y’,且版本号值最高)

package com.inspur.factory.factoryAppManage.domain;import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.inspur.common.annotation.Excel;
import com.inspur.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;/*** app版本管理对象 factory_app_manage**/
@TableName("factory_app_manage")@Data
public class FactoryAppManage extends BaseEntity
{private static final long serialVersionUID = 1L;/** 主键 */@TableIdprivate Long id;/** 版本号名称 */@Excel(name = "版本号名称")private String version;/** 版本号值 */@Excel(name = "版本号值")private Long versionValue;/** 手机品牌 */@Excel(name = "手机品牌")private String phoneBrand;/** 文件名(安装包名称) */@Excel(name = "文件名(安装包名称)")private String fileName;/** 安装包地址 */@Excel(name = "安装包地址")private String filePath;/** 下载地址 */@Excel(name = "下载地址")private String fileUrl;/** 上传时间 */
//    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@Excel(name = "上传时间", width = 30, dateFormat = "yyyy-MM-dd")private Date fileTime;/** 状态 */@Excel(name = "状态")private String status;/** 更新说明 */@Excel(name = "更新说明")private String upgradeDescription;/** 文件大小 */@Excel(name = "文件大小")private String fileSize;/** 使用临时地址 */@Excel(name = "使用临时地址",readConverterExp = "Y=是,N=否")private String isUrlDownload;}@Overridepublic String toString() {return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("id", getId()).append("version", getVersion()).append("versionValue", getVersionValue()).append("phoneBrand", getPhoneBrand()).append("fileName", getFileName()).append("filePath", getFilePath()).append("fileUrl", getFileUrl()).append("fileTime", getFileTime()).append("status", getStatus()).append("upgradeDescription", getUpgradeDescription()).append("fileSize", getFileSize()).append("createTime", getCreateTime()).append("createBy", getCreateBy()).append("updateTime", getUpdateTime()).append("updateBy", getUpdateBy()).append("remark", getRemark()).toString();}
}

2、检查版本更新

    检查用户当前的版本是否可用。‘Y’为可用,即使用户安装的是旧版本,也可以不更新。‘N’为版本停用,如果用户当前安装的版本状态为停用,则强制更新到最新版(状态为‘Y’,且版本号值最高)。

//获取应当安装的app版本@Override
public FactoryAppManage getAppVersion(FactoryAppManage factoryAppManage){//传入版本号、手机系统类型List<FactoryAppManage> oldVersion = factoryAppManageMapper.selectFactoryAppManageList(factoryAppManage);if(oldVersion!=null && oldVersion.size()!=0){//如果当前版本还可使用,返回当前版本if(oldVersion.get(0).getStatus().equals("Y")){return oldVersion.get(0);}else{//如果当前版本不可使用强制更新,返回最新版本FactoryAppManage factoryAppManageQuery = new FactoryAppManage();factoryAppManageQuery.setStatus("Y");factoryAppManageQuery.setPhoneBrand(factoryAppManage.getPhoneBrand());List<FactoryAppManage> newVersion = factoryAppManageMapper.selectFactoryAppManageList(factoryAppManageQuery);if(newVersion!=null){return newVersion.get(0);}}}return null;
}

二、前端uniapp设计

版本号比较后,更新包安装提示弹窗,点击确认下载文件。

文件下载和打开主要方法如下:

1、主要应用技术

(1)直接地址下载:

uni.saveFile({})

(2)Minio下载:

Url为本地接口地址

plus.downloader.createDownload(url, {})plus.io.convertLocalFileSystemURLplus.runtime.openFile(d.filename); //选择软件打开文件

(3)H5平台下载:

主要用于电脑调试,BLOB转化,具体不做解释

(4)软件信息获取

uni.getSystemInfoSync()获取:phoneBrand(版本)version(版本号)

2、实现方法(***重点***)

App.vue根组件,每次打开任何页面都会执行到,在此文件下检测版本和更新包安装。

(1)版本检测

当前版本号为参数,后台请求对比最新版本号(版本号值最大为最新版本),返回应当安装的版本。

如果需要更新,则弹窗显示,点击确定进行安装。

根据web前台配置的是否用直接地址下载,进入安装包下载安装。

      checkUploadVersion(){//检测更新let server = config.baseUrl +'/factory/factoryAppManage/getAppVersion'; //检查更新地址(minio检测地址)let info = uni.getSystemInfoSync()uni.request({url: server,data: {phoneBrand: info.platform,version: info.appVersion},success: (res) => {if (res.data.data.version != info.appVersion) {// if (1) {let upgradeDescription = res.data.data.upgradeDescriptionuni.showModal({ //提醒用户更新title: "更新提示",content: '版本更新内容:'+ upgradeDescription,showCancel:false,success: (e) => {if (e.confirm) {if(info.uniPlatform=='web'){//h5平台调用后端minio接口下载this.downloadApp2(res.data.data)}else if(info.platform!='windows' && info.uniPlatform!='web' && res.data.data.isUrlDownload == 'Y'){//app手机端使用临时地址下载this.downloadApp1(res.data.data)}else if(info.platform!='windows' && info.uniPlatform!='web' && res.data.data.isUrlDownload == 'N'){//app手机端调用后端minio接口下载this.downloadApp3(res.data.data)}}}})}}})},

(2) minio下载

此方式具有参考意义,可以不用购买云空间存放安装包文件,直接使用minio文件存储。


   

   /** app安装包下载-(下载方式3-APP调用后端minio下载接口下载)*/downloadApp3(appVersionInfo) {var url = config.baseUrl +'/fileManage/downloadFile'+'?filePath=' + appVersionInfo.filePath+'&fileName=' + appVersionInfo.fileName; //请求下载接口地址var name = appVersionInfo.fileName;// console.log('method', reqMethod)uni.showLoading({title: '正在下载'});
// 本地路径开头使用file://,跟上手机文件本地目录storage/emulated/0,
// 这时用户文件管理器能看到的了,之后创建 京唐港app 作为文件夹,let dtask = plus.downloader.createDownload(url, {filename: "file://storage/emulated/0/京唐港app/" + name //利用保存路径,实现下载文件的重命名},(d, status)=> {//d为下载的文件对象if (status == 200) {uni.hideLoading();uni.showToast({icon: 'none',mask: true,title: '已保存到文件夹:/京唐港app/' + name, //保存路径duration: 3000,});//下载成功,d.filename是文件在保存在本地的相对路径,使用下面的API可转为平台绝对路径let fileSaveUrl = plus.io.convertLocalFileSystemURL(d.filename);setTimeout(()=>{plus.runtime.openFile(d.filename); //选择软件打开文件},1500)} else {//下载失败uni.hideLoading();plus.downloader.clear(); //清除下载任务uni.showToast({icon:'none',mask:true,title: '下载失败,请稍后重试',});}})dtask.start();},

(3)直接地址下载

此方式需要云空间

  

    /** app安装包下载-(下载方式1-APP指定url下载)*/downloadApp1(appVersionInfo){//下载方式1:指定url下载let downloadUrl = appVersionInfo.fileUrl// let downloadUrl = 'https://mp-fdbd529e-1d38-4f4a-bf37-72ba880de14a.cdn.bspapp.com/cloudstorage/00b0e017-b375-4758-88c8-4acfab810d7a.apk'uni.downloadFile({url: downloadUrl,
/*          data:{filePath:'mnQ0lCrayctz3TkHxB4rB0PeVTD7fbXNhULFZo4g+iPK0KXkzzzYJWCIJ5vxfiu1a8fzsYOb07weXbcXd92dkw==',fileName: '3.jpg'},method: 'POST',*/success: (res) => {console.log('downloadFile success, res is', res)//文件保存到本地uni.saveFile({tempFilePath: res.tempFilePath, //临时路径success: function(re) {uni.showToast({icon: 'none',mask: true,title: '文件已保存:' + re.savedFilePath, //保存路径duration: 3000,});setTimeout(() => {//打开查看uni.openDocument({filePath: re.savedFilePath,success: function(res) {// console.log('打开成功');}});}, 3000)}});uni.hideLoading();},fail: (err) => {console.log('downloadFile fail, err is:', err)uni.hideLoading();}})},

(4) H5平台电脑端下载

      /** app安装包下载-(下载方式2-h5平台web使用后端minio后端接口下载)*/downloadApp2(appVersionInfo){//下载方式2:请求接口下载let server = config.baseUrl +'/fileManage/downloadFile'+'?filePath=' + appVersionInfo.filePath+'&fileName=' + appVersionInfo.fileName; //请求下载接口地址uni.request({url: server,method: 'post',success: (res) => {/** h5 平台下载*/try {// const res = await exportOrderById({ id });//获取返回的二进制数据const blob = new Blob([res.data]); // 通过返回的流数据 手动构建blob 流const reader = new FileReader();reader.readAsDataURL(blob); // 转换为base64,可以直接放入a标签的hrefreader.onload = (e) => {// 转换完成,创建一个a标签用于下载const a = document.createElement("a");a.download = appVersionInfo.fileName; // 构建 下载的文件名称以及下载的文件格式(可通过传值输入)if (typeof e.target.result === "string") {a.href = e.target.result;}a.click();};} catch (err) {this.$message.error("遇到错误!");}}})},

三、前端web设计

1、版本页面展示

<template><div class="app-container"><el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="90px" style="margin-bottom: 5px"><div class="con-container"><div class="lab-container"><label class="condition-item-title">版本号名称</label><el-form-item label="" prop="version" class="custom-el-form-item"><el-inputv-model="queryParams.version" class="query-param"placeholder="请输入版本号名称"clearablesize="small"@keyup.enter.native="handleQuery"/></el-form-item></div><div class="btn-container"><el-form-item><el-button type="primary" icon="el-icon-setting" size="mini" @click="conditionToggle">高级查询</el-button><el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button><el-button type="primary" icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button><el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"v-hasPermi="['factory:factoryAppManage:add']">新增</el-button><el-button type="primary" icon="el-icon-download" size="mini" @click="handleExport"v-hasPermi="['factory:factoryAppManage:export']">导出</el-button><el-button type="primary" icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"v-hasPermi="['factory:factoryAppManage:remove']">删除</el-button></el-form-item></div></div><div class="toggle-container" ref="toggle-container" style="display: none;"><div class="condition-item"><label class="condition-item-title">手机品牌</label><el-form-item label="" prop="phoneBrand"><el-inputv-model="queryParams.phoneBrand"placeholder="请输入手机品牌"clearablesize="small" class="query-param"@keyup.enter.native="handleQuery"/></el-form-item></div><div class="condition-item"><label class="condition-item-title">状态</label><el-form-item label="" prop="status"><el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small" class="query-param"><el-optionv-for="item in statusOptions":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item></div></div></el-form><el-table v-loading="loading" ref="table" border:height="tableHeight" :header-cell-style="{fontSize:'14px', fontWeight:'500'}":data="factoryAppManageList" @selection-change="handleSelectionChange"><el-table-column type="selection" width="55" align="center" /><el-table-column label="序号" type="index" width="60" align="left"><template slot-scope="scope"><span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span></template></el-table-column>
<!--      <el-table-column label="主键" align="center" prop="id" />--><el-table-column label="手机品牌" align="center" prop="phoneBrand"><template slot-scope="scope"><dict-tag :options="dict.type.phone_brand" :value="scope.row.phoneBrand"/></template></el-table-column><el-table-column label="版本号名称" align="center" prop="version" /><el-table-column label="版本号值" align="center" prop="versionValue" /><el-table-column label="安装包名称" :show-overflow-tooltip="true" align="center" prop="fileName" /><el-table-column label="安装包地址" :show-overflow-tooltip="true" align="center" prop="filePath" />
<!--      <el-table-column label="下载地址" align="center" prop="fileUrl" />--><el-table-column label="上传时间" align="center" prop="fileTime" width="180"><template slot-scope="scope"><span>{{ parseTime(scope.row.fileTime) }}</span></template></el-table-column><el-table-column label="状态" align="center" prop="status"><template slot-scope="scope"><el-tag type="warning" v-if="scope.row.status=='N'">停用</el-tag><el-tag type="success" v-if="scope.row.status=='Y'">启用</el-tag></template></el-table-column>
<!--      <el-table-column label="更新说明" align="center" prop="upgradeDescription" />--><el-table-column label="文件大小(MB)" align="center" prop="fileSize" />
<!--      <el-table-column label="备注" align="center" prop="remark" />--><el-table-column label="操作" min-width="200" align="center" class-name="small-padding fixed-width"><template slot-scope="scope"><el-buttonsize="mini"type="text"icon="el-icon-download"@click="handleDownload(scope.row.filePath,scope.row.fileName)">下载</el-button><el-buttonsize="mini"type="text"icon="el-icon-tickets"@click="handleView(scope.row)"v-hasPermi="['factory:factoryAppManage:query']">详情</el-button><el-buttonsize="mini"type="text"icon="el-icon-edit"@click="handleUpdate(scope.row)"v-hasPermi="['factory:factoryAppManage:edit']">修改</el-button><el-buttonsize="mini"type="text"icon="el-icon-delete"@click="handleDelete(scope.row)"v-hasPermi="['factory:factoryAppManage:remove']">删除</el-button></template></el-table-column></el-table><paginationv-show="total>0":total="total":page.sync="queryParams.pageNum":limit.sync="queryParams.pageSize"@pagination="getList"/><!-- 添加或修改app版本管理对话框 --><el-dialog :visible.sync="open" @opened="openDialog"><div slot="title"><span>{{ title }}</span></div><div class="factoryAppManage-body"></div><el-form ref="form" :model="form" :rules="rules" label-width="120px"><div class="sub-project"><div class="sub-title"><div class="sub-title-name">app版本管理信息</div></div><div class="sub-body"><el-row><el-col :span="8" v-if="!readOnly"><el-form-item label="安装包"><up-record @sendRecordData="getRecordData"></up-record></el-form-item></el-col><el-col :span="8"><el-form-item label="上传时间" prop="fileTime" v-show="!readOnly"><el-date-picker clearable size="small"v-model="form.fileTime"type="date"value-format="yyyy-MM-dd"disabledstyle="width:100%"placeholder="选择上传时间"></el-date-picker></el-form-item><el-form-item label="上传时间:" prop="fileTime" v-show="readOnly" class="custom-form-item">{{form.fileTime}}</el-form-item></el-col><el-col :span="8"><el-form-item label="手机品牌" prop="phoneBrand" v-show="!readOnly"><el-select v-model="form.phoneBrand" placeholder="请选择手机品牌" class="custom-form-item"><el-optionv-for="dict in dict.type.phone_brand":key="dict.value":label="dict.label":value="dict.value"></el-option></el-select></el-form-item><el-form-item label="手机品牌:" prop="phoneBrand" v-show="readOnly" class="custom-form-item">{{form.phoneBrand}}</el-form-item></el-col><el-col :span="12"><el-form-item label="安装包名称" prop="fileName" v-show="!readOnly"><el-input v-model="form.fileName" placeholder="安装包名称" class="form-item" disabled/></el-form-item><el-form-item label="安装包名称:" prop="fileName" v-show="readOnly" class="custom-form-item">{{form.fileName}}</el-form-item></el-col><el-col :span="12"><el-form-item label="安装包地址" prop="filePath" v-show="!readOnly"><el-input v-model="form.filePath" placeholder="请输入安装包地址" class="form-item" disabled/></el-form-item><el-form-item label="安装包地址:" prop="filePath" v-show="readOnly" class="custom-form-item">{{form.filePath}}</el-form-item></el-col><el-col :span="8"><el-form-item label="版本号名称" prop="version" v-show="!readOnly"><el-input v-model="form.version" placeholder="四位,如(4.0.0.0)" class="form-item"/></el-form-item><el-form-item label="版本号名称:" prop="version" v-show="readOnly" class="custom-form-item">{{form.version}}</el-form-item></el-col><el-col :span="8"><el-form-item label="版本号值" prop="versionValue" v-show="!readOnly"><div v-if="!versionValueShow" @click="generateVersionValue" style="align-items: center"><el-link type="primary">计算版本号值</el-link></div><el-input v-model="form.versionValue" placeholder="请输入版本号值" disabled class="form-item" v-if="versionValueShow"/></el-form-item><el-form-item label="版本号值:" prop="versionValue" v-show="readOnly" class="custom-form-item">{{form.versionValue}}</el-form-item></el-col><el-col :span="8"><el-form-item label="直接下载地址" prop="fileUrl" v-show="!readOnly"><el-input v-model="form.fileUrl" placeholder="请输入下载地址" class="form-item"/></el-form-item><el-form-item label="直接下载地址:" prop="fileUrl" v-show="readOnly" class="custom-form-item">{{form.fileUrl}}</el-form-item></el-col><el-col :span="24"><el-form-item label="更新说明" prop="upgradeDescription" v-show="!readOnly"><el-input type="textarea" :autosize="{ minRows: 4, maxRows: 4 }" v-model="form.upgradeDescription" placeholder="请输入更新说明" maxlength="85" show-word-limit class="form-item"/></el-form-item><el-form-item label="更新说明:" prop="upgradeDescription" v-show="readOnly" class="custom-form-item">{{form.upgradeDescription}}</el-form-item></el-col><el-col :span="24"><el-form-item label="状态" v-if="!readOnly"><el-radio-group v-model="form.status" class="form-item"><el-radiov-for="dict in statusOptions":key="dict.value":label="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item><el-form-item label="状态" v-if="readOnly"><el-tag type="warning" v-if="form.status=='N'">停用</el-tag><el-tag type="success" v-if="form.status=='Y'">启用</el-tag></el-form-item></el-col></el-row></div></div></el-form><div slot="footer" class="dialog-footer"><el-button type="primary" @click="submitForm" v-show="!readOnly">确 定</el-button><el-button @click="cancel">取 消</el-button></div></el-dialog></div>
</template><script>
import { listFactoryAppManage, getFactoryAppManage, countFactoryAppManage, delFactoryAppManage, addFactoryAppManage, updateFactoryAppManage, exportFactoryAppManage } from "@/api/factory/factoryAppManage";
import upRecord from "@/components/FileUpload/upRecord";
import $ from 'jquery'
import selectSingleDevice from "@/components/esis/selectSingleDevice";
import {addFactoryDeviceFile} from "@/api/factory/factoryDeviceFile";
export default {name: "FactoryAppManage",dicts: ['phone_brand'],components: {upRecord},data() {// 唯一字段校验const validateUnique = (comment, rule, value, callback) => {let param = {}value =  value.trim()if (!value || value.length === 0) {callback(new Error(comment + "不能为空"));return;}this.$set(param, rule.field, value)let id =  this.form.idif(!id){ // 新增唯一校验countFactoryAppManage(param).then(res => {if(res.code === 200){if(res.data > 0){callback(new Error(comment + "已存在"));}else{callback()}}else{callback()}})}else { // 修改唯一校验this.$set(param, "id", id)countFactoryAppManage(param).then(res => {if(res.code === 200){if(res.data > 0){callback(new Error(comment + "已存在"));}else{callback()}}else{callback()}})}};return {// 遮罩层loading: true,// 导出遮罩层exportLoading: false,// 选中数组ids: [],// 非单个禁用single: true,// 非多个禁用multiple: true,// 显示搜索条件showSearch: true,versionValueShow: false,// 总条数total: 0,tableHeight: 450,// app版本管理表格数据factoryAppManageList: [],recordFileSucc: [],statusOptions:[{value:'Y',label: '启用'},{value:'N',label: '停用'}],// 弹出层标题title: "",// 是否显示弹出层open: false,//查看按钮默认不能编辑readOnly: false,// 查询参数queryParams: {pageNum: 1,pageSize: 10,version: null,versionValue: null,phoneBrand: null,fileName: null,filePath: null,fileUrl: null,fileTime: null,status: null,upgradeDescription: null,fileSize: null,},// 表单参数form: {},// 表单校验rules: {}};},watch: {'$store.state.app.screenHeight': function() { //监听屏幕高度变化if (this.$refs.table.$el.offsetTop) {this.tableHeight = window.innerHeight - this.$refs.table.$el.offsetTop - 160} else {this.tableHeight = window.innerHeight - 62 - 160}this.openDialog()}},created() {this.getList();},methods: {openDialog() {$('.factoryAppManage-body').css('top', 0).css('overflow-y', 'auto')},generateVersionValue(){debuggerlet dotVal = this.form.version.split('.')this.form.versionValue = 4*Number(dotVal[0]) + 3*Number(dotVal[1])+ 2*Number(dotVal[2])+ 1*Number(dotVal[3])this.versionValueShow = true},/** 查询app版本管理列表 */getList() {this.loading = true;listFactoryAppManage(this.queryParams).then(response => {this.factoryAppManageList = response.rows;this.total = response.total;this.loading = false;});},/** 文件下载处理*/getRecordData(val) {this.recordFileSucc = valthis.form.fileName = val[0].appendixNamethis.form.filePath = val[0].appendixPaththis.form.fileTime = new Date()this.form.createBy = val[0].createBythis.form.fileSize = val[0].fileSize.toFixed(2)},conditionToggle() {if(this.$refs['toggle-container'].style.display === 'none'){this.$refs['toggle-container'].style.display = 'inline-block';this.tableHeight = window.innerHeight - this.$refs.table.$el.offsetTop -  160}else{this.$refs['toggle-container'].style.display = 'none';this.tableHeight = window.innerHeight - this.$refs.table.$el.offsetTop -  160}},// 取消按钮cancel() {this.open = false;this.reset();},// 表单重置reset() {this.form = {id: null,version: null,versionValue: null,phoneBrand: null,fileName: null,filePath: null,fileUrl: null,fileTime: null,status: "Y",upgradeDescription: null,fileSize: null,createTime: null,createBy: null,updateTime: null,updateBy: null,remark: null};this.resetForm("form");},/** 搜索按钮操作 */handleQuery() {this.queryParams.pageNum = 1;this.getList();},/** 重置按钮操作 */resetQuery() {this.resetForm("queryForm");this.handleQuery();},// 多选框选中数据handleSelectionChange(selection) {this.ids = selection.map(item => item.id)this.single = selection.length!==1this.multiple = !selection.length},/** 新增按钮操作 */handleAdd() {this.reset();this.recordFileSucc = []this.open = true;this.readOnly = falsethis.title = "添加";},/** 修改按钮操作 */handleUpdate(row) {this.reset();const id = row.id || this.idsgetFactoryAppManage(id).then(response => {this.form = response.data;this.open = true;this.readOnly = falsethis.title = "修改";});},//下载按钮操作handleDownload(url,name){// window.location.href = process.env.VUE_APP_BASE_API + '/fileManage/downloadFile?url=' + url + '&name=' + namethis.$minio.downloadFile(url,name)},/** 详情按钮操作 */handleView(row) {this.reset();const id = row.id || this.idsgetFactoryAppManage(id).then(response => {this.form = response.data;this.open = true;this.readOnly = truethis.title = "详情";});},/** 提交按钮 */submitForm() {this.$refs["form"].validate(valid => {if (valid) {if (this.form.id != null) {updateFactoryAppManage(this.form).then(response => {this.msgSuccess("修改成功");this.open = false;this.getList();});} else {this.recordFileSucc.filter(res => {let obj = {version: this.form.version,versionValue: this.form.versionValue,phoneBrand: this.form.phoneBrand,fileName: res.appendixName,filePath: res.appendixPath,status: this.form.status,upgradeDescription: this.form.upgradeDescription,// fileId: res.fileId,// fileType: res.appendixName.substring(res.appendixName.lastIndexOf(".") + 1, res.appendixName.length),fileTime: new Date(),createBy: res.createBy,fileSize: res.fileSize.toFixed(2),}addFactoryAppManage(obj).then(response => {this.msgSuccess("新增成功");this.open = false;this.getList();});})}}});},/** 删除按钮操作 */handleDelete(row) {const ids = row.id || this.ids;this.$confirm('是否确认删除?', "警告", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning"}).then(function() {return delFactoryAppManage(ids);}).then(() => {this.getList();this.msgSuccess("删除成功");}).catch(() => {});},/** 导出按钮操作 */handleExport() {const queryParams = this.queryParams;this.$confirm('是否确认导出所有app版本管理数据项?', "警告", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning"}).then(() => {this.exportLoading = true;return exportFactoryAppManage(queryParams);}).then(response => {this.download(response.msg);this.exportLoading = false;}).catch(() => {});}},mounted() {this.$nextTick(function() {this.tableHeight = window.innerHeight - this.$refs.table.$el.offsetTop - 160})}
};</script><style scoped>.form-item{width: 100%;}
</style>

2、文件上传组件

<!--文件上传组件(限制1个)-->
<template><div><el-uploadclass="upload-demo"ref="recordUpload":headers="headers":action="uploadUrl":on-remove="handleRemoveRecord":on-progress="uploadProcess":before-upload="beforeUpload":on-success="handleUpFileSuccess":file-list="recordFileList"><el-button size="small" type="primary" style="width: 100%">点击上传</el-button></el-upload><!--    <div class="el-upload__tip" slot="tip"><template>最多上传一个文件,每个文件最大不能超过20MB!!!</template></div>--><!--    文件上传遮罩--><el-dialog :visible.sync="uploadFlag" :show-close="false"><div class="sysFolderManage-body"></div><el-progress v-if="uploadFlag == true" :percentage="videoUploadPercent"></el-progress></el-dialog></div>
</template><script>
import {getToken} from "@/utils/auth";export default {name: "upRecord",data() {return {uploadUrl: process.env.VUE_APP_BASE_API + "/fileManage/uploadWithManage",headers: {Authorization: "Bearer " + getToken(),},uploadFlag: false,videoUploadPercent: 0,recordFileList: [],recordFileSucc: []}},methods: {beforeUpload(file) {if (this.recordFileSucc.length === 1) {this.msgError("单次最多上传3个文件!")return false}//判断文件大小var limitFileSize = file.size / 1024 / 1024 < 30if (!limitFileSize) {this.msgError("上传文件大小不能超过 30MB!")return limitFileSize}},/**文件上传遮罩 进度条*/uploadProcess(event, file, fileList) {this.uploadFlag = true;this.videoUploadPercent = parseInt(event.percent);},//文件上传处理handleUpFileSuccess(res, file, recordList) {if (res.code != 200) {this.msgError(res.msg);} else {this.uploadFlag = false;this.recordFileSucc = []this.handleFileList(recordList)this.$emit('sendRecordData', this.recordFileSucc);}},//文件删除处理handleRemoveRecord(file, recordList) {this.recordFileSucc = []this.handleFileList(recordList)this.$emit('sendRecordData', this.recordFileSucc);},//数据转换handleFileList(recordList) {recordList.filter(a => {this.recordFileSucc.push({fileId: a.response.appendix.id,fileSize: a.size / 1024 / 1024,appendixName: a.response.appendix.appendixName,appendixPath: a.response.appendix.appendixPath,createBy: a.response.appendix.createBy})})}}
}
</script>


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

相关文章

使用matplotlab绘制多条形图

##黑马程序学习 这种多个条形图放在一起的图形该怎么画呢&#xff1f; 请看以下代码 #横着的条形图 from matplotlib import pyplot as plt import matplotlib#设置显示中文 和 负号 matplotlib.rcParams[font.sans-serif][SimHei] matplotlib.rcParams[axes.unicode_minus]F…

学会这2招,让你轻松提取长视频中的文案!

在当今数字化时代&#xff0c;短视频已成为备受欢迎的内容形式&#xff0c;众多品牌和营销人员借助短视频推广宣传产品。 短视频文案作为短视频内容的关键部分&#xff0c;能够在极短时间内向受众传达品牌信息和产品特点。 不过&#xff0c;短视频文案的提取和创作确实极具挑…

CleanMyMac X2024破解版mac电脑清理工具

今天&#xff0c;我要跟大家分享一个让我彻底告别电脑卡顿的秘密武器——CleanMyMac X。这不仅仅是一款普通的清理工具&#xff0c;它是你电脑的私人健身教练&#xff0c;让电脑焕发青春活力&#xff01; CleanMyMac直装官方版下载地址&#xff1a; http://wm.makeding.com/i…

Xinstall助力App全渠道统计,参数传递下载提升用户体验!

在移动互联网时代&#xff0c;App已成为我们日常生活中不可或缺的一部分。然而&#xff0c;对于App开发者来说&#xff0c;如何有效地推广和运营自己的应用&#xff0c;却是一个不小的挑战。尤其是在面对众多渠道、复杂的数据统计和用户需求多样化的情况下&#xff0c;如何精准…

活动系统开发之采用设计模式与非设计模式的区别-需求整理

用户需求(活动系统)&#xff1a; 1、活动类型&#xff1a;答题、图片展示、签到、抽奖、组团等活动 2、活动介绍&#xff1a; a、答题活动&#xff1a; 第一种是签到后&#xff0c;随机抽取10道题&#xff0c;答对8到就可以抽奖&#xff1b; 第二种是随机抽取一道题&#xff0…

RSS/RFS/RPS

概念 在多核CPU中&#xff0c;有几种方式对网卡接收到到的数据进行分流以提升网络接收处理性能&#xff1a; RSS&#xff08;接收端缩放&#xff0c;Receive Side Scaling&#xff09;是一种网络适配器技术&#xff0c;用于将网络流量分配到多个CPU核上&#xff0c;从而提高并…

Linux操作系统:yum安装报错问题

目录 采用yum命令安装软件或库&#xff0c;报错的解决办法&#xff01; 第1步&#xff1a;检查yum组件 第2步&#xff1a;检查网络 第3步&#xff1a;检查网络防火墙 第4步&#xff1a;将yum源换成国内镜像源 采用yum命令安装软件或库&#xff0c;报错的解决办法&#xff…

macos 使用port查询并安装python2, python3多版本, 设置默认python版本方法

不管是新版macos还是旧版本的macos都可以使用macport这个包管理工具简单方便的在mac上面安装并存多个版本的python, 还可以利用port select --set python python3 来设置默认的python版本等. port search查询可用python安装包 命令 port search --name --line --regex ^pytho…

队列-数据结构

一、队列 FIFO 特点&#xff1a;先进先出&#xff0c;后进后出 允许从一段插入数据&#xff0c;另一端删除数据的线性存储结构 队尾&#xff1a;插入数据 入队 队头&#xff1a;删除数据 出队 管道实质上也是一个队列。 用途&#xff1a;缓存数据&#xff08;主要是避免两…

设置vim的tab宽度

设置vim的tab宽度 [gblocalhost test]$ vim ~/.vimrc set tabstop4 " 设置制表符的宽度为4个空格 set shiftwidth4 " 设置缩进时使用的空格数为4个空格 set expandtab " 将制表符自动转换为空格 set autoindent " 启用自动缩进…

HarmonyOS 开发范式、应用模型

ArkUI框架两种开发范式&#xff1a; 基于ArkTS的声明式开发范式&#xff08;简称“声明式开发范式”&#xff09;兼容JS的类Web开发范式&#xff08;简称“类Web开发范式”&#xff09;。 以下是两种开发范式的简单对比: 开发范式名称 语言生态 UI更新方式 声明式开发范式…

qt5.15.2 模拟LVGL8.3

目录 1.下载需要的东西1.SDL 动态库2.LVGL模拟器源码3.下载lv_drivers4.下载lvgl 2.创建QT例程3.往qt里移植lvgl1.将lv_port_pc_eclipse-release-v8.3文件夹里的文件全部复制到Qt_LVGL_Demo文件夹中2.将lv_drivers和lvgl文件夹复制到Qt_LVGL_Demo3.复制SDL2和lib文件夹 4.配置Q…

OpenCV绘图函数(14)图像上绘制文字的函数putText()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在图像上绘制指定的文本字符串。 cv::putText 函数在图像上绘制指定的文本字符串。无法使用指定字体渲染的符号会被问号&#xff08;?&#xff…

前端请求的路径baseURL怎么来的 ?nodejs解决cors问题的一种方法

背景&#xff1a;后端使用node.js搭建&#xff0c;用的是express 前端请求的路径baseURL怎么来的 &#xff1f; 前后端都在同一台电脑上运行&#xff0c;后端的域名就是localhost&#xff0c;如果使用的是http协议&#xff0c;后端监听的端口号为3000&#xff0c;那么前端请求…

Web3开发与安全:6个月高效学习路径

学习计划概览 总时长&#xff1a;6个月每周学习时间&#xff1a;10-15小时目标&#xff1a;掌握 Solidity 智能合约开发&#xff0c;并具备基本的智能合约安全审计能力。 第一阶段&#xff1a;基础准备&#xff08;第1-2周&#xff09; 1. 区块链基础&#xff08;1周&#x…

随机生成一个圆柱体

随机生成一个圆柱体 import os import random import numpy as np import matplotlib.pyplot as plt def plot_cylinder(center, radius, height, num_points=100):# 生成圆柱体的侧面点坐标theta = np.linspace(0, 2*np.pi, num_points)intervalZ = height/num_pointsindx2 =…

vue3 响应式 API:shallowRef()和shallowReactive()

shallowRef() shallowRef()是一个用于创建浅层响应式引用的函数。它创建一个响应式数据&#xff0c;但只对顶层属性进行响应式处理。 特点&#xff1a; 只跟踪引用值的变化&#xff0c;不关心值内部的属性变化。 <template><div>{{ shallowRefObj }}</div>…

Tortoise-ORM FastAPI integration 中文文档(完整版)

Tortoise-ORM FastAPI integration 中文文档(完整版) 前言 初衷:在学习的时候发现 Tortoise-ORM FastAPI integration 官方文档缺中文版,翻阅英文文档效率低,萌生翻译想法。 本系列旨在原汁原味的翻译 Tortoise-ORM FastAPI integration 官方文档,帮助英语不好的小伙伴快速…

电脑桌面一键整理,高效整理,让你的电脑桌面焕然一新!

电脑桌面整理是一个能够提高工作效率、增强安全性、简化资产管理、改善用户体验的电脑软件。无论是图标管理还是文件整理&#xff0c;通过专业的电脑桌面整理软件都能轻松搞定&#xff0c;有序的管理文件、应用程序。 下面是关于Windows桌面工具的介绍与说明&#xff01; 一、…

在 “Label Studio” 和 “Android Studio” 中,“studio”的含义

这个词通常有以下含义&#xff1a; 一、工作场所或空间 可以理解为一个专门用于特定任务的工作区域。就像艺术家的工作室是他们进行创作的地方一样&#xff0c;在软件领域&#xff0c;这些带有 “studio” 的工具为开发者或使用者提供了一个集中进行特定开发、标注等工作的环…