Переглянути джерело

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/view/fileManager/qiniuTransfer.vue
wangbin 3 роки тому
батько
коміт
491452a93d

+ 1 - 0
package.json

@@ -20,6 +20,7 @@
     "mitt": "^3.0.0",
     "path": "^0.12.7",
     "pinia": "^2.0.9",
+    "qiniu-js": "^3.4.1",
     "qs": "^6.8.0",
     "quill": "^1.3.7",
     "screenfull": "^5.0.2",

+ 64 - 1
src/api/fileManager.js

@@ -2,7 +2,7 @@
  * @Author: 倚楼听风雨 18408246387@163.com
  * @Date: 2023-01-09 16:01:45
  * @LastEditors: 倚楼听风雨 18408246387@163.com
- * @LastEditTime: 2023-02-24 14:28:05
+ * @LastEditTime: 2023-03-08 14:12:48
  * @FilePath: \log-server-web\src\api\rentComputer.js
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -29,3 +29,66 @@ export const getFolderFileList = (data) => {
     data,
   });
 };
+export const getQiniuToken = (data) => {
+  return service({
+    url: "/fileManager/getQiniuToken",
+    method: "post",
+    data,
+  });
+};
+export const getAllFileType = (data) => {
+  return service({
+    url: "/fileManager/getAllFileType",
+    method: "post",
+    data,
+  });
+};
+export const selectFolderMsg = (data) => {
+  return service({
+    url: "/fileManager/selectFolderMsg",
+    method: "post",
+    data,
+  });
+};
+export const queryVersionByType = (data) => {
+  return service({
+    url: "/fileManager/queryVersionByType",
+    method: "post",
+    data,
+  });
+};
+export const addQiniuFile = (data) => {
+  return service({
+    url: "/fileManager/addQiniuFile",
+    method: "post",
+    data,
+  });
+};
+export const deleteQiniuFile = (data) => {
+  return service({
+    url: "/fileManager/deleteQiniuFile",
+    method: "post",
+    data,
+  });
+};
+export const deleteQiniuFileAndRecord = (data) => {
+  return service({
+    url: "/fileManager/deleteQiniuFileAndRecord",
+    method: "post",
+    data,
+  });
+};
+export const renameQiniuFileAndRecord = (data) => {
+  return service({
+    url: "/fileManager/renameQiniuFileAndRecord",
+    method: "post",
+    data,
+  });
+};
+export const queryFolder = (data) => {
+  return service({
+    url: "/fileManager/queryFolder",
+    method: "post",
+    data,
+  });
+};

+ 24 - 0
src/api/upload.js

@@ -17,4 +17,28 @@ export const addFileUpdate = (data) => {
     method: 'post',
     data
   })
+}
+
+export const getGameTaskList = (data) => {
+  return service({
+    url: '/gameTask/getGameTaskList',
+    method: 'post',
+    data
+  })
+}
+
+export const getScriptList = (data) => {
+  return service({
+    url: '/gameTask/getScriptList',
+    method: 'post',
+    data
+  })
+}
+
+export const statusChange = (data) => {
+  return service({
+    url: '/gameTask/statusChange',
+    method: 'post',
+    data
+  })
 }

Різницю між файлами не показано, бо вона завелика
+ 1 - 0
src/assets/file_type_apk.svg


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
src/assets/file_type_dll.svg


BIN
src/assets/file_type_ld.png


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
src/assets/file_type_other.svg


BIN
src/assets/file_type_yeshen.webp


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
src/assets/not_selected.svg


Різницю між файлами не показано, бо вона завелика
+ 1 - 0
src/assets/selected.svg


+ 93 - 82
src/utils/request.js

@@ -1,135 +1,146 @@
-import axios from 'axios' // 引入axios
-import { ElMessage, ElMessageBox } from 'element-plus'
-import { useUserStore } from '@/pinia/modules/user'
-import { emitter } from '@/utils/bus.js'
-import router from '@/router/index'
+import axios from "axios"; // 引入axios
+import { ElMessage, ElMessageBox } from "element-plus";
+import { useUserStore } from "@/pinia/modules/user";
+import { emitter } from "@/utils/bus.js";
+import router from "@/router/index";
 
 const service = axios.create({
   baseURL: import.meta.env.VITE_BASE_API,
-  timeout: 99999
-})
-let acitveAxios = 0
-let timer
+  timeout: 99999,
+});
+let acitveAxios = 0;
+let timer;
 const showLoading = () => {
-  acitveAxios++
+  acitveAxios++;
   if (timer) {
-    clearTimeout(timer)
+    clearTimeout(timer);
   }
   timer = setTimeout(() => {
     if (acitveAxios > 0) {
-      emitter.emit('showLoading')
+      emitter.emit("showLoading");
     }
-  }, 400)
-}
+  }, 400);
+};
 
 const closeLoading = () => {
-  acitveAxios--
+  acitveAxios--;
   if (acitveAxios <= 0) {
-    clearTimeout(timer)
-    emitter.emit('closeLoading')
+    clearTimeout(timer);
+    emitter.emit("closeLoading");
   }
-}
+};
 // http request 拦截器
 service.interceptors.request.use(
-  config => {
+  (config) => {
     if (!config.donNotShowLoading) {
-      showLoading()
+      showLoading();
     }
-    const userStore = useUserStore()
+    const userStore = useUserStore();
     config.headers = {
-      'Content-Type': 'application/json',
-      'x-token': userStore.token,
-      'x-user-id': userStore.userInfo.ID,
-      ...config.headers
-    }
-    return config
+      "Content-Type": "application/json",
+      "x-token": userStore.token,
+      "x-user-id": userStore.userInfo.ID,
+      ...config.headers,
+    };
+    return config;
   },
-  error => {
-    closeLoading()
+  (error) => {
+    closeLoading();
     ElMessage({
       showClose: true,
       message: error,
-      type: 'error'
-    })
-    return error
+      type: "error",
+    });
+    return error;
   }
-)
+);
 
 // http response 拦截器
 service.interceptors.response.use(
-  response => {
-    const userStore = useUserStore()
-    closeLoading()
-    if (response.headers['new-token']) {
-      userStore.setToken(response.headers['new-token'])
+  (response) => {
+    const userStore = useUserStore();
+    closeLoading();
+    if (response.headers["new-token"]) {
+      userStore.setToken(response.headers["new-token"]);
     }
-    if (response.data.code === 0 || response.headers.success === 'true') {
+    if (response.data.code === 0 || response.headers.success === "true") {
       if (response.headers.msg) {
-        response.data.msg = decodeURI(response.headers.msg)
+        response.data.msg = decodeURI(response.headers.msg);
       }
-      return response.data
+      return response.data;
     } else {
       ElMessage({
         showClose: true,
         message: response.data.msg || decodeURI(response.headers.msg),
-        type: 'error'
-      })
+        type: "error",
+      });
       if (response.data.data && response.data.data.reload) {
-        userStore.token = ''
-        localStorage.clear()
-        router.push({ name: 'Login', replace: true })
+        userStore.token = "";
+        localStorage.clear();
+        router.push({ name: "Login", replace: true });
       }
-      return response.data.msg ? response.data : response
+      return response.data.msg ? response.data : response;
     }
   },
-  error => {
-    closeLoading()
+  (error) => {
+    closeLoading();
 
     if (!error.response) {
-      ElMessageBox.confirm(`
+      ElMessageBox.confirm(
+        `
         <p>检测到请求错误</p>
         <p>${error}</p>
-        `, '请求报错', {
-        dangerouslyUseHTMLString: true,
-        distinguishCancelAndClose: true,
-        confirmButtonText: '稍后重试',
-        cancelButtonText: '取消'
-      })
-      return
+        `,
+        "请求报错",
+        {
+          dangerouslyUseHTMLString: true,
+          distinguishCancelAndClose: true,
+          confirmButtonText: "稍后重试",
+          cancelButtonText: "取消",
+        }
+      );
+      return;
     }
 
     switch (error.response.status) {
       case 500:
-        ElMessageBox.confirm(`
+        ElMessageBox.confirm(
+          `
         <p>检测到接口错误${error}</p>
         <p>错误码<span style="color:red"> 500 </span>:此类错误内容常见于后台panic,请先查看后台日志,如果影响您正常使用可强制登出清理缓存</p>
-        `, '接口报错', {
-          dangerouslyUseHTMLString: true,
-          distinguishCancelAndClose: true,
-          confirmButtonText: '清理缓存',
-          cancelButtonText: '取消'
-        })
-          .then(() => {
-            const userStore = useUserStore()
-            userStore.token = ''
-            localStorage.clear()
-            router.push({ name: 'Login', replace: true })
-          })
-        break
+        `,
+          "接口报错",
+          {
+            dangerouslyUseHTMLString: true,
+            distinguishCancelAndClose: true,
+            confirmButtonText: "清理缓存",
+            cancelButtonText: "取消",
+          }
+        ).then(() => {
+          const userStore = useUserStore();
+          userStore.token = "";
+          localStorage.clear();
+          router.push({ name: "Login", replace: true });
+        });
+        break;
       case 404:
-        ElMessageBox.confirm(`
+        ElMessageBox.confirm(
+          `
           <p>检测到接口错误${error}</p>
           <p>错误码<span style="color:red"> 404 </span>:此类错误多为接口未注册(或未重启)或者请求路径(方法)与api路径(方法)不符--如果为自动化代码请检查是否存在空格</p>
-          `, '接口报错', {
-          dangerouslyUseHTMLString: true,
-          distinguishCancelAndClose: true,
-          confirmButtonText: '我知道了',
-          cancelButtonText: '取消'
-        })
-        break
+          `,
+          "接口报错",
+          {
+            dangerouslyUseHTMLString: true,
+            distinguishCancelAndClose: true,
+            confirmButtonText: "我知道了",
+            cancelButtonText: "取消",
+          }
+        );
+        break;
     }
 
-    return error
+    return error;
   }
-)
-export default service
+);
+export default service;

+ 28 - 21
src/view/dataStatistics/data_abnormal_rate.vue

@@ -64,7 +64,7 @@
           fixed="left"
           prop="new_date"
           label="日期"
-          min-width="80"
+          min-width="90"
           sortable
         />
         <el-table-column
@@ -103,6 +103,27 @@
           min-width="60"
           align="center"
         />
+        <el-table-column prop="" label="目标" min-width="60" align="center">
+          <el-table-column
+            prop="new_target"
+            label="新增"
+            min-width="60"
+            align="center"
+          />
+          <el-table-column
+            prop="retained_target"
+            label="留存"
+            min-width="60"
+            align="center"
+          />
+          <el-table-column
+            prop="pay_target"
+            label="付费"
+            min-width="60"
+            align="center"
+          />
+        </el-table-column>
+
         <el-table-column
           prop="num_pull_account"
           label="下发账号"
@@ -370,24 +391,6 @@ const shortcuts = [
   },
 ];
 
-const getSpanArr = (data) => {
-  spanArr = [];
-  var pos = 0;
-  for (var i = 0; i < data.length; i++) {
-    if (i === 0) {
-      spanArr.push(1);
-      pos = 0;
-    } else {
-      if (data[i].pc_code === data[i - 1].pc_code) {
-        spanArr[pos] += 1;
-        spanArr.push(0);
-      } else {
-        spanArr.push(1);
-        pos = i;
-      }
-    }
-  }
-};
 //获取下拉框list
 const getSelectList = async () => {
   //游戏负责人列表===============================
@@ -398,7 +401,9 @@ const getSelectList = async () => {
   ];
   const data3 = directorRes.data.list;
   data3.forEach((e) => {
-    directorList.push({ value: e.name, label: e.name });
+    if (e.name != "备用") {
+      directorList.push({ value: e.name, label: e.name });
+    }
   });
   directorOptions.value = directorList;
 };
@@ -524,10 +529,12 @@ const getTableData = async () => {
           rate3: rate3,
           rate4: rate4,
           rate5: rate5,
+          new_target: e.new_target,
+          pay_target: e.pay_target,
+          retained_target: e.retained_target,
         };
         tableData.value.push(obj1);
       });
-      getSpanArr(table.data.list);
     }
     // console.log(tableData);
     total.value = table.data.total;

+ 0 - 20
src/view/dataStatistics/wechat_scanner_api.vue

@@ -126,25 +126,6 @@ const disabledDate = (time) => {
   return time.getTime() > Date.now();
 };
 
-const getSpanArr = (data) => {
-  spanArr = [];
-  var pos = 0;
-  for (var i = 0; i < data.length; i++) {
-    if (i === 0) {
-      spanArr.push(1);
-      pos = 0;
-    } else {
-      if (data[i].pc_code === data[i - 1].pc_code) {
-        spanArr[pos] += 1;
-        spanArr.push(0);
-      } else {
-        spanArr.push(1);
-        pos = i;
-      }
-    }
-  }
-  // console.log(spanArr);
-};
 
 // 分页
 const handleSizeChange = (val) => {
@@ -196,7 +177,6 @@ const getTableData = async () => {
     total.value = table.data.total;
     page.value = table.data.page;
     pageSize.value = table.data.pageSize;
-    getSpanArr(table.data.list);
   }
 };
 getTableData();

+ 0 - 20
src/view/dataStatistics/wechat_scanner_detailed.vue

@@ -151,25 +151,6 @@ const disabledDate = (time) => {
   return time.getTime() > Date.now();
 };
 
-const getSpanArr = (data) => {
-  spanArr = [];
-  var pos = 0;
-  for (var i = 0; i < data.length; i++) {
-    if (i === 0) {
-      spanArr.push(1);
-      pos = 0;
-    } else {
-      if (data[i].pc_code === data[i - 1].pc_code) {
-        spanArr[pos] += 1;
-        spanArr.push(0);
-      } else {
-        spanArr.push(1);
-        pos = i;
-      }
-    }
-  }
-  // console.log(spanArr);
-};
 
 // 分页
 const handleSizeChange = (val) => {
@@ -223,7 +204,6 @@ const getTableData = async () => {
     total.value = table.data.total;
     page.value = table.data.page;
     pageSize.value = table.data.pageSize;
-    getSpanArr(table.data.list);
   }
 };
 getTableData();

+ 0 - 21
src/view/dataStatistics/wechat_scanner_ledger.vue

@@ -167,26 +167,6 @@ const disabledDate = (time) => {
   return time.getTime() > Date.now();
 };
 
-const getSpanArr = (data) => {
-  spanArr = [];
-  var pos = 0;
-  for (var i = 0; i < data.length; i++) {
-    if (i === 0) {
-      spanArr.push(1);
-      pos = 0;
-    } else {
-      if (data[i].pc_code === data[i - 1].pc_code) {
-        spanArr[pos] += 1;
-        spanArr.push(0);
-      } else {
-        spanArr.push(1);
-        pos = i;
-      }
-    }
-  }
-  // console.log(spanArr);
-};
-
 // 分页
 const handleSizeChange = (val) => {
   pageSize.value = val;
@@ -250,7 +230,6 @@ const getTableData = async () => {
     total.value = table.data.total;
     page.value = table.data.page;
     pageSize.value = table.data.pageSize;
-    getSpanArr(table.data.list);
   }
 };
 getTableData();

Різницю між файлами не показано, бо вона завелика
+ 1268 - 0
src/view/fileManager/qiniuTransfer.vue


+ 261 - 0
src/view/gameTask/scriptList.vue

