Browse Source

客户端配置修改

Administrator 6 tháng trước cách đây
mục cha
commit
a5a02777c8

+ 46 - 0
src/api/clientConfig.ts

@@ -0,0 +1,46 @@
+import request from './request'
+
+
+export default {
+
+    add(data) {
+        return request({
+            url: '/client_config/add',
+            method: 'post',
+            data
+        });
+    },
+
+    query(data) {
+        return request({
+            url: '/client_config/query',
+            method: 'post',
+            data
+        });
+    },
+
+    update(data) {
+        return request({
+            url: '/client_config/update',
+            method: 'put',
+            data
+        });
+    },
+
+    delete(data) {
+        return request({
+            url: '/client_config/delete',
+            method: 'delete',
+            data
+        });
+    },
+
+    deleteBatch(data) {
+        return request({
+            url: '/client_config/delete_batch',
+            method: 'delete',  
+            data
+        });
+    }
+
+}

+ 8 - 1
src/routers/modules/operation.ts

@@ -53,6 +53,7 @@ const operationRouter = [{
             name: 'gmmail',
             meta: { title: 'GM邮件', keepAlive: true , icon: 'Message'}
         },
+   
         {
             path: '/operation/announcement',
             component: () => import('@/views/operation/announcement/index.vue'),
@@ -64,7 +65,13 @@ const operationRouter = [{
           component: () => import('@/views/operation/sendcmd/index.vue'),
           name: 'sendcmd',
           meta: { title: '发送命令', keepAlive: true  , icon: 'Monitor'}
-      },
+        },
+        {
+            path: '/operation/clientConfig',
+            component: () => import('@/views/operation/clientConfig/index.vue'),
+            name: 'clientConfig',
+            meta: { title: '客户端配置', keepAlive: true  , icon: 'Setting'}
+        }
     ]
 }]
 

+ 440 - 0
src/views/operation/clientConfig/index.vue

