前端页面增加批量应用上传功能

dependabot/npm_and_yarn/fir_admin/path-parse-1.0.7
youngS 3 years ago
parent cb3738f4de
commit 436e26af37
  1. 8
      fir_client/src/components/FirDownload.vue
  2. 6
      fir_client/src/components/ShortDownload.vue
  3. 381
      fir_client/src/components/apps/FirApps.vue
  4. 33
      fir_client/src/utils/index.js

@ -387,7 +387,7 @@
let download_url = res.data.download_url; let download_url = res.data.download_url;
this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url); this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url);
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => { this.timer = setTimeout(data => {
this.gomobile = false; this.gomobile = false;
}, 5000); }, 5000);
} }
@ -397,7 +397,7 @@
window.location.href = this.downloadurl; window.location.href = this.downloadurl;
if (res.data.extra_url !== "") { if (res.data.extra_url !== "") {
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => { this.timer = setTimeout(data => {
window.location.href = res.data.extra_url; window.location.href = res.data.extra_url;
}, 3000); }, 3000);
} }
@ -411,7 +411,7 @@
if (res.data.extra_url !== "") { if (res.data.extra_url !== "") {
this.mobileprovision = res.data.extra_url; this.mobileprovision = res.data.extra_url;
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => { this.timer = setTimeout(data => {
this.gomobile = false; this.gomobile = false;
}, 5000); }, 5000);
} }
@ -606,7 +606,7 @@
} else { } else {
if (data.msg) { if (data.msg) {
document.title = data.msg; document.title = data.msg;
this.wrong=true; this.wrong = true;
this.$message({ this.$message({
message: data.msg, message: data.msg,
type: 'error', type: 'error',

@ -380,7 +380,7 @@
let download_url = res.data.download_url; let download_url = res.data.download_url;
this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url); this.downloadurl = "itms-services://?action=download-manifest&url=" + encodeURIComponent(download_url);
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => { this.timer = setTimeout(data => {
this.gomobile = false; this.gomobile = false;
}, 5000); }, 5000);
} }
@ -390,7 +390,7 @@
window.location.href = this.downloadurl; window.location.href = this.downloadurl;
if (res.data.extra_url !== "") { if (res.data.extra_url !== "") {
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => { this.timer = setTimeout(data => {
window.location.href = res.data.extra_url; window.location.href = res.data.extra_url;
}, 3000); }, 3000);
} }
@ -404,7 +404,7 @@
if (res.data.extra_url !== "") { if (res.data.extra_url !== "") {
this.mobileprovision = res.data.extra_url; this.mobileprovision = res.data.extra_url;
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
this.timmer = setTimeout(data => { this.timer = setTimeout(data => {
this.gomobile = false; this.gomobile = false;
}, 5000); }, 5000);
} }

@ -77,6 +77,63 @@
</span> </span>
</el-dialog> </el-dialog>
<el-dialog
:title="`应用批量上传,`+multiFileList.filter(function(val){return val}).length +` 个应用待上传`"
:visible.sync="multiupload"
@closed="closeUpload"
:destroy-on-close="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
:center="true"
width="766px">
<el-table
:data="multiFileList"
stripe
border
height="366px"
style="width: 100%">
<el-table-column
prop="name"
label="文件名称">
</el-table-column>
<el-table-column
prop="size"
label="文件大小"
width="80">
<template slot-scope="scope">
{{ scope.row.size|diskSize }}
</template>
</el-table-column>
<el-table-column
label="短连接"
width="70">
<template slot-scope="scope">
{{ uploadprocess[uploadprocessList[multiFileList.indexOf(scope.row)]].short }}
</template>
</el-table-column>
<el-table-column
label="应用名称">
<template slot-scope="scope">
{{ uploadprocess[uploadprocessList[multiFileList.indexOf(scope.row)]].appname }}
</template>
</el-table-column>
<el-table-column
prop="raw.lastModified"
width="80"
align="center"
label="上传进度">
<template slot-scope="scope">
{{ uploadprocess[uploadprocessList[multiFileList.indexOf(scope.row)]].process }} %
</template>
</el-table-column>
</el-table>
<span slot="footer" class="dialog-footer">
<el-button plain @click="closeUpload"> </el-button>
<el-button type="primary" plain @click="multiuploadFun"
:disabled="multiuploaddisable">开始上传</el-button>
</span>
</el-dialog>
<el-dialog class="upload-app" <el-dialog class="upload-app"
style="position: fixed" style="position: fixed"
@ -223,10 +280,13 @@
</div> </div>
</div> </div>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer" v-if="currentfile&& currentfile.uid">
<el-progress :text-inside="true" :stroke-width="26" :percentage="uploadprocess" {{ uploadprocess[currentfile.uid] }}
<el-progress :text-inside="true" :stroke-width="26"
:percentage="uploadprocess[uploadprocessList[multiFileList.indexOf(currentfile)]].process"
v-if="uploadflag === true"/> v-if="uploadflag === true"/>
<el-button type="primary" plain @click="uploadcloud" v-else>{{ analyseappinfo.is_new|get_upload_text}}</el-button> <el-button type="primary" plain
@click="uploadcloud(analyseappinfo,currentfile,false,getappsFun)" v-else>{{ analyseappinfo.is_new|get_upload_text}}</el-button>
</span> </span>
</el-dialog> </el-dialog>
@ -374,10 +434,13 @@
<div class=" card app card-ios" style="padding: 0"> <div class=" card app card-ios" style="padding: 0">
<el-upload <el-upload
drag drag
ref="upload"
:on-change="onUploadChange"
:show-file-list="false" :show-file-list="false"
:before-upload="beforeAvatarUpload"
accept=".ipa , .apk" accept=".ipa , .apk"
action="#" action="#"
:auto-upload="false"
:limit="50"
multiple> multiple>
<i class="el-icon-upload" style="color: #fff"/> <i class="el-icon-upload" style="color: #fff"/>
<div class="el-upload__text" style="color: #fff;margin-top: 20px">拖拽到这里上传</div> <div class="el-upload__text" style="color: #fff;margin-top: 20px">拖拽到这里上传</div>
@ -409,8 +472,6 @@
:src="r.has_combo.master_release.icon_url|make_icon_url" alt=""> :src="r.has_combo.master_release.icon_url|make_icon_url" alt="">
</a> </a>
</div> </div>
<br> <br>
<p class="appname"><i class="el-icon-user-solid"/><span <p class="appname"><i class="el-icon-user-solid"/><span
class="ng-binding">{{ r.name }}</span> class="ng-binding">{{ r.name }}</span>
@ -497,14 +558,27 @@
getWindowHeight, getWindowHeight,
uploadaliyunoss, uploadaliyunoss,
uploadlocalstorage, uploadlocalstorage,
uploadqiniuoss uploadqiniuoss,
getUserInfoFun,
makeFiveC,
deepCopy,
diskSize
} from "@/utils"; } from "@/utils";
import {getUserInfoFun} from "../../utils";
let fiveProcess = {};
let fiveProcessList = [];
for (const c of makeFiveC()) {
fiveProcess[c] = {process: 0, short: '', appname: ''};
fiveProcessList.push(c)
}
export default { export default {
name: "FirApps", name: "FirApps",
data() { data() {
return { return {
timer: '',
multiupload: false,
multiuploaddisable: false,
multiFileList: [],
default_pay_radio: '', default_pay_radio: '',
default_price_radio: '', default_price_radio: '',
pay_choices: [], pay_choices: [],
@ -526,8 +600,8 @@
autoloadflag: true, autoloadflag: true,
firstloadflag: true, firstloadflag: true,
currentfile: null, currentfile: null,
uploadprocess: 0, uploadprocess: deepCopy(fiveProcess),
uploadsuccess: 0, uploadprocessList: fiveProcessList,
loadingobj: null, loadingobj: null,
show_buy_download_times: false, show_buy_download_times: false,
data_package_prices: [], data_package_prices: [],
@ -540,6 +614,79 @@
PaymentQuestionMsg: '', PaymentQuestionMsg: '',
} }
}, methods: { }, methods: {
multirun(process, keylist, func) {
let thr = [];
for (let i = 0; i < process; i++) {
thr.push(Promise.resolve())
}
for (let j = 0; j < keylist.length; j += process) {
for (let i = 0; i < process; i++) {
if (i + j < keylist.length) {
// eslint-disable-next-line no-unused-vars
thr[(j + i) % process] = thr[(j + i) % process].then(_ => func(keylist[i + j]))
}
}
}
},
uploadasync(file) {
return new Promise((resolve, reject) => {
try {
const loading = this.$loading({
lock: true,
text: `文件 ${file.name} 解析中`,
spinner: 'el-icon-loading',
});
getappinfo(file.raw, appinfo => {
if (appinfo && appinfo.bundleid) {
let analyseappinfo = appinfo;
if (this.currentfile) {
this.analyseappinfo = appinfo;
}
analyseApps(data => {
if (data.code === 1000) {
this.short = data.data.short;
for (let name of Object.keys(data.data)) {
analyseappinfo[name] = data.data[name]
}
if (this.currentfile) {
this.willuploadApp = true;
resolve()
} else {
this.uploadcloud(analyseappinfo, file, true, resolve)
}
} else {
this.$message.error("应用 " + analyseappinfo.appname + " 上传token获取失败,请刷新重试")
}
loading.close();
}, {
'methods': 'POST',
'data': {"bundleid": analyseappinfo.bundleid, "type": analyseappinfo.type}
});
} else {
this.$message.error("文件 " + file.raw.name + " 解析失败,请检查是否为APP应用")
}
}, err => {
loading.close();
this.$message.error("应用解析失败,请检查是否为APP应用");
// eslint-disable-next-line no-console
console.log('Error ', err);
});
} catch (e) {
reject(e);
}
});
},
multiuploadFun() {
this.multiuploaddisable = true;
if (this.multiFileList && this.multiFileList.length > 0) {
this.multirun(3, this.multiFileList, this.uploadasync)
}
},
show_package_prices() { show_package_prices() {
get_package_prices(res => { get_package_prices(res => {
if (res.code === 1000) { if (res.code === 1000) {
@ -588,89 +735,101 @@
dangerouslyUseHTMLString: true, dangerouslyUseHTMLString: true,
}); });
}, },
updateappinfo(file) { updateappinfo(file, analyseappinfo, multiFlag, binaryFlag, resolve) {
this.uploadsuccess += 1; if (binaryFlag) {
if (this.uploadsuccess === 2) { delete analyseappinfo.icon;
delete this.analyseappinfo.icon; this.$message.success(file.raw.name + '上传成功');
this.$message.success(file.name + '上传成功'); if (!multiFlag) {
this.analyseappinfo.short = this.short; analyseappinfo.short = this.short;
}
const loading = this.$loading({ const loading = this.$loading({
lock: true, lock: true,
text: '应用入库中,请耐心等待', text: `应用 ${analyseappinfo.appname} 入库中,请耐心等待`,
spinner: 'el-icon-loading', spinner: 'el-icon-loading',
// background: 'rgba(0, 0, 0, 0.7)'
}); });
analyseApps(data => { analyseApps(data => {
if (data.code === 1000) { if (data.code === 1000) {
let app_uuid = this.analyseappinfo.app_uuid; if (!multiFlag) {
this.closeUpload();
this.$router.push({name: 'FirAppInfostimeline', params: {id: analyseappinfo.app_uuid}});
} else {
this.$message.success(analyseappinfo.appname + ' 入库成功');
}
}
loading.close();
const start = this.multiFileList.indexOf(file);
if (start > -1) {
delete this.multiFileList[start]
}
if (this.multiFileList && this.multiFileList.filter(function (val) {
return val
}).length === 0) {
this.closeUpload(); this.closeUpload();
this.$router.push({name: 'FirAppInfostimeline', params: {id: app_uuid}}); this.searchFun();
} }
loading.close() resolve()
}, {'methods': 'PUT', 'data': this.analyseappinfo}); }, {'methods': 'PUT', 'data': analyseappinfo});
} }
}, },
uploadtostorage(file, certinfo) { uploadtostorage(file, analyseappinfo, multiFlag, binaryFlag, resolve) {
let upload_key = analyseappinfo.png_key;
if (this.analyseappinfo.storage === 1) { let upload_token = analyseappinfo.png_token;
let rawfile = file;
let process_key = '';
if (binaryFlag) {
upload_key = analyseappinfo.upload_key;
upload_token = analyseappinfo.upload_token;
process_key = this.uploadprocessList[this.multiFileList.indexOf(file)];
rawfile = file.raw
}
let certinfo = {
'upload_key': upload_key,
'upload_token': upload_token
};
if (analyseappinfo.storage === 1) {
// eslint-disable-next-line no-unused-vars,no-unreachable // eslint-disable-next-line no-unused-vars,no-unreachable
uploadqiniuoss(file, certinfo, this, res => { uploadqiniuoss(rawfile, certinfo, this, res => {
this.updateappinfo(file) this.updateappinfo(file, analyseappinfo, multiFlag, binaryFlag, resolve)
}, process => { }, process => {
if (this.uploadsuccess === 1) { if (binaryFlag && process_key) {
this.uploadprocess = process; this.uploadprocess[process_key] = {process, analyseappinfo};
} }
}) })
} else if (this.analyseappinfo.storage === 2) { } else if (analyseappinfo.storage === 2) {
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
uploadaliyunoss(file, certinfo, this, res => { uploadaliyunoss(rawfile, certinfo, this, res => {
this.updateappinfo(file) this.updateappinfo(file, analyseappinfo, multiFlag, binaryFlag, resolve)
}, process => { }, process => {
if (this.uploadsuccess === 1) { if (binaryFlag && process_key) {
this.uploadprocess = process; this.uploadprocess[process_key] = {
process,
short: analyseappinfo.short,
appname: analyseappinfo.appname
};
} }
}); });
} else { } else {
// //
if (this.analyseappinfo.domain_name) { if (analyseappinfo.domain_name) {
certinfo.upload_url = getuploadurl(this.analyseappinfo.domain_name) certinfo.upload_url = getuploadurl(analyseappinfo.domain_name)
} else { } else {
certinfo.upload_url = getuploadurl(); certinfo.upload_url = getuploadurl();
} }
certinfo.ftype = 'app'; certinfo.ftype = 'app';
certinfo.app_id = this.analyseappinfo.app_uuid; certinfo.app_id = analyseappinfo.app_uuid;
// eslint-disable-next-line no-unused-vars,no-unreachable // eslint-disable-next-line no-unused-vars,no-unreachable
uploadlocalstorage(file, certinfo, this, res => { uploadlocalstorage(rawfile, certinfo, this, res => {
this.updateappinfo(file) this.updateappinfo(file, analyseappinfo, multiFlag, binaryFlag, resolve)
}, process => { }, process => {
if (this.uploadsuccess === 1) { if (binaryFlag && process_key) {
this.uploadprocess = process; this.uploadprocess[process_key] = {process, analyseappinfo};
} }
}) })
} }
}, },
getuploadtoken(loading) { uploadcloud(analyseappinfo, binary_file, multiFlag, resolve) {
analyseApps(data => { if (analyseappinfo.binary_url !== '') {
if (data.code === 1000) { this.$confirm(`该应用 ${analyseappinfo.appname} 存在第三方下载链接 <a target="_blank" href="${analyseappinfo.binary_url}"> ${analyseappinfo.binary_url} </a>更新之后,将不会自动跳转第三方下载;若您还需要第三方跳转,请在第三方平台更新该应用。`, '确定更新应用?', {
this.short = data.data.short;
for (let name of Object.keys(data.data)) {
this.analyseappinfo[name] = data.data[name]
}
this.willuploadApp = true;
} else {
this.$message.error("上传token获取失败,请刷新重试")
}
loading.close();
}, {
'methods': 'POST',
'data': {"bundleid": this.analyseappinfo.bundleid, "type": this.analyseappinfo.type}
})
},
uploadcloud() {
if (this.analyseappinfo.binary_url !== '') {
this.$confirm(`该应用存在第三方下载链接 <a target="_blank" href="${this.analyseappinfo.binary_url}"> ${this.analyseappinfo.binary_url} </a>更新之后,将不会自动跳转第三方下载;若您还需要第三方跳转,请在第三方平台更新该应用。`, '确定更新应用?', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
dangerouslyUseHTMLString: true, dangerouslyUseHTMLString: true,
@ -678,52 +837,52 @@
}).then(() => { }).then(() => {
this.$message({ this.$message({
type: 'success', type: 'success',
message: '开始更新' message: '确定更新'
}); });
this.uploadstorage() this.uploadstorage(analyseappinfo, binary_file, multiFlag, resolve)
}).catch(() => { }).catch(() => {
this.$message({ this.$message({
type: 'info', type: 'info',
message: '已取消更新' message: `应用 ${analyseappinfo.appname} 已取消更新`
}); });
this.closeUpload(); if (!multiFlag) {
this.closeUpload();
} else {
const start = this.multiFileList.indexOf(binary_file);
if (start > -1) {
delete this.multiFileList[start]
}
resolve()
}
}); });
} else { } else {
this.uploadstorage() this.uploadstorage(analyseappinfo, binary_file, multiFlag, resolve)
} }
}, },
uploadstorage() { uploadstorage(analyseappinfo, binary_file, multiFlag, resolve) {
this.uploadflag = true; if (!multiFlag) {
this.uploading = true; this.uploadflag = true;
// eslint-disable-next-line no-unused-vars this.uploading = true;
// this.timmer = setTimeout(data => { }
// let canvas = this.$refs.canvas; let file = dataURLtoFile(analyseappinfo.icon, analyseappinfo.png_key);
// show_beautpic(this, canvas, 888, 0.6); this.uploadtostorage(file, analyseappinfo, multiFlag, false, resolve);
// }, 100); this.uploadtostorage(binary_file, analyseappinfo, multiFlag, true, resolve);
let file = dataURLtoFile(this.analyseappinfo.icon, this.analyseappinfo.png_key);
this.uploadtostorage(file, {
'upload_key': this.analyseappinfo.png_key,
'upload_token': this.analyseappinfo.png_token
});
file = this.currentfile;
this.uploadtostorage(file, {
'upload_key': this.analyseappinfo.upload_key,
'upload_token': this.analyseappinfo.upload_token
});
}, },
closeUpload() { closeUpload() {
this.uploadsuccess = 0;
this.uploadprocess = 0;
this.uploadflag = false; this.uploadflag = false;
this.uploading = false; this.uploading = false;
this.willuploadApp = false; this.willuploadApp = false;
this.currentfile = null;
this.uploadflag = false; this.uploadflag = false;
this.analyseappinfo = {}; this.analyseappinfo = {};
this.multiupload = false;
this.multiuploaddisable = false;
this.multiFileList = [];
this.$refs.upload.clearFiles();
this.$refs.upload.abort();
this.uploadprocess = deepCopy(fiveProcess);
this.uploadprocessList = fiveProcessList;
}, },
searchFun() { searchFun() {
@ -819,28 +978,19 @@
}, parms); }, parms);
}, },
beforeAvatarUpload(file) { onUploadChange(file, fileList) {
const loading = this.$loading({ if (fileList && fileList.length > 1) {
lock: true, this.multiupload = true;
text: '应用解析中', }
spinner: 'el-icon-loading', this.multiFileList = fileList;
// background: 'rgba(0, 0, 0, 0.7)' // eslint-disable-next-line no-unused-vars
}); this.timer = setTimeout(data => {
getappinfo(file, appinfo => { if (fileList && fileList.length === 1) {
if (appinfo.bundleid) { this.currentfile = this.multiFileList[0];
this.analyseappinfo = appinfo; this.multiuploadFun();
this.getuploadtoken(loading);
this.currentfile = file;
} else {
this.$message.error("应用解析失败,请检查是否为APP应用")
} }
}, err => { clearTimeout(this.timer);
loading.close(); }, 300);
this.$message.error("应用解析失败,请检查是否为APP应用");
// eslint-disable-next-line no-console
console.log('Error ', err);
});
return false;
}, },
delApp() { delApp() {
let loadingobj = this.$loading({ let loadingobj = this.$loading({
@ -891,6 +1041,7 @@
}, },
}, },
filters: { filters: {
diskSize,
formatMoney: function (money) { formatMoney: function (money) {
return format_money(money, 19); return format_money(money, 19);
}, },
@ -1049,6 +1200,10 @@
margin-top: -43px; margin-top: -43px;
} }
.appdownload /deep/ .el-upload-list__item {
font-size: 17px;
line-height: 1;
}
.page-apps .card.app .action a, .page-apps .card.app .appname, .page-apps .card.app table tr td, .upload-modal .state-form .release-body .input-addon { .page-apps .card.app .action a, .page-apps .card.app .appname, .page-apps .card.app table tr td, .upload-modal .state-form .release-body .input-addon {
font-family: 'Open Sans', sans-serif font-family: 'Open Sans', sans-serif

@ -573,3 +573,36 @@ export function getUserInfoFun(self) {
} }
}, {"methods": "GET"}) }, {"methods": "GET"})
} }
function getChar(n) {
let SL = [];
for (let i = 65; i <= n + 65; i++) {
SL.push(String.fromCharCode(i))
}
return SL
}
export function makeFiveC() {
let SL = [];
for (const i of getChar(10)) {
for (const j of getChar(5)) {
SL.push(i + j)
}
}
return SL
}
export function diskSize(num) {
if (num === 0) return '0 B';
let k = 1024; //设定基础容量大小
let sizeStr = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; //容量单位
let i = 0; //单位下标和次幂
for (let l = 0; l < 8; l++) { //因为只有8个单位所以循环八次
if (num / Math.pow(k, l) < 1) { //判断传入数值 除以 基础大小的次幂 是否小于1,这里小于1 就代表已经当前下标的单位已经不合适了所以跳出循环
break; //小于1跳出循环
}
i = l; //不小于1的话这个单位就合适或者还要大于这个单位 接着循环
}
return (num / Math.pow(k, i)).toFixed(1) + ' ' + sizeStr[i]; //循环结束 或 条件成立 返回字符
}

Loading…
Cancel
Save