Browse Source

feat:app版本管理

maliang 3 tuần trước cách đây
mục cha
commit
c1187dfb9f

+ 87 - 0
jshERP-web/src/views/system/AppVersionList.vue

@@ -0,0 +1,87 @@
+<template>
+  <a-row :gutter="24">
+    <a-col :md="24">
+      <a-card :style="cardStyle" :bordered="false">
+        <!-- 操作按钮区域 -->
+        <div class="table-operator" style="margin-top: 5px">
+          <a-button @click="handleAdd" type="primary" icon="plus">发布新版本</a-button>
+        </div>
+        <!-- table区域-begin -->
+        <div>
+          <a-table
+            ref="table"
+            size="middle"
+            bordered
+            rowKey="id"
+            :columns="columns"
+            :dataSource="dataSource"
+            :pagination="ipagination"
+            :scroll="scroll"
+            :loading="loading"
+            @change="handleTableChange"
+          >
+          </a-table>
+        </div>
+        <!-- table区域-end -->
+        <!-- 表单区域 -->
+        <app-version-modal ref="modalForm" @ok="modalFormOk"></app-version-modal>
+      </a-card>
+    </a-col>
+  </a-row>
+</template>
+<script>
+import AppVersionModal from './modules/AppVersionModal'
+import { JeecgListMixin } from '@/mixins/JeecgListMixin'
+import { postAction } from '@/api/manage'
+
+export default {
+  name: 'AppVersionList',
+  mixins: [JeecgListMixin],
+  components: {
+    AppVersionModal,
+  },
+  data() {
+    return {
+      // 表头
+      columns: [
+        { title: '版本号', dataIndex: 'version', },
+        { title: '发布时间', dataIndex: 'createTime', },
+        { title: '文件路径', dataIndex: 'url',},
+      ],
+      url: {
+        list: '/apkVersion/list',
+      },
+    }
+  },
+  computed: {},
+  methods: {
+    loadData(arg) {
+      if (!this.url.list) {
+        this.$message.error('请设置url.list属性!')
+        return
+      }
+      //加载数据 若传入参数1则加载第一页的内容
+      if (arg === 1) {
+        this.ipagination.current = 1
+      }
+      this.loading = true
+      postAction(this.url.list, {}).then((res) => {
+        if (res.code === 200) {
+          this.dataSource = res.data.rows
+          this.ipagination.total = Number(res.data.total)
+          this.tableAddTotalRow(this.columns, this.dataSource)
+        } else if (res.code === 510) {
+          this.$message.warning(res.data)
+        } else {
+          this.$message.warning(res.data.message)
+        }
+        this.loading = false
+        this.onClearSelected()
+      })
+    },
+  },
+}
+</script>
+<style scoped>
+@import '~@assets/less/common.less';
+</style>

+ 293 - 0
jshERP-web/src/views/system/modules/AppVersionModal.vue

