Commit 090d2f11 authored by wanli's avatar wanli

feat(): 应用管理前端,提高用户体验。

parent 12f16b50
''' '''
Author: your name Author: your name
Date: 2021-06-30 18:03:41 Date: 2021-06-30 18:03:41
LastEditTime: 2021-07-22 10:11:34 LastEditTime: 2021-07-22 16:09:28
LastEditors: Please set LastEditors LastEditors: Please set LastEditors
Description: In User Settings Edit Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\controllers\package.py FilePath: \evm-store\tools\build_out\controllers\package.py
...@@ -58,7 +58,10 @@ class PackageResource(object): ...@@ -58,7 +58,10 @@ class PackageResource(object):
temp = [] temp = []
for item in result: for item in result:
temp.append({ "name": item.app.app_name, "uuid": str(item.uuid) }) temp.append({ "name": item.app.app_name, "uuid": str(item.uuid) })
return temp, len(temp), "get build_logs {}.".format("success" if temp else "fail") if len(temp):
return temp, ResponseCode.HTTP_SUCCESS
else:
return None, ResponseCode.HTTP_NOT_FOUND
temp = [PackageModel.is_delete==False, PackageModel.create_by==user.id] temp = [PackageModel.is_delete==False, PackageModel.create_by==user.id]
if params.get("app") and isinstance(params.get("app"), str): if params.get("app") and isinstance(params.get("app"), str):
...@@ -68,6 +71,7 @@ class PackageResource(object): ...@@ -68,6 +71,7 @@ class PackageResource(object):
temp.append(PackageModel.app==app.id) temp.append(PackageModel.app==app.id)
else: else:
return None, ResponseCode.HTTP_NOT_FOUND return None, ResponseCode.HTTP_NOT_FOUND
if params.get("app_version"): if params.get("app_version"):
temp.append(PackageModel.app_version==params.get("app_version")) temp.append(PackageModel.app_version==params.get("app_version"))
if params.get("algorithm"): if params.get("algorithm"):
......
...@@ -46,17 +46,13 @@ class PackageModel(PrimaryModel): ...@@ -46,17 +46,13 @@ class PackageModel(PrimaryModel):
return '<PackageModel %r>' % (self.app) return '<PackageModel %r>' % (self.app)
def to_dict(self): def to_dict(self):
source = 'Frontend'
if self.source == 1:
source = 'API'
return { return {
'uuid': self.uuid, 'uuid': self.uuid,
'app_version': self.app_version, 'app_version': self.app_version,
'package_info': self.package_info, 'package_info': self.package_info,
'algorithm': self.algorithm, 'algorithm': self.algorithm,
'file_path': self.file_path, 'file_path': self.file_path,
'source': source, 'source': self.source,
'user_agent': self.user_agent, 'user_agent': self.user_agent,
'download_url': self.download_url, 'download_url': self.download_url,
'ip': self.ip, 'ip': self.ip,
......
...@@ -56,9 +56,10 @@ ...@@ -56,9 +56,10 @@
name="avatar" name="avatar"
list-type="picture-card" list-type="picture-card"
class="avatar-uploader" class="avatar-uploader"
:show-upload-list="false" :show-upload-list="true"
:before-upload="beforeUpload" :before-upload="beforeUpload"
@change="handleLogoChange" @change="handleLogoChange"
@preview="handlePreview"
> >
<img v-if="imageUrl" :src="imageUrl" alt="avatar" /> <img v-if="imageUrl" :src="imageUrl" alt="avatar" />
<div v-else> <div v-else>
...@@ -66,6 +67,13 @@ ...@@ -66,6 +67,13 @@
<div class="ant-upload-text">上传</div> <div class="ant-upload-text">上传</div>
</div> </div>
</a-upload> </a-upload>
<a-modal
:visible="previewVisible"
:footer="null"
@cancel="handleCancel"
>
<img alt="example" style="width: 100%" :src="previewImage" />
</a-modal>
</a-form-item> </a-form-item>
<a-form-item <a-form-item
label="适配尺寸" label="适配尺寸"
...@@ -73,8 +81,17 @@ ...@@ -73,8 +81,17 @@
:wrapperCol="{ span: 10 }" :wrapperCol="{ span: 10 }"
:required="true" :required="true"
> >
<a-select :default-value="sizeList[0].label" v-model="post.app_screen_size" :allowClear="true" style="width: 120px"> <a-select
<a-select-option v-for="item in sizeList" :key="item.value" :value="item.label"> :default-value="sizeList[0].label"
v-model="post.app_screen_size"
:allowClear="true"
style="width: 120px"
>
<a-select-option
v-for="item in sizeList"
:key="item.value"
:value="item.label"
>
{{ item.label }} {{ item.label }}
</a-select-option> </a-select-option>
</a-select> </a-select>
...@@ -85,8 +102,17 @@ ...@@ -85,8 +102,17 @@
:wrapperCol="{ span: 10 }" :wrapperCol="{ span: 10 }"
:required="true" :required="true"
> >
<a-select :default-value="portList[0].label" v-model="post.app_arch" :allowClear="true" style="width: 120px"> <a-select
<a-select-option v-for="item in portList" :key="item.value" :value="item.label"> :default-value="portList[0].label"
v-model="post.app_arch"
:allowClear="true"
style="width: 120px"
>
<a-select-option
v-for="item in portList"
:key="item.value"
:value="item.label"
>
{{ item.label }} {{ item.label }}
</a-select-option> </a-select-option>
</a-select> </a-select>
...@@ -96,14 +122,22 @@ ...@@ -96,14 +122,22 @@
:labelCol="{ span: 7 }" :labelCol="{ span: 7 }"
:wrapperCol="{ span: 10 }" :wrapperCol="{ span: 10 }"
> >
<a-textarea v-model="post.remarks" rows="4" placeholder="请输入应用介绍" /> <a-textarea
v-model="post.remarks"
rows="4"
placeholder="请输入应用介绍"
/>
</a-form-item> </a-form-item>
<a-form-item <a-form-item
label="元信息" label="元信息"
:labelCol="{ span: 7 }" :labelCol="{ span: 7 }"
:wrapperCol="{ span: 10 }" :wrapperCol="{ span: 10 }"
> >
<a-textarea v-model="post.meta_data" rows="4" placeholder="可以存储一些JSON格式应用元信息,接口获取" /> <a-textarea
v-model="post.meta_data"
rows="4"
placeholder="可以存储一些JSON格式应用元信息,接口获取"
/>
</a-form-item> </a-form-item>
<a-form-item <a-form-item
label="应用源文件" label="应用源文件"
...@@ -120,20 +154,20 @@ ...@@ -120,20 +154,20 @@
<p class="ant-upload-drag-icon"> <p class="ant-upload-drag-icon">
<a-icon type="inbox" /> <a-icon type="inbox" />
</p> </p>
<p class="ant-upload-text"> <p class="ant-upload-text">点击或拖拽文件到此</p>
点击或拖拽文件到此 <p class="ant-upload-hint">支持单次或批量上传</p>
</p>
<p class="ant-upload-hint">
支持单次或批量上传
</p>
</a-upload-dragger> </a-upload-dragger>
</a-form-item> </a-form-item>
<a-form-item <a-form-item
style="margin-top: 24px" style="margin-top: 24px"
:wrapperCol="{ span: 10, offset: 7 }" :wrapperCol="{ span: 10, offset: 7 }"
> >
<a-button type="primary" v-if="title == '添加'" @click="onSumbit">提交</a-button> <a-button type="primary" v-if="title == '添加'" @click="onSumbit"
<a-button style="margin-left: 8px" v-else @click="updateApplication">保存</a-button> >提交</a-button
>
<a-button style="margin-left: 8px" v-else @click="updateApplication"
>保存</a-button
>
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-card> </a-card>
...@@ -160,7 +194,7 @@ import { ...@@ -160,7 +194,7 @@ import {
PageHeader, PageHeader,
DatePicker, DatePicker,
InputNumber, InputNumber,
message message,
} from "ant-design-vue"; } from "ant-design-vue";
import PageHeaderWrapper from "@/components/PageHeaderWrapper"; import PageHeaderWrapper from "@/components/PageHeaderWrapper";
import DescriptionItem from "@/components/DescriptionItem"; import DescriptionItem from "@/components/DescriptionItem";
...@@ -168,10 +202,21 @@ import DescriptionItem from "@/components/DescriptionItem"; ...@@ -168,10 +202,21 @@ import DescriptionItem from "@/components/DescriptionItem";
import { mapTrim } from "@/utils/index"; import { mapTrim } from "@/utils/index";
import { postApplication, updateApplication } from "@/api/openapi"; import { postApplication, updateApplication } from "@/api/openapi";
function getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
}
export default { export default {
name: "ApplicationForm", name: "ApplicationForm",
data() { data() {
return { return {
previewVisible: false,
previewImage: "",
loading: false, loading: false,
imageUrl: "", imageUrl: "",
uuid: null, uuid: null,
...@@ -186,26 +231,26 @@ export default { ...@@ -186,26 +231,26 @@ export default {
remarks: null, remarks: null,
meta_data: null, meta_data: null,
logo: null, logo: null,
fileList: [] fileList: [],
}, },
logo: null, logo: null,
fileList: [], fileList: [],
categoryList: [ categoryList: [
{ label: '影音视听', value: 1 }, { label: "影音视听", value: 1 },
{ label: '实用工具', value: 2 }, { label: "实用工具", value: 2 },
{ label: '图书阅读', value: 3 }, { label: "图书阅读", value: 3 },
{ label: '学习教育', value: 4 }, { label: "学习教育", value: 4 },
{ label: '医疗健康', value: 5 }, { label: "医疗健康", value: 5 },
{ label: '未定义', value: 6 } { label: "未定义", value: 6 },
], ],
sizeList: [ sizeList: [
{ label: '240 * 240', value: 1 }, { label: "240 * 240", value: 1 },
{ label: '390 * 390', value: 2 }, { label: "390 * 390", value: 2 },
{ label: '450 * 450', value: 3 } { label: "450 * 450", value: 3 },
], ],
portList: [ portList: [
{ label: 'ASR3601', value: 1 }, { label: "ASR3601", value: 1 },
{ label: 'ASR3603', value: 2 }, { label: "ASR3603", value: 2 },
], ],
}; };
}, },
...@@ -241,6 +286,16 @@ export default { ...@@ -241,6 +286,16 @@ export default {
ARangePicker: DatePicker.RangePicker, ARangePicker: DatePicker.RangePicker,
}, },
methods: { methods: {
handleCancel() {
this.previewVisible = false;
},
async handlePreview(file) {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj);
}
this.previewImage = file.url || file.preview;
this.previewVisible = true;
},
handleRemove(file) { handleRemove(file) {
const index = this.fileList.indexOf(file); const index = this.fileList.indexOf(file);
const newFileList = this.fileList.slice(); const newFileList = this.fileList.slice();
...@@ -260,9 +315,9 @@ export default { ...@@ -260,9 +315,9 @@ export default {
this.fileList = [...this.fileList, file]; this.fileList = [...this.fileList, file];
const status = file.file.status; const status = file.file.status;
if (status === 'done') { if (status === "done") {
message.success(`${file.file.name} file uploaded successfully.`); message.success(`${file.file.name} file uploaded successfully.`);
} else if (status === 'error') { } else if (status === "error") {
message.error(`${file.file.name} file upload failed.`); message.error(`${file.file.name} file upload failed.`);
} }
}, },
...@@ -270,41 +325,45 @@ export default { ...@@ -270,41 +325,45 @@ export default {
this.uploading = true; this.uploading = true;
let formData = new FormData(); let formData = new FormData();
this.fileList.forEach(item => { this.fileList.forEach((item) => {
formData.append("fileList", item.file) formData.append("fileList", item.file);
}); });
formData.append("logo", this.logo.file) formData.append("logo", this.logo.file);
Object.keys(this.post).forEach(k => { Object.keys(this.post).forEach((k) => {
if (this.post[k] && typeof this.post[k] !== "object") { if (this.post[k] && typeof this.post[k] !== "object") {
formData.append(k, this.post[k]) formData.append(k, this.post[k]);
} }
}); });
this.postApplication(formData) this.postApplication(formData);
}, },
updateApplication() { updateApplication() {
updateApplication(this.uuid, mapTrim(this.post)).then(res => { updateApplication(this.uuid, mapTrim(this.post))
message.success(res.msg) .then((res) => {
}).catch(err => { message.success(res.msg);
message.error(err.msg)
}) })
.catch((err) => {
message.error(err.msg);
});
}, },
postApplication(formData) { postApplication(formData) {
postApplication(formData).then(res => { postApplication(formData)
.then((res) => {
this.fileList = []; this.fileList = [];
this.logo = null; this.logo = null;
this.post.fileList = []; this.post.fileList = [];
this.post.logo = null; this.post.logo = null;
this.uploading = false; this.uploading = false;
message.success(res.msg); message.success(res.msg);
}).catch(err => { })
.catch((err) => {
this.uploading = false; this.uploading = false;
message.error(err.msg); message.error(err.msg);
}) });
}, },
onSumbit() { onSumbit() {
this.handleUpload() this.handleUpload();
} },
}, },
computed: { computed: {
desc() { desc() {
...@@ -312,14 +371,14 @@ export default { ...@@ -312,14 +371,14 @@ export default {
}, },
}, },
created() { created() {
const params = this.$route.params const params = this.$route.params;
console.log(params) console.log(params);
if (params.title) { if (params.title) {
this.title = params.title this.title = params.title;
} }
if(params.record) { if (params.record) {
this.uuid = params.record.uuid this.uuid = params.record.uuid;
this.post = params.record this.post = params.record;
} }
}, },
}; };
......
...@@ -285,6 +285,8 @@ ...@@ -285,6 +285,8 @@
<template slot="action" slot-scope="text, record"> <template slot="action" slot-scope="text, record">
<a href="javascript:;" @click="handleEdit(record)">编辑应用</a> <a href="javascript:;" @click="handleEdit(record)">编辑应用</a>
<a-divider type="vertical" /> <a-divider type="vertical" />
<a href="javascript:;" @click="downloadFile(record)">下载EPK</a>
<a-divider type="vertical" />
<a href="javascript:;" @click="rebuildApplication(record)" <a href="javascript:;" @click="rebuildApplication(record)"
>重新打包</a >重新打包</a
> >
...@@ -362,6 +364,7 @@ const columns = [ ...@@ -362,6 +364,7 @@ const columns = [
{ {
title: "Action", title: "Action",
key: "action", key: "action",
width: "35%",
scopedSlots: { customRender: "action" }, scopedSlots: { customRender: "action" },
}, },
]; ];
...@@ -374,7 +377,7 @@ import { ...@@ -374,7 +377,7 @@ import {
updateLauncher updateLauncher
} from "@/api/openapi"; } from "@/api/openapi";
import { mapTrim } from "@/utils/index"; import { mapTrim, download } from "@/utils/index";
export default { export default {
name: "ApplicationIndex", name: "ApplicationIndex",
...@@ -481,6 +484,10 @@ export default { ...@@ -481,6 +484,10 @@ export default {
message.error(err.msg) message.error(err.msg)
}) })
}, },
downloadFile(record) {
console.log(record)
download(`${record.app_name}.epk`, record.download_url);
},
resetForm() { resetForm() {
this.$nextTick(() => { this.$nextTick(() => {
this.form.resetFields(); this.form.resetFields();
......
...@@ -156,10 +156,11 @@ const columns = [ ...@@ -156,10 +156,11 @@ const columns = [
}, },
{ {
title: "打包来源", title: "打包来源",
dataIndex: "source", dataIndex: "source_text",
filters: [ filters: [
{ text: "API", value: 0 }, { text: "API", value: "API" },
{ text: "Frontend", value: 1 }, { text: "Frontend", value: "Frontend" },
{ text: "API", value: "API" },
], ],
}, },
{ {
...@@ -259,7 +260,11 @@ export default { ...@@ -259,7 +260,11 @@ export default {
.then((res) => { .then((res) => {
message.success(res.msg); message.success(res.msg);
if (res.code == 200) { if (res.code == 200) {
this.tableData.list = res.data; this.tableData.list = res.data.map(item => {
if (item.source == 1) item.source_text = "Frontend"
else item.source_text = "API"
return item;
});
this.tableData.pagination.pageSize = res.pageSize; this.tableData.pagination.pageSize = res.pageSize;
this.tableData.pagination.total = res.total; this.tableData.pagination.total = res.total;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment