倚楼听风雨 лет назад: 3
Родитель
Сommit
eb5012901f

+ 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)
+  }
+}

+ 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============================================================================

+ 42 - 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,19 @@ 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,
+  });
+};

+ 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;

+ 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">