1
This commit is contained in:
parent
71ec511819
commit
48aaeb8ac2
@ -21,10 +21,12 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.domain.R;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.system.service.ISysDictDataService;
|
||||
import com.ruoyi.utils.OssUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
@ -75,6 +77,8 @@ public class WebController extends BaseController {
|
||||
private IBaseAppService appService;
|
||||
@Autowired
|
||||
private GoogleConfig googleConfig;
|
||||
@Autowired
|
||||
private OssUtil ossUtil;
|
||||
|
||||
/**
|
||||
* 导航栏接口--所有分类
|
||||
@ -474,46 +478,17 @@ public class WebController extends BaseController {
|
||||
return R.ok(appService.selectNewApp());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@ApiOperation("下载APK文件")
|
||||
@GetMapping("/downloadApk")
|
||||
public void downloadApk(HttpServletResponse response) {
|
||||
try {
|
||||
// APK文件路径
|
||||
File file = new File(googleConfig.getAppDownload());
|
||||
|
||||
// 检查文件是否存在
|
||||
if (!file.exists()) {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
response.getWriter().write("文件不存在");
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置响应头
|
||||
response.setContentType("application/vnd.android.package-archive");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=truck.apk");
|
||||
response.setHeader("Content-Length", String.valueOf(file.length()));
|
||||
|
||||
// 写入响应流
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
OutputStream os = response.getOutputStream();
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = fis.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
|
||||
fis.close();
|
||||
os.flush();
|
||||
os.close();
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.getWriter().write("文件下载失败: " + e.getMessage());
|
||||
} catch (Exception ex) {
|
||||
logger.error("下载APK文件时发生错误", ex);
|
||||
}
|
||||
public void downloadApk(HttpServletResponse response,@RequestParam(required = false) String id) {
|
||||
BaseApp appVersion;
|
||||
if(StringUtils.isNotEmpty(id)){
|
||||
appVersion = appService.getById(id);
|
||||
}else{
|
||||
appVersion = appService.selectNewApp();
|
||||
}
|
||||
ossUtil.downloadFile(response, appVersion.getApkUrl(), appVersion.getVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,6 +33,10 @@ public class BaseApp extends DlBaseEntity
|
||||
@Excel(name = "版本")
|
||||
private String version;
|
||||
|
||||
/** app包下载地址 */
|
||||
@Excel(name = "app包下载地址")
|
||||
private String apkUrl;
|
||||
|
||||
/** 本次升级描述 */
|
||||
@Excel(name = "本次升级描述")
|
||||
private String content;
|
||||
|
@ -0,0 +1,82 @@
|
||||
package com.ruoyi.utils;
|
||||
|
||||
import com.aliyun.oss.ClientBuilderConfiguration;
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import com.aliyuncs.utils.IOUtils;
|
||||
import com.ruoyi.common.config.OssConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class OssUtil {
|
||||
@Autowired
|
||||
private OssConfig ossConfig;
|
||||
|
||||
/**
|
||||
* 上传文件(fileKey-InputStream)
|
||||
*/
|
||||
public void uploadFile(String fileKey, InputStream stream) throws IOException {
|
||||
ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
|
||||
OSS client = new OSSClientBuilder().build(ossConfig.getEndPoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret(), conf);
|
||||
|
||||
try {
|
||||
client.putObject(ossConfig.getBucketName(), fileKey, stream);
|
||||
} finally {
|
||||
stream.close();
|
||||
if (client != null) {
|
||||
client.shutdown();
|
||||
}
|
||||
IOUtils.closeQuietly(stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 文件下载
|
||||
*/
|
||||
public void downloadFile(HttpServletResponse response, String fileKey, String fileName) throws IOException {
|
||||
fileKey = fileKey.replace("https://"+ossConfig.getBucketName()+"."+ossConfig.getEndPoint()+"/","");
|
||||
InputStream stream = null;
|
||||
BufferedInputStream bufferedInputStream = null;
|
||||
ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
|
||||
OSS client = new OSSClientBuilder().build(ossConfig.getEndPoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret(), conf);
|
||||
try {
|
||||
stream = client.getObject(ossConfig.getBucketName(), fileKey).getObjectContent();
|
||||
response.reset();
|
||||
response.setContentType("application/octet-stream");
|
||||
response.addHeader("Content-Disposition", "attachment;filename=CDbay-" + URLEncoder.encode(fileName, "UTF-8")
|
||||
.replace("+", "%20")+".apk");
|
||||
OutputStream outputStream = response.getOutputStream();
|
||||
bufferedInputStream = new BufferedInputStream(stream);
|
||||
byte[] buf = new byte[16384];
|
||||
int bytesRead;
|
||||
while ((bytesRead = stream.read(buf, 0, buf.length)) >= 0) {
|
||||
outputStream.write(buf, 0, bytesRead);
|
||||
outputStream.flush();
|
||||
}
|
||||
} finally {
|
||||
if (client != null) {
|
||||
client.shutdown();
|
||||
}
|
||||
|
||||
if (bufferedInputStream != null || stream != null) {
|
||||
try {
|
||||
bufferedInputStream.close();
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
log.error("Oss Download IOException,fileKey:" + fileKey, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<resultMap type="BaseApp" id="BaseAppResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="version" column="version" />
|
||||
<result property="apkUrl" column="apk_url" />
|
||||
<result property="content" column="content" />
|
||||
<result property="creator" column="creator" />
|
||||
<result property="createTime" column="create_time" />
|
||||
@ -16,7 +17,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectBaseAppVo">
|
||||
select id, version, content, creator, create_time, updater, update_time, del_flag from dl_base_app
|
||||
select id, version, apk_url, content, creator, create_time, updater, update_time, del_flag from dl_base_app
|
||||
</sql>
|
||||
|
||||
<select id="queryListPage" parameterType="BaseApp" resultMap="BaseAppResult">
|
||||
@ -24,6 +25,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<where>
|
||||
<if test="entity.version != null "> and version like concat('%', #{entity.version}, '%')</if>
|
||||
</where>
|
||||
order by version DESC,create_time desc
|
||||
order by create_time desc
|
||||
</select>
|
||||
</mapper>
|
@ -1,15 +1,34 @@
|
||||
|
||||
<template>
|
||||
<div class="content">
|
||||
<!-- 压缩比例设置 -->
|
||||
<div class="compression-setting">
|
||||
<div class="compression-info">
|
||||
图片压缩比例: {{ compressionRatio.toFixed(1) }}x
|
||||
<el-tooltip class="item" effect="dark" content="值越小压缩率越高,图片质量越低"
|
||||
placement="bottom"
|
||||
>
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-slider
|
||||
v-model="compressionRatio"
|
||||
:min="0.1"
|
||||
:max="1.0"
|
||||
:step="0.1"
|
||||
:show-stops="true"
|
||||
:tooltip-format="formatCompressionRatio"
|
||||
></el-slider>
|
||||
</div>
|
||||
<vue-ueditor-wrap v-model="value"
|
||||
:destroy="true"
|
||||
:config="editorConfig"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:editorDependencies="['ueditor.config.js','ueditor.all.js']"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import VueUeditorWrap from 'vue-ueditor-wrap';
|
||||
import VueUeditorWrap from 'vue-ueditor-wrap'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -19,12 +38,12 @@ export default {
|
||||
/* 编辑器的内容 */
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(newVaue, oldValue) {
|
||||
this.$emit('input', newVaue);
|
||||
this.$emit('input', newVaue)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@ -39,8 +58,127 @@ export default {
|
||||
//**代码补充231218**
|
||||
UEDITOR_CORS_URL: '/UEditor/',
|
||||
zIndex: 999,//设置z轴顺序值,避免工具栏下拉组件被遮挡
|
||||
// 图片上传相关配置
|
||||
imageMaxSize: 5 * 1024 * 1024, // 5MB,这里只是限制,实际压缩还需处理
|
||||
imageAllowFiles: ['.png', '.jpg', '.jpeg', '.gif', '.bmp']
|
||||
},
|
||||
// 压缩比例 (0.1-1.0)
|
||||
compressionRatio: 0.9
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 格式化压缩比例显示
|
||||
formatCompressionRatio(value) {
|
||||
return `${value.toFixed(1)}x`
|
||||
},
|
||||
/**
|
||||
* 上传前处理图片压缩
|
||||
* @param {File} file 原始文件
|
||||
* @param {Function} callback 回调函数
|
||||
*/
|
||||
handleBeforeUpload(file, callback) {
|
||||
debugger
|
||||
// 只处理图片文件
|
||||
if (!file.type.match(/image\/\w+/)) {
|
||||
return callback(file, true) // 非图片直接上传
|
||||
}
|
||||
|
||||
// 小于100KB的图片不压缩
|
||||
if (file.size < 100 * 1024) {
|
||||
return callback(file, true)
|
||||
}
|
||||
|
||||
// 进行图片压缩
|
||||
this.compressImage(file).then(compressedFile => {
|
||||
callback(compressedFile, true)
|
||||
}).catch(err => {
|
||||
console.error('图片压缩失败:', err)
|
||||
callback(file, true) // 压缩失败则上传原图
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 图片压缩处理
|
||||
* @param {File} file 原始图片文件
|
||||
* @returns {Promise<File>} 压缩后的文件
|
||||
*/
|
||||
compressImage(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image()
|
||||
const reader = new FileReader()
|
||||
|
||||
reader.onload = (e) => {
|
||||
img.src = e.target.result
|
||||
}
|
||||
|
||||
img.onload = () => {
|
||||
// 创建canvas元素
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d')
|
||||
|
||||
// 计算压缩后的尺寸
|
||||
let width = img.width
|
||||
let height = img.height
|
||||
|
||||
// 设置canvas尺寸
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
|
||||
// 绘制图片到canvas
|
||||
ctx.drawImage(img, 0, 0, width, height)
|
||||
|
||||
// 将canvas内容转为Blob
|
||||
canvas.toBlob(
|
||||
(blob) => {
|
||||
if (!blob) {
|
||||
reject(new Error('压缩失败'))
|
||||
return
|
||||
}
|
||||
|
||||
// 构建新的File对象
|
||||
const compressedFile = new File(
|
||||
[blob],
|
||||
file.name,
|
||||
{
|
||||
type: blob.type || file.type,
|
||||
lastModified: Date.now()
|
||||
}
|
||||
)
|
||||
|
||||
resolve(compressedFile)
|
||||
},
|
||||
file.type || 'image/jpeg',
|
||||
this.compressionRatio
|
||||
)
|
||||
}
|
||||
|
||||
img.onerror = (err) => {
|
||||
reject(err)
|
||||
}
|
||||
|
||||
reader.readAsDataURL(file)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
// 压缩设置样式
|
||||
.compression-setting {
|
||||
width: 300px;
|
||||
margin-bottom: 15px;
|
||||
padding: 0 10px 8px 10px;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
|
||||
.compression-info {
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-slider__runway {
|
||||
margin: 0 !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,5 +1,25 @@
|
||||
<template>
|
||||
<div class="component-upload-image">
|
||||
<!-- 压缩比例设置 -->
|
||||
<div class="compression-setting" v-if="showCompressionSetting">
|
||||
<div class="compression-info">
|
||||
压缩比例: {{ compressionRatio.toFixed(1) }}x
|
||||
<el-tooltip class="item" effect="dark" content="值越小压缩率越高,图片质量越低"
|
||||
placement="bottom"
|
||||
>
|
||||
<i class="el-icon-question"></i>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-slider
|
||||
v-model="compressionRatio"
|
||||
:min="0.1"
|
||||
:max="1.0"
|
||||
:step="0.1"
|
||||
:show-stops="true"
|
||||
:tooltip-format="formatCompressionRatio"
|
||||
></el-slider>
|
||||
</div>
|
||||
|
||||
<el-upload
|
||||
multiple
|
||||
:action="uploadImgUrl"
|
||||
@ -17,6 +37,7 @@
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:disabled="disabled"
|
||||
:class="{hide: this.fileList.length >= this.limit}"
|
||||
:http-request="customUpload"
|
||||
>
|
||||
<i class="el-icon-plus"></i>
|
||||
</el-upload>
|
||||
@ -64,7 +85,7 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 文件类型, 例如['png', 'jpg', 'jpeg']
|
||||
// 文件类型, 例如['png', 'jpeg', 'jpg']
|
||||
fileType: {
|
||||
type: Array,
|
||||
default: () => ["png", "jpg", "jpeg"],
|
||||
@ -73,6 +94,16 @@ export default {
|
||||
isShowTip: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 是否显示压缩设置
|
||||
showCompression: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 默认压缩比例
|
||||
defaultCompressionRatio: {
|
||||
type: Number,
|
||||
default: 0.9
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -87,9 +118,21 @@ export default {
|
||||
headers: {
|
||||
Authorization: "Bearer " + getToken(),
|
||||
},
|
||||
fileList: []
|
||||
fileList: [],
|
||||
// 压缩比例 (0.1-1.0)
|
||||
compressionRatio: this.defaultCompressionRatio
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 是否显示提示
|
||||
showTip() {
|
||||
return this.isShowTip && (this.fileType || this.fileSize);
|
||||
},
|
||||
// 是否显示压缩设置
|
||||
showCompressionSetting() {
|
||||
return this.showCompression && !this.disabled && this.fileList.length < this.limit;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
@ -114,26 +157,32 @@ export default {
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
},
|
||||
// 监听默认压缩比例变化
|
||||
defaultCompressionRatio: {
|
||||
handler(val) {
|
||||
this.compressionRatio = val;
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否显示提示
|
||||
showTip() {
|
||||
return this.isShowTip && (this.fileType || this.fileSize);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 上传前loading加载
|
||||
handleBeforeUpload(file) {
|
||||
// 格式化压缩比例显示
|
||||
formatCompressionRatio(value) {
|
||||
return `${value.toFixed(1)}x`;
|
||||
},
|
||||
|
||||
// 上传前验证
|
||||
async handleBeforeUpload(file) {
|
||||
let isImg = false;
|
||||
if (this.fileType.length) {
|
||||
let fileExtension = "";
|
||||
if (file.name.lastIndexOf(".") > -1) {
|
||||
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
|
||||
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1).toLowerCase();
|
||||
}
|
||||
isImg = this.fileType.some(type => {
|
||||
if (file.type.indexOf(type) > -1) return true;
|
||||
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
|
||||
if (fileExtension && fileExtension === type.toLowerCase()) return true;
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
@ -144,28 +193,151 @@ export default {
|
||||
this.$modal.msgError(`文件格式不正确,请上传${this.fileType.join("/")}图片格式文件!`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file.name.includes(',')) {
|
||||
this.$modal.msgError('文件名不正确,不能包含英文逗号!');
|
||||
return false;
|
||||
}
|
||||
if (this.fileSize) {
|
||||
const isLt = file.size / 1024 / 1024 < this.fileSize;
|
||||
if (!isLt) {
|
||||
this.$modal.msgError(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.$modal.loading("正在上传图片,请稍候...");
|
||||
|
||||
// 这里只做验证,不限制大小,因为用户可以通过压缩来减小文件大小
|
||||
this.$modal.loading("正在处理图片,请稍候...");
|
||||
this.number++;
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
// 自定义上传方法,包含压缩逻辑
|
||||
customUpload(options) {
|
||||
const file = options.file;
|
||||
|
||||
// 调用图片压缩方法
|
||||
this.compressImage(file, this.compressionRatio)
|
||||
.then(compressedFile => {
|
||||
// 创建FormData对象,模拟表单提交
|
||||
const formData = new FormData();
|
||||
formData.append('file', compressedFile, file.name);
|
||||
|
||||
// 创建XMLHttpRequest对象
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('post', this.uploadImgUrl, true);
|
||||
|
||||
// 设置请求头
|
||||
Object.keys(this.headers).forEach(key => {
|
||||
xhr.setRequestHeader(key, this.headers[key]);
|
||||
});
|
||||
|
||||
// 上传进度处理
|
||||
xhr.upload.addEventListener('progress', (e) => {
|
||||
if (e.total > 0) {
|
||||
e.percent = e.loaded / e.total * 100;
|
||||
}
|
||||
options.onProgress(e);
|
||||
});
|
||||
|
||||
// 上传成功处理
|
||||
xhr.addEventListener('load', () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
options.onSuccess(response);
|
||||
} else {
|
||||
options.onError(xhr.responseText);
|
||||
}
|
||||
});
|
||||
|
||||
// 上传错误处理
|
||||
xhr.addEventListener('error', () => {
|
||||
options.onError(xhr.responseText);
|
||||
});
|
||||
|
||||
// 发送请求
|
||||
xhr.send(formData);
|
||||
})
|
||||
.catch(error => {
|
||||
this.$modal.msgError('图片压缩失败: ' + error.message);
|
||||
this.$modal.closeLoading();
|
||||
this.number--;
|
||||
options.onError(error);
|
||||
});
|
||||
},
|
||||
|
||||
// 图片压缩核心方法
|
||||
compressImage(file, quality = 0.8) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 如果不是图片,直接返回原文件
|
||||
if (!file.type.match(/image.*/)) {
|
||||
resolve(file);
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = (e) => {
|
||||
const img = new Image();
|
||||
|
||||
img.onload = () => {
|
||||
// 创建canvas元素
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// 设置canvas尺寸,保持原图比例
|
||||
canvas.width = img.width;
|
||||
canvas.height = img.height;
|
||||
|
||||
// 在canvas上绘制图片
|
||||
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||
|
||||
// 获取图片类型
|
||||
const mimeType = file.type || 'image/jpeg';
|
||||
|
||||
// 将canvas内容转为Blob对象
|
||||
canvas.toBlob((blob) => {
|
||||
if (!blob) {
|
||||
reject(new Error('无法压缩图片'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 将Blob转为File对象
|
||||
const compressedFile = new File([blob], file.name, {
|
||||
type: mimeType,
|
||||
lastModified: Date.now()
|
||||
});
|
||||
|
||||
resolve(compressedFile);
|
||||
}, mimeType, quality);
|
||||
};
|
||||
|
||||
img.onerror = (error) => {
|
||||
reject(new Error('无法加载图片进行压缩'));
|
||||
};
|
||||
|
||||
// 加载图片
|
||||
img.src = e.target.result;
|
||||
};
|
||||
|
||||
reader.onerror = (error) => {
|
||||
reject(new Error('无法读取图片文件'));
|
||||
};
|
||||
|
||||
// 读取文件
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
},
|
||||
|
||||
// 文件个数超出
|
||||
handleExceed() {
|
||||
this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`);
|
||||
},
|
||||
|
||||
// 上传成功回调
|
||||
handleUploadSuccess(res, file) {
|
||||
if (res.code === 200) {
|
||||
this.uploadList.push({ name: res.name, url: res.fileName,size:res.size,width:res.width,height:res.height });
|
||||
this.uploadList.push({
|
||||
name: res.name,
|
||||
url: res.fileName,
|
||||
size: res.size,
|
||||
width: res.width,
|
||||
height: res.height
|
||||
});
|
||||
this.uploadedSuccessfully();
|
||||
} else {
|
||||
this.number--;
|
||||
@ -175,6 +347,7 @@ export default {
|
||||
this.uploadedSuccessfully();
|
||||
}
|
||||
},
|
||||
|
||||
// 删除图片
|
||||
handleDelete(file) {
|
||||
const findex = this.fileList.map(f => f.name).indexOf(file.name);
|
||||
@ -183,27 +356,31 @@ export default {
|
||||
this.$emit("input", this.listToString(this.fileList));
|
||||
}
|
||||
},
|
||||
|
||||
// 上传失败
|
||||
handleUploadError() {
|
||||
this.$modal.msgError("上传图片失败,请重试");
|
||||
this.$modal.closeLoading();
|
||||
},
|
||||
|
||||
// 上传结束处理
|
||||
uploadedSuccessfully() {
|
||||
if (this.number > 0 && this.uploadList.length === this.number) {
|
||||
this.fileList = this.fileList.concat(this.uploadList);
|
||||
this.$emit('uploadedImg',this.fileList)
|
||||
this.$emit('uploadedImg', this.fileList);
|
||||
this.uploadList = [];
|
||||
this.number = 0;
|
||||
this.$emit("input", this.listToString(this.fileList));
|
||||
this.$modal.closeLoading();
|
||||
}
|
||||
},
|
||||
|
||||
// 预览
|
||||
handlePictureCardPreview(file) {
|
||||
this.dialogImageUrl = file.url;
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
|
||||
// 对象转成指定字符串分隔
|
||||
listToString(list, separator) {
|
||||
let strs = "";
|
||||
@ -213,7 +390,7 @@ export default {
|
||||
strs += list[i].url.replace(this.baseUrl, "") + separator;
|
||||
}
|
||||
}
|
||||
return strs != '' ? strs.substr(0, strs.length - 1) : '';
|
||||
return strs !== '' ? strs.substr(0, strs.length - 1) : '';
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -223,6 +400,7 @@ export default {
|
||||
::v-deep.hide .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// 去掉动画效果
|
||||
::v-deep .el-list-enter-active,
|
||||
::v-deep .el-list-leave-active {
|
||||
@ -233,6 +411,21 @@ export default {
|
||||
opacity: 0;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
// 压缩设置样式
|
||||
.compression-setting {
|
||||
margin-bottom: 15px;
|
||||
padding: 0 10px 8px 10px;
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
|
||||
.compression-info {
|
||||
margin-top: 8px;
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
::v-deep .el-slider__runway{
|
||||
margin:0 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['base:app:edit']"
|
||||
>修改</el-button>
|
||||
>下载</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
@ -69,7 +69,10 @@
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="版本" prop="version">
|
||||
<el-input v-model="form.version" placeholder="请输入版本" />
|
||||
<el-input type="input" v-model="form.version" placeholder="请输入版本" />
|
||||
</el-form-item>
|
||||
<el-form-item label="app包" prop="apkUrl">
|
||||
<file-upload v-model="form.apkUrl" :limit="1" :fileType="fileType" :fileSize="50"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="本次升级描述" prop="content">
|
||||
<el-input v-model="form.content" type="textarea" placeholder="请输入内容" />
|
||||
@ -122,7 +125,11 @@ export default {
|
||||
version: [
|
||||
{ required: true, message: '请输入版本号', trigger: 'blur' }
|
||||
],
|
||||
}
|
||||
apkUrl: [
|
||||
{ required: true, message: '请上传程序包', trigger: 'blur' }
|
||||
],
|
||||
},
|
||||
baseUrl: process.env.VUE_APP_BASE_API,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
@ -148,6 +155,7 @@ export default {
|
||||
this.form = {
|
||||
id: null,
|
||||
version: null,
|
||||
apkUrl: null,
|
||||
content: null,
|
||||
creator: null,
|
||||
createTime: null,
|
||||
@ -179,15 +187,18 @@ export default {
|
||||
this.open = true;
|
||||
this.title = "添加app版本管理";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
/** 下载 */
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
const id = row.id || this.ids
|
||||
getApp(id).then(response => {
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改app版本管理";
|
||||
});
|
||||
let a = document.createElement("a"); // 创建a标签
|
||||
a.style.display = "none";
|
||||
a.href = this.baseUrl + "/web/downloadApk?id="+row.id;
|
||||
a.setAttribute(
|
||||
"download",
|
||||
a.href.split("/")[a.href.split("/").length - 1]
|
||||
); // 给a标签设置download属性值,为从接口中获取到的需要下载的文件地址
|
||||
document.body.appendChild(a); // 将标签添加到页面
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
|
@ -105,7 +105,7 @@
|
||||
<el-form-item label="所属分类" prop="catgId">
|
||||
<div class="dl-flex-column">
|
||||
<treeselect style="width: 200px" v-model="form.catgId" :options="catgOptions" :normalizer="normalizer"
|
||||
:noResultsText="'暂无数据'" placeholder="请选择新闻分类"
|
||||
:noResultsText="'暂无数据'" placeholder="请选择新闻分类" :disable-branch-nodes="true"
|
||||
/>
|
||||
<div class="dl-add-catg" @click="goCatgView">添加新闻分类</div>
|
||||
</div>
|
||||
@ -184,7 +184,7 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-col :span="9">
|
||||
<el-form-item label="新闻图" prop="mainPic">
|
||||
<el-tag v-if="!form.mainPic" style="cursor: pointer" @click="choosePic('mainPic',1)">图片库选择</el-tag>
|
||||
<image-upload @uploadedImg="uploadedImg" v-model="form.mainPic" :limit="1"/>
|
||||
|
@ -102,7 +102,7 @@
|
||||
<el-form-item label="所属分类" prop="catgId">
|
||||
<div class="dl-flex-column">
|
||||
<treeselect style="width: 200px" v-model="form.catgId" :options="catgOptions" :normalizer="normalizer"
|
||||
:noResultsText="'暂无数据'" placeholder="请选择产品分类"
|
||||
:noResultsText="'暂无数据'" placeholder="请选择产品分类" :disable-branch-nodes="true"
|
||||
/>
|
||||
<div class="dl-add-catg" @click="goCatgView">添加产品分类</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user