Explorar o código

Merge branch 'dev' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend-wms into dev

yusheng hai 11 meses
pai
achega
799f5a0cd6

+ 26 - 0
src/api/system/file/index.js

@@ -80,3 +80,29 @@ export async function getFile(params, fileName) {
   const arr = params.objectName.split('/');
   download(res.data, fileName || arr[arr.length - 1]);
 }
+
+
+export async function importBatch(data) {
+  const formData = new FormData();
+  data.multiPartFiles.forEach((item, index) => {
+    formData.append(`multiPartFiles`, item);
+  });
+  const res = await request.post(
+    `/wms/outintwo/importStock?module=${data.module}`,
+    formData
+  );
+  if (res.data.code === '0') {
+    return res.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+
+export async function downLoadTemplateNew(url,fileName) {
+  const res = await request.post(url,{}, {
+    responseType: 'blob'
+  });
+  console.log(res.data,'***********');
+  download(res.data, fileName);
+
+}

+ 109 - 0
src/components/upload/WithView.vue

@@ -0,0 +1,109 @@
+<template>
+  <div>
+    <div class="img-view" v-if="dialogImageUrl">
+      <img :src="dialogImageUrl" alt="" srcset="" />
+    </div>
+    <div class="placeholder-box" v-else>
+      <img src="~@/assets/upload-placeholder.svg" alt="" />
+    </div>
+    <div class="btn-box">
+      <el-upload class="avatar-div" action="#" accept="image/png,image/jpeg" :show-file-list="false" ref="uploadRef"
+        :on-exceed="handleExceed" :limit="1" :http-request="handlSuccess" :multiple="false">
+        <el-button type="text">上传{{ assetName }}图片</el-button>
+      </el-upload>
+      <el-button type="text" @click="clearImg">清除图片</el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { uploadFile, removeFile } from '@/api/system/file/index.js';
+import { getImageUrl } from '@/utils/file';
+export default {
+  props: {
+    assetName: {
+      type: String,
+      default: '设备'
+    },
+    value: {
+      type: Object,
+      default: () => []
+    },
+    // 所属模块
+    module: {
+      type: String,
+      default: 'main'
+    }
+  },
+  data() {
+    return {};
+  },
+  computed: {
+    dialogImageUrl() {
+      return this.value?.storePath && getImageUrl(this.value.storePath);
+    }
+  },
+  methods: {
+    // 清空已上传的文件列表
+    clearUploadFiles() { },
+    //图片添加
+    async handlSuccess(params) {
+      let res = await uploadFile({
+        multiPartFile: params.file,
+        module: this.module
+      });
+      if (res?.data) {
+        this.$emit('input', res.data);
+      }
+    },
+    async clearImg() {
+      await removeFile({ fileId: this.value.id });
+      this.$emit('input', {});
+      this.$refs.uploadRef.clearFiles();
+    },
+    // 限制上传的数量
+    handleExceed(files, fileList) {
+      this.$message.warning(`最多允许上传一张图片!`);
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+.img-view {
+  width: 280px;
+  height: 342px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  border-width: 1px;
+  border-style: solid;
+  border-color: rgba(215, 215, 215, 1);
+
+  img {
+    max-width: 100%;
+  }
+}
+
+.placeholder-box {
+  width: 250px;
+  height: 200px;
+  text-align: center;
+
+  background-color: rgba(242, 242, 242, 1);
+  box-sizing: border-box;
+  border-width: 1px;
+  border-style: solid;
+  border-color: rgba(215, 215, 215, 1);
+  padding-top: 60px;
+
+  img {
+    width: 100px;
+    height: 100px;
+  }
+}
+
+.btn-box {
+  display: flex;
+  justify-content: space-around;
+}
+</style>

+ 279 - 0
src/components/upload/fileUpload.vue

@@ -0,0 +1,279 @@
+<template>
+  <div class="upload-file">
+    <el-upload
+      class="upload-demo"
+      action="#"
+      :http-request="handlRequest"
+      :before-remove="beforeRemove"
+      :on-remove="handleRemove"
+      :on-preview="handleItem"
+      multiple
+      :before-upload="beforeUpload"
+      :file-list="fileList"
+      :show-file-list="!showLib"
+    >
+      <slot>
+        <el-button type="primary" icon="el-icon-plus" size="mini">点击上传</el-button>
+      </slot>
+    </el-upload>
+    <el-button type="primary" class="lib" @click="handleOpenLib" v-if="showLib"
+      >文档库</el-button
+    >
+    <div class="imgs-box" v-if="fileList.length && showLib">
+      <p class="imgs-p">
+        <span> {{ fileList[0].name }}</span>
+        <el-link @click="delFileList" type="primary" class="link">删除</el-link>
+      </p>
+    </div>
+    <!--图文档弹窗 -->
+    <el-dialog
+      title="图文档"
+      append-to-body
+      :visible.sync="documentVisible"
+      width="72%"
+    >
+      <el-form label-width="100px">
+        <el-row :gutter="12">
+          <el-col :span="8">
+            <el-form-item label-width="70px" label="文档名称">
+              <el-input v-model="documentForm.name"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-button type="primary" @click="reload">搜索</el-button>
+          </el-col>
+        </el-row>
+      </el-form>
+      <ele-pro-table
+        ref="table"
+        :current.sync="selectItem"
+        :columns="columns"
+        highlight-current-row
+        :datasource="datasource"
+        :initLoad="false"
+        height="500px"
+        class="dict-table"
+        tool-class="ele-toolbar-actions"
+      >
+      </ele-pro-table>
+      <div slot="footer" class="dialog-footer">
+        <el-button size="small" @click="documentVisible = false"
+          >关 闭</el-button
+        >
+        <el-button size="small" @click="submitDocument" type="primary"
+          >确 认</el-button
+        >
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+  import {
+    uploadFile,
+    removeFile,
+    getFileList,
+    getFile
+  } from '@/api/system/file/index.js';
+  import { getImageUrl, getImagePath } from '@/utils/file';
+  export default {
+    props: {
+      value: {
+        type: [Array,String],
+        default: () => []
+      },
+      // 所属模块
+      module: {
+        type: String,
+        required: true
+      },
+      // 文档库
+      showLib: {
+        type: Boolean,
+        default: false
+      },
+      // 限制数量
+      limit: {
+        type: Number,
+        default: -1
+      },
+      // 限制大小 mb
+      size: {
+        type: Number,
+        default: 10
+      }
+    },
+    data () {
+      return {
+        documentVisible: false,
+        selectItem: null,
+        documentForm: {
+          name: ''
+        },
+        columns: [
+          {
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center'
+          },
+          {
+            label: '文档名称',
+            prop: 'name',
+            minWidth: '180',
+            showOverflowTooltip: true
+          },
+          {
+            label: '文档类型',
+            prop: 'type'
+          },
+          {
+            label: '系统'
+          },
+          {
+            label: '储存路径',
+            prop: 'storePath',
+            minWidth: '180',
+            showOverflowTooltip: true
+          },
+          {
+            label: '模块名',
+            prop: 'module'
+          },
+          {
+            label: '上传时间',
+            prop: 'createTime'
+          }
+        ]
+      };
+    },
+    computed: {
+      fileList: {
+        set (val) {
+          // console.log(val);
+          this.$emit(
+            'input',
+            val.map((item) => ({
+              ...item,
+              url: getImagePath(item.url)
+            }))
+          );
+        },
+        get () {
+          // console.log(this.value, 2);
+          if(!Array.isArray(this.value)) return []
+          const arr =
+            (this.value &&
+              this.value.map((item) => ({
+                ...item,
+                url: getImageUrl(item.url)
+              }))) ||
+            [];
+          return arr;
+        }
+      }
+    },
+
+    methods: {
+      //点击查看图片
+      handleItem(file){
+
+       getFile({ objectName: file.storePath }, file.name);
+      },
+      delFileList () {
+        this.$emit('input', []);
+      },
+      handleOpenLib () {
+        this.documentVisible = true;
+        this.$nextTick(() => {
+          this.reload();
+        });
+      },
+      //图文档勾选
+      submitDocument () {
+        this.$emit('input', [
+          { url: this.selectItem.storePath, ...this.selectItem }
+        ]);
+        this.documentVisible = false;
+      },
+      datasource ({ page, limit }) {
+        return getFileList({
+          ...this.documentForm,
+          pageNum: page,
+          size: limit
+        });
+      },
+      reload () {
+        this.$refs.table.reload();
+      },
+      beforeRemove (file) {
+        if (file.id) {
+          return removeFile({
+            fileId: file.id
+          }).then(() => {
+            return true;
+          });
+        } else {
+          return true;
+        }
+      },
+      handleRemove (file, fileList) {
+        this.fileList = fileList;
+      },
+      beforeUpload (file) {
+        if (file.size / 1024 / 1024 > this.size) {
+          this.$message.error(`大小不能超过 ${this.size}MB`);
+          return false;
+        }
+
+        if (this.limit > 0 && this.fileList.length === this.limit) {
+          this.$message.error(`最多上传 ${this.limit}个文件`);
+          return false;
+        }
+        console.log(file);
+        return uploadFile({
+          module: this.module,
+          multiPartFile: file
+        }).then((res) => {
+          if (res.data) {
+            this.$emit('input', [
+              ...(this.value || []),
+              { ...file, url: res.data.storePath, ...res.data }
+            ]);
+          }
+          return res.data;
+        });
+      },
+      handlRequest () {
+        return Promise.resolve();
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .upload-file {
+    display: flex;
+    justify-content: flex-start;
+    align-items: center;
+
+    .lib {
+      margin-left: 12px;
+    }
+
+    .imgs-box {
+      margin-left: 10px;
+      flex: 1;
+    }
+    .imgs-box .imgs-p {
+      height: 30px;
+      background: #f0f3f3;
+      line-height: 30px;
+      min-width: 480px;
+      margin-bottom: 5px;
+      padding: 0 10px;
+      display: flex;
+      justify-content: space-between;
+    }
+  }
+</style>

+ 106 - 0
src/components/upload/imgUpload.vue

@@ -0,0 +1,106 @@
+<template>
+  <ele-image-upload
+    v-model="images"
+    :limit="limit"
+    :drag="true"
+    :multiple="true"
+    :upload-handler="uploadHandler"
+    :beforeUpload="beforeUpload"
+    @upload="onUpload"
+  >
+  </ele-image-upload>
+</template>
+
+<script>
+  import EleImageUpload from 'ele-admin/es/ele-image-upload';
+  import { getImageUrl, getImagePath } from '@/utils/file';
+  import { uploadFile } from '@/api/system/file/index';
+
+  export default {
+    components: { EleImageUpload },
+    props: {
+      // 所属模块
+      module: {
+        type: String,
+        default: 'main'
+      },
+      // 限制数量
+      limit: {
+        type: Number,
+        default: -1
+      },
+      value: {
+        type: Array,
+        default: () => []
+      }
+    },
+    data () {
+      return {};
+    },
+    computed: {
+      images: {
+        set (val) {
+          this.$emit(
+            'input',
+            val.map((item) => ({
+              ...item,
+              url: getImagePath(item.url)
+            }))
+          );
+        },
+        get () {
+          const arr =
+            (this.value &&
+              this.value.map((item) => ({
+                ...item,
+                url: getImageUrl(item.url)
+              }))) ||
+            [];
+
+          return arr;
+        }
+      }
+    },
+    methods: {
+      // beforeUpload(){},
+      /* 上传事件 */
+      uploadHandler (file) {
+        const item = {
+          file,
+          uid: file.uid,
+          name: file.name,
+          progress: 0,
+          status: null
+        };
+        if (!file.type.startsWith('image')) {
+          this.$message.error('只能选择图片');
+          return;
+        }
+        if (file.size / 1024 / 1024 > 2) {
+          this.$message.error('大小不能超过 2MB');
+          return;
+        }
+        this.$emit('input', [...this.value, item]);
+        this.onUpload(item);
+      },
+      /* 上传 item */
+      async onUpload (item) {
+        // 模拟上传
+        item.status = 'uploading';
+        item.progress = 20;
+
+        const res = await uploadFile({
+          module: this.module,
+          multiPartFile: item.file
+        });
+        if (res.data) {
+          item.url = res.data.storePath;
+          item.id = res.data.id;
+
+          item.progress === 100;
+          item.status = 'done';
+        }
+      }
+    }
+  };
+</script>

+ 131 - 0
src/components/upload/import-dialog.vue

@@ -0,0 +1,131 @@
+<template>
+  <!-- 上传 -->
+  <el-dialog title="导入文件上传" :visible.sync="dialogVisible" width="40%">
+    <el-form label-width="110px" class="zw-criterion">
+      <el-form-item label="选择文件">
+        <el-upload
+          class="avatar-uploader"
+          action="#"
+          :show-file-list="false"
+          :http-request="handlSuccess"
+          :before-upload="beforeUpload"
+        >
+          <el-button icon="el-icon-plus" size="small" type="primary"
+            >文件上传</el-button
+          >
+          <div slot="tip" class="el-upload__tip">
+            只能上传excel文件,点击
+            <el-link
+              type="primary"
+              :underline="false"
+              @click="downLoadTemplate()"
+            >
+              下载模板</el-link
+            >
+          </div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item label="上传列表">
+        <div class="imgs-box">
+          <p v-for="(item, index) in attaments" :key="index" class="imgs-p">
+            <span> {{ item.name }}</span>
+            <el-link @click="delFileList(index)" type="primary">删除</el-link>
+          </p>
+        </div>
+      </el-form-item>
+    </el-form>
+    <div slot="footer" class="dialog-footer">
+      <el-button size="small" @click="dialogVisible = false">关 闭</el-button>
+      <el-button size="small" @click="upload" type="primary">上 传</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { importBatch,downLoadTemplate } from '@/api/system/file/index.js';
+
+export default {
+  props: {
+    // eslint-disable-next-line vue/require-prop-type-constructor
+    defModule: ''
+  },
+  //注册组件
+  data() {
+    return {
+      showViewer: false, // 显示查看器
+      dialogVisible: false,
+      uploadShow: false,
+      module: '',
+      attaments: [], //上传文件
+      file: ''
+    };
+  },
+  created() {},
+  methods: {
+    open() {
+      this.attaments = [];
+      this.module = '';
+      this.dialogVisible = true;
+    },
+    //删除附件
+    delFileList(index) {
+      this.attaments.splice(index, 1);
+    },
+    //上传限制
+    beforeUpload(file) {
+      const isLt10M = file.size / 1024 / 1024 < 10;
+      if (!isLt10M) {
+        this.$message.error('导入单文件大小不能超过 10MB!');
+      }
+      return isLt10M;
+    },
+    //图片上传
+    handlSuccess(param) {
+      this.file = param.file;
+      this.attaments.push(param.file);
+    },
+    // 文件上传
+    async upload() {
+      if (this.attaments.length == 0) {
+        return this.$message.warning('文件不能为空!');
+      }
+      this.module = this.$props.defModule;
+
+      await importBatch({
+        module: this.module,
+        multiPartFiles: this.attaments
+      });
+      this.$message.success('操作成功!');
+      this.dialogVisible = false;
+      this.$emit('success');
+    },
+    //下载模板
+    downLoadTemplate(){
+      downLoadTemplate()
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+.zw-table-header {
+  float: right;
+}
+
+.imgs-box .imgs-p {
+  height: 30px;
+  background: #f0f3f3;
+  line-height: 30px;
+  width: 372px;
+  margin-bottom: 5px;
+  padding: 0 10px;
+  display: flex;
+  justify-content: space-between;
+}
+.zw-criterion-normal {
+  padding: 20px 0 0 0;
+}
+.el-main {
+  overflow: hidden;
+}
+</style>

+ 137 - 0
src/components/upload/import-dialogNew.vue

@@ -0,0 +1,137 @@
+<template>
+  <!-- 上传 -->
+  <el-dialog title="导入文件上传" :visible.sync="dialogVisible" width="40%">
+    <el-form label-width="110px" class="zw-criterion">
+      <el-form-item label="选择文件">
+        <el-upload
+          class="avatar-uploader"
+          action="#"
+          :show-file-list="false"
+          :http-request="handlSuccess"
+          :before-upload="beforeUpload"
+          :multiple="true"
+        >
+          <el-button icon="el-icon-plus" size="small" type="primary"
+            >文件上传</el-button
+          >
+          <div slot="tip" class="el-upload__tip" v-if="fileUrl">
+            只能上传excel文件,点击
+            <el-link
+              type="primary"
+              :underline="false"
+              @click="downLoadTemplate()"
+            >
+              下载模板</el-link
+            >
+          </div>
+        </el-upload>
+      </el-form-item>
+      <el-form-item label="上传列表">
+        <div class="imgs-box">
+          <p v-for="(item, index) in attaments" :key="index" class="imgs-p">
+            <span> {{ item.name }}</span>
+            <el-link @click="delFileList(index)" type="primary">删除</el-link>
+          </p>
+        </div>
+      </el-form-item>
+    </el-form>
+    <div slot="footer" class="dialog-footer">
+      <el-button size="small" @click="dialogVisible = false">关 闭</el-button>
+      <el-button size="small" @click="upload" type="primary">上 传</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+  import { importBatch } from '@/api/system/file/index.js';
+  // import { download1 } from '@/utils/file';
+  import {downLoadTemplateNew } from '@/api/system/file/index.js';
+  export default {
+    props: {
+      // eslint-disable-next-line vue/require-prop-type-constructor
+      defModule: '',
+      fileUrl: '',
+      fileName: '',
+      apiUrl: ''
+    },
+    //注册组件
+    data() {
+      return {
+        showViewer: false, // 显示查看器
+        dialogVisible: false,
+        uploadShow: false,
+        module: '',
+        attaments: [], //上传文件
+        file: ''
+      };
+    },
+
+    created() {},
+    methods: {
+      open() {
+        this.attaments = [];
+        this.module = '';
+        this.dialogVisible = true;
+      },
+      //删除附件
+      delFileList(index) {
+        this.attaments.splice(index, 1);
+      },
+      //上传限制
+      beforeUpload(file) {
+        const isLt10M = file.size / 1024 / 1024 < 10;
+        if (!isLt10M) {
+          this.$message.error('导入单文件大小不能超过 10MB!');
+        }
+        return isLt10M;
+      },
+      //图片上传
+      handlSuccess(param) {
+        this.file = param.file;
+        this.attaments.push(param.file);
+      },
+      // 文件上传
+      async upload() {
+        if (this.attaments.length == 0) {
+          return this.$message.warning('文件不能为空!');
+        }
+        this.module = this.$props.defModule;
+
+        await importBatch({
+          module: this.module,
+          multiPartFiles: this.attaments
+        });
+        this.$message.success('操作成功!');
+        this.dialogVisible = false;
+        this.$emit('success');
+      },
+      //下载模板
+      downLoadTemplate() {
+        downLoadTemplateNew(this.fileUrl, this.fileName);
+      }
+    }
+  };
+</script>
+
+<style lang="scss">
+  .zw-table-header {
+    float: right;
+  }
+
+  .imgs-box .imgs-p {
+    height: 30px;
+    background: #f0f3f3;
+    line-height: 30px;
+    width: 372px;
+    margin-bottom: 5px;
+    padding: 0 10px;
+    display: flex;
+    justify-content: space-between;
+  }
+  .zw-criterion-normal {
+    padding: 20px 0 0 0;
+  }
+  .el-main {
+    overflow: hidden;
+  }
+</style>

+ 109 - 3
src/views/warehouseManagement/stockLedger/components/item-list.vue

@@ -33,6 +33,37 @@
         >
           打印条码
         </el-button>
+
+        <div class="upload">
+          <!-- <el-upload
+            v-if="!isLoading"
+            :show-file-list="false"
+            class="upload-demo"
+            action=""
+            :before-upload="beforeUpload"
+            :on-success="successUpload"
+            :on-error="errorUpload"
+          >
+            <slot>
+              <el-button
+                type="primary"
+                size="small"
+                plain
+                icon="el-icon-upload2"
+                >导入</el-button
+              >
+            </slot>
+          </el-upload> -->
+          <el-button
+            type="primary"
+            size="small"
+            icon="el-icon-upload2"
+            plain
+            @click="uploadFile"
+            >导入</el-button
+          >
+        </div>
+
         <!-- <el-button
           v-if="selectedDime == 2 || selectedDime == 3"
           size="small"
@@ -149,12 +180,42 @@
     <!-- <printSr ref="printSrRef" :dimension="selectedDime"></printSr>
     <printTg ref="printTgRef" :dimension="selectedDime"></printTg> -->
     <allot ref="allotRef" :dimension="selectedDime"></allot>
+
+    <!-- 导入错误弹框 -->
+    <el-dialog
+      title="导入失败"
+      :visible.sync="exportErrorDioalogVisible"
+      width="60%"
+    >
+      <el-table :data="errorData" style="width: 100%">
+        <el-table-column label="名称" prop="name"> </el-table-column>
+        <el-table-column label="型号" prop="modeType"> </el-table-column>
+        <el-table-column label="编号" prop="codeNo"> </el-table-column>
+        <el-table-column label="物料组" prop="code"> </el-table-column>
+        <el-table-column label="失败原因" prop="remark"> </el-table-column>
+      </el-table>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="exportErrorDioalogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="exportErrorDioalogVisible = false"
+          >确 定</el-button
+        >
+      </span>
+    </el-dialog>
+
+    <importDialog
+      :defModule="moudleName"
+      ref="importDialogRef"
+      :fileUrl="'/wms/outintwo/importTemplate'"
+      fileName="库存导入模板"
+      @success="reload"
+    />
   </div>
 </template>
 
 <script>
   import print from '@/components/print/indexMultiple.vue';
   import allot from './allot.vue';
+  import importDialog from '@/components/upload/import-dialogNew.vue';
   // import print from './print.vue';
   // import printSr from './printSr.vue';
   // import printTg from './printTg.vue';
@@ -178,7 +239,7 @@
 
   export default {
     mixins: [tabMixins],
-    components: { ItemSearch, print, allot },
+    components: { ItemSearch, print, allot, importDialog },
     props: {
       // 机构id
       organizationId: [Number, String],
@@ -195,6 +256,7 @@
     },
     data() {
       return {
+        moudleName: 'stock',
         qualityStatus,
         qualityResults,
         config: [],
@@ -209,7 +271,10 @@
         diffCacheKeyUrl:
           'eos-439decaa-warehouseManagement-stockLedger-products',
         cacheKeyUrl: 'eos-439decaa-warehouseManagement-stockLedger-products2', //默认查询key值
-        columnsVersion: 1
+        columnsVersion: 1,
+        isLoading: false,
+        exportErrorDioalogVisible: false,
+        errorData: []
       };
     },
     created() {
@@ -705,7 +770,40 @@
             categoryCode: row.categoryCode
           }
         });
-      }
+      },
+      beforeUpload(file) {
+        if (file.size / 1024 / 1024 > this.size) {
+          this.$message.error(`大小不能超过 ${this.size}MB`);
+          return false;
+        }
+
+        if (this.limit > 0 && this.fileList.length === this.limit) {
+          this.$message.error(`最多上传 ${this.limit}个文件`);
+          return false;
+        }
+        let formData = new FormData();
+        formData.append('file', file);
+        this.isLoading = true;
+        return importCategorySparePart(formData).then((res) => {
+          if (res.data.length > 0) {
+            this.exportErrorDioalogVisible = true;
+            this.errorData = res.data;
+          } else {
+            this.$message.success('导入成功!');
+          }
+          this.isLoading = false;
+          return false;
+        });
+      },
+      successUpload(response) {
+        this.isLoading = false;
+      },
+      errorUpload(response) {
+        this.isLoading = false;
+      },
+       uploadFile() {
+        this.$refs.importDialogRef.open();
+      },
     },
 
     watch: {
@@ -728,3 +826,11 @@
     }
   };
 </script>
+
+<style lang="scss" scoped>
+  .upload {
+    display: inline-block;
+    width: 100px;
+    margin-left: 10px;
+  }
+</style>