Selaa lähdekoodia

Merge branch 'master' of http://10.8.230.114:3000/wangbin/log-server-web

maker 3 vuotta sitten
vanhempi
commit
d6e35a4aff

+ 39 - 1
src/api/data_abnormal_rate.js

@@ -2,7 +2,7 @@
  * @Author: 倚楼听风雨 18408246387@163.com
  * @Date: 2023-02-02 13:47:20
  * @LastEditors: 倚楼听风雨 18408246387@163.com
- * @LastEditTime: 2023-02-08 11:51:59
+ * @LastEditTime: 2023-02-13 11:22:07
  * @FilePath: \log-server-web\src\api\data_abnormal_rate.js
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -40,3 +40,41 @@ export const getWeChatScannerLedgerList = (data) => {
     data,
   });
 };
+export const exportLedgerListExcel = (tableData, fileName) => {
+  service({
+    url: "/dataStatistics/exportLedgerListExcel",
+    method: "post",
+    data: {
+      fileName: fileName,
+      infoList: tableData,
+    },
+    responseType: "blob",
+  }).then((res) => {
+    handleFileError(res, fileName);
+  });
+};
+
+const handleFileError = (res, fileName) => {
+  if (typeof (res.data) !== 'undefined') {
+    if (res.data.type === 'application/json') {
+      const reader = new FileReader()
+      reader.onload = function() {
+        const message = JSON.parse(reader.result).msg
+        ElMessage({
+          showClose: true,
+          message: message,
+          type: 'error'
+        })
+      }
+      reader.readAsText(new Blob([res.data]))
+    }
+  } else {
+    var downloadUrl = window.URL.createObjectURL(new Blob([res]))
+    var a = document.createElement('a')
+    a.style.display = 'none'
+    a.href = downloadUrl
+    a.download = fileName
+    var event = new MouseEvent('click')
+    a.dispatchEvent(event)
+  }
+}

+ 23 - 0
src/api/log.js

@@ -68,6 +68,14 @@ export const updateComputerUseRemarks = (data) => {
   })
 }
 
+export const getLogScanningList = (data) => {
+  return service({
+    url: '/loging/getLogScanningList',
+    method: 'post',
+    data
+  })
+}
+
 
 const handleFileError = (res, fileName) => {
   if (typeof (res.data) !== 'undefined') {
@@ -114,4 +122,19 @@ export const exportExcel = (tableData, fileName) => {
   }).then((res) => {
     handleFileError(res, fileName)
   })
+}
+
+
+export const computerRateExport = (tableData, fileName) => {
+  service({
+    url: '/loging/computerRateExport',
+    method: 'post',
+    data: {
+      fileName: fileName,
+      infoList: tableData
+    },
+    responseType: 'blob'
+  }).then((res) => {
+    handleFileError(res, fileName)
+  })
 }

+ 76 - 1
src/api/rentComputer.js

@@ -2,7 +2,7 @@
  * @Author: 倚楼听风雨 18408246387@163.com
  * @Date: 2023-01-09 16:01:45
  * @LastEditors: 倚楼听风雨 18408246387@163.com
- * @LastEditTime: 2023-01-16 17:21:43
+ * @LastEditTime: 2023-02-20 09:49:31
  * @FilePath: \log-server-web\src\api\rentComputer.js
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
@@ -167,5 +167,80 @@ export const uploadExcel = (data) => {
     data,
   });
 };
+export const renewRentComputer = (data) => {
+  return service({
+    url: "/rentComputer/renewRentComputer",
+    method: "post",
+    data,
+  });
+};
+export const replaceNumRentComputer = (data) => {
+  return service({
+    url: "/rentComputer/replaceNumRentComputer",
+    method: "post",
+    data,
+  });
+};
+export const rentingOutRentComputer = (data) => {
+  return service({
+    url: "/rentComputer/rentingOutRentComputer",
+    method: "post",
+    data,
+  });
+};
 
 //RentComputer============================================================================
+//RentComputerLedger============================================================================
+export const getRentComputerLedgerList = (data) => {
+  return service({
+    url: "/rentComputer/getRentComputerLedgerList",
+    method: "post",
+    data,
+  });
+};
+export const getRentComputerLedgerNum = (data) => {
+  return service({
+    url: "/rentComputer/getRentComputerLedgerNum",
+    method: "post",
+    data,
+  });
+};
+export const exportRentLedgerListExcel = (tableData, fileName) => {
+  service({
+    url: "/rentComputer/exportRentLedgerListExcel",
+    method: "post",
+    data: {
+      fileName: fileName,
+      infoList: tableData,
+    },
+    responseType: "blob",
+  }).then((res) => {
+    handleFileError(res, fileName);
+  });
+};
+
+const handleFileError = (res, fileName) => {
+  if (typeof res.data !== "undefined") {
+    if (res.data.type === "application/json") {
+      const reader = new FileReader();
+      reader.onload = function () {
+        const message = JSON.parse(reader.result).msg;
+        ElMessage({
+          showClose: true,
+          message: message,
+          type: "error",
+        });
+      };
+      reader.readAsText(new Blob([res.data]));
+    }
+  } else {
+    var downloadUrl = window.URL.createObjectURL(new Blob([res]));
+    var a = document.createElement("a");
+    a.style.display = "none";
+    a.href = downloadUrl;
+    a.download = fileName;
+    var event = new MouseEvent("click");
+    a.dispatchEvent(event);
+  }
+};
+//RentComputerLedger============================================================================

+ 57 - 31
src/api/responsiblePerson.js

@@ -1,4 +1,4 @@
-import service from '@/utils/request'
+import service from "@/utils/request";
 // @Tags api
 // @Summary 分页获取角色列表
 // @Security ApiKeyAuth
@@ -13,11 +13,11 @@ import service from '@/utils/request'
 // }
 export const getApiList = (data) => {
   return service({
-    url: '/responsiblePerson/getResponsiblePerson',
-    method: 'post',
-    data
-  })
-}
+    url: "/responsiblePerson/getResponsiblePerson",
+    method: "post",
+    data,
+  });
+};
 
 // @Tags Api
 // @Summary 创建基础api
@@ -29,11 +29,11 @@ export const getApiList = (data) => {
 // @Router /api/createApi [post]
 export const createApi = (data) => {
   return service({
-    url: '/responsiblePerson/createResponsiblePerson',
-    method: 'post',
-    data
-  })
-}
+    url: "/responsiblePerson/createResponsiblePerson",
+    method: "post",
+    data,
+  });
+};
 
 // @Tags menu
 // @Summary 根据id获取菜单
@@ -45,11 +45,11 @@ export const createApi = (data) => {
 // @Router /menu/getApiById [post]
 export const getApiById = (data) => {
   return service({
-    url: '/responsiblePerson/getResponsiblePersonById',
-    method: 'post',
-    data
-  })
-}
+    url: "/responsiblePerson/getResponsiblePersonById",
+    method: "post",
+    data,
+  });
+};
 
 // @Tags Api
 // @Summary 更新api
@@ -61,11 +61,11 @@ export const getApiById = (data) => {
 // @Router /api/updateApi [post]
 export const updateApi = (data) => {
   return service({
-    url: '/responsiblePerson/updateResponsiblePerson',
-    method: 'post',
-    data
-  })
-}
+    url: "/responsiblePerson/updateResponsiblePerson",
+    method: "post",
+    data,
+  });
+};
 
 // @Tags Api
 // @Summary 更新api
@@ -108,11 +108,11 @@ export const updateApi = (data) => {
 // @Router /api/deleteApi [post]
 export const deleteApi = (data) => {
   return service({
-    url: '/responsiblePerson/deleteResponsiblePerson',
-    method: 'post',
-    data
-  })
-}
+    url: "/responsiblePerson/deleteResponsiblePerson",
+    method: "post",
+    data,
+  });
+};
 
 // @Tags SysApi
 // @Summary 删除选中Api
@@ -124,8 +124,34 @@ export const deleteApi = (data) => {
 // @Router /api/deleteApisByIds [delete]
 export const deleteApisByIds = (data) => {
   return service({
-    url: '/responsiblePerson/deleteResponsiblePersonsByIds',
-    method: 'delete',
-    data
-  })
-}
+    url: "/responsiblePerson/deleteResponsiblePersonsByIds",
+    method: "delete",
+    data,
+  });
+};
+
+/***
+ * 获取在职使用人列表
+ */
+export const getDirectorList = (data) => {
+  return service({
+    url: "/responsiblePerson/getDirectorList",
+    method: "post",
+    data,
+  });
+};
+
+// @Tags SysApi
+// @Summary 获取列表筛选
+// @Security ApiKeyAuth
+// @accept application/json
+// @Produce application/json
+// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功成功"}"
+// @Router /responsiblePerson/selectResponsiblePerson [post]
+export const selectResponsiblePerson = (data) => {
+  return service({
+    url: "/responsiblePerson/selectResponsiblePerson",
+    method: "post",
+    data,
+  });
+};

+ 103 - 0
src/api/task.js

@@ -70,4 +70,107 @@ export const createGameTask = (data) => {
       method: 'post',
       data
     })
+  }
+
+  export const everyDayStatistics = (data) => {
+    return service({
+      url: '/gameTask/everyDayStatistics',
+      method: 'post',
+      data
+    })
+  }
+
+  export const monthStatistics = (data) => {
+    return service({
+      url: '/gameTask/monthStatistics',
+      method: 'post',
+      data
+    })
+  }
+  
+  export const gameStatistics = (data) => {
+    return service({
+      url: '/gameTask/gameStatistics',
+      method: 'post',
+      data
+    })
+  }
+
+  export const gameList = (data) => {
+    return service({
+      url: '/gameTask/gameList',
+      method: 'post',
+      data
+    })
+  }
+
+  export const getGameTxTaskList = (data) => {
+    return service({
+      url: '/gameTask/getGameTxTaskList',
+      method: 'post',
+      data
+    })
+  }
+
+  export const taskResetFee = (data) => {
+    return service({
+      url: '/gameTask/taskResetFee',
+      method: 'post',
+      data
+    })
+  }
+
+  export const getFeeAccountList = (data) => {
+    return service({
+      url: '/gameTask/getFeeAccountList',
+      method: 'post',
+      data
+    })
+  }
+
+  const handleFileError = (res, fileName) => {
+    if (typeof (res.data) !== 'undefined') {
+      if (res.data.type === 'application/json') {
+        const reader = new FileReader()
+        reader.onload = function() {
+          const message = JSON.parse(reader.result).msg
+          ElMessage({
+            showClose: true,
+            message: message,
+            type: 'error'
+          })
+        }
+        reader.readAsText(new Blob([res.data]))
+      }
+    } else {
+      var downloadUrl = window.URL.createObjectURL(new Blob([res]))
+      var a = document.createElement('a')
+      a.style.display = 'none'
+      a.href = downloadUrl
+      a.download = fileName
+      var event = new MouseEvent('click')
+      a.dispatchEvent(event)
+    }
+  }
+  
+  // @Tags excel
+  // @Summary 导出Excel
+  // @Security ApiKeyAuth
+  // @accept application/json
+  // @Produce  application/octet-stream
+  // @Param data body model.ExcelInfo true "导出Excel文件信息"
+  // @Success 200
+  // @Router /gameTask/taskTargetExport [post]
+  export const taskTargetExport = (tableData, fileName) => {
+    service({
+      url: '/gameTask/taskTargetExport',
+      method: 'post',
+      data: {
+        fileName: fileName,
+        infoList: tableData
+      },
+      responseType: 'blob'
+    }).then((res) => {
+      handleFileError(res, fileName)
+    })
   }

+ 2 - 2
src/view/about/index.vue

@@ -49,7 +49,7 @@
             </el-row>
           </div>
         </el-card>
-        <el-card style="margin-top: 20px">
+        <!-- <el-card style="margin-top: 20px">
           <template #header>
             <div>flipped-aurora团队</div>
           </template>
@@ -74,7 +74,7 @@
               </el-col>
             </el-row>
           </div>
-        </el-card>
+        </el-card> -->
       </el-col>
       <el-col :span="12">
         <el-card>

+ 38 - 19
src/view/dataStatistics/data_abnormal_rate.vue

@@ -41,7 +41,6 @@
       <el-table
         :data="tableData"
         border
-        style="width: 100%; cursor: pointer"
         stripe
         align="center"
         header-align="center"
@@ -165,23 +164,6 @@
             </el-table-column>
           </el-table-column>
         </el-table-column>
-        <el-table-column label="下发账号" align="center">
-          <el-table-column label="脚本启动" align="center">
-            <el-table-column
-              prop="num_pull_account,num_start_script"
-              align="center"
-              label="成功率"
-              sortable
-              :sort-method="sortBySuccess2"
-            >
-              <template #default="scope">
-                {{ scope.row.step2 }}
-                <el-divider style="margin: 0" />
-                {{ Math.round(scope.row.rate2 * 10000) / 100 + "%" }}
-              </template>
-            </el-table-column>
-          </el-table-column>
-        </el-table-column>
         <el-table-column label="脚本启动" align="center">
           <el-table-column label="进入游戏" align="center">
             <el-table-column
@@ -202,6 +184,23 @@
             </el-table-column>
           </el-table-column>
         </el-table-column>
+        <el-table-column label="下发账号" align="center">
+          <el-table-column label="脚本启动" align="center">
+            <el-table-column
+              prop="num_pull_account,num_start_script"
+              align="center"
+              label="成功率"
+              sortable
+              :sort-method="sortBySuccess2"
+            >
+              <template #default="scope">
+                {{ scope.row.step2 }}
+                <el-divider style="margin: 0" />
+                {{ Math.round(scope.row.rate2 * 10000) / 100 + "%" }}
+              </template>
+            </el-table-column>
+          </el-table-column>
+        </el-table-column>
         <el-table-column label="脚本启动" align="center">
           <el-table-column label="活跃成功" align="center">
             <el-table-column
@@ -242,6 +241,26 @@
             </el-table-column>
           </el-table-column>
         </el-table-column>
+        <el-table-column label="微信扫码" align="center">
+          <el-table-column label="新增成功" align="center">
+            <el-table-column
+              prop="num_into_game,num_start_game"
+              label="成功率"
+              align="center"
+              sortable
+              :sort-method="sortBySuccess3"
+            >
+              <template #default="scope">
+                {{ scope.row.num_start_script }}
+                <el-divider style="margin: 0 5px" direction="vertical" />{{
+                  scope.row.num_into_game
+                }}
+                <el-divider style="margin: 0" />
+                {{ Math.round(scope.row.rate3 * 10000) / 100 + "%" }}
+              </template>
+            </el-table-column>
+          </el-table-column>
+        </el-table-column>
         <!-- <el-table-column
           fixed="right"
           label="操作"