@@ -0,0 +1,293 @@
+<template>
+  <div ref="container">
+    <a-modal
+      title="发布新版本"
+      :visible="visible"
+      :confirmLoading="confirmLoading"
+      :getContainer="() => $refs.container"
+      :maskStyle="{ top: '93px', left: '154px' }"
+      :wrapClassName="wrapClassNameInfo()"
+      :mask="isDesktop()"
+      :maskClosable="false"
+      @cancel="handleCancel"
+      :footer="null"
+      width="500px"
+      style="top: 5%"
+    >
+      <a-spin :spinning="confirmLoading">
+        <a-form :form="form" class="form-content" id="appVersionModal">
+          <a-form-item label="版本号" :labelCol="labelCol" :wrapperCol="wrapperCol">
+            <a-input placeholder="请输入" allowClear v-decorator="['version', validatorRules.version]" />
+          </a-form-item>
+          
+          <a-form-item label="上传文件" :labelCol="labelCol" :wrapperCol="wrapperCol">
+            <div class="upload-container">
+              <a-upload
+                name="file"
+                :data="uploadOpts.data"
+                :showUploadList="true"
+                :multiple="false"
+                :headers="uploadOpts.headers"
+                :action="uploadOpts.action"
+                :method="uploadOpts.method"
+                :accept="uploadOpts.accept"
+                :fileList="fileList"
+                @change="handleChange"
+                :beforeUpload="beforeUpload"
+                @reject="handleReject"
+              >
+                <div class="upload-content">
+                  <div class="upload-icon">
+                    <a-icon type="folder-open" style="color: #4e73f8; font-size: 32px;" />
+                  </div>
+                  <a-button type="primary" class="upload-button">上传文件</a-button>
+                </div>
+              </a-upload>
+            </div>
+          </a-form-item>
+          
+          <div class="form-actions">
+            <a-button @click="handleCancel" class="cancel-button">取消</a-button>
+            <a-button type="primary" @click="handleOk" :loading="confirmLoading" class="confirm-button">确定发布新版本</a-button>
+          </div>
+        </a-form>
+      </a-spin>
+    </a-modal>
+  </div>
+</template>
+<script>
+import Vue from 'vue'
+import { ACCESS_TOKEN } from '@/store/mutation-types'
+import pick from 'lodash.pick'
+import { autoJumpNextInput } from '@/utils/util'
+import { mixinDevice } from '@/utils/mixin'
+import { postAction } from '@/api/manage'
+
+export default {
+  name: 'AppVersionModal',
+  mixins: [mixinDevice],
+  data() {
+    return {
+      visible: false,
+      confirmLoading: false,
+      labelCol: { span: 4 },
+      wrapperCol: { span: 20 },
+      fileList: [],
+      validatorRules: {
+        version: {
+          rules: [
+            { required: true, message: '请输入版本号!' },
+            { pattern: /^\d+\.\d+\.\d+$/, message: '版本号格式不正确!' }
+          ]
+        },
+        url: {
+          rules: [
+            { required: true, message: '请上传.apk文件!' }
+          ]
+        }
+      },
+      form: this.$form.createForm(this),
+      model: {},
+      uploadOpts:{
+        headers: {
+          'X-Access-Token': Vue.ls.get(ACCESS_TOKEN)
+        },
+        method: 'POST',
+        action: window._CONFIG['domianURL'] + '/apkVersion/upload',
+        accept: '.apk',
+        data:{
+          biz: 'bill' 
+        }
+      },
+    }
+  },
+  methods: {
+    add() {
+      this.edit({})
+    },
+    edit(record) {
+      this.form.resetFields()
+      this.model = Object.assign({}, record)
+      this.fileList = []
+      this.visible = true
+      this.$nextTick(() => {
+        this.form.setFieldsValue(
+          pick(
+            this.model,
+            'url',
+            'version'
+          )
+        )
+        autoJumpNextInput('appVersionModal')
+      })
+    },
+    beforeUpload(file) {
+      // 检查文件类型
+      const isAPK = file.type === 'application/vnd.android.package-archive' || file.name.endsWith('.apk')
+      if (!isAPK) {
+        this.$message.error('只能上传APK文件!')
+        return false
+      }
+      
+      // 阻止自动上传
+      return true
+    },
+    handleChange(info) {
+      this.fileList = [info.file]
+      console.log('文件列表:', this.fileList)
+      if (info.file.status === 'uploading') {
+        console.log(info.file, info.fileList)
+        this.confirmLoading = true
+      }else if(info.file.status === 'removed'){
+        this.fileList = []
+        this.model.url = ''
+      }else if (info.file.status === 'done') {
+        this.confirmLoading = false
+        console.log('model=====', this.model)
+        if (info.file.response) {
+          if (info.file.response.code === 200) {
+            info.file.name = info.file.response.data
+            this.model.url = info.file.response.data
+          } else {
+            this.$message.warning(info.file.response.data, 8)
+          }
+        } else {
+          this.$message.error(`${info.file.name} ${info.file.response.data}.`)
+        }
+      } else if (info.file.status === 'error') {
+        this.confirmLoading = false
+        this.$message.error(`文件上传失败: ${info.file.msg} `)
+      }
+    },
+    handleReject(file) {
+      console.log('文件类型不正确:', file)
+      this.$message.error('文件类型不正确,请上传.apk文件!')
+    },
+    handleOk() {
+      this.form.validateFields((err, values) => {
+        if (err) return
+        console.log('values======',values)
+        if (this.fileList.length === 0) {
+          this.$message.error('请上传.apk类型文件!')
+          return
+        }
+        
+        const formData = {
+          version: values.version,
+          url: this.fileList[0].name // 实际应用中这里应该是上传后的URL
+        }
+        
+        this.confirmLoading = true
+        
+        postAction('/apkVersion/add', formData).then(res => {
+          if (res.code === 200) {
+            this.$message.success(res.msg)
+            this.visible = false
+            this.$emit('ok', formData)
+          } else {
+            this.$message.error(res.data||'操作失败')
+          }
+        }).catch(err => {
+          console.error(err)
+        }).finally(() => {
+          this.confirmLoading = false
+        })
+      })
+    },
+    handleCancel() {
+      this.visible = false
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.form-content {
+  padding: 0 10px;
+}
+
+.upload-container {
+  border: 1px dashed #d9d9d9;
+  border-radius: 4px;
+  padding: 24px;
+  background-color: #fafafa;
+}
+
+.upload-content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  padding: 10px 0;
+}
+
+.upload-icon {
+  margin-bottom: 16px;
+}
+
+.upload-button {
+  height: 32px;
+  font-size: 14px;
+  border-radius: 4px;
+  background-color: #4e73f8;
+  border-color: #4e73f8;
+}
+
+.reupload-button {
+  background-color: #4e73f8;
+  border-color: #4e73f8;
+}
+
+.form-actions {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 24px;
+  
+  .cancel-button {
+    margin-right: 12px;
+    min-width: 80px;
+    height: 32px;
+  }
+  
+  .confirm-button {
+    background-color: #4e73f8;
+    border-color: #4e73f8;
+    min-width: 120px;
+    height: 32px;
+  }
+}
+
+/deep/ .ant-upload.ant-upload-select {
+  display: block;
+}
+
+/deep/ .ant-upload-list-item {
+  margin-top: 8px;
+}
+
+/deep/ .ant-form-item-label {
+  text-align: left;
+  line-height: 32px;
+}
+
+/deep/ .ant-form-item {
+  margin-bottom: 24px;
+}
+
+/deep/ .ant-modal-close-x {
+  width: 46px;
+  height: 46px;
+  line-height: 46px;
+}
+
+/deep/ .ant-modal-body {
+  padding: 16px 24px 24px;
+}
+
+/deep/ .ant-form-item-control {
+  line-height: 32px;
+}
+
+/deep/ .ant-input {
+  height: 32px;
+}
+</style>