<template> <a-page-header-wrapper :title="title"> <a-card :body-style="{ padding: '24px 32px' }" :bordered="false"> <a-form> <a-form-item label="标题" :labelCol="{ span: 7 }" :wrapperCol="{ span: 10 }" :required="true" > <a-input v-model="post.app_name" placeholder="给应用起个名字" /> </a-form-item> <a-form-item label="打包算法" :labelCol="{ span: 7 }" :wrapperCol="{ span: 10 }" > <a-radio-group v-model="post.algorithm"> <a-radio-button value="zlib"> zlib </a-radio-button> <a-radio-button value="heatshrink"> heatshrink </a-radio-button> </a-radio-group> </a-form-item> <a-form-item label="应用版本号" :labelCol="{ span: 7 }" :wrapperCol="{ span: 10 }" :required="false" > <a-input v-model="post.app_version" placeholder="请输入版本号" /> </a-form-item> <a-form-item label="应用类别" :labelCol="{ span: 7 }" :wrapperCol="{ span: 10 }" :required="true" > <a-select v-model="post.category" mode="default" style="width: 100%" placeholder="应用所属类别" :allowClear="true" > <a-select-option v-for="item in categoryList" :key="item.value"> {{ item.label }} </a-select-option> </a-select> </a-form-item> <a-form-item label="应用ICON" :labelCol="{ span: 7 }" :wrapperCol="{ span: 10 }" :required="true" > <a-upload name="avatar" list-type="picture-card" class="avatar-uploader" :show-upload-list="true" :before-upload="beforeUpload" @change="handleLogoChange" @preview="handlePreview" > <img v-if="imageUrl" :src="imageUrl" alt="avatar" /> <div v-else> <a-icon :type="loading ? 'loading' : 'plus'" /> <div class="ant-upload-text">上传</div> </div> </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 label="适配尺寸" :labelCol="{ span: 7 }" :wrapperCol="{ span: 10 }" :required="true" > <a-select :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 }} </a-select-option> </a-select> </a-form-item> <a-form-item label="适配平台" :labelCol="{ span: 7 }" :wrapperCol="{ span: 10 }" :required="true" > <a-select :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 }} </a-select-option> </a-select> </a-form-item> <a-form-item label="应用介绍" :labelCol="{ span: 7 }" :wrapperCol="{ span: 10 }" > <a-textarea v-model="post.remarks" rows="4" placeholder="请输入应用介绍" /> </a-form-item> <a-form-item label="元信息" :labelCol="{ span: 7 }" :wrapperCol="{ span: 10 }" > <a-textarea v-model="post.meta_data" rows="4" placeholder="可以存储一些JSON格式应用元信息,接口获取" /> </a-form-item> <a-form-item label="应用源文件" :labelCol="{ span: 7 }" :wrapperCol="{ span: 10 }" :required="true" > <a-upload-dragger name="file" :multiple="true" :before-upload="beforeUpload" @change="handleSourceFileChange" > <p class="ant-upload-drag-icon"> <a-icon type="inbox" /> </p> <p class="ant-upload-text">点击或拖拽文件到此</p> <p class="ant-upload-hint">支持单次或批量上传</p> </a-upload-dragger> </a-form-item> <a-form-item style="margin-top: 24px" :wrapperCol="{ span: 10, offset: 7 }" > <a-button type="primary" v-if="title == '添加'" @click="onSumbit" >提交</a-button > <a-button style="margin-left: 8px" v-else @click="updateApplication" >保存</a-button > </a-form-item> </a-form> </a-card> </a-page-header-wrapper> </template> <script> import { Avatar, Row, Col, Card, List, Button, Form, Icon, Table, Divider, Dropdown, Input, Select, Radio, Upload, PageHeader, DatePicker, InputNumber, message, } from "ant-design-vue"; import PageHeaderWrapper from "@/components/PageHeaderWrapper"; import DescriptionItem from "@/components/DescriptionItem"; import { mapTrim } from "@/utils/index"; 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 { name: "ApplicationForm", data() { return { previewVisible: false, previewImage: "", loading: false, imageUrl: "", uuid: null, title: "添加", post: { app_name: null, app_icon: null, app_version: null, category: null, app_screen_size: null, app_arch: null, remarks: null, meta_data: null, logo: null, fileList: [], }, logo: null, fileList: [], categoryList: [ { label: "影音视听", value: 1 }, { label: "实用工具", value: 2 }, { label: "图书阅读", value: 3 }, { label: "学习教育", value: 4 }, { label: "医疗健康", value: 5 }, { label: "未定义", value: 6 }, ], sizeList: [ { label: "240 * 240", value: 1 }, { label: "390 * 390", value: 2 }, { label: "450 * 450", value: 3 }, ], portList: [ { label: "ASR3601", value: 1 }, { label: "ASR3603", value: 2 }, ], }; }, components: { Icon, AUpload: Upload, APageHeader: PageHeader, ATextarea: Input.TextArea, ARadio: Radio, ARadioGroup: Radio.Group, ARadioButton: Radio.Button, AInputNumber: InputNumber, AAvatar: Avatar, ARow: Row, ACol: Col, ACard: Card, ACardGrid: Card.Grid, ACardMeta: Card.Meta, AList: List, AButton: Button, AForm: Form, AFormItem: Form.Item, AIcon: Icon, ATable: Table, ADivider: Divider, ADropdown: Dropdown, AInput: Input, ASelect: Select, AUploadDragger: Upload.Dragger, ASelectOption: Select.Option, ADescriptionItem: DescriptionItem, APageHeaderWrapper: PageHeaderWrapper, ARangePicker: DatePicker.RangePicker, }, 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) { const index = this.fileList.indexOf(file); const newFileList = this.fileList.slice(); newFileList.splice(index, 1); this.fileList = newFileList; }, handleLogoChange(file) { this.logo = file; }, beforeUpload(file) { if (file.size / 1024 / 1024 > 2) { message.error("Image must smaller than 2MB!"); } return false; }, handleSourceFileChange(file) { this.fileList = [...this.fileList, file]; const status = file.file.status; if (status === "done") { message.success(`${file.file.name} file uploaded successfully.`); } else if (status === "error") { message.error(`${file.file.name} file upload failed.`); } }, handleUpload() { this.uploading = true; let formData = new FormData(); this.fileList.forEach((item) => { formData.append("fileList", item.file); }); formData.append("logo", this.logo.file); Object.keys(this.post).forEach((k) => { if (this.post[k] && typeof this.post[k] !== "object") { formData.append(k, this.post[k]); } }); this.postApplication(formData); }, updateApplication() { updateApplication(this.uuid, mapTrim(this.post)) .then((res) => { message.success(res.msg); }) .catch((err) => { message.error(err.msg); }); }, postApplication(formData) { postApplication(formData) .then((res) => { this.fileList = []; this.logo = null; this.post.fileList = []; this.post.logo = null; this.uploading = false; message.success(res.msg); }) .catch((err) => { this.uploading = false; message.error(err.msg); }); }, onSumbit() { this.handleUpload(); }, }, computed: { desc() { return this.$t("pageDesc"); }, }, created() { const params = this.$route.params; console.log(params); if (params.title) { this.title = params.title; } if (params.record) { this.uuid = params.record.uuid; this.post = params.record; } }, }; </script> <style scoped> .avatar-uploader > .ant-upload { width: 128px; height: 128px; } .ant-upload-select-picture-card i { font-size: 32px; color: #999; } .ant-upload-select-picture-card .ant-upload-text { margin-top: 8px; color: #666; } </style>