@@ -379,7 +398,7 @@ const sortChange = ({ prop, order }) => {
 const onSubmit = () => {
   loading.value = true;
   page.value = 1;
-  pageSize.value = 10;
+  pageSize.value = 100;
 
   if (typeof searchInfo.value.task_id != "undefined") {
     searchInfo.value.task_id = Number(searchInfo.value.task_id);

+ 44 - 1
src/view/dataStatistics/wechat_scanner_ledger.vue

@@ -30,6 +30,14 @@
             <el-button size="small" icon="refresh" @click="onReset"
               >重置</el-button
             >
+            <el-button
+              class="excel-btn"
+              size="small"
+              type="primary"
+              icon="download"
+              @click="handleExcelExport"
+              >导出表格</el-button
+            >
           </el-form-item>
         </el-form>
       </div>
@@ -69,6 +77,20 @@
           min-width="100"
           prop="platform"
         />
+        <el-table-column label="单价" align="center" min-width="200">
+          <el-table-column
+            align="left"
+            label="新增单价"
+            min-width="100"
+            prop="unit_price_new"
+          />
+          <el-table-column
+            align="left"
+            label="留存单价"
+            min-width="100"
+            prop="unit_price_retained"
+          />
+        </el-table-column>
         <el-table-column
           align="left"
           label="消耗"
@@ -111,7 +133,10 @@ export default {
 </script>
 
 <script setup>
-import { getWeChatScannerLedgerList } from "@/api/data_abnormal_rate";
+import {
+  getWeChatScannerLedgerList,
+  exportLedgerListExcel,
+} from "@/api/data_abnormal_rate";
 import { toSQLLine } from "@/utils/stringFun";
 import { ref } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
@@ -187,6 +212,24 @@ const sortChange = ({ prop, order }) => {
   getTableData();
 };
 
+const handleExcelExport = async () => {
+  var fileName = "";
+  if (searchInfo.value.new_date == null) {
+    let dt = new Date();
+    var y = dt.getFullYear();
+    var mt = (dt.getMonth() + 1).toString().padStart(2, "0");
+    var day = dt.getDate().toString().padStart(2, "0");
+    var timeStr = y + "-" + mt + "-" + day;
+    fileName = timeStr + "-扫码消耗明细.xlsx";
+  } else {
+    fileName = searchInfo.value.new_date + "-扫码消耗明细.xlsx";
+  }
+  exportLedgerListExcel(
+    { page: page.value, pageSize: pageSize.value, ...searchInfo.value },
+    fileName
+  );
+};
+
 // 搜索
 const onSubmit = () => {
   page.value = 1;

+ 205 - 42
src/view/gameTarget/target.vue

@@ -5,55 +5,101 @@
           <el-form-item label="任务Id">
             <el-input v-model="searchInfo.task_id" placeholder="任务ID" />
           </el-form-item>
-          <el-form-item label="使用者">
-            <el-input v-model="searchInfo.user" placeholder="使用者" />
+          <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 label="日期" prop="create_date">
-          <el-date-picker
-            v-model="searchInfo.create_date"
-            popper-class="picker-popovers"
-            class="timefilter"
-            type="datetime"
-            placeholder="选择日期时间"
-            value-format="YYYY-MM-DD"
-          >
-          </el-date-picker>
+          <el-form-item label="游戏端口">
+            <el-select v-model="searchInfo.game_port_id" placeholder="请选择" style="width:100%">
+                  <el-option
+                    v-for="item in GamePortOptions"
+                    :key="item.id"
+                    :label="`${item.name}`"
+                    :value="item.id"
+                  />
+                </el-select>
+          </el-form-item>
+          
+          <el-form-item label="状态">
+          <el-select v-model="searchInfo.is_complete" placeholder="是否完成" >
+              <el-option
+                v-for="item in searchStatusOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+                :disabled="item.disabled"
+              />
+            </el-select>
         </el-form-item>
+        <el-form-item label="日期" prop="date">
+            <el-date-picker
+              v-model="searchInfo.date"
+              size="default"
+              type="daterange"
+              unlink-panels
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              :disabled-date="disabledDate"
+              :shortcuts="shortcuts"
+            />
+          </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-button class="excel-btn" size="small" type="primary" icon="download" @click="handleExcelExport">导出</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 label="任务ID" min-width="60" prop="task_id" sortable="custom" />
-          <el-table-column label="任务日期" min-width="70" prop="create_date" />
-          <el-table-column label="任务名称" min-width="80" prop="task_name" sortable="custom" />
-          <el-table-column label="负责人" min-width="60" prop="user" sortable="custom" />
-          <el-table-column label="登录方式" min-width="60" prop="login_method" />
-          <el-table-column label="新增目标" min-width="45" prop="new_target" />
-          <el-table-column  label="新增完成" min-width="45" prop="new_complete" />
-          <el-table-column  label="留存目标" min-width="45" prop="retained_target" />
-          <el-table-column label="留存完成" min-width="45" prop="retained_complete" />
-          <el-table-column  label="付费目标" min-width="45" prop="pay_target" />
-          <el-table-column  label="付费完成" min-width="45" prop="pay_complete" />
-          <el-table-column  label="付费流水" min-width="45" prop="amount"/>
-          <el-table-column  label="手动新增" min-width="45" prop="hand_new_complete"/>
-          <el-table-column  label="手动留存" min-width="45" prop="hand_retained_complete"/>
-          <el-table-column  label="手动付费" min-width="45" prop="hand_pay_complete"/>
-          <el-table-column align="left" label="是否完成" min-width="45" prop="is_complete" >
+        
+        <el-table :data="tableData" border @sort-change="sortChange" @selection-change="handleSelectionChange" style="width: 100%">
+          <el-table-column label="任务ID" width="70" prop="task_id" sortable="custom" />
+          <el-table-column label="任务日期" min-width="100" prop="create_date" />
+          <el-table-column label="任务名称" width="130" prop="task_name" sortable="custom" />
+          <el-table-column label="负责人" width="75" prop="user" sortable="custom" />
+          <el-table-column label="登录方式" width="75" prop="login_method" />
+          <el-table-column label="新增目标" width="75" prop="new_target" />
+          <el-table-column  label="新增完成" width="75" prop="new_complete" />
+          <el-table-column  label="剩余新增" width="75" prop="new_target1">
+            <template #default="scope">
+              {{ scope.row.new_target <= scope.row.new_complete  ? 0 : scope.row.new_complete-scope.row.new_target}}
+            </template>
+          </el-table-column>
+          <el-table-column  label="留存目标" width="75" prop="retained_target" />
+          <el-table-column label="留存完成" width="75" prop="retained_complete" />
+          <el-table-column label="剩余留存" width="75" prop="retained_target1">
+            <template #default="scope">
+              {{ scope.row.retained_target <= scope.row.retained_complete  ? 0 : scope.row.retained_complete-scope.row.retained_target}}
+            </template>
+          </el-table-column>
+          <el-table-column  label="付费目标" width="75" prop="pay_target" />
+          <el-table-column label="付费完成" width="75" prop="pay_complete" />
+          <el-table-column label="剩余付费" width="75" prop="pay_target1">
+            <template #default="scope">
+              {{ scope.row.pay_target <= scope.row.pay_complete  ? 0 : scope.row.pay_complete-scope.row.pay_target}}
+            </template>
+          </el-table-column>
+          <el-table-column label="付费流水" width="75" prop="amount"/>
+          <el-table-column label="群控效率" width="75" prop="game_rate"/>
+          <el-table-column label="手动新增" width="75" prop="hand_new_complete"/>
+          <el-table-column label="手动留存" width="75" prop="hand_retained_complete"/>
+          <el-table-column label="手动付费" width="75" prop="hand_pay_complete"/>
+          <el-table-column label="手动付费金额" width="75" prop="hand_amount_total"/>
+          <el-table-column fixed="right" align="right" label="是否完成" width="75" prop="is_complete" >
           <template #default="scope">
             <div>
               <el-tag :type="scope.row.is_complete === -1 ? 'warning' : 'success'">{{ statusFiletr(scope.row.is_complete) }}</el-tag>
             </div>
           </template>
         </el-table-column>
-          <el-table-column align="left" fixed="right" label="操作" width="200">
+          <el-table-column fixed="right" label="操作" width="160">
             <template #default="scope">
               <el-button
                 icon="edit"
@@ -62,6 +108,20 @@
                 link
                 @click="editCardFunc(scope.row)"
               >编辑</el-button>
+              <el-button
+                icon="edit"
+                size="small"
+                type="primary"
+                link
+                @click="resetFeeFunc(scope.row)"
+              >重置付费</el-button>
+              <el-button
+                icon="edit"
+                size="small"
+                type="primary"
+                link
+                @click="accountListFunc(scope.row)"
+              >可付费账号</el-button>
             </template>
           </el-table-column>
         </el-table>
@@ -203,6 +263,17 @@
           </div>
         </template>
       </el-dialog>
+      <el-dialog v-model="accountFormVisible" :before-close="closeAccount" :title="accountTitle">
+        <el-table :data="tableData1">
+          <el-table-column align="left" label="账号" show-overflow-tooltip min-width="160" prop="account" />
+          <el-table-column align="left" label="密码" show-overflow-tooltip min-width="160" prop="password" />
+        </el-table>
+        <template #footer>
+          <div class="dialog-footer">
+            <el-button size="small" @click="closeAccount">取 消</el-button>
+          </div>
+        </template>
+    </el-dialog>
     </div>
   </template>
   
@@ -217,10 +288,17 @@
     getGameTaskTargetById,
     updateGameTaskTarget,
     getGameTaskTargetList,
+    taskResetFee,
+    getFeeAccountList,
+    taskTargetExport
   } from '@/api/task'
+  import {
+    selectResponsiblePerson,
+} from '@/api/responsiblePerson'
   import { toSQLLine } from '@/utils/stringFun'
   import warningBar from '@/components/warningBar/warningBar.vue'
   import { ref } from 'vue'
+  import dayjs from "dayjs";
   import { ElMessage, ElMessageBox } from 'element-plus'
 
   const statusFiletr = (value) => {
@@ -241,6 +319,7 @@
   },
 ])
 
+const ResponsiblePerson = ref([])
   
   const apis = ref([])
   const rules = ref({
@@ -332,6 +411,19 @@
     },
   ])
 
+  const searchStatusOptions = ref([
+ {
+    value: -1,
+    label: '未完成',
+    type: 'wain'
+  },
+  {
+    value: 1,
+    label: '已完成',
+    type: 'success'
+  },
+])
+
   const accountTypeOptions = ref([
     {
       id: 1,
@@ -436,6 +528,7 @@ const deleteBtn = async(btns, index) => {
   const total = ref(0)
   const pageSize = ref(10)
   const tableData = ref([])
+  const tableData1 = ref([])
   const searchInfo = ref({})
   
   const onReset = () => {
@@ -447,6 +540,14 @@ const deleteBtn = async(btns, index) => {
     page.value = 1
     pageSize.value = 10
     searchInfo.value.task_id = Number(searchInfo.value.task_id)
+    if (typeof searchInfo.value.date != "undefined") {
+      searchInfo.value.date[0] = dayjs(searchInfo.value.date[0]).format(
+        "YYYY-MM-DD"
+      );
+      searchInfo.value.date[1] = dayjs(searchInfo.value.date[1]).format(
+        "YYYY-MM-DD"
+      );
+  }
     getTableData()
   }
   
@@ -485,11 +586,63 @@ const deleteBtn = async(btns, index) => {
   }
   
   getTableData()
+
   
+  const getResponsiblePerson = async() => {
+    const table = await selectResponsiblePerson()
+    if (table.code === 0) {
+      ResponsiblePerson.value = table.data
+    }
+  }
+  getResponsiblePerson()
   // 批量操作
   const handleSelectionChange = (val) => {
     apis.value = val
   }
+
+  const handleExcelExport = async() => {
+    var fileName = Date.parse(new Date()) + "-task.xlsx"
+    if(searchInfo.value.create_date == null){
+      let dt = new Date()
+            var y = dt.getFullYear()
+            var mt = (dt.getMonth() + 1).toString().padStart(2,'0')
+            var day = dt.getDate().toString().padStart(2,'0')
+            var timeStr = y + "-" + mt + "-" + day
+      fileName = timeStr + "-task.xlsx"
+    }else{
+      fileName = searchInfo.value.create_date + "-task.xlsx"
+    }
+    taskTargetExport({ page: page.value, pageSize: pageSize.value, ...searchInfo.value },fileName)
+}
+
+  const shortcuts = [
+  {
+    text: "今日",
+    value: () => {
+      const end = new Date();
+      const start = new Date();
+      return [start, end];
+    },
+  },
+  {
+    text: "最近一周",
+    value: () => {
+      const end = new Date();
+      const start = new Date();
+      start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
+      return [start, end];
+    },
+  },
+  {
+    text: "最近一月",
+    value: () => {
+      const end = new Date();
+      const start = new Date();
+      start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
+      return [start, end];
+    },
+  },
+];
   
   const deleteVisible = ref(false)
   
@@ -557,6 +710,7 @@ const deleteBtn = async(btns, index) => {
   
   const dialogTitle = ref('新增')
   const dialogFormVisible = ref(false)
+  const accountFormVisible = ref(false)
   const openDialog = (key) => {
     switch (key) {
       case 'addCard':
@@ -577,6 +731,10 @@ const deleteBtn = async(btns, index) => {
     initForm()
     dialogFormVisible.value = false
   }
+
+  const closeAccount = () => {
+    accountFormVisible.value = false
+  }
   
   const editCardFunc = async(row) => {
     const res = await getGameTaskTargetById({ id: row.task_id, create_date:row.create_date })
@@ -584,7 +742,15 @@ const deleteBtn = async(btns, index) => {
       form.value = res.data
       openDialog('edit')
     }
-    
+  }
+
+  const accountListFunc = async(row) => {
+    const res = await getFeeAccountList({ id: row.task_id, create_date:row.create_date })
+    if (res.code === 0) {
+      tableData1.value = res.data
+      dialogTitle.value = '可付费账号'
+      accountFormVisible.value = true
+    }
   }
   
   const enterDialog = async() => {
@@ -633,22 +799,19 @@ const deleteBtn = async(btns, index) => {
     })
   }
   
-  const deleteApiFunc = async(row) => {
-    ElMessageBox.confirm('此操作将永久删除所有角色下该api, 是否继续?', '提示', {
+  const resetFeeFunc = async(row) => {
+    ElMessageBox.confirm('此操作将重置付费, 是否继续?', '提示', {
       confirmButtonText: '确定',
       cancelButtonText: '取消',
       type: 'warning'
     })
       .then(async() => {
-        const res = await deleteGameTask(row)
+        const res = await taskResetFee(row)
         if (res.code === 0) {
           ElMessage({
             type: 'success',
-            message: '删除成功!'
+            message: '重置成功!'
           })
-          if (tableData.value.length === 1 && page.value > 1) {
-            page.value--
-          }
           getTableData()
         }
       })

+ 100 - 25
src/view/gameTask/list.vue

@@ -5,9 +5,27 @@
           <el-form-item label="任务Id">
             <el-input v-model="searchInfo.task_id" placeholder="任务Id" />
           </el-form-item>
-          <el-form-item label="使用者">
-            <el-input v-model="searchInfo.user" placeholder="使用者" />
+          <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 label="状态">
+          <el-select v-model="searchInfo.status" placeholder="是否完成" >
+              <el-option
+                v-for="item in searchStatusOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+                :disabled="item.disabled"
+              />
+            </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>
@@ -31,8 +49,16 @@
           <el-table-column align="left" label="登录方式" min-width="60" prop="login_method" />
           <el-table-column align="left" label="开始时间" min-width="80" prop="date" />
           <el-table-column align="left" label="停止时间" min-width="110" prop="stop_time" />
-          <el-table-column align="left" label="新增目标" min-width="45" prop="new_target" />
-          <el-table-column align="left" label="留存目标" min-width="45" prop="retained_target" />
+          <el-table-column align="left" label="新增目标" min-width="80" prop="new_target">
+            <template #default="scope">
+              {{ scope.row.new_target_h === 0 ? 0 : scope.row.new_target+"~"+scope.row.new_target_h}}
+            </template>
+          </el-table-column>
+          <el-table-column align="left" label="留存目标" min-width="80" prop="retained_target">
+            <template #default="scope">
+              {{ scope.row.retained_target_h === scope.row.retained_target ? scope.row.retained_target_h : scope.row.retained_target+"~"+scope.row.retained_target_h}}
+            </template>
+          </el-table-column>
           <el-table-column align="left" label="付费目标" min-width="45" prop="pay_target" />
           <el-table-column align="left" label="付费单价" min-width="45" prop="pay_price"  />
           <!-- <el-table-column align="left" label="状态" min-width="60" prop="status" >
@@ -55,7 +81,7 @@
         </el-table-column>
           <el-table-column align="left" label="创建时间" min-width="120" prop="create_time" sortable="custom" />
           <el-table-column align="left" label="更新时间" min-width="120" prop="update_time" sortable="custom" />
-          <el-table-column align="left" fixed="right" label="操作" width="200">
+          <el-table-column align="left" fixed="right" label="操作" width="140">
             <template #default="scope">
               <el-button
                 icon="edit"
@@ -97,7 +123,14 @@
             <el-input v-model="form.task_name" autocomplete="off"/>
           </el-form-item>
           <el-form-item label="负责人" prop="user" >
-            <el-input v-model="form.user" autocomplete="off"/>
+            <el-select v-model="form.user" placeholder="请选择" style="width:100%">
+                  <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="重要参数">
             <el-radio-group v-model="form.new_retained">
@@ -189,19 +222,27 @@
             </el-form>
           </el-tab-pane>
           <el-tab-pane label="数优目标">
-              <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px" :inline="true">
-                <el-form-item  label="新增目标" prop="new_target">
-                <el-input v-model="form.new_target" autocomplete="off" />
-              </el-form-item>
-              <el-form-item label="付费目标" prop="pay_target">
-                <el-input v-model="form.pay_target" autocomplete="off"/>
-              </el-form-item>
-              <el-form-item label="留存目标" prop="retained_target" >
-                <el-input v-model="form.retained_target" autocomplete="off"/>
-              </el-form-item>
-              <el-form-item label="付费单价" prop="pay_price" >
-                <el-input v-model="form.pay_price" autocomplete="off"/>
-              </el-form-item>
+              <el-form ref="apiForm" :model="form" :rules="rules" label-width="120px" :inline="true">
+                <el-form-item  label="新增目标下限" prop="new_target">
+                  <el-input v-model="form.new_target" autocomplete="off" />
+                </el-form-item>
+                <el-form-item  label="新增目标上限" prop="new_target_h">
+                  <el-input v-model="form.new_target_h" autocomplete="off" />
+                </el-form-item>
+                <el-form-item label="付费目标" prop="pay_target">
+                  <el-input v-model="form.pay_target" autocomplete="off"/>
+                </el-form-item>
+            </el-form>
+            <el-form ref="apiForm" :model="form" :rules="rules" label-width="120px" :inline="true">
+                <el-form-item label="留存目标下限" prop="retained_target" >
+                  <el-input v-model="form.retained_target" autocomplete="off"/>
+                </el-form-item>
+                <el-form-item label="留存目标上限" prop="retained_target_h" >
+                  <el-input v-model="form.retained_target_h" autocomplete="off"/>
+                </el-form-item>
+                <el-form-item label="付费单价" prop="pay_price" >
+                  <el-input v-model="form.pay_price" autocomplete="off"/>
+                </el-form-item>
             </el-form>
           </el-tab-pane>
         </el-tabs>
@@ -237,6 +278,9 @@
     updateGameTask,
     deleteGameTask,
   } from '@/api/task'
+  import {
+    selectResponsiblePerson,
+} from '@/api/responsiblePerson'
   import { useUserStore } from '@/pinia/modules/user'
   import { toSQLLine } from '@/utils/stringFun'
   import warningBar from '@/components/warningBar/warningBar.vue'
@@ -274,6 +318,14 @@
     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 searchStatusOptions = ref([
     {
       value: -1,
@@ -323,14 +375,17 @@
     new_target: [
       { required: true, message: '请输入新增目标', trigger: 'blur' }
     ],
+    new_target_h: [
+      { required: true, message: '请输入新增上限', trigger: 'blur' }
+    ],
     pay_target: [
       { required: true, message: '请输入付费目标', trigger: 'blur' }
     ],
     retained_target: [
       { required: true, message: '请输入留存目标', trigger: 'blur' }
     ],
-    retained_target: [
-      { required: true, message: '请输入付费单价', trigger: 'blur' }
+    retained_target_h: [
+      { required: true, message: '请输入留存上限', trigger: 'blur' }
     ]
   })
   const form = ref({
@@ -630,6 +685,24 @@
       form.value.pay_price = Number(form.value.pay_price)
       form.value.pay_target = Number(form.value.pay_target)
       form.value.retained_target = Number(form.value.retained_target)
+      form.value.new_target_h = Number(form.value.new_target_h)
+      form.value.retained_target_h = Number(form.value.retained_target_h)
+      if(form.value.new_target > form.value.new_target_h){
+        ElMessage({
+                  type: 'warning',
+                  message: '新增目标下限不能大于上限',
+                  showClose: false
+                })
+                return
+      }
+      if(form.value.retained_target > form.value.retained_target_h){
+        ElMessage({
+                  type: 'warning',
+                  message: '活跃目标下限不能大于上限',
+                  showClose: false
+                })
+                return
+      }
       if (valid) {
         switch (type.value) {
           case 'addCard':
@@ -641,9 +714,10 @@
                   message: '添加成功',
                   showClose: true
                 })
+                getTableData()
+                closeDialog()
               }
-              getTableData()
-              closeDialog()
+              
             }
   
             break
@@ -656,9 +730,10 @@
                   message: '编辑成功',
                   showClose: true
                 })
+                getTableData()
+                closeDialog()
               }
-              getTableData()
-              closeDialog()
+              
             }
             break
           default:

+ 1 - 11
src/view/layout/bottomInfo/bottomInfo.vue

@@ -1,16 +1,6 @@
 <template>
   <div class="bottom-info">
-    <div>
-      <span>Powered by</span>
-      <span>
-        <a href="https://github.com/flipped-aurora/gin-vue-admin">{{ $GIN_VUE_ADMIN.appName }}</a>
-      </span>
-      <el-divider direction="vertical" />
-      <span>Copyright</span>
-      <span>
-        <a href="https://github.com/flipped-aurora">flipped-aurora团队</a>
-      </span>
-    </div>
+    
   </div>
 </template>
 

+ 1 - 4
src/view/logComputer/computerUseLog.vue

@@ -43,10 +43,7 @@
         <el-table :data="tableData"  @sort-change="sortChange" @selection-change="handleSelectionChange"
         border
         >
-          <el-table-column
-            type="selection"
-            width="55"
-          />
+          
           <el-table-column align="left" label="电脑编号" min-width="100" prop="pc_code" sortable="custom"/>
           <el-table-column align="left" label="使用者" min-width="150" prop="operator" sortable="custom"/>
           <el-table-column align="left" label="日期" min-width="150" prop="create_date" />

+ 18 - 4
src/view/logComputer/list.vue

@@ -39,13 +39,12 @@
       </el-tooltip>
     </div>
       <div class="gva-table-box">
+        <div class="gva-btn-list">
+        <el-button class="excel-btn" size="small" type="primary" icon="download" @click="handleExcelExport">导出</el-button>
+      </div>
         <el-table :data="tableData"  @sort-change="sortChange" @selection-change="handleSelectionChange"
         border
         >
-          <el-table-column
-            type="selection"
-            width="55"
-          />
           <el-table-column align="left" label="电脑编号" min-width="100" prop="pc_code" sortable="custom"/>
           <el-table-column align="left" label="脚本负责人" min-width="150" prop="operator" sortable="custom"/>
           <el-table-column align="left" label="日期" min-width="150" prop="create_date" />
@@ -101,6 +100,7 @@
   import {
     logComputerList,
     logComputerNum,
+    computerRateExport,
   } from '@/api/log'
   import { toSQLLine } from '@/utils/stringFun'
   import { ref } from 'vue'
@@ -157,6 +157,20 @@
     } 
   }
   
+  const handleExcelExport = async() => {
+    var fileName = Date.parse(new Date()) + "-cpc.xlsx"
+    if(searchInfo.value.create_date == null){
+      let dt = new Date()
+            var y = dt.getFullYear()
+            var mt = (dt.getMonth() + 1).toString().padStart(2,'0')
+            var day = dt.getDate().toString().padStart(2,'0')
+            var timeStr = y + "-" + mt + "-" + day
+      fileName = timeStr + "-cpc.xlsx"
+    }else{
+      fileName = searchInfo.value.create_date + "-cpc.xlsx"
+    }
+    computerRateExport({ page: page.value, pageSize: pageSize.value, ...searchInfo.value },fileName)
+}
 
   const value = ref('')
   const statusList = [

+ 41 - 5
src/view/logStatistics/codeList.vue

@@ -23,12 +23,9 @@
         </el-form>
       </div>
       <div class="gva-table-box">
-        <el-table :data="tableData" @sort-change="sortChange" @selection-change="handleSelectionChange" height="500" style="width: 100%">
-          <el-table-column
-            type="selection"
-            width="55"
-          />
+        <el-table :data="tableData" :span-method="objectSpanMethod" @sort-change="sortChange" @selection-change="handleSelectionChange" height="500" style="width: 100%">
           <el-table-column fixed="left" align="left" label="游戏id" min-width="90" prop="game_id" sortable="custom" />
+          <el-table-column fixed="left" align="left" label="任务名称" min-width="90" prop="game_name" sortable="custom" />
           <el-table-column fixed="left" align="left" label="日期" min-width="90" prop="create_date" />
           <el-table-column fixed="left" align="left" label="脚本负责人" min-width="90" prop="operator" />
           <el-table-column fixed="left" align="left" label="类型" min-width="60" prop="type" sortable="custom">
@@ -65,6 +62,12 @@
         <el-table-column prop="login_ok" label="成功" width="60" />
         <el-table-column prop="login_fail" label="失败" width="60" />
       </el-table-column>
+      <el-table-column label="微信授权">
+        <el-table-column prop="enter_scanning_code" label="进入" width="60" />
+        <el-table-column prop="scanning_code_success" label="成功" width="60" />
+        <el-table-column prop="transcoding_fail" label="转码失败" width="60" />
+        <el-table-column prop="third_party_fail" label="三方失败" width="60" />
+      </el-table-column>
       <el-table-column label="实名认证">
         <el-table-column prop="enter_authentication" label="进入" width="60" />
         <el-table-column prop="authentication_ok" label="成功" width="60" />
@@ -238,6 +241,7 @@
       total.value = table.data.total
       page.value = table.data.page
       pageSize.value = table.data.pageSize
+      getSpanArr(table.data.list)
     }
   }
   
@@ -334,6 +338,38 @@
       }
     })
   }
+
+  let 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].game_id === data[i - 1].game_id) {
+              spanArr[pos] += 1;
+              spanArr.push(0);
+            } else {
+              spanArr.push(1);
+              pos = i;
+            }
+          }
+        }
+        console.log(spanArr)  
+  }
+
+  const objectSpanMethod = (row) => {
+    if (row.columnIndex === 0 || row.columnIndex === 3 ||  row.columnIndex === 2 ||  row.columnIndex === 1) {
+          const rowspan = spanArr[row.rowIndex];
+          const colspan = rowspan > 0 ? 1 : 0;
+          return {
+            rowspan: rowspan,
+            colspan: colspan
+          }
+        }
+  }
   
   
   </script>