@@ -0,0 +1,440 @@
+<template>
+  <div class="app-container" ref="appContainer">
+    <PropTable :loading="loading" @selection-change="selectionChange" :columns="column" :data="list" @reset="reset"
+      @onSubmit="onSubmit">
+      <template v-slot:btn>
+        <div style="display: flex; justify-content: flex-end">
+          <el-button type="primary" @click="add"><el-icon>
+              <plus />
+            </el-icon>添加</el-button>
+          <el-button type="danger" @click="batchDelete"><el-icon>
+              <delete />
+            </el-icon>删除</el-button>
+        </div>
+      </template>
+      <template v-slot:loadType="scope">{{ getLoadTypeLabel(scope.row.loadType) }}</template>
+      <template v-slot:operation="scope">
+        <el-button type="primary" size="small" icon="Edit" @click="edit(scope.row)">
+          编辑
+        </el-button>
+        <el-button @click="del(scope.row)" type="danger" size="small" icon="Delete">
+          删除
+        </el-button>
+      </template>
+    </PropTable>
+
+    <el-dialog v-model="dialogVisible" :title='title' width="50%">
+      <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="120px" class="demo-ruleForm"
+        :size="formSize">
+        <el-form-item label="ID" prop="id">
+          <el-input v-model="ruleForm.id" />
+        </el-form-item>
+        <el-form-item label="资源地址" prop="assetsUrl">
+          <el-input v-model="ruleForm.assetsUrl" />
+        </el-form-item>
+        <el-form-item label="资源版本号" prop="assetsVer">
+          <el-input v-model="ruleForm.assetsVer" />
+        </el-form-item>
+        <el-form-item label="资源加载类型" prop="loadType">
+          <el-radio-group v-model="ruleForm.loadType">
+            <el-radio :label="0">远程加载</el-radio>
+            <el-radio :label="1">本地加载</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="安装包版本号" prop="apkVer">
+          <el-input v-model="ruleForm.apkVer" />
+        </el-form-item>
+        <el-form-item label="打包版本号" prop="buildVer">
+          <el-input v-model="ruleForm.buildVer" />
+        </el-form-item>
+        <el-form-item label="协议版本号" prop="protocolVer">
+          <el-input v-model="ruleForm.protocolVer" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="dialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="handleClose(ruleFormRef)">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+<script lang="ts" setup name="comprehensive">
+import { ref, reactive, onMounted, nextTick, onBeforeMount } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import type { FormInstance } from 'element-plus'
+import clientConfigApi from '@/api/clientConfig'
+import dateUtils from '@/common/dateUtils'
+
+const loading = ref(true)
+const appContainer = ref(null)
+import PropTable from '@/components/Table/PropTable/index.vue'
+
+// import { ref } from 'vue'
+
+import ExcelJS from 'exceljs'
+import { UploadFilled } from '@element-plus/icons-vue'
+import type { UploadProps, UploadInstance } from 'element-plus'
+// import { ElMessage } from 'element-plus'
+const tableData = ref([])
+const tableHeader = ref([])
+const upload = ref<UploadInstance>()
+
+const tableColumn = ["title","type","validTime","invalidTime","content"]
+const beforeUploadAction = (file, fileLi) => {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader()
+    reader.onload = async (e) => {
+      const data = e.target.result
+      const workbook = new ExcelJS.Workbook()
+      try {
+        let res = await workbook.xlsx.load(data)
+        const sheets =
+          res._worksheets && res._worksheets.filter((item) => typeof item !== 'undefined')
+        const table = []
+        let headers = []
+        sheets.forEach((sheet) => {
+          sheet._rows.forEach((row, index) => {
+            if (index === 0) {
+              row.values.forEach((it, i) => {
+                // console.log("string" + it + " " + i + "" + tableColumn[i])
+                headers.push({label: it, value: tableColumn[i - 1]})
+              })
+            } else {
+              let obj = {}
+              let arr = []
+              row.values.forEach((it) => {
+                arr.push(it)
+              })
+              tableColumn.forEach((ite, i) => {
+                if (arr[i] == undefined)  {
+                  obj[ite] = null
+                } else {
+                  obj[ite] = arr[i]
+                }
+              })
+              table.push(obj)
+            }
+            // const tableRow = {
+            //   position: "",
+            //   val: "",
+            // };
+            // row._cells.forEach((cell) => {
+            //   tableRow.position = cell._address;
+            //   tableRow.val = cell._value.model.value || "";
+            // });
+          })
+        })
+        tableData.value = table
+        tableHeader.value = headers
+        console.log("table", table)
+        console.log("headers", headers)
+      } catch (e) {
+        ElMessage.error('解析失败')
+      }
+    }
+    reader.readAsArrayBuffer(file)
+  })
+}
+
+const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
+  tableData.value = null
+  tableHeader.value = null
+}
+
+const data = ref([])
+let currPageNum = 1;
+const pageSize = 1000;
+onBeforeMount(() => {
+  loadClientConfigInfo()
+})
+
+const loadClientConfigInfo = () => {
+  let queryParams = reactive({
+    pageNum: currPageNum,
+    pageSize: pageSize
+  })
+  clientConfigApi.query(queryParams).then(res => {
+    data.value = res.data.result;
+    console.log(data)
+  })
+}
+
+const column = [
+  { type: 'selection', width: 60, fixed: 'left' },
+  { name: 'id', label: 'ID', width: 80, inSearch: true, valueType: 'input' },
+  { name: 'assetsUrl', label: '资源地址' },
+  { name: 'assetsVer', label: '资源版本号' },
+  { name: 'loadType', label: '资源加载类型', slot: true},
+  { name: 'apkVer', label: '安装包版本号' },
+  { name: 'buildVer', label: '打包版本号' },
+  { name: 'protocolVer', label: '协议版本号' },
+  { name: 'operation', slot: true, fixed: 'right', width: 200, label: '操作' },
+]
+
+const getLoadTypeLabel = (val) => {
+  if (val == 0) {
+    return '远程加载'
+  } else if (val == 1) {
+    return '本地加载'
+  }
+}
+
+const list = ref(data)
+
+const formSize = ref('default')
+const ruleFormRef = ref<FormInstance>()
+
+const ruleForm = reactive({
+    id: null,
+    assetsUrl: null,
+    assetsVer: null,
+    apkVer: null,
+    buildVer: null,
+    protocolVer: null,
+    loadType:0
+})
+
+const rules = reactive({
+  id: [
+    {
+      required: true,
+      message: '请输入ID',
+      trigger: 'change',
+    },
+  ],
+  assetsUrl: [
+    {
+      required: true,
+      message: '请输入资源地址',
+      trigger: 'change',
+    },
+  ],
+  assetsVer: [
+    {
+      required: true,
+      message: '请输入资源版本号',
+      trigger: 'change',
+    },
+  ]
+})
+
+const dialogVisible = ref(false)
+const importVisible = ref(false)
+
+const rowObj = ref({})
+const selectObj = ref([])
+const title = ref('详情')
+
+const add = () => {
+  title.value = '新增'
+  dialogVisible.value = true
+  ruleForm.id = null
+  ruleForm.assetsUrl = null
+  ruleForm.assetsVer = null
+  ruleForm.loadType = 0
+  ruleForm.apkVer = null
+  ruleForm.buildVer = null
+  ruleForm.protocolVer = null
+}
+
+const handleConfirm = () => {
+  // 验证table数据
+  // ...
+  let importParams = reactive({
+    importValue: tableData.value
+  })
+  clientConfigApi.importBatch(importParams).then(res => {
+    console.log('result', res)
+    if (res.data.code = 200) {
+      loadClientConfigInfo()
+      importVisible.value = false
+      return ElMessage.success(res.data.msg)
+    } else {
+      return ElMessage.error(res.data.msg)
+    }
+  })
+  console.log('import submit!')
+}
+
+const handleClose = async (done: () => void) => {
+  await ruleFormRef.value.validate((valid, fields) => {
+    if (valid) {
+      if (title.value == '新增') {
+        clientConfigApi.add(ruleForm).then(res => {
+          console.log('result', res)
+          if (res.data.code = 200) {
+            loadClientConfigInfo()
+            dialogVisible.value = false
+            return ElMessage.success(res.data.msg)
+          } else {
+            return ElMessage.error(res.data.msg)
+          }
+        })
+        console.log('add submit!')
+      } else {
+        // let updateParams = reactive({
+        //   id: rowObj.value.id,
+        //   updateValue: ruleForm
+        // })
+        clientConfigApi.update(ruleForm).then(res => {
+          if (res.data.code = 200) {
+            loadClientConfigInfo()
+            dialogVisible.value = false
+            return ElMessage.success('修改成功')
+          } else {
+            return ElMessage.error('修改失败')
+          }
+        })
+        console.log('update submit!')
+      }
+      console.log('submit!', ruleForm)
+    } else {
+      console.log('error submit!', fields)
+    }
+  })
+}
+
+const batchDelete = () => {
+  if (!selectObj.value.length) {
+    return ElMessage.error('未选中任何行')
+  }
+  ElMessageBox.confirm('你确定要删除选中项吗?', '温馨提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning',
+    draggable: true,
+  })
+    .then(() => {
+      let selectClientConfigIds = reactive([])
+      for (let value of selectObj.value) {
+        selectClientConfigIds.push(value.id)
+      }
+      let deleteParams = reactive({
+        deleteIds: selectClientConfigIds
+      })
+      clientConfigApi.deleteBatch(deleteParams).then(res => {
+        loadClientConfigInfo()
+        ElMessage.success('批量删除成功')
+      })
+
+      list.value = list.value.concat([])
+    })
+    .catch(() => { })
+}
+
+
+const selectionChange = (val) => {
+  selectObj.value = val
+}
+
+const edit = (row) => {
+  title.value = '编辑'
+  rowObj.value = row
+  dialogVisible.value = true
+  ruleForm.id = row.id
+  ruleForm.assetsUrl = row.assetsUrl
+  ruleForm.assetsVer = row.assetsVer == null ? row.assetsVer : row.assetsVer.toString()
+  ruleForm.loadType = row.loadType
+  ruleForm.apkVer = row.apkVer == null ? row.apkVer : row.apkVer.toString()
+  ruleForm.buildVer = row.buildVer == null ? row.buildVer : row.buildVer.toString()
+  ruleForm.protocolVer = row.protocolVer == null ? row.protocolVer : row.protocolVer.toString()
+}
+
+const del = (row) => {
+  console.log('row==', row)
+  ElMessageBox.confirm('你确定要删除当前项吗?', '温馨提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning',
+    draggable: true,
+  })
+    .then(() => {
+      let deleteParams = reactive({
+        id: row.id
+      })
+      clientConfigApi.delete(deleteParams).then(res => {
+        loadClientConfigInfo()
+        ElMessage.success('删除成功')
+      })
+      loading.value = true
+      setTimeout(() => {
+        loading.value = false
+      }, 500)
+    })
+    .catch(() => { })
+}
+
+const reset = () => {
+  loadClientConfigInfo()
+  loading.value = true
+  setTimeout(() => {
+    loading.value = false
+  }, 500)
+  ElMessage.success('重置成功')
+}
+
+const onSubmit = (val) => {
+  if (val.id == null) {
+    ElMessage.warning('请输入查询条件')
+    return
+  }
+  let queryParams = reactive({
+    pageNum: 1,
+    pageSize: pageSize,
+    condition: val
+  })
+  clientConfigApi.query(queryParams).then(res => {
+    data.value = res.data.result;
+    console.log(data.value)
+  })
+  loading.value = true
+  setTimeout(() => {
+    loading.value = false
+  }, 500)
+}
+
+const getHeight = () => {
+
+}
+
+onMounted(() => {
+  nextTick(() => {
+    // let data = appContainer.value.
+  })
+  setTimeout(() => {
+    loading.value = false
+  }, 500)
+})
+</script>
+
+<style scoped>
+.edit-input {
+  padding-right: 100px;
+}
+
+.app-container {
+  flex: 1;
+  display: flex;
+  width: 100%;
+  padding: 16px;
+  box-sizing: border-box;
+}
+
+.cancel-btn {
+  position: absolute;
+  right: 15px;
+  top: 10px;
+}
+
+.m-upload-excel {
+  .el-upload {
+    width: 100%;
+  }
+
+  .el-upload-dragger {
+    width: 100%;
+  }
+}
+</style>