@@ -0,0 +1,261 @@
+<template>
+    <div>
+        <div class="gva-search-box">
+            <el-form ref="searchForm" :inline="true" :model="searchInfo">
+                <el-form-item label="任务Id">
+                    <el-input v-model="searchInfo.task_id" placeholder="任务Id" />
+                </el-form-item>
+                <el-form-item label="负责人">
+                    <el-select v-model="searchInfo.responsible_person" placeholder="负责人">
+                        <el-option v-for="item in ResponsiblePerson" :key="item.id" :label="item.name" :value="item.name" />
+                    </el-select>
+                </el-form-item>
+                <el-form-item>
+                    <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button>
+                    <el-button size="small" icon="refresh" @click="onReset">重置</el-button>
+                </el-form-item>
+            </el-form>
+        </div>
+        <div class="gva-table-box">
+            <el-table :data="tableData" border @sort-change="sortChange" @selection-change="handleSelectionChange">
+                <el-table-column type="selection" width="55" />
+                <el-table-column align="left" label="任务ID" min-width="60" prop="task_id" sortable="custom" />
+                <el-table-column align="left" label="脚本名称" min-width="60" prop="name" sortable="custom" />
+                <el-table-column align="left" label="负责人" min-width="60" prop="responsible_person" sortable="custom" />
+                <el-table-column align="left" label="下载链接" min-width="80" prop="url" />
+                <el-table-column align="left" label="版本号" min-width="60" prop="version" />
+                <el-table-column align="left" label="md5值" min-width="60" prop="md5_string" />
+                <el-table-column align="left" label="状态" min-width="60">
+                    <template #default="scope">
+                        <el-switch v-model="scope.row.state" inline-prompt :active-value="1" :inactive-value="-1"
+                            @change="() => { switchEnable(scope.row) }" />
+                    </template>
+                </el-table-column>
+                <el-table-column align="left" label="创建时间" min-width="110" prop="create_time" sortable="custom" />
+                <el-table-column align="left" label="更新时间" min-width="80" prop="update_time" />
+
+            </el-table>
+            <div class="gva-pagination">
+                <el-pagination :current-page="page" :page-size="pageSize" :page-sizes="[10, 30, 50, 100]" :total="total"
+                    layout="total, sizes, prev, pager, next, jumper" @current-change="handleCurrentChange"
+                    @size-change="handleSizeChange" />
+            </div>
+
+        </div>
+    </div>
+</template>
+  
+<script>
+export default {
+    name: 'ScriptList',
+}
+</script>
+  
+<script setup>
+import {
+    statusChange,
+    getScriptList,
+} from '@/api/upload'
+import {
+    selectResponsiblePerson,
+} from '@/api/responsiblePerson'
+import { useUserStore } from '@/pinia/modules/user'
+import { toSQLLine } from '@/utils/stringFun'
+import warningBar from '@/components/warningBar/warningBar.vue'
+import { ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { downloadTemplate } from '@/api/excel'
+
+
+const path = ref(import.meta.env.VITE_BASE_API)
+const userStore = useUserStore()
+const typeFiletr = (value) => {
+    const target = typeOptions.value.filter(item => item.value === value)[0]
+    return target && `${target.label}`
+}
+
+const statusFiletr = (value) => {
+    const target = statusOptions.value.filter(item => item.value === value)[0]
+    return target && `${target.label}`
+}
+const ResponsiblePerson = ref([])
+const getResponsiblePerson = async () => {
+    const table = await selectResponsiblePerson()
+    if (table.code === 0) {
+        ResponsiblePerson.value = table.data
+    }
+}
+getResponsiblePerson()
+const apis = ref([])
+
+const form = ref({
+    task_id: '',
+    name: '',
+    responsible_person: '',
+    url: '',
+    version: '',
+    md5_string: '',
+    state: '',
+})
+const statusOptions = ref([
+    {
+        value: -1,
+        label: '关闭',
+        type: 'wain'
+    },
+    {
+        value: 1,
+        label: '使用',
+        type: 'success'
+    }
+])
+
+const GamePortOptions = ref([
+])
+
+const accountTypeOptions = ref([
+])
+
+const loginMethodOptions = ref([
+])
+
+
+const type = ref('')
+
+
+const page = ref(1)
+const total = ref(0)
+const pageSize = ref(10)
+const tableData = ref([])
+const searchInfo = ref({})
+
+const onReset = () => {
+    searchInfo.value = {}
+    getTableData()
+}
+// 搜索
+const onSubmit = () => {
+    page.value = 1
+    pageSize.value = 10
+    searchInfo.value.task_id = Number(searchInfo.value.task_id)
+    getTableData()
+}
+
+// 分页
+const handleSizeChange = (val) => {
+    pageSize.value = val
+    getTableData()
+}
+
+const handleCurrentChange = (val) => {
+    page.value = val
+    getTableData()
+}
+
+// 排序
+const sortChange = ({ prop, order }) => {
+    if (prop) {
+        if (prop === 'id') {
+            prop = 'id'
+        }
+        searchInfo.value.orderKey = toSQLLine(prop)
+        searchInfo.value.desc = order === 'descending'
+    }
+    getTableData()
+}
+
+// 查询
+const getTableData = async () => {
+    const table = await getScriptList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
+    if (table.code === 0) {
+        tableData.value = table.data.list
+        total.value = table.data.total
+        // GamePortOptions.value = table.data.option.game_port
+        // loginMethodOptions.value = table.data.option.login_type
+        // accountTypeOptions.value = table.data.option.account_type
+        // links.value = table.data.option.game_list
+        page.value = table.data.page
+        pageSize.value = table.data.pageSize
+    }
+}
+
+getTableData()
+
+// 批量操作
+const handleSelectionChange = (val) => {
+    apis.value = val
+}
+
+const deleteVisible = ref(false)
+
+// 弹窗相关
+const apiForm = ref(null)
+const initForm = () => {
+    apiForm.value.resetFields()
+    form.value = {
+        task_id: '',
+        name: '',
+        responsible_person: '',
+        url: '',
+        version: '',
+        md5_string: '',
+        state: '',
+    }
+}
+
+const switchEnable = async (row) => {
+    const res = await statusChange({ state: row.state, id: row.id })
+    if (res.code === 0) {
+        ElMessage({ type: 'success', message: `${row.state === -1 ? '停止' : '开启'}成功` })
+    }
+}
+
+const links = ref([])
+
+const querySearch = (queryString, cb) => {
+    const results = queryString
+        ? links.value.filter(createFilter(queryString))
+        : links.value
+    // call callback function to return suggestion objects
+    cb(results)
+}
+const createFilter = (queryString) => {
+    return (restaurant) => {
+        return (
+            restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
+        )
+    }
+}
+
+const handleSelect = (item) => {
+    form.value.game_id = item.game_id
+    console.log(item)
+}
+
+const handleIconClick = (ev) => {
+    console.log(ev)
+}
+
+// links.value = loadAll()
+
+</script>
+  
+<style scoped lang="scss">
+.button-box {
+    padding: 10px 20px;
+
+    .el-button {
+        float: right;
+    }
+}
+
+:deep(.el-tabs__nav-scroll) {
+    width: 35%;
+    margin: 0 auto
+}
+
+:deep(.el-tabs__nav-scroll) .warning {
+    color: #dc143c;
+}
+</style>
+  

+ 0 - 152
src/view/gameTask/upload.vue

@@ -1,152 +0,0 @@
-<template>
-    <div class="addFileUpdate">
-      <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
-        <!-- <el-form-item label="版本号" prop="version">
-          <el-input v-model="ruleForm.version" style="width: 200px;"></el-input>
-        </el-form-item> -->
-        <!-- <el-form-item label="更新日志" prop="log">
-          <el-input type="textarea" v-model="ruleForm.log" style="width:500px;"></el-input>
-        </el-form-item> -->
-        <el-form-item label="gameid" prop="game_id">
-          <el-input type="textarea" v-model="ruleForm.game_id" style="width:500px;"></el-input>
-        </el-form-item>
-        <el-form-item label="上传文件" prop="file">
-          <el-upload ref="upload" class="upload-demo" action="/manager/appupdate/addFileUpdate" :headers="headers"
-            :http-request="httpRequest" :before-remove="beforeRemove" :before-upload="beforeUploadFile" :on-exceed="handleExceed"
-            multiple :limit="1" :auto-upload="false" :on-change="getFile" :data="ruleForm" :file-list="fileList" name="annexFile"
-            style="width: 500px;">
-            <el-button size="small" type="primary">点击上传</el-button>
-            <div slot="tip" class="el-upload__tip">{{message}}</div>
-          </el-upload>
-        </el-form-item>
-  
-        <el-form-item>
-          <el-button type="primary" @click="submitForm('ruleForm')" v-loading.fullscreen.lock="fullscreenLoading">立即创建</el-button>
-          <el-button @click="resetForm('ruleForm')">重置</el-button>
-        </el-form-item>
-      </el-form>
-    </div>
-  </template>
-  
-  <script>
-    import {
-      addFileUpdate
-    } from "../../api/upload.js"
-    export default {
-      name: 'AddFileUpdate',
-      data() {
-        return {
-          fullscreenLoading: false,
-          //表单
-          ruleForm: {
-            game_id: '' //游戏id
-          },
-          //上传
-          headers: {
-            // token: getStore('zxdAdmintoken'),
-            "content-type": "multipart/form-data"
-          },
-          message: '请上传dll文件',
-          fileList: [], //文件列表
-          fd: {}, //用于放数据  FormData类型
-  
-          //校验规则
-          rules: {
-            game_id: [{
-              required: true,
-              message: '请输入游戏id',
-              trigger: 'blur'
-            }, ],
-            // log: [{
-            //   required: true,
-            //   message: '请填写更新日志',
-            //   trigger: 'blur'
-            // }]
-          }
-        }
-      },
-      methods: {
-        //上传
-        getFile(file, fileList) {
-          this.fileList = fileList;
-          // console.log(this.fileList)
-          const fd = new FormData() // FormData 对象
-          this.fd = fd
-        },
-        //上传前
-        beforeUploadFile(file) {
-          let extension = file.name.substring(file.name.lastIndexOf('.') + 1);
-          console.log(extension)
-          if (extension !== 'dll') {
-            // this.$message.warning('只能上传后缀是.zip/.rar/.apk的文件'); //控制文件类型
-            this.$message.warning('文件类型不对'); //控制文件类型
-            return false
-          }
-        },
-        //超限制
-        handleExceed(files, fileList) {
-          this.$message.warning("目前只能上传一款脚本")
-        },
-        //移除
-        beforeRemove(file, fileList) {
-          let extension = file.name.substring(file.name.lastIndexOf('.') + 1);
-          if (extension !== 'dll') {
-            return
-          }
-          return this.$confirm(`确定移除 ${file.name}?`)
-        },
-        httpRequest(param) {
-          const fileObj = param.file // 相当于input里取得的files
-          this.fd.append('file', fileObj) // 文件对象
-          console.log("文件包" + this.fd.get('file'));
-        },
-        //提交
-        submitForm(formName) {
-          // let fileArr = this.$refs.upload.uploadFiles;
-          // console.log(fileArr)
-          this.$refs[formName].validate((valid) => {
-            if (valid) {
-              if (this.fileList.length <= 0) {
-                this.$message.error("至少上传一款脚本!");
-                return;
-              }
-              this.$refs.upload.submit();
-              //换行自动添加为<br/>
-              // this.ruleForm.log= this.ruleForm.log.replace(/\n/g,"<br/>");
-              // console.log(this.ruleForm.log)
-              //将表单内其他内容添加进fd
-              this.fd.append('game_id', this.ruleForm.game_id)
-              // this.fd.append('log', this.ruleForm.log)
-              this.fd.append('type', "0")
-              this.fullscreenLoading = true;
-              //调用后端接口,提交即可
-              addFileUpdate(this.fd).then(data => {
-                console.log(data)
-                if (data.code == 0) {
-                  this.fullscreenLoading = false;
-                  this.$message({
-                    message: '上传成功',
-                    type: 'success'
-                  });
-                  this.fd = {}
-                  this.fileList = []
-                  resetForm(formName)
-                } else {
-                  this.$message.error("上传失败");
-                }
-              })
-            } else {
-              // console.log('error submit!!');
-              return false;
-            }
-          });
-        },
-        //重置
-        resetForm(formName) {
-          this.$refs[formName].resetFields();
-          this.$refs.upload.clearFiles()
-        },
-  
-      }
-    }
-  </script>

+ 546 - 0
src/view/gameTask/uploadView.vue

@@ -0,0 +1,546 @@
+<template>
+  <div>
+    <div class="gva-search-box">
+      <el-form ref="searchForm" :inline="true" :model="searchInfo">
+        <el-form-item label="任务Id">
+          <el-input v-model="searchInfo.task_id_string" placeholder="任务Id" />
+        </el-form-item>
+        <el-form-item label="负责人">
+          <el-select v-model="searchInfo.user" placeholder="负责人">
+            <el-option v-for="item in ResponsiblePerson" :key="item.id" :label="item.name" :value="item.name" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button size="small" type="primary" icon="search" @click="onSubmit">查询</el-button>
+          <el-button size="small" icon="refresh" @click="onReset">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="gva-table-box">
+      <!-- <div class="gva-btn-list">
+        <el-button size="small" type="primary" icon="plus" @click="openDialog('addCard')">新增</el-button>
+      </div> -->
+      <el-table :data="tableData" border @sort-change="sortChange" @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55" />
+        <el-table-column align="left" label="任务ID" min-width="60" prop="task_id" sortable="custom" />
+        <el-table-column align="left" label="任务名称" min-width="60" prop="task_name" sortable="custom" />
+        <el-table-column align="left" label="负责人" min-width="60" prop="user" sortable="custom" />
+        <el-table-column align="left" label="游戏名称" min-width="80" prop="game_name" sortable="custom" />
+        <el-table-column align="left" fixed="right" label="操作" width="140">
+          <template #default="scope">
+            <el-button icon="edit" size="small" type="primary" link @click="uploadFunc(scope.row)">上传</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="gva-pagination">
+        <el-pagination :current-page="page" :page-size="pageSize" :page-sizes="[10, 30, 50, 100]" :total="total"
+          layout="total, sizes, prev, pager, next, jumper" @current-change="handleCurrentChange"
+          @size-change="handleSizeChange" />
+      </div>
+
+    </div>
+    <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle">
+      <el-form :model="form" :rules="rules" ref="uploadForm" label-width="100px" class="demo-ruleForm">
+        <el-form-item label="任务id" prop="task_id">
+          <el-input type="textarea" v-model="form.task_id" style="width:500px;"></el-input>
+        </el-form-item>
+        <el-form-item label="负责人">
+          <el-select v-model="form.responsible_person" placeholder="负责人">
+            <el-option v-for="item in ResponsiblePerson" :key="item.id" :label="item.name" :value="item.name" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="上传文件" prop="file">
+          <el-upload ref="upload" class="upload-demo" action="#" :before-remove="beforeRemove" :limit="1"
+            :on-exceed="handleExceed" :on-remove="handleRemove" :on-change="handleChange" :file-list="fileList.data"
+            :http-request="httpRequest" :data="form" :auto-upload="false" name="annexFile" style="width: 500px;">
+            <el-button size="small" type="primary">点击上传</el-button>
+            <div slot="tip" class="el-upload__tip">{{ message }}</div>
+          </el-upload>
+        </el-form-item>
+
+        <el-form-item>
+          <el-button type="primary" @click="submitUpload" v-loading.fullscreen.lock="fullscreenLoading">立即创建</el-button>
+          <el-button @click="resetForm()">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+
+  </div>
+</template>
+  
+<script lang="ts">
+export default {
+  name: 'AddFileUpdate',
+}
+</script>
+  
+<script lang="ts" setup>
+
+import {
+  addFileUpdate,
+  getGameTaskList,
+} from '@/api/upload'
+import {
+  selectResponsiblePerson,
+} from '@/api/responsiblePerson'
+import { useUserStore } from '@/pinia/modules/user'
+import { toSQLLine } from '@/utils/stringFun'
+import warningBar from '@/components/warningBar/warningBar.vue'
+import { ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { async } from 'q'
+import { reactive } from 'vue'
+import { genFileId } from 'element-plus'
+// import { ElMessage, ElMessageBox } from 'element-plus'
+import { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
+
+const ResponsiblePerson = ref([{
+  id: 0,
+  name: "",
+}
+])
+const getResponsiblePerson = async () => {
+  const table = await selectResponsiblePerson()
+  if (table.code === 0) {
+    ResponsiblePerson.value = table.data
+  }
+}
+getResponsiblePerson()
+
+const GamePortOptions = ref([
+])
+
+const accountTypeOptions = ref([
+])
+
+const loginMethodOptions = ref([
+])
+const type = ref('')
+const page = ref(1)
+const total = ref(0)
+const pageSize = ref(10)
+const tableData = ref([])
+const searchInfo = ref({
+  task_id_string: "",
+  orderKey: "",
+  desc: false,
+  task_id: 0,
+  user: "",
+})
+
+const onReset = () => {
+  searchInfo.value = {
+    task_id_string: "",
+    orderKey: "",
+    desc: false,
+    task_id: 0,
+    user: "",
+  }
+}
+// 搜索
+const onSubmit = () => {
+  page.value = 1
+  pageSize.value = 10
+  searchInfo.value.task_id = Number(searchInfo.value.task_id_string)
+  getTableData()
+}
+// 分页
+const handleSizeChange = (val) => {
+  pageSize.value = val
+  getTableData()
+}
+const handleCurrentChange = (val) => {
+  page.value = val
+  getTableData()
+}
+
+// 排序
+const sortChange = ({ prop, order }) => {
+  if (prop) {
+    if (prop === 'id') {
+      prop = 'id'
+    }
+    searchInfo.value.orderKey = toSQLLine(prop)
+    searchInfo.value.desc = order === 'descending'
+  }
+  getTableData()
+}
+
+// 查询
+const getTableData = async () => {
+  const table = await getGameTaskList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
+  if (table.code === 0) {
+    tableData.value = table.data.list
+    total.value = table.data.total
+    GamePortOptions.value = table.data.option.game_port
+    loginMethodOptions.value = table.data.option.login_type
+    accountTypeOptions.value = table.data.option.account_type
+    links.value = table.data.option.game_list
+    page.value = table.data.page
+    pageSize.value = table.data.pageSize
+  }
+}
+
+getTableData()
+
+const apis: any = 0
+// 批量操作
+const handleSelectionChange = (val) => {
+  apis.value = val
+}
+
+// 弹窗相关
+const initForm = () => {
+
+  uploadForm.value.resetFields()
+  upload.value!.clearFiles()
+  form.value = {
+    task_id: '',//游戏id
+    responsible_person: '',
+  }
+}
+
+const uploadFunc = async (row) => {
+  // const res = await getGameTaskById({ id: row.task_id })
+  form.value.task_id = row.task_id
+  form.value.responsible_person = row.user
+  openDialog('upload')
+}
+
+const dialogTitle = ref('新增')
+const dialogFormVisible = ref(false)
+const openDialog = (key) => {
+  switch (key) {
+    case 'upload':
+      dialogTitle.value = '上传'
+      // form.value.is_add = 1
+      break
+    // case 'edit':
+    //   dialogTitle.value = '编辑'
+    //   form.value.is_add = 0
+    //   break
+    default:
+      break
+  }
+  type.value = key
+  dialogFormVisible.value = true
+}
+const closeDialog = () => {
+  initForm()
+  dialogFormVisible.value = false
+}
+
+const links = ref([])
+
+const createFilter = (queryString) => {
+  return (restaurant) => {
+    return (
+      restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
+    )
+  }
+}
+
+
+let fullscreenLoading = false
+// const uploadForm = ref([])
+const upload = ref<UploadInstance>()
+const uploadForm: any = ref(null)
+const imageUrl = ref('')
+const fileList = reactive({
+  data: []
+});
+
+//上传
+const headers = ref({
+  // token: getStore('zxdAdmintoken'),
+  "content-type": "multipart/form-data"
+})
+const message = ref('请上传dll/exe文件')
+
+//校验规则
+const rules = ref({
+  task_id: [{
+    required: true,
+    message: '请输入游戏id',
+    trigger: 'blur'
+  }],
+})
+
+const form = ref({
+  task_id: '',//游戏id
+  responsible_person: '',
+})
+
+
+const handleExceed: UploadProps['onExceed'] = (files) => {
+  console.log("数组超标")
+  upload.value!.clearFiles()
+  const file = files[0] as UploadRawFile
+  file.uid = genFileId()
+  upload.value!.handleStart(file)
+}
+
+const handleChange: UploadProps['onChange'] = (file, fileList) => {
+
+  let extension = file.name.substring(file.name.lastIndexOf('.') + 1);
+  console.log(extension)
+  if (extension !== 'dll' && extension !== 'exe') {
+    // this.$message.warning('只能上传后缀是.zip/.rar/.apk的文件'); //控制文件类型
+    ElMessage.error('文件类型不对'); //控制文件类型
+    upload.value!.clearFiles()
+    return false
+  }
+  else if (Number(file.size) / 1024 / 1024 > 20) {
+    ElMessage.error('Avatar file size can not exceed 20MB!')
+    upload.value!.clearFiles()
+    return false
+  }
+  return true
+}
+
+const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => {
+  return ElMessageBox.confirm(
+    `Cancel the transfert of ${uploadFile.name} ?`
+  ).then(
+    () => true,
+    () => false
+  )
+}
+let fd = new FormData()
+const httpRequest = (param: any) => {
+
+
+
+  // let fd = new FormData();
+  const fileObj = param.file // 相当于input里取得的files
+  fd.append('file', fileObj) // 文件对象
+  console.log("文件包" + fd.get('file'));
+  const url = '';
+}
+
+const handleRemove: UploadProps['onRemove'] = (file, fileList) => {
+  console.log(fileList)
+}
+
+
+const submitUpload = async () => {
+  uploadForm.value.validate(async valid => {
+    if (valid) {
+      if (fileList.data.length <= 0) {
+        ElMessage.error("至少上传一款脚本!");
+        return;
+      }
+      upload.value!.submit()
+      fd.append('task_id', form.value.task_id)
+      fd.append('responsible_person', form.value.responsible_person)
+      // this.fd.append('log', this.ruleForm.log)
+      fullscreenLoading = true;
+      //调用后端接口,提交即可
+      const res = await addFileUpdate(fd)
+      console.log(res)
+      if (res.code == 0) {
+        fullscreenLoading = false;
+        ElMessage({
+          message: '上传成功',
+          type: 'success'
+        });
+        fd = new FormData()
+        fileList.data = []
+        resetForm()
+        getTableData()
+        closeDialog()
+      } else {
+        ElMessage.error("上传失败");
+        getTableData()
+        closeDialog()
+      }
+    } else {
+      // console.log('error submit!!');
+      return false;
+    }
+  });
+
+
+}
+
+
+//重置
+const resetForm = async () => {
+  uploadForm.value.resetFields()
+  // console.log(uploadForm.file)
+  upload.value!.clearFiles()
+  form.value = {
+    task_id: '',//游戏id
+    responsible_person: '',
+  }
+}
+
+</script>
+  
+
+<!-- <script lang="ts" setup>
+import { ref, reactive } from 'vue'
+import { genFileId } from 'element-plus'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import type { UploadInstance, UploadProps, UploadRawFile } from 'element-plus'
+
+const fullscreenLoading = ref(false)
+const uploadForm = ref(null)
+const upload = ref<UploadInstance>()
+const imageUrl = ref('')
+const fileList = reactive({
+    data: []
+});
+
+//上传
+const headers = ref({
+  // token: getStore('zxdAdmintoken'),
+  "content-type": "multipart/form-data"
+})
+const message = ref('请上传dll文件')
+
+//校验规则
+const rules = ref({
+  game_id: [{
+    required: true,
+    message: '请输入游戏id',
+    trigger: 'blur'
+  }],
+})
+
+const uploadForm = ref(null)
+const form = ref({
+  game_id: '' //游戏id
+})
+
+
+
+const handleExceed: UploadProps['onExceed'] = (files) => {
+    upload.value!.clearFiles()
+    const file = files[0] as UploadRawFile
+    file.uid = genFileId()
+    upload.value!.handleStart(file)
+}
+
+const handleChange: UploadProps['onChange'] = (file, fileList) => {
+
+    let extension = file.name.substring(file.name.lastIndexOf('.') + 1);
+    console.log(extension)
+    if (extension !== 'dll') {
+        // this.$message.warning('只能上传后缀是.zip/.rar/.apk的文件'); //控制文件类型
+        ElMessage.error('文件类型不对'); //控制文件类型
+        upload.value!.clearFiles()
+        return false
+    }
+    else if (Number(file.size) / 1024 / 1024 > 2) {
+        ElMessage.error('Avatar picture size can not exceed 2MB!')
+        upload.value!.clearFiles()
+        return false
+    }
+    return true
+}
+
+const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => {
+    return ElMessageBox.confirm(
+        `Cancel the transfert of ${uploadFile.name} ?`
+    ).then(
+        () => true,
+        () => false
+    )
+}
+
+const httpRequest = (param) => {
+
+
+    let fd = new FormData();
+    const fileObj = param.file // 相当于input里取得的files
+    fd.append('file', fileObj) // 文件对象
+    console.log("文件包" + fd.get('file'));
+    const url = '';
+}
+
+const handleRemove: UploadProps['onRemove'] = (file, fileList) => {
+    console.log(file, fileList)
+}
+
+const submitUpload = () => {
+  uploadForm.value.validate(async valid => {
+    if (valid) {
+      if (fileList.length <= 0) {
+        $message.error("至少上传一款脚本!");
+        return;
+      }
+      upload.submit();
+      //换行自动添加为<br/>
+      // this.ruleForm.log= this.ruleForm.log.replace(/\n/g,"<br/>");
+      // console.log(this.ruleForm.log)
+      //将表单内其他内容添加进fd
+      fd.append('game_id', form.game_id)
+      // this.fd.append('log', this.ruleForm.log)
+      fd.append('type', "0")
+      fullscreenLoading = true;
+      //调用后端接口,提交即可
+      const res = await addFileUpdate(fd)
+      console.log(res)
+      if (res.code == 0) {
+        fullscreenLoading = false;
+        $message({
+          message: '上传成功',
+          type: 'success'
+        });
+        fd = {}
+        fileList = []
+        resetForm(formName)
+      } else {
+        $message.error("上传失败");
+      }
+    } else {
+      // console.log('error submit!!');
+      return false;
+    }
+  });
+
+    upload.value!.submit()
+}
+
+
+//重置
+const resetForm = async (form) => {
+  uploadForm.value.resetFields()
+  console.log(uploadForm.file)
+  upload.value.clearFiles()
+  // form.value = {
+  //   game_id: '' //游戏id
+  // }
+}
+
+
+
+
+</script> -->
+
+
+
+
+
+
+
+<style scoped lang="scss">
+.button-box {
+  padding: 10px 20px;
+
+  .el-button {
+    float: right;
+  }
+}
+
+:deep(.el-tabs__nav-scroll) {
+  width: 35%;
+  margin: 0 auto
+}
+
+:deep(.el-tabs__nav-scroll) .warning {
+  color: #dc143c;
+}
+</style>
+  

+ 21 - 21
src/view/rentComputer/rent_computer.vue

@@ -2,7 +2,7 @@
  * @Author: 倚楼听风雨 18408246387@163.com
  * @Date: 2022-11-16 17:16:17
  * @LastEditors: 倚楼听风雨 18408246387@163.com
- * @LastEditTime: 2023-02-27 16:23:57
+ * @LastEditTime: 2023-02-28 10:34:39
  * @FilePath: \log-server-web\src\view\logComputer\list_computer_distinct.vue
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 -->
@@ -990,25 +990,25 @@ const downloadExcelTemplate = () => {
   downloadTemplate("RentComputerTemplate.xlsx");
 };
 
-const getSpanArr = (data) => {
-  spanArr = [];
-  var pos = 0;
-  for (var i = 0; i < data.length; i++) {
-    if (i === 0) {
-      spanArr.push(1);
-      pos = 0;
-    } else {
-      if (data[i].pc_code === data[i - 1].pc_code) {
-        spanArr[pos] += 1;
-        spanArr.push(0);
-      } else {
-        spanArr.push(1);
-        pos = i;
-      }
-    }
-  }
-  // console.log(spanArr);
-};
+// const getSpanArr = (data) => {
+//   spanArr = [];
+//   var pos = 0;
+//   for (var i = 0; i < data.length; i++) {
+//     if (i === 0) {
+//       spanArr.push(1);
+//       pos = 0;
+//     } else {
+//       if (data[i].pc_code === data[i - 1].pc_code) {
+//         spanArr[pos] += 1;
+//         spanArr.push(0);
+//       } else {
+//         spanArr.push(1);
+//         pos = i;
+//       }
+//     }
+//   }
+//   // console.log(spanArr);
+// };
 
 // 分页
 const handleSizeChange = (val) => {
@@ -1067,7 +1067,7 @@ const getTableData = async () => {
     total.value = table.data.total;
     page.value = table.data.page;
     pageSize.value = table.data.pageSize;
-    getSpanArr(table.data.list);
+    // getSpanArr(table.data.list);
     getComputerNum();
     getSelectList();
   }

+ 20 - 20
src/view/rentComputer/rent_computer_ledger.vue

@@ -374,25 +374,25 @@ const calculateRentDuration = async (scope) => {
   );
 };
 
-const getSpanArr = (data) => {
-  spanArr = [];
-  var pos = 0;
-  for (var i = 0; i < data.length; i++) {
-    if (i === 0) {
-      spanArr.push(1);
-      pos = 0;
-    } else {
-      if (data[i].pc_code === data[i - 1].pc_code) {
-        spanArr[pos] += 1;
-        spanArr.push(0);
-      } else {
-        spanArr.push(1);
-        pos = i;
-      }
-    }
-  }
-  // console.log(spanArr);
-};
+// const getSpanArr = (data) => {
+//   spanArr = [];
+//   var pos = 0;
+//   for (var i = 0; i < data.length; i++) {
+//     if (i === 0) {
+//       spanArr.push(1);
+//       pos = 0;
+//     } else {
+//       if (data[i].pc_code === data[i - 1].pc_code) {
+//         spanArr[pos] += 1;
+//         spanArr.push(0);
+//       } else {
+//         spanArr.push(1);
+//         pos = i;
+//       }
+//     }
+//   }
+//   // console.log(spanArr);
+// };
 
 // 分页
 const handleSizeChange = (val) => {
@@ -468,7 +468,7 @@ const getTableData = async () => {
     total.value = table.data.total;
     page.value = table.data.page;
     pageSize.value = table.data.pageSize;
-    getSpanArr(table.data.list);
+    // getSpanArr(table.data.list);
     getComputerNum();
     getSelectList();
   }

+ 20 - 20
src/view/rentComputer/rent_computer_shop.vue

@@ -195,25 +195,25 @@ const tableData = ref([]);
 let spanArr = [];
 const searchInfo = ref({});
 
-const getSpanArr = (data) => {
-  spanArr = [];
-  var pos = 0;
-  for (var i = 0; i < data.length; i++) {
-    if (i === 0) {
-      spanArr.push(1);
-      pos = 0;
-    } else {
-      if (data[i].pc_code === data[i - 1].pc_code) {
-        spanArr[pos] += 1;
-        spanArr.push(0);
-      } else {
-        spanArr.push(1);
-        pos = i;
-      }
-    }
-  }
-  console.log(spanArr);
-};
+// const getSpanArr = (data) => {
+//   spanArr = [];
+//   var pos = 0;
+//   for (var i = 0; i < data.length; i++) {
+//     if (i === 0) {
+//       spanArr.push(1);
+//       pos = 0;
+//     } else {
+//       if (data[i].pc_code === data[i - 1].pc_code) {
+//         spanArr[pos] += 1;
+//         spanArr.push(0);
+//       } else {
+//         spanArr.push(1);
+//         pos = i;
+//       }
+//     }
+//   }
+//   console.log(spanArr);
+// };
 
 // 分页
 const handleSizeChange = (val) => {
@@ -250,7 +250,7 @@ const getTableData = async () => {
     total.value = table.data.total;
     page.value = table.data.page;
     pageSize.value = table.data.pageSize;
-    getSpanArr(table.data.list);
+    // getSpanArr(table.data.list);
     // console.log(table);
     getComputerShopNum();
   }

+ 20 - 20
src/view/rentComputer/rent_set_meal.vue

@@ -258,25 +258,25 @@ const tableData = ref([]);
 let spanArr = [];
 const searchInfo = ref({});
 
-const getSpanArr = (data) => {
-  spanArr = [];
-  var pos = 0;
-  for (var i = 0; i < data.length; i++) {
-    if (i === 0) {
-      spanArr.push(1);
-      pos = 0;
-    } else {
-      if (data[i].pc_code === data[i - 1].pc_code) {
-        spanArr[pos] += 1;
-        spanArr.push(0);
-      } else {
-        spanArr.push(1);
-        pos = i;
-      }
-    }
-  }
-  console.log(spanArr);
-};
+// const getSpanArr = (data) => {
+//   spanArr = [];
+//   var pos = 0;
+//   for (var i = 0; i < data.length; i++) {
+//     if (i === 0) {
+//       spanArr.push(1);
+//       pos = 0;
+//     } else {
+//       if (data[i].pc_code === data[i - 1].pc_code) {
+//         spanArr[pos] += 1;
+//         spanArr.push(0);
+//       } else {
+//         spanArr.push(1);
+//         pos = i;
+//       }
+//     }
+//   }
+//   console.log(spanArr);
+// };
 
 // 分页
 const handleSizeChange = (val) => {
@@ -313,7 +313,7 @@ const getTableData = async () => {
     total.value = table.data.total;
     page.value = table.data.page;
     pageSize.value = table.data.pageSize;
-    getSpanArr(table.data.list);
+    // getSpanArr(table.data.list);
     getComputerNum();
   }
 };

+ 290 - 313
src/view/typeManage/accountType.vue

@@ -1,341 +1,318 @@
 <template>
-    <div>
-      <div class="gva-search-box">
-        <el-form ref="searchForm" :inline="true" :model="searchInfo">
-          <el-form-item>
-            <el-select v-model="searchInfo.searchKey"  >
-              <el-option
-                v-for="item in searchOptions"
-                :key="item.value"
-                :label="item.label"
-                :value="item.value"
-              />
-            </el-select>
-          </el-form-item>
-          <el-form-item>
-            <el-input v-model="searchInfo.type_name" placeholder="请输入关键字"/>
-          </el-form-item>
-          <el-form-item>
-            <el-button size="small" type="primary" icon="search" @click="onSubmit">搜索</el-button>
-          </el-form-item>
-        </el-form>
+  <div>
+    <div class="gva-search-box">
+      <el-form ref="searchForm" :inline="true" :model="searchInfo">
+        <el-form-item>
+          <el-select v-model="searchInfo.searchKey">
+            <el-option v-for="item in searchOptions" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-input v-model="searchInfo.type_name" placeholder="请输入关键字" />
+        </el-form-item>
+        <el-form-item>
+          <el-button size="small" type="primary" icon="search" @click="onSubmit">搜索</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="gva-table-box">
+      <div class="gva-btn-list">
+        <el-button size="small" icon="refresh" @click="onReset">刷新</el-button>
+        <el-button size="small" type="primary" icon="plus" @click="openDialog('addAccountType')">新增</el-button>
+        <el-popover v-model="deleteVisible" placement="top" width="160">
+          <p>确定要删除吗?</p>
+          <div style="text-align: right; margin-top: 8px;">
+            <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button>
+            <el-button size="small" type="primary" @click="onDelete">确定</el-button>
+          </div>
+          <template #reference>
+            <el-button icon="delete" type="danger" size="small" :disabled="!apis.length" style="margin-left: 10px;"
+              @click="deleteVisible = true">删除</el-button>
+          </template>
+        </el-popover>
       </div>
-      <div class="gva-table-box">
-        <div class="gva-btn-list">
-          <el-button size="small" icon="refresh" @click="onReset">刷新</el-button>
-          <el-button size="small" type="primary" icon="plus" @click="openDialog('addAccountType')">新增</el-button>
-          <el-popover v-model="deleteVisible" placement="top" width="160">
-            <p>确定要删除吗?</p>
-            <div style="text-align: right; margin-top: 8px;">
-              <el-button size="small" type="primary" link @click="deleteVisible = false">取消</el-button>
-              <el-button size="small" type="primary" @click="onDelete">确定</el-button>
-            </div>
-            <template #reference>
-              <el-button icon="delete" type="danger" size="small" :disabled="!apis.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button>
-            </template>
-          </el-popover>
-        </div>
-        <el-table :data="tableData" @sort-change="sortChange" @selection-change="handleSelectionChange">
-          <el-table-column
-            type="selection"
-            width="55"
-          />
-          <el-table-column align="left" label="类型名称" min-width="100" prop="type_name" sortable="custom" />
-          <el-table-column align="left" label="类型描述" min-width="150" prop="type_desc"  />
-          <el-table-column align="left" label="创建时间" min-width="150" prop="create_time" sortable="custom" />
-          <el-table-column align="left" label="更新时间" min-width="150" prop="update_time" sortable="custom" />
-  
-          <el-table-column align="left" fixed="right" label="操作" width="200">
-            <template #default="scope">
-              <el-button
-                icon="edit"
-                size="small"
-                type="primary"
-                link
-                @click="editApiFunc(scope.row)"
-              >编辑</el-button>
-              <el-button
-                icon="delete"
-                size="small"
-                type="primary"
-                link
-                @click="deleteApiFunc(scope.row)"
-              >删除</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-        <div class="gva-pagination">
-          <el-pagination
-            :current-page="page"
-            :page-size="pageSize"
-            :page-sizes="[10, 30, 50, 100]"
-            :total="total"
-            layout="total, sizes, prev, pager, next, jumper"
-            @current-change="handleCurrentChange"
-            @size-change="handleSizeChange"
-          />
-        </div>
-  
+      <el-table :data="tableData" @sort-change="sortChange" @selection-change="handleSelectionChange">
+        <el-table-column type="selection" width="55" />
+        <el-table-column align="left" label="类型名称" min-width="100" prop="type_name" sortable="custom" />
+        <el-table-column align="left" label="类型描述" min-width="150" prop="type_desc" />
+        <el-table-column align="left" label="创建时间" min-width="150" prop="create_time" sortable="custom" />
+        <el-table-column align="left" label="更新时间" min-width="150" prop="update_time" sortable="custom" />
+
+        <el-table-column align="left" fixed="right" label="操作" width="200">
+          <template #default="scope">
+            <el-button icon="edit" size="small" type="primary" link @click="editApiFunc(scope.row)">编辑</el-button>
+            <el-button icon="delete" size="small" type="primary" link @click="deleteApiFunc(scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="gva-pagination">
+        <el-pagination :current-page="page" :page-size="pageSize" :page-sizes="[10, 30, 50, 100]" :total="total"
+          layout="total, sizes, prev, pager, next, jumper" @current-change="handleCurrentChange"
+          @size-change="handleSizeChange" />
       </div>
-  
-      <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle">
-        <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px">
-          <el-form-item label="类型名称" prop="type_name" >
-            <el-input v-model="form.type_name" autocomplete="off" />
-          </el-form-item>
-          <el-form-item label="类型描述" prop="type_desc" >
-            <el-input v-model="form.type_desc" autocomplete="off" />
-          </el-form-item>
-        </el-form>
-        <template #footer>
-          <div class="dialog-footer">
-            <el-button size="small" @click="closeDialog">取 消</el-button>
-            <el-button size="small" type="primary" @click="enterDialog">确 定</el-button>
-          </div>
-        </template>
-      </el-dialog>
+
     </div>
-  </template>
+
+    <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle">
+      <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="类型名称" prop="type_name">
+          <el-input v-model="form.type_name" autocomplete="off" />
+        </el-form-item>
+        <el-form-item label="类型描述" prop="type_desc">
+          <el-input v-model="form.type_desc" autocomplete="off" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button size="small" @click="closeDialog">取 消</el-button>
+          <el-button size="small" type="primary" @click="enterDialog">确 定</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
   
-  <script>
-  export default {
-    name: 'Api',
-    
-  }
-  </script>
+<script>
+export default {
+  name: 'Api',
+
+}
+</script>
   
-  <script setup>
-  import {
-    getApiById,
-    getApiList,
-    createApi,
-    updateApi,
-    deleteApi,
-    deleteApisByIds
-  } from '@/api/accountType'
-  import { toSQLLine } from '@/utils/stringFun'
+<script setup>
+import {
+  getApiById,
+  getApiList,
+  createApi,
+  updateApi,
+  deleteApi,
+  deleteApisByIds
+} from '@/api/accountType'
+import { toSQLLine } from '@/utils/stringFun'
 //   import warningBar from '@/components/warningBar/warningBar.vue'
-  import { ref } from 'vue'
-  import { ElMessage, ElMessageBox } from 'element-plus'
+import { ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
 // import { isNumber } from 'lodash'
-  
-  const methodFiletr = (value) => {
-    const target = searchOptions.value.filter(item => item.value === value)[0]
-    return target && `${target.label}`
-  }
-  
-  const apis = ref([])
-  const form = ref({
-    type_name: '',
-    type_desc: ''
-  })
-  const     searchOptions = ref([
-    {
-      value: 'type_name',
-      label: '账号类型',
 
-    },
-  ])
-  const type = ref('')
-  const rules = ref({
-    type_name: [{ required: true, message: '请输入类型名称', trigger: 'blur' }],
-  })
-  
-  const page = ref(1)
-  const total = ref(0)
-  const pageSize = ref(10)
-  const tableData = ref([])
-  const searchInfo = ref({
-    searchKey:"type_name",
-  })
-  
-  const onReset = () => {
-    searchInfo.value = {}
-    getTableData()
-  }
-  // 搜索
-  
-  const onSubmit = () => {
-    page.value = 1
-    pageSize.value = 10
-    getTableData()
-  }
-  
-  // 分页
-  const handleSizeChange = (val) => {
-    pageSize.value = val
-    getTableData()
-  }
-  
-  const handleCurrentChange = (val) => {
-    page.value = val
-    getTableData()
-  }
-  
-  // 排序
-  const sortChange = ({ prop, order }) => {
-    if (prop) {
-      if (prop === 'ID') {
-        prop = 'id'
-      }
-      searchInfo.value.orderKey = toSQLLine(prop)
-      searchInfo.value.desc = order === 'descending'
-    }
-    getTableData()
-  }
-  
-  // 查询
-  const getTableData = async() => {
-    const table = await getApiList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value})
-    if (table.code === 0) {
-      tableData.value = table.data.list
-      total.value = table.data.total
-      page.value = table.data.page
-      pageSize.value = table.data.pageSize
-    }
-  }
-  
+const methodFiletr = (value) => {
+  const target = searchOptions.value.filter(item => item.value === value)[0]
+  return target && `${target.label}`
+}
+
+const apis = ref([])
+const form = ref({
+  type_name: '',
+  type_desc: ''
+})
+const searchOptions = ref([
+  {
+    value: 'type_name',
+    label: '账号类型',
+
+  },
+])
+const type = ref('')
+const rules = ref({
+  type_name: [{ required: true, message: '请输入类型名称', trigger: 'blur' }],
+})
+
+const page = ref(1)
+const total = ref(0)
+const pageSize = ref(10)
+const tableData = ref([])
+const searchInfo = ref({
+  searchKey: "type_name",
+})
+
+const onReset = () => {
+  searchInfo.value = {}
   getTableData()
-  
-  // 批量操作
-  const handleSelectionChange = (val) => {
-    apis.value = val
-  }
-  
-  const deleteVisible = ref(false)
-  const onDelete = async() => {
-    const ids = apis.value.map(item => item.id)
-    const res = await deleteApisByIds({ ids })
-    if (res.code === 0) {
-      ElMessage({
-        type: 'success',
-        message: res.msg
-      })
-      if (tableData.value.length === ids.length && page.value > 1) {
-        page.value--
-      }
-      deleteVisible.value = false
-      getTableData()
+}
+// 搜索
+
+const onSubmit = () => {
+  page.value = 1
+  pageSize.value = 10
+  getTableData()
+}
+
+// 分页
+const handleSizeChange = (val) => {
+  pageSize.value = val
+  getTableData()
+}
+
+const handleCurrentChange = (val) => {
+  page.value = val
+  getTableData()
+}
+
+// 排序
+const sortChange = ({ prop, order }) => {
+  if (prop) {
+    if (prop === 'ID') {
+      prop = 'id'
     }
+    searchInfo.value.orderKey = toSQLLine(prop)
+    searchInfo.value.desc = order === 'descending'
   }
-  
-  // 弹窗相关
-  const apiForm = ref(null)
-  const initForm = () => {
-    apiForm.value.resetFields()
-    form.value = {
-        type_name: '',
-        type_desc: ''
-    }
+  getTableData()
+}
+
+// 查询
+const getTableData = async () => {
+  const table = await getApiList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
+  if (table.code === 0) {
+    tableData.value = table.data.list
+    total.value = table.data.total
+    page.value = table.data.page
+    pageSize.value = table.data.pageSize
   }
-  
-  const dialogTitle = ref('新增Api')
-  const dialogFormVisible = ref(false)
-  const openDialog = (key) => {
-    switch (key) {
-      case 'addAccountType':
-        dialogTitle.value = '新增'
-        break
-      case 'editAccountType':
-        dialogTitle.value = '编辑'
-        break
-      default:
-        break
+}
+
+getTableData()
+
+// 批量操作
+const handleSelectionChange = (val) => {
+  apis.value = val
+}
+
+const deleteVisible = ref(false)
+const onDelete = async () => {
+  const ids = apis.value.map(item => item.id)
+  const res = await deleteApisByIds({ ids })
+  if (res.code === 0) {
+    ElMessage({
+      type: 'success',
+      message: res.msg
+    })
+    if (tableData.value.length === ids.length && page.value > 1) {
+      page.value--
     }
-    type.value = key
-    dialogFormVisible.value = true
+    deleteVisible.value = false
+    getTableData()
   }
-  const closeDialog = () => {
-    initForm()
-    dialogFormVisible.value = false
+}
+
+// 弹窗相关
+const apiForm = ref(null)
+const initForm = () => {
+  apiForm.value.resetFields()
+  form.value = {
+    type_name: '',
+    type_desc: ''
   }
-  
-  const editApiFunc = async(row) => {
-    const res = await getApiById({ id: row.id })
-    form.value = res.data.account_type
-    openDialog('editAccountType')
+}
+
+const dialogTitle = ref('新增Api')
+const dialogFormVisible = ref(false)
+const openDialog = (key) => {
+  switch (key) {
+    case 'addAccountType':
+      dialogTitle.value = '新增'
+      break
+    case 'editAccountType':
+      dialogTitle.value = '编辑'
+      break
+    default:
+      break
   }
-  
-  const enterDialog = async() => {
-    apiForm.value.validate(async valid => {
-      if (valid) {
-        switch (type.value) {
-          case 'addAccountType':
-            {
-              const res = await createApi(form.value)
-              if (res.code === 0) {
-                ElMessage({
-                  type: 'success',
-                  message: '添加成功',
-                  showClose: true
-                })
-              }
-              getTableData()
-              closeDialog()
-            }
-  
-            break
-          case 'editAccountType':
-            {
-              const res = await updateApi(form.value)
-              if (res.code === 0) {
-                ElMessage({
-                  type: 'success',
-                  message: '编辑成功',
-                  showClose: true
-                })
-              }
-              getTableData()
-              closeDialog()
+  type.value = key
+  dialogFormVisible.value = true
+}
+const closeDialog = () => {
+  initForm()
+  dialogFormVisible.value = false
+}
+
+const editApiFunc = async (row) => {
+  const res = await getApiById({ id: row.id })
+  form.value = res.data.account_type
+  openDialog('editAccountType')
+}
+
+const enterDialog = async () => {
+  apiForm.value.validate(async valid => {
+    if (valid) {
+      switch (type.value) {
+        case 'addAccountType':
+          {
+            const res = await createApi(form.value)
+            if (res.code === 0) {
+              ElMessage({
+                type: 'success',
+                message: '添加成功',
+                showClose: true
+              })
             }
-            break
-          default:
-            // eslint-disable-next-line no-lone-blocks
-            {
+            getTableData()
+            closeDialog()
+          }
+
+          break
+        case 'editAccountType':
+          {
+            const res = await updateApi(form.value)
+            if (res.code === 0) {
               ElMessage({
-                type: 'error',
-                message: '未知操作',
+                type: 'success',
+                message: '编辑成功',
                 showClose: true
               })
             }
-            break
+            getTableData()
+            closeDialog()
+          }
+          break
+        default:
+          // eslint-disable-next-line no-lone-blocks
+          {
+            ElMessage({
+              type: 'error',
+              message: '未知操作',
+              showClose: true
+            })
+          }
+          break
+      }
+    }
+  })
+}
+
+const deleteApiFunc = async (row) => {
+  ElMessageBox.confirm('此操作将永久删除此账号类型, 是否继续?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning'
+  })
+    .then(async () => {
+      const res = await deleteApi(row)
+      if (res.code === 0) {
+        ElMessage({
+          type: 'success',
+          message: '删除成功!'
+        })
+        if (tableData.value.length === 1 && page.value > 1) {
+          page.value--
         }
+        getTableData()
       }
     })
-  }
-  
-  const deleteApiFunc = async(row) => {
-    ElMessageBox.confirm('此操作将永久删除此账号类型, 是否继续?', '提示', {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning'
-    })
-      .then(async() => {
-        const res = await deleteApi(row)
-        if (res.code === 0) {
-          ElMessage({
-            type: 'success',
-            message: '删除成功!'
-          })
-          if (tableData.value.length === 1 && page.value > 1) {
-            page.value--
-          }
-          getTableData()
-        }
-      })
-  }
-  
-  </script>
+}
+
+</script>
   
-  <style scoped lang="scss">
-  .button-box {
-    padding: 10px 20px;
-    .el-button {
-      float: right;
-    }
-  }
-  .warning {
-    color: #dc143c;
+<style scoped lang="scss">
+.button-box {
+  padding: 10px 20px;
+
+  .el-button {
+    float: right;
   }
-  </style>
+}
+
+.warning {
+  color: #dc143c;
+}
+</style>
   

+ 69 - 0
tsconfig.json

@@ -0,0 +1,69 @@
+{
+    "compilerOptions": {
+        // 允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。
+        "allowSyntheticDefaultImports": true,
+        // 解析非相对模块名的基准目录
+        "baseUrl": ".",
+        "esModuleInterop": true,
+        // 从 tslib 导入辅助工具函数(比如 __extends, __rest等)
+        "importHelpers": true,
+        // 指定生成哪个模块系统代码
+        "module": "esnext",
+        // 决定如何处理模块。
+        "moduleResolution": "node",
+        // 启用所有严格类型检查选项。
+        // 启用 --strict相当于启用 --noImplicitAny, --noImplicitThis, --alwaysStrict,
+        // --strictNullChecks和 --strictFunctionTypes和--strictPropertyInitialization。
+        "strict": true,
+        "noImplicitAny": false, //关闭implicitly has an 'any' type
+        // 支持jsx语法
+        "jsx": "preserve",
+        // 生成相应的 .map文件。
+        "sourceMap": true,
+        // 忽略所有的声明文件( *.d.ts)的类型检查。
+        "skipLibCheck": true,
+        // 指定ECMAScript目标版本
+        "target": "esnext",
+        // 要包含的类型声明文件名列表
+        "types": [
+            "node"
+        ],
+        "typeRoots": [
+            "../node_modules/@types"
+        ],
+        "isolatedModules": true,
+        // 模块名到基于 baseUrl的路径映射的列表。
+        "paths": {
+            "@/*": [
+                "src/*"
+            ]
+        },
+        "vueCompilerOptions": {
+            "experimentalDisableTemplateSupport": true //去掉volar下el标签红色波浪线问题
+        },
+        // 编译过程中需要引入的库文件的列表。
+        "lib": [
+            "ESNext",
+            "DOM",
+            "DOM.Iterable",
+            "ScriptHost"
+        ]
+    },
+    // 解析的文件
+    "include": [
+        "src/**/*.ts",
+        "src/**/*.d.ts",
+        "src/**/*.tsx",
+        "src/**/*.vue",
+        "src/*.js",
+        "src/**/*.jsx",
+    ],
+    "exclude": [
+        "node_modules"
+    ],
+    "references": [
+        {
+            "path": "./tsconfig.json"
+        }
+    ]
+}