+ 5 - 6
src/view/logStatistics/list.vue

@@ -28,7 +28,6 @@
         :span-method="objectSpanMethod"
         @sort-change="sortChange" 
         @selection-change="handleSelectionChange" 
-        height="500" 
         header-align="center"
         >
           <el-table-column
@@ -109,12 +108,12 @@
         </el-table-column>
       </el-table-column>
       <el-table-column label="微信扫码率" align="center"  min-width="100" prop="scanning_success_rate" sortable="custom">
-        <el-table-column label="任务总数" align="center">
-          <el-table-column prop="pull_account_fail,pull_account_fail" label="扫码总数" align="center" min-width="100">
+        <el-table-column label="扫码成功" align="center">
+          <el-table-column prop="scanning_code_success,enter_scanning_code" label="扫码总数" align="center" min-width="100">
             <template #default="scope">
-							{{ scope.row.target_num }}
+							{{ scope.row.scanning_code_success }}
 							<el-divider style="margin:0 5px" direction="vertical" />
-              {{ scope.row.new_scanning_code}}
+              {{ scope.row.enter_scanning_code}}
 							<el-divider style="margin:0" />
 							{{ scope.row.scanning_success_rate + '%'}}
 						</template>
@@ -311,7 +310,7 @@ const renderheader = ({ column, $index  }) => {
   }
 
   const objectSpanMethod = (row) => {
-    if (row.columnIndex === 1 || row.columnIndex === 3 || row.columnIndex === 7 || row.columnIndex === 0 || row.columnIndex === 2 || row.columnIndex === 12|| row.columnIndex === 14|| row.columnIndex === 15|| row.columnIndex === 16|| row.columnIndex === 17) {
+    if (row.columnIndex === 1 || row.columnIndex === 3 || row.columnIndex === 7 || row.columnIndex === 0 || row.columnIndex === 2 || row.columnIndex === 14|| row.columnIndex === 15|| row.columnIndex === 16|| row.columnIndex === 17) {
           const rowspan = spanArr[row.rowIndex];
           const colspan = rowspan > 0 ? 1 : 0;
           return {

+ 539 - 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-01 09:58:23
+ * @LastEditTime: 2023-02-20 11:58:25
  * @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
 -->
@@ -44,12 +44,22 @@
               <el-option label="明日到期" value="2" />
             </el-select>
           </el-form-item>
-          <el-form-item label="是否下架">
+          <el-form-item label="使用人">
+            <el-select v-model="searchInfo.director_name" size="small">
+              <el-option
+                v-for="item in directorOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+          <!-- <el-form-item label="是否下架">
             <el-select v-model="searchInfo.is_off_shelf" size="small">
               <el-option label="否" value="0" />
               <el-option label="是" value="1" />
             </el-select>
-          </el-form-item>
+          </el-form-item> -->
           <el-form-item>
             <el-button
               size="small"
@@ -86,6 +96,25 @@
         >
           <el-button size="small" type="primary" icon="upload">导入</el-button>
         </el-upload>
+        <el-button
+          icon="delete"
+          size="small"
+          type="danger"
+          :disabled="!apis.length"
+          style="margin-left: 10px"
+          @click="deletesMenu()"
+          >删除</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" size="small" :disabled="!apis.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button>
+          </template>
+        </el-popover> -->
       </div>
     </div>
     <div class="row center">
@@ -104,7 +133,7 @@
         <el-table-column
           align="left"
           label="供应商"
-          min-width="100"
+          min-width="70"
           prop="shop_name"
         />
         <!-- <el-table-column
@@ -162,6 +191,12 @@
           prop="rent_duration"
         />
         <el-table-column
+          align="left"
+          label="使用人"
+          min-width="80"
+          prop="director_name"
+        />
+        <el-table-column
           align="center"
           label="是否到期"
           min-width="100"
@@ -191,10 +226,10 @@
             >
           </template>
         </el-table-column>
-        <el-table-column
+        <!-- <el-table-column
           align="center"
           label="是否下架"
-          min-width="150"
+          min-width="100"
           prop="is_off_shelf"
         >
           <template #default="scope">
@@ -207,7 +242,7 @@
             >
             <el-button v-else size="small" type="success" plain>否</el-button>
           </template>
-        </el-table-column>
+        </el-table-column> -->
         <el-table-column
           align="left"
           label="TD号"
@@ -235,8 +270,9 @@
         <el-table-column
           align="left"
           label="备注"
-          min-width="50"
+          min-width="250"
           prop="remark"
+          show-overflow-tooltip
         />
         <el-table-column
           align="left"
@@ -244,7 +280,7 @@
           min-width="150"
           prop="update_time"
         />
-        <el-table-column align="left" fixed="right" label="操作" width="300">
+        <el-table-column align="left" fixed="right" label="操作" width="380">
           <template #default="scope">
             <el-button
               size="small"
@@ -259,6 +295,32 @@
               type="primary"
               link
               icon="edit"
+              @click="switchRenew(scope.row)"
+              >续费</el-button
+            >
+            <el-button
+              v-if="scope.row.is_expire != 1"
+              size="small"
+              type="primary"
+              link
+              icon="edit"
+              @click="switchRentingOut(scope.row)"
+              >退租</el-button
+            >
+            <el-button
+              v-if="scope.row.is_expire != 1"
+              size="small"
+              type="primary"
+              link
+              icon="edit"
+              @click="switchReplaceNum(scope.row)"
+              >换编号</el-button
+            >
+            <el-button
+              size="small"
+              type="primary"
+              link
+              icon="edit"
               @click="editMenu(scope.row.id)"
               >编辑</el-button
             >
@@ -332,6 +394,18 @@
               </el-select>
             </el-form-item>
           </el-col>
+          <el-col :span="6">
+            <el-form-item label="使用人" prop="director_name">
+              <el-select v-model="form.director_name" size="small">
+                <el-option
+                  v-for="item in directorOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
         </el-row>
         <el-row :gutter="10">
           <el-col :span="6">
@@ -398,13 +472,13 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <el-row :gutter="10">
+        <!-- <el-row :gutter="10">
           <el-col :span="12">
             <el-form-item label="是否下架" prop="is_off_shelf">
               <el-switch v-model="form.is_off_shelf" />
             </el-form-item>
           </el-col>
-        </el-row>
+        </el-row> -->
         <el-row :gutter="10">
           <el-col :span="20">
             <el-form-item label="备注" prop="remark">
@@ -428,6 +502,220 @@
         </div>
       </template>
     </el-dialog>
+    <el-dialog title="租机续费" v-model="visible_renew">
+      <el-form :model="renewForm" size="default" label-width="100px">
+        <el-row>
+          <el-form-item label="警告:" prop="">
+            <el-col :span="24">
+              <p style="color: red; font-size: larger">请勿随意操作!!!</p>
+            </el-col>
+          </el-form-item>
+        </el-row>
+        <el-row>
+          <el-form-item label="租机编号" prop="pc_num">
+            <el-col :span="12">
+              <el-input
+                v-model="renewForm.pc_num"
+                placeholder="租机编号"
+                :disabled="true"
+              ></el-input>
+            </el-col>
+          </el-form-item>
+          <el-form-item label="续费时间" prop="rent_renew">
+            <el-col>
+              <el-date-picker
+                v-model="renewForm.rent_renew"
+                format="YYYY-MM-DD HH:mm:ss"
+                type="datetime"
+                :style="{ width: '100%' }"
+                placeholder="请选择日期"
+                clearable
+                @change="calculateRenewDay(renewForm)"
+              ></el-date-picker>
+            </el-col>
+          </el-form-item>
+        </el-row>
+        <el-row>
+          <el-form-item label="续费天数" prop="">
+            <el-col :span="24">
+              <el-tag :key="renewForm.day" type="warning" effect="light">
+                {{ renewForm.day }}
+              </el-tag>
+            </el-col>
+          </el-form-item>
+        </el-row>
+        <el-divider />
+        <el-form-item>
+          <el-button size="small" @click="visible_renew = false"
+            >取消</el-button
+          >
+          <el-button type="primary" size="small" @click="renew(renewForm)"
+            >提交</el-button
+          >
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+    <!--退租-->
+    <el-dialog title="租机退租" v-model="visible_rentingOut">
+      <el-form
+        ref="elForm"
+        :model="rentingOutForm"
+        size="medium"
+        label-width="100px"
+      >
+        <el-row>
+          <el-form-item label="警告:" prop="">
+            <el-col :span="24">
+              <p style="color: red; font-size: larger">请勿随意操作!!!</p>
+            </el-col>
+          </el-form-item>
+        </el-row>
+        <el-row>
+          <el-form-item label="租机编号" prop="pc_num">
+            <el-col :span="12">
+              <el-input
+                v-model="rentingOutForm.pc_num"
+                placeholder="租机编号"
+                :disabled="true"
+              ></el-input>
+            </el-col>
+          </el-form-item>
+          <el-form-item label="退租时间" prop="rent_end">
+            <el-col>
+              <el-date-picker
+                v-model="rentingOutForm.rent_end"
+                format="YYYY-MM-DD HH:mm:ss"
+                type="datetime"
+                :style="{ width: '100%' }"
+                placeholder="请选择日期"
+                clearable
+                @change="calculateRentDay(rentingOutForm)"
+              ></el-date-picker>
+            </el-col>
+          </el-form-item>
+        </el-row>
+        <el-row>
+          <el-form-item label="剩余天数" prop="">
+            <el-col :span="24">
+              <el-tag :key="rentingOutForm.day" type="warning" effect="light">
+                {{ rentingOutForm.day }}
+              </el-tag>
+            </el-col>
+          </el-form-item>
+        </el-row>
+        <el-row
+          ><el-col :span="12" style="margin-left: 30px"
+            ><el-button size="small" @click="addCardMsg()"
+              >匀时间</el-button
+            ></el-col
+          ></el-row
+        >
+        <el-row>
+          <div class="container-scrollbar">
+            <el-scrollbar max-height="200px">
+              <el-row
+                :gutter="24"
+                v-for="(item, index) in cardList"
+                :key="index"
+              >
+                <el-col :span="10">
+                  <el-form-item label="租机编号">
+                    <el-input v-model="item.pc_num"></el-input>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="8">
+                  <el-form-item label="增加天数">
+                    <el-input v-model="item.add_day"></el-input>
+                  </el-form-item>
+                </el-col>
+                <el-col :span="2" v-if="cardList.length !== 1">
+                  <el-button
+                    size="mini"
+                    circle
+                    icon="delete"
+                    @click="deleteCardMsg(index)"
+                  ></el-button>
+                </el-col>
+              </el-row>
+            </el-scrollbar>
+          </div>
+        </el-row>
+        <el-divider />
+        <el-form-item>
+          <el-button size="small" @click="visible_rentingOut = false"
+            >取消</el-button
+          >
+          <el-button
+            type="primary"
+            size="small"
+            @click="rentingOut(rentingOutForm)"
+            >提交</el-button
+          >
+        </el-form-item>
+      </el-form>
+    </el-dialog>
+    <!--租机编号更换-->
+    <el-dialog title="租机编号更换" v-model="visible_replaceNum">
+      <el-form
+        ref="elForm"
+        :model="replaceNumForm"
+        size="medium"
+        label-width="100px"
+      >
+        <el-row>
+          <el-form-item label="警告:" prop="">
+            <el-col :span="24">
+              <p style="color: red; font-size: larger">
+                请勿随意更换,会影响租机续费
+              </p>
+            </el-col>
+          </el-form-item>
+        </el-row>
+        <el-row>
+          <el-form-item label="供应商:" prop="shop_name">
+            <el-col :span="24">
+              <p>
+                <span style="color: red; font-size: larger">{{
+                  replaceNumForm.shop_name
+                }}</span
+                >, 只可更改为同一供应商的编号
+              </p>
+            </el-col>
+          </el-form-item>
+        </el-row>
+        <el-row>
+          <el-form-item label="原租机编号" prop="pc_num_old">
+            <el-col :span="24">
+              <el-input
+                v-model="replaceNumForm.pc_num_old"
+                placeholder="原租机编号"
+                :disabled="true"
+              ></el-input>
+            </el-col>
+          </el-form-item>
+          <el-form-item label="更换编号" prop="pc_num_new">
+            <el-col :span="24">
+              <el-input
+                v-model="replaceNumForm.pc_num_new"
+                placeholder="更换编号"
+              ></el-input>
+            </el-col>
+          </el-form-item>
+        </el-row>
+        <el-divider />
+        <el-form-item>
+          <el-button size="small" @click="visible_replaceNum = false"
+            >取消</el-button
+          >
+          <el-button
+            type="primary"
+            size="small"
+            @click="replaceNum(replaceNumForm)"
+            >提交</el-button
+          >
+        </el-form-item>
+      </el-form>
+    </el-dialog>
   </div>
 </template>
 
@@ -447,13 +735,19 @@ import {
   addRentComputer,
   editRentComputer,
   deleteRentComputerById,
+  deleteRentComputerByIds,
+  renewRentComputer,
+  replaceNumRentComputer,
+  rentingOutRentComputer,
 } from "@/api/rentComputer";
+import { getDirectorList } from "@/api/responsiblePerson";
 import { useUserStore } from "@/pinia/modules/user";
 import { toSQLLine } from "@/utils/stringFun";
 import { ref } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
 import { formatDate } from "@/utils/format";
 import { downloadTemplate } from "@/api/excel";
+import dayjs from "dayjs";
 
 const apis = ref([]);
 const form = ref({
@@ -472,6 +766,7 @@ const form = ref({
   remark: "",
   is_expire: -1,
   is_off_shelf: -1,
+  director_name: "",
 });
 const rules = ref({
   pc_num: [{ required: true, message: "请输入电脑编号", trigger: "blur" }],
@@ -496,11 +791,201 @@ let spanArr = [];
 const searchInfo = ref({});
 const computerNum = ref("");
 const shopOptions = ref();
+const directorOptions = ref();
 const setMealOptions = ref();
 const defaultTime = ref(new Date(2000, 1, 1, 12, 0, 0));
 const path = ref(import.meta.env.VITE_BASE_API);
 const userStore = useUserStore();
+const visible_renew = ref(false);
+const visible_rentingOut = ref(false);
+const visible_replaceNum = ref(false);
+const rent_end = ref("");
+const renewForm = ref({
+  pc_num: "",
+  pc_id: 0,
+  day: 0,
+  rent_renew: dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"),
+});
+const rentingOutForm = ref({
+  pc_num: "",
+  pc_id: 0,
+  day: 0,
+  rent_end: dayjs(new Date()).format("YYYY-MM-DD HH:mm:ss"),
+  addList: [],
+});
+const replaceNumForm = ref({
+  pc_num_old: "",
+  pc_num_new: "",
+  shop_id: 0,
+  shop_name: "",
+});
+let cardList = ref([]);
 
+// 计算租机到期时间
+const calculateRentDuration = async (scope) => {
+  scope.rent_end = new Date(
+    Date.parse(scope.rent_start) +
+      1 * 24 * 60 * 60 * 1000 * parseInt(scope.rent_duration)
+  );
+};
+// 计算退租剩余时间
+function calculateRentDay(scope) {
+  if (Date.parse(rent_end.value) < Date.parse(scope.rent_end)) {
+    scope.rent_end = rent_end.value;
+    ElMessage.error("退租时间不能大于到期时间");
+  }
+  scope.day = Math.ceil(
+    parseInt(
+      (Date.parse(rent_end.value) - Date.parse(scope.rent_end)) /
+        (24 * 60 * 60 * 1000) +
+        ""
+    )
+  );
+  // console.log(scope.day);
+}
+// 计算续费时间
+function calculateRenewDay(scope) {
+  if (Date.parse(rent_end.value) >= Date.parse(scope.rent_renew)) {
+    scope.rent_renew = rent_end.value;
+    ElMessage.error("续费时间不能小于到期时间");
+    visible_renew.value = false;
+  }
+  scope.day = Math.ceil(
+    parseInt(
+      (Date.parse(scope.rent_renew) - Date.parse(rent_end.value)) /
+        (24 * 60 * 60 * 1000) +
+        ""
+    )
+  );
+}
+// 拉起续费弹窗
+async function switchRenew(rowData) {
+  // console.log(rowData);
+  renewForm.value.pc_num = rowData.pc_num;
+  renewForm.value.pc_id = rowData.id;
+  renewForm.value.rent_renew = rowData.rent_end;
+  renewForm.value.day = 0;
+  rent_end.value = rowData.rent_end;
+  // console.log(renewForm);
+  if (visible_renew.value == false) {
+    visible_renew.value = true;
+  }
+}
+// 续费
+async function renew(rowData) {
+  let doForm = {
+    pc_num: rowData.pc_num,
+    pc_id: rowData.pc_id,
+    rent_renew: dayjs(new Date(rowData.rent_renew)).format(
+      "YYYY-MM-DD HH:mm:ss"
+    ),
+    day: rowData.day,
+  };
+  // renewRentComputer
+  const data = await renewRentComputer(doForm);
+  if (data.code == 0) {
+    visible_renew.value = false;
+    ElMessage.success(data.msg);
+    getTableData();
+  } else {
+    ElMessage.error(data.msg);
+  }
+}
+// 拉起退租弹窗
+async function switchRentingOut(rowData) {
+  cardList.value = [];
+  rentingOutForm.value.pc_num = rowData.pc_num;
+  rentingOutForm.value.pc_id = rowData.id;
+  rentingOutForm.value.rent_end = dayjs(new Date(rowData.rent_end)).format(
+    "YYYY-MM-DD HH:mm:ss"
+  );
+  rentingOutForm.value.day = 0;
+  rent_end.value = rowData.rent_end;
+  if (visible_rentingOut.value == false) {
+    visible_rentingOut.value = true;
+  }
+}
+function addCardMsg() {
+  let hasFlag = false;
+  for (let i = 0; i < cardList.value.length; i++) {
+    if (
+      cardList.value[i].pc_num == "" ||
+      cardList.value[i].add_day == undefined
+    ) {
+      hasFlag = true;
+      break;
+    }
+  }
+  if (hasFlag == true) {
+    ElMessage.error("有未填写项");
+  } else {
+    cardList.value.push({
+      pc_id: "",
+      add_day: null,
+    });
+  }
+}
+function deleteCardMsg(index) {
+  cardList.value.splice(index, 1);
+}
+// 退租
+async function rentingOut(rowData) {
+  var numDay = 0;
+  let AddList = [];
+  cardList.value.forEach((e) => {
+    numDay += e.add_day;
+    let temp = {
+      pc_num: e.pc_num,
+      add_day: Number(e.add_day),
+    };
+    AddList.push(temp);
+  });
+  if (numDay != rowData.day) {
+    ElMessage.error("匀时间天数错误!!!");
+    return;
+  }
+  let doForm = {
+    pc_id: rowData.pc_id,
+    rent_end: dayjs(new Date(rowData.rent_end)).format("YYYY-MM-DD HH:mm:ss"),
+    add_list: AddList,
+  };
+
+  const data = await rentingOutRentComputer(doForm);
+  // console.log(data)
+  if (data.code == 0) {
+    visible_rentingOut.value = false;
+    ElMessage.success(data.msg);
+    getTableData();
+  } else {
+    // ElMessage.error(data.msg);
+  }
+}
+// 拉起换编号弹窗
+async function switchReplaceNum(rowData) {
+  replaceNumForm.value.pc_num_old = rowData.pc_num;
+  replaceNumForm.value.shop_id = rowData.shop_id;
+  replaceNumForm.value.shop_name = rowData.shop_name;
+  if (visible_replaceNum.value == false) {
+    visible_replaceNum.value = true;
+  }
+}
+// 换编
+async function replaceNum(rowData) {
+  let doForm = {
+    pc_num_old: rowData.pc_num_old,
+    pc_num_new: rowData.pc_num_new,
+    shop_id: rowData.shop_id,
+  };
+  const data = await replaceNumRentComputer(doForm);
+  // console.log(data)
+  if (data.code == 0) {
+    visible_replaceNum.value = false;
+    ElMessage.success(data.msg);
+    getTableData();
+  } else {
+    // ElMessage.error(data.msg);
+  }
+}
 const downloadExcelTemplate = () => {
   downloadTemplate("RentComputerTemplate.xlsx");
 };
@@ -553,7 +1038,7 @@ const sortChange = ({ prop, order }) => {
 // 搜索
 const onSubmit = () => {
   page.value = 1;
-  pageSize.value = 10;
+  pageSize.value = 20;
 
   if (typeof searchInfo.value.set_meal_id != "undefined") {
     searchInfo.value.set_meal_id = Number(searchInfo.value.set_meal_id);
@@ -565,7 +1050,7 @@ const onSubmit = () => {
     searchInfo.value.is_off_shelf = Number(searchInfo.value.is_off_shelf);
   }
 
-  console.log(searchInfo);
+  // console.log(searchInfo);
 
   getTableData();
 };
@@ -623,14 +1108,20 @@ const getSelectList = async () => {
     });
   });
   setMealOptions.value = setMealList;
-};
-
-// 计算租机到期时间
-const calculateRentDuration = async (scope) => {
-  scope.rent_end = new Date(
-    Date.parse(scope.rent_start) +
-      1 * 24 * 60 * 60 * 1000 * parseInt(scope.rent_duration)
-  );
+  //游戏负责人列表===============================
+  const directorRes = await getDirectorList({
+    page: 1,
+    pageSize: 999,
+  });
+  let directorList = [
+    { value: "ALL", label: "所有机器" },
+    { value: "", label: "未使用" },
+  ];
+  const data3 = directorRes.data.list;
+  data3.forEach((e) => {
+    directorList.push({ value: e.name, label: e.name });
+  });
+  directorOptions.value = directorList;
 };
 
 // 查询
@@ -752,6 +1243,7 @@ const editMenu = async (id) => {
   dialogTitle.value = "编辑租机";
   const res = await getRentComputerById({ id });
   form.value = res.data;
+  // console.log(form.value);
   if (form.value.is_off_shelf == 1) {
     form.value.is_off_shelf = true;
   } else {
@@ -767,6 +1259,32 @@ const closeDialog = () => {
   initForm();
   dialogFormVisible.value = false;
 };
+// 批量删除菜单
+const deletesMenu = async () => {
+  ElMessageBox.confirm("确定批量删除所选吗?", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  })
+    .then(async () => {
+      const ids = apis.value.map((item) => item.id);
+      // console.log(ids);
+      const res = await deleteRentComputerByIds({ ids });
+      if (res.code === 0) {
+        ElMessage({
+          type: "success",
+          message: "删除成功!",
+        });
+        getTableData();
+      }
+    })
+    .catch(() => {
+      ElMessage({
+        type: "info",
+        message: "已取消删除",
+      });
+    });
+};
 // 删除菜单
 const deleteMenu = async (id) => {
   ElMessageBox.confirm("确定删除?", "提示", {

+ 733 - 0
src/view/rentComputer/rent_computer_ledger.vue

@@ -0,0 +1,733 @@
+<!--
+ * @Author: 倚楼听风雨 18408246387@163.com
+ * @Date: 2022-11-16 17:16:17
+ * @LastEditors: 倚楼听风雨 18408246387@163.com
+ * @LastEditTime: 2023-02-20 15:47:22
+ * @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
+-->
+<template>
+  <div>
+    <div class="gva-search-box">
+      <div class="gva-btn-list">
+        <el-form ref="searchForm" :inline="true" :model="searchInfo">
+          <el-form-item label="电脑编号">
+            <el-input
+              v-model="searchInfo.pc_num"
+              placeholder="编号"
+              size="small"
+            />
+          </el-form-item>
+          <el-form-item label="供应商">
+            <el-select v-model="searchInfo.shop_id" size="small">
+              <el-option
+                v-for="item in shopOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="套餐">
+            <el-select v-model="searchInfo.set_meal_id" size="small"
+              ><el-option
+                v-for="item in setMealOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+            /></el-select>
+          </el-form-item>
+          <el-form-item label="日期" prop="new_date">
+            <el-date-picker
+              v-model="searchInfo.new_date"
+              popper-class="picker-popovers"
+              class="timefilter"
+              type="date"
+              :disabled-date="disabledDate"
+              :shortcuts="shortcuts"
+              placeholder="选择日期时间"
+              value-format="YYYY-MM-DD"
+            >
+            </el-date-picker>
+          </el-form-item>
+          <!-- <el-form-item label="是否到期">
+            <el-select v-model="searchInfo.is_expire" size="small">
+              <el-option label="否" value="0" />
+              <el-option label="是" value="1" />
+              <el-option label="明日到期" value="2" />
+            </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-button
+              class="excel-btn"
+              size="small"
+              type="primary"
+              icon="download"
+              @click="handleExcelRentExport"
+              >导出表格</el-button
+            >
+          </el-form-item>
+        </el-form>
+      </div>
+      <!-- <div class="gva-btn-list">
+        <el-button
+          icon="delete"
+          size="small"
+          type="danger"
+          :disabled="!apis.length"
+          style="margin-left: 10px"
+          @click="deletesMenu()"
+          >删除</el-button
+        >
+      </div> -->
+    </div>
+    <div class="row center">
+      <el-tag size="large">电脑数量 : {{ computerNum }} </el-tag>
+    </div>
+    <div class="gva-table-box">
+      <el-table
+        height="500px"
+        :data="tableData"
+        @sort-change="sortChange"
+        @selection-change="handleSelectionChange"
+        border
+      >
+        <el-table-column type="selection" width="55" />
+        <el-table-column
+          align="left"
+          label="日期"
+          min-width="80"
+          prop="new_date"
+        />
+        <el-table-column
+          align="left"
+          label="供应商"
+          min-width="70"
+          prop="shop_name"
+        />
+        <el-table-column
+          align="left"
+          label="编号"
+          min-width="80"
+          prop="pc_num"
+        />
+        <el-table-column
+          align="left"
+          label="机房名称"
+          min-width="80"
+          prop="pc_name"
+        />
+        <el-table-column
+          align="left"
+          label="起租时间"
+          min-width="150"
+          prop="rent_start_then"
+        />
+        <el-table-column
+          align="left"
+          label="到期时间"
+          min-width="150"
+          prop="rent_end_then"
+        />
+        <el-table-column
+          align="left"
+          label="租期"
+          min-width="50"
+          prop="rent_duration_then"
+        />
+        <el-table-column
+          align="left"
+          label="套餐"
+          min-width="70"
+          prop="set_meal_name"
+        />
+        <el-table-column
+          align="left"
+          label="价格"
+          min-width="70"
+          prop="rent_price_then"
+        />
+        <!-- <el-table-column
+          align="center"
+          label="套餐"
+          min-width="150"
+          prop="set_meal_name"
+        >
+          <template #default="scope">
+            <span v-if="scope.row.price_type == 0">{{
+              scope.row.set_meal_name +
+              "-天卡(" +
+              scope.row.rent_price_then +
+              "元)"
+            }}</span>
+            <span v-else-if="scope.row.price_type == 1">{{
+              scope.row.set_meal_name +
+              "-周卡(" +
+              scope.row.rent_price_then +
+              "元)"
+            }}</span>
+            <span v-else>{{
+              scope.row.set_meal_name +
+              "-月卡(" +
+              scope.row.rent_price_then +
+              "元)"
+            }}</span>
+          </template>
+        </el-table-column> -->
+        <el-table-column
+          align="left"
+          label="折算天租金"
+          min-width="100"
+          prop="rent_price_day_then"
+        />
+        <el-table-column
+          align="left"
+          label="已产生租金"
+          min-width="100"
+          prop="rent_price_used_then"
+        />
+        <!-- <el-table-column
+          align="center"
+          label="是否到期"
+          min-width="100"
+          prop="is_expire"
+        >
+          <template #default="scope">
+            <el-button
+              v-if="scope.row.is_expire == 2"
+              size="small"
+              type="warning"
+              plain
+              >即将到期</el-button
+            >
+            <el-button
+              v-if="scope.row.is_expire == 1"
+              size="small"
+              type="info"
+              plain
+              >到期未续</el-button
+            >
+            <el-button
+              v-if="scope.row.is_expire == 0"
+              size="small"
+              type="success"
+              plain
+              >在租期中</el-button
+            >
+          </template>
+        </el-table-column> -->
+        <el-table-column
+          align="left"
+          label="备注"
+          min-width="150"
+          prop="remark"
+          show-overflow-tooltip
+        />
+        <el-table-column
+          align="left"
+          label="更新时间"
+          min-width="150"
+          prop="update_time"
+        />
+        <el-table-column align="left" fixed="right" label="操作" width="130">
+          <template #default="scope">
+            <el-button
+              size="small"
+              type="primary"
+              link
+              icon="edit"
+              @click="editMenu(scope.row.id)"
+              >编辑</el-button
+            >
+            <el-button
+              size="small"
+              type="primary"
+              link
+              icon="delete"
+              @click="deleteMenu(scope.row.id)"
+              >删除</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <!-- </el-scrollbar> -->
+      <div class="gva-pagination">
+        <el-pagination
+          :current-page="page"
+          :page-size="pageSize"
+          :page-sizes="[10, 20, 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: "computer",
+};
+</script>
+
+<script setup>
+import {
+  getRentComputerLedgerList,
+  getRentComputerLedgerNum,
+  listRentComputerShopList,
+  listRentSetMealList,
+  getRentComputerById,
+  exportRentLedgerListExcel,
+  editRentComputer,
+  deleteRentComputerById,
+  deleteRentComputerByIds,
+} from "@/api/rentComputer";
+// import { useUserStore } from "@/pinia/modules/user";
+import { toSQLLine } from "@/utils/stringFun";
+import { ref } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { formatDate } from "@/utils/format";
+// import { downloadTemplate } from "@/api/excel";
+// import dayjs from "dayjs";
+
+const apis = ref([]);
+const form = ref({
+  id: 0,
+  pc_num: "",
+  pc_name: "",
+  shop_id: null,
+  set_meal_id: null,
+  todesk_id: "",
+  todesk_password: "",
+  sunflower_id: "",
+  sunflower_password: "",
+  rent_start: new Date(),
+  rent_duration: 0,
+  rent_end: new Date(),
+  remark: "",
+  // is_expire: -1,
+  is_off_shelf: -1,
+});
+const rules = ref({
+  pc_num: [{ required: true, message: "请输入电脑编号", trigger: "blur" }],
+  pc_name: [{ required: true, message: "请输入电脑名称", trigger: "blur" }],
+  shop_id: [{ required: true, message: "请选择供应商", trigger: "blur" }],
+  set_meal_id: [{ required: true, message: "请选择套餐", trigger: "blur" }],
+  rent_start: [{ required: true, message: "请选择起租日期", trigger: "blur" }],
+  rent_duration: [
+    { required: true, message: "请输入租赁天数", trigger: "blur" },
+  ],
+  // is_expire: [{ required: true, message: "请选择是否到期", trigger: "blur" }],
+  // is_off_shelf: [
+  //   { required: true, message: "请选择是否下架", trigger: "blur" },
+  // ],
+});
+
+const page = ref(1);
+const total = ref(0);
+const pageSize = ref(20);
+const tableData = ref([]);
+let spanArr = [];
+const searchInfo = ref({});
+const computerNum = ref("");
+const shopOptions = ref();
+const setMealOptions = ref();
+// const defaultTime = ref(new Date(2000, 1, 1, 12, 0, 0));
+// const path = ref(import.meta.env.VITE_BASE_API);
+// const userStore = useUserStore();
+
+const shortcuts = [
+  {
+    text: "今日",
+    value: new Date(),
+  },
+  {
+    text: "昨日",
+    value: () => {
+      const date = new Date();
+      date.setTime(date.getTime() - 3600 * 1000 * 24);
+      return date;
+    },
+  },
+];
+const disabledDate = (time) => {
+  return time.getTime() > Date.now();
+};
+
+// 计算租机到期时间
+const calculateRentDuration = async (scope) => {
+  scope.rent_end = new Date(
+    Date.parse(scope.rent_start) +
+      1 * 24 * 60 * 60 * 1000 * parseInt(scope.rent_duration)
+  );
+};
+
+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;
+  getTableData();
+};
+const onReset = () => {
+  searchInfo.value = {};
+};
+const handleCurrentChange = (val) => {
+  page.value = val;
+  getTableData();
+};
+
+const handleExcelRentExport = async () => {
+  var fileName = "";
+  if (searchInfo.value.new_date == null) {
+    let dt = new Date(Date.parse(new Date()) - 1 * 24 * 60 * 60 * 1000);
+    var y = dt.getFullYear();
+    var mt = (dt.getMonth() + 1).toString().padStart(2, "0");
+    var day = dt.getDate().toString().padStart(2, "0");
+    var timeStr = y + "-" + mt + "-" + day;
+    fileName = timeStr + "-租机台账.xlsx";
+  } else {
+    fileName = searchInfo.value.new_date + "-租机台账.xlsx";
+  }
+  exportRentLedgerListExcel(
+    { page: page.value, pageSize: pageSize.value, ...searchInfo.value },
+    fileName
+  );
+};
+
+// 排序
+const sortChange = ({ prop, order }) => {
+  if (prop) {
+    if (prop === "id") {
+      prop = "id";
+    }
+    searchInfo.value.orderKey = toSQLLine(prop);
+    searchInfo.value.desc = order === "descending";
+  }
+  getTableData();
+};
+
+// 搜索
+const onSubmit = () => {
+  page.value = 1;
+  pageSize.value = 20;
+
+  if (typeof searchInfo.value.set_meal_id != "undefined") {
+    searchInfo.value.set_meal_id = Number(searchInfo.value.set_meal_id);
+  }
+  // if (typeof searchInfo.value.is_expire != "undefined") {
+  //   searchInfo.value.is_expire = Number(searchInfo.value.is_expire);
+  // }
+  // if (typeof searchInfo.value.is_off_shelf != "undefined") {
+  //   searchInfo.value.is_off_shelf = Number(searchInfo.value.is_off_shelf);
+  // }
+  // console.log(searchInfo);
+
+  getTableData();
+};
+
+// 查询
+const getTableData = async () => {
+  const table = await getRentComputerLedgerList({
+    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;
+    getSpanArr(table.data.list);
+    getComputerNum();
+    getSelectList();
+  }
+};
+
+//获取下拉框list
+const getSelectList = async () => {
+  //listRentComputerShopList
+  const rentComputerShop = await listRentComputerShopList({
+    page: 1,
+    pageSize: 999,
+  });
+  let rentComputerShopList = [];
+  const data = rentComputerShop.data.list;
+  data.forEach((e) => {
+    rentComputerShopList.push({ value: e.id, label: e.name });
+  });
+  shopOptions.value = rentComputerShopList;
+  //listRentSetMealList
+  const setMealShop = await listRentSetMealList({
+    page: 1,
+    pageSize: 999,
+  });
+  let setMealList = [];
+  const data2 = setMealShop.data.list;
+  data2.forEach((e) => {
+    var priceStr = "";
+    if (e.price_type == 0) {
+      priceStr = "天卡(" + e.rent_price + "元)";
+    } else if (e.price_type == 1) {
+      priceStr = "周卡(" + e.rent_price + "元)";
+    } else {
+      priceStr = "月卡(" + e.rent_price + "元)";
+    }
+    setMealList.push({
+      value: e.id,
+      label: e.shop_name + "-" + e.name + "-" + priceStr,
+    });
+  });
+  setMealOptions.value = setMealList;
+};
+
+// 查询
+const getComputerNum = async () => {
+  const table = await getRentComputerLedgerNum({ ...searchInfo.value });
+  if (table.code === 0) {
+    // console.log(table.data);
+    computerNum.value = table.data;
+  }
+};
+getTableData();
+
+// 批量操作
+const handleSelectionChange = (val) => {
+  apis.value = val;
+};
+
+const dialogFormVisible = ref(false);
+// 弹窗相关
+const menuForm = ref(null);
+const checkFlag = ref(false);
+const initForm = () => {
+  checkFlag.value = false;
+  menuForm.value.resetFields();
+  form.value = {
+    id: 0,
+    coding: "",
+    describe: "",
+    parent_id: "",
+  };
+};
+const menuOption = ref([
+  {
+    id: "0",
+    title: "根编号",
+  },
+]);
+const setOptions = () => {
+  menuOption.value = [
+    {
+      id: "0",
+      title: "根目录",
+    },
+  ];
+  setMenuOptions(tableData.value, menuOption.value, false);
+};
+const setMenuOptions = (menuData, optionsData, disabled) => {
+  menuData &&
+    menuData.forEach((item) => {
+      if (item.children && item.children.length) {
+        const option = {
+          ID: String(item.id),
+          disabled: disabled || item.id === form.value.id,
+          children: [],
+        };
+        setMenuOptions(
+          item.children,
+          option.children,
+          disabled || item.id === form.value.id
+        );
+        optionsData.push(option);
+      } else {
+        const option = {
+          ID: String(item.id),
+          disabled: disabled || item.id === form.value.id,
+        };
+        optionsData.push(option);
+      }
+    });
+};
+
+const loadExcel = (res) => {
+  if (res.code === 0) {
+    ElMessage({
+      type: "success",
+      message: res.msg,
+    });
+  } else {
+    ElMessage({
+      type: "error",
+      message: res.msg,
+      showClose: true,
+    });
+  }
+  getTableData();
+};
+
+// 添加菜单方法,id为 0则为添加根菜单
+const isEdit = ref(false);
+const dialogTitle = ref("新增租机");
+const addMenu = async (id) => {
+  dialogTitle.value = "新增租机";
+  form.value.parent_id = String(id);
+  isEdit.value = false;
+  setOptions();
+  dialogFormVisible.value = true;
+  getSelectList();
+};
+// 修改菜单方法
+const editMenu = async (id) => {
+  dialogTitle.value = "编辑租机";
+  const res = await getRentComputerById({ id });
+  form.value = res.data;
+  if (form.value.is_off_shelf == 1) {
+    form.value.is_off_shelf = true;
+  } else {
+    form.value.is_off_shelf = false;
+  }
+  isEdit.value = true;
+  setOptions();
+  dialogFormVisible.value = true;
+  getSelectList();
+};
+
+const closeDialog = () => {
+  initForm();
+  dialogFormVisible.value = false;
+};
+// 批量删除菜单
+const deletesMenu = async () => {
+  ElMessageBox.confirm("确定批量删除所选吗?", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  })
+    .then(async () => {
+      const ids = apis.value.map((item) => item.id);
+      // console.log(ids);
+      const res = await deleteRentComputerByIds({ ids });
+      if (res.code === 0) {
+        ElMessage({
+          type: "success",
+          message: "删除成功!",
+        });
+        getTableData();
+      }
+    })
+    .catch(() => {
+      ElMessage({
+        type: "info",
+        message: "已取消删除",
+      });
+    });
+};
+// 删除菜单
+const deleteMenu = async (id) => {
+  ElMessageBox.confirm("确定删除?", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  })
+    .then(async () => {
+      console.log(id);
+
+      const res = await deleteRentComputerById({ id });
+      if (res.code === 0) {
+        ElMessage({
+          type: "success",
+          message: "删除成功!",
+        });
+        getTableData();
+      }
+    })
+    .catch(() => {
+      ElMessage({
+        type: "info",
+        message: "已取消删除",
+      });
+    });
+};
+// const enterDialog = async () => {
+//   //   console.log(form.value);
+//   menuForm.value.validate(async (valid) => {
+//     if (valid) {
+//       let res;
+//       form.value.id = Number(form.value.id);
+//       form.value.shop_id = Number(form.value.shop_id);
+//       form.value.set_meal_id = Number(form.value.set_meal_id);
+//       form.value.rent_duration = Number(form.value.rent_duration);
+//       form.value.rent_start = formatDate(form.value.rent_start);
+//       form.value.rent_end = formatDate(form.value.rent_end);
+//       form.value.is_expire = Number(form.value.is_expire);
+//       if (form.value.is_off_shelf == true) {
+//         form.value.is_off_shelf = 1;
+//       } else {
+//         form.value.is_off_shelf = 0;
+//       }
+//       if (isEdit.value) {
+//         res = await editRentComputer(form.value);
+//       } else {
+//         // res = await addRentComputer(form.value);
+//       }
+//       if (res.code === 0) {
+//         ElMessage({
+//           type: "success",
+//           message: isEdit.value ? "编辑成功" : "添加成功!",
+//         });
+//         getTableData();
+//       } else {
+//         ElMessage({
+//           type: "error",
+//           message: res.message,
+//         });
+//       }
+//       initForm();
+//       dialogFormVisible.value = false;
+//     }
+//   });
+// };
+</script>
+
+<style scoped lang="scss">
+.button-box {
+  padding: 10px 20px;
+  .el-button {
+    float: right;
+  }
+}
+.warning {
+  color: #dc143c;
+}
+</style>

+ 246 - 183
src/view/superAdmin/api/api.vue

@@ -22,35 +22,91 @@
           </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-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('addApi')">新增</el-button>
+        <el-button
+          size="small"
+          type="primary"
+          icon="plus"
+          @click="openDialog('addApi')"
+          >新增</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 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" size="small" :disabled="!apis.length" style="margin-left: 10px;" @click="deleteVisible = true">删除</el-button>
+            <el-button
+              icon="delete"
+              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
+        :data="tableData"
+        @sort-change="sortChange"
+        @selection-change="handleSelectionChange"
+      >
+        <el-table-column type="selection" width="55" />
+        <el-table-column
+          align="left"
+          label="id"
+          min-width="60"
+          prop="ID"
+          sortable="custom"
+        />
         <el-table-column
-          type="selection"
-          width="55"
+          align="left"
+          label="API路径"
+          min-width="150"
+          prop="path"
+          sortable="custom"
         />
-        <el-table-column align="left" label="id" min-width="60" prop="ID" sortable="custom" />
-        <el-table-column align="left" label="API路径" min-width="150" prop="path" sortable="custom" />
-        <el-table-column align="left" label="API分组" min-width="150" prop="apiGroup" sortable="custom" />
-        <el-table-column align="left" label="API简介" min-width="150" prop="description" sortable="custom" />
-        <el-table-column align="left" label="请求" min-width="150" prop="method" sortable="custom">
+        <el-table-column
+          align="left"
+          label="API分组"
+          min-width="150"
+          prop="apiGroup"
+          sortable="custom"
+        />
+        <el-table-column
+          align="left"
+          label="API简介"
+          min-width="150"
+          prop="description"
+          sortable="custom"
+        />
+        <el-table-column
+          align="left"
+          label="请求"
+          min-width="150"
+          prop="method"
+          sortable="custom"
+        >
           <template #default="scope">
             <div>
               {{ scope.row.method }} / {{ methodFiletr(scope.row.method) }}
@@ -66,14 +122,16 @@
               type="primary"
               link
               @click="editApiFunc(scope.row)"
-            >编辑</el-button>
+              >编辑</el-button
+            >
             <el-button
               icon="delete"
               size="small"
               type="primary"
               link
               @click="deleteApiFunc(scope.row)"
-            >删除</el-button>
+              >删除</el-button
+            >
           </template>
         </el-table-column>
       </el-table>
@@ -88,17 +146,24 @@
           @size-change="handleSizeChange"
         />
       </div>
-
     </div>
 
-    <el-dialog v-model="dialogFormVisible" :before-close="closeDialog" :title="dialogTitle">
+    <el-dialog
+      v-model="dialogFormVisible"
+      :before-close="closeDialog"
+      :title="dialogTitle"
+    >
       <warning-bar title="新增API,需要在角色管理内配置权限才可使用" />
       <el-form ref="apiForm" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="路径" prop="path">
           <el-input v-model="form.path" autocomplete="off" />
         </el-form-item>
         <el-form-item label="请求" prop="method">
-          <el-select v-model="form.method" placeholder="请选择" style="width:100%">
+          <el-select
+            v-model="form.method"
+            placeholder="请选择"
+            style="width: 100%"
+          >
             <el-option
               v-for="item in methodOptions"
               :key="item.value"
@@ -117,7 +182,9 @@
       <template #footer>
         <div class="dialog-footer">
           <el-button size="small" @click="closeDialog">取 消</el-button>
-          <el-button size="small" type="primary" @click="enterDialog">确 定</el-button>
+          <el-button size="small" type="primary" @click="enterDialog"
+            >确 定</el-button
+          >
         </div>
       </template>
     </el-dialog>
@@ -126,8 +193,8 @@
 
 <script>
 export default {
-  name: 'Api',
-}
+  name: "Api",
+};
 </script>
 
 <script setup>
@@ -137,245 +204,241 @@ import {
   createApi,
   updateApi,
   deleteApi,
-  deleteApisByIds
-} from '@/api/api'
-import { toSQLLine } from '@/utils/stringFun'
-import warningBar from '@/components/warningBar/warningBar.vue'
-import { ref } from 'vue'
-import { ElMessage, ElMessageBox } from 'element-plus'
+  deleteApisByIds,
+} from "@/api/api";
+import { toSQLLine } from "@/utils/stringFun";
+import warningBar from "@/components/warningBar/warningBar.vue";
+import { ref } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
 
 const methodFiletr = (value) => {
-  const target = methodOptions.value.filter(item => item.value === value)[0]
-  return target && `${target.label}`
-}
+  const target = methodOptions.value.filter((item) => item.value === value)[0];
+  return target && `${target.label}`;
+};
 
-const apis = ref([])
+const apis = ref([]);
 const form = ref({
-  path: '',
-  apiGroup: '',
-  method: '',
-  description: ''
-})
+  path: "",
+  apiGroup: "",
+  method: "",
+  description: "",
+});
 const methodOptions = ref([
   {
-    value: 'POST',
-    label: '创建',
-    type: 'success'
+    value: "POST",
+    label: "创建",
+    type: "success",
   },
   {
-    value: 'GET',
-    label: '查看',
-    type: ''
+    value: "GET",
+    label: "查看",
+    type: "",
   },
   {
-    value: 'PUT',
-    label: '更新',
-    type: 'warning'
+    value: "PUT",
+    label: "更新",
+    type: "warning",
   },
   {
-    value: 'DELETE',
-    label: '删除',
-    type: 'danger'
-  }
-])
+    value: "DELETE",
+    label: "删除",
+    type: "danger",
+  },
+]);
 
-const type = ref('')
+const type = ref("");
 const rules = ref({
-  path: [{ required: true, message: '请输入api路径', trigger: 'blur' }],
-  apiGroup: [
-    { required: true, message: '请输入组名称', trigger: 'blur' }
-  ],
-  method: [
-    { required: true, message: '请选择请求方式', trigger: 'blur' }
-  ],
-  description: [
-    { required: true, message: '请输入api介绍', trigger: 'blur' }
-  ]
-})
+  path: [{ required: true, message: "请输入api路径", trigger: "blur" }],
+  apiGroup: [{ required: true, message: "请输入组名称", trigger: "blur" }],
+  method: [{ required: true, message: "请选择请求方式", trigger: "blur" }],
+  description: [{ required: true, message: "请输入api介绍", trigger: "blur" }],
+});
 
-const page = ref(1)
-const total = ref(0)
-const pageSize = ref(10)
-const tableData = ref([])
-const searchInfo = ref({})
+const page = ref(1);
+const total = ref(0);
+const pageSize = ref(10);
+const tableData = ref([]);
+const searchInfo = ref({});
 
 const onReset = () => {
-  searchInfo.value = {}
-}
+  searchInfo.value = {};
+};
 // 搜索
 
 const onSubmit = () => {
-  page.value = 1
-  pageSize.value = 10
-  getTableData()
-}
+  page.value = 1;
+  pageSize.value = 10;
+  getTableData();
+};
 
 // 分页
 const handleSizeChange = (val) => {
-  pageSize.value = val
-  getTableData()
-}
+  pageSize.value = val;
+  getTableData();
+};
 
 const handleCurrentChange = (val) => {
-  page.value = val
-  getTableData()
-}
+  page.value = val;
+  getTableData();
+};
 
 // 排序
 const sortChange = ({ prop, order }) => {
   if (prop) {
-    if (prop === 'ID') {
-      prop = 'id'
+    if (prop === "ID") {
+      prop = "id";
     }
-    searchInfo.value.orderKey = toSQLLine(prop)
-    searchInfo.value.desc = order === 'descending'
+    searchInfo.value.orderKey = toSQLLine(prop);
+    searchInfo.value.desc = order === "descending";
   }
-  getTableData()
-}
+  getTableData();
+};
 
 // 查询
-const getTableData = async() => {
-  const table = await getApiList({ page: page.value, pageSize: pageSize.value, ...searchInfo.value })
+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
+    tableData.value = table.data.list;
+    total.value = table.data.total;
+    page.value = table.data.page;
+    pageSize.value = table.data.pageSize;
   }
-}
+};
 
-getTableData()
+getTableData();
 
 // 批量操作
 const handleSelectionChange = (val) => {
-  apis.value = val
-}
+  apis.value = val;
+};
 
-const deleteVisible = ref(false)
-const onDelete = async() => {
-  const ids = apis.value.map(item => item.ID)
-  const res = await deleteApisByIds({ ids })
+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
-    })
+      type: "success",
+      message: res.msg,
+    });
     if (tableData.value.length === ids.length && page.value > 1) {
-      page.value--
+      page.value--;
     }
-    deleteVisible.value = false
-    getTableData()
+    deleteVisible.value = false;
+    getTableData();
   }
-}
+};
 
 // 弹窗相关
-const apiForm = ref(null)
+const apiForm = ref(null);
 const initForm = () => {
-  apiForm.value.resetFields()
+  apiForm.value.resetFields();
   form.value = {
-    path: '',
-    apiGroup: '',
-    method: '',
-    description: ''
-  }
-}
+    path: "",
+    apiGroup: "",
+    method: "",
+    description: "",
+  };
+};
 
-const dialogTitle = ref('新增Api')
-const dialogFormVisible = ref(false)
+const dialogTitle = ref("新增Api");
+const dialogFormVisible = ref(false);
 const openDialog = (key) => {
   switch (key) {
-    case 'addApi':
-      dialogTitle.value = '新增Api'
-      break
-    case 'edit':
-      dialogTitle.value = '编辑Api'
-      break
+    case "addApi":
+      dialogTitle.value = "新增Api";
+      break;
+    case "edit":
+      dialogTitle.value = "编辑Api";
+      break;
     default:
-      break
+      break;
   }
-  type.value = key
-  dialogFormVisible.value = true
-}
+  type.value = key;
+  dialogFormVisible.value = true;
+};
 const closeDialog = () => {
-  initForm()
-  dialogFormVisible.value = false
-}
+  initForm();
+  dialogFormVisible.value = false;
+};
 
-const editApiFunc = async(row) => {
-  const res = await getApiById({ id: row.ID })
-  form.value = res.data.api
-  openDialog('edit')
-}
+const editApiFunc = async (row) => {
+  const res = await getApiById({ id: row.ID });
+  form.value = res.data.api;
+  openDialog("edit");
+};
 
-const enterDialog = async() => {
-  apiForm.value.validate(async valid => {
+const enterDialog = async () => {
+  apiForm.value.validate(async (valid) => {
     if (valid) {
       switch (type.value) {
-        case 'addApi':
+        case "addApi":
           {
-            const res = await createApi(form.value)
+            const res = await createApi(form.value);
             if (res.code === 0) {
               ElMessage({
-                type: 'success',
-                message: '添加成功',
-                showClose: true
-              })
+                type: "success",
+                message: "添加成功",
+                showClose: true,
+              });
             }
-            getTableData()
-            closeDialog()
+            getTableData();
+            closeDialog();
           }
 
-          break
-        case 'edit':
+          break;
+        case "edit":
           {
-            const res = await updateApi(form.value)
+            const res = await updateApi(form.value);
             if (res.code === 0) {
               ElMessage({
-                type: 'success',
-                message: '编辑成功',
-                showClose: true
-              })
+                type: "success",
+                message: "编辑成功",
+                showClose: true,
+              });
             }
-            getTableData()
-            closeDialog()
+            getTableData();
+            closeDialog();
           }
-          break
+          break;
         default:
           // eslint-disable-next-line no-lone-blocks
           {
             ElMessage({
-              type: 'error',
-              message: '未知操作',
-              showClose: true
-            })
+              type: "error",
+              message: "未知操作",
+              showClose: true,
+            });
           }
-          break
+          break;
       }
     }
-  })
-}
+  });
+};
 
-const deleteApiFunc = async(row) => {
-  ElMessageBox.confirm('此操作将永久删除所有角色下该api, 是否继续?', '提示', {
-    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("此操作将永久删除所有角色下该api, 是否继续?", "提示", {
+    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>
 
 <style scoped lang="scss">