iZaiZaiA 2 years ago
parent
commit
6ab8e644d0

+ 5 - 5
package.json

@@ -10,14 +10,14 @@
         "axios": "^0.27.2",
         "crypto-js": "^4.1.1",
         "echarts": "^5.3.3",
-        "element-plus": "^2.2.13",
+        "element-plus": "^2.2.14",
         "js-base64": "^3.7.2",
         "js-cookie": "^3.0.1",
         "js-md5": "^0.7.3",
-        "js-web-screen-shot": "^1.7.1",
+        "js-web-screen-shot": "^1.7.3",
         "moment": "^2.29.4",
         "naive-ui": "^2.32.2",
-        "pinia": "^2.0.19",
+        "pinia": "^2.0.20",
         "vue": "^3.2.37",
         "vue-router": "^4.1.3",
         "vue-utils-plus": "^1.0.2",
@@ -29,12 +29,12 @@
         "autoprefixer": "^10.4.7",
         "nprogress": "^0.2.0",
         "postcss": "^8.4.16",
-        "sass": "^1.54.4",
+        "sass": "^1.54.5",
         "tailwindcss": "^3.1.8",
         "unplugin-auto-import": "^0.11.2",
         "unplugin-vue-components": "^0.22.4",
         "vfonts": "^0.0.3",
-        "vite": "^3.0.8",
+        "vite": "^3.0.9",
         "vooks": "^0.2.12"
     }
 }

+ 1 - 0
src/api/request/httpApi.js

@@ -24,6 +24,7 @@ const getResData = (response, error = false) => {
         code: response?.data?.code,
         msg: response?.data?.msg,
         status: response?.status,
+        disposition: response?.headers['content-disposition'],
         error: error
     }
 }

+ 4 - 0
src/global/components/hc-card/index.vue

@@ -98,9 +98,13 @@ const isSlotSearchBar = ref(!!slots.search);
         .hc-card-header {
             position: relative;
             flex: 1;
+            display: flex;
+            align-items: center;
         }
         .hc-card-header-extra {
             position: relative;
+            display: flex;
+            align-items: center;
         }
     }
     .el-card__body {

+ 1 - 1
src/layout/modules/HelpInfoBar.vue

@@ -28,7 +28,7 @@
         </div>
     </el-popover>
     <!--当前页面功能讲解-->
-    <el-dialog v-model="videoPreviewModal" width="62rem" :before-close="videoPreviewModalClose">
+    <el-dialog v-model="videoPreviewModal" width="62rem" destroy-on-close :before-close="videoPreviewModalClose">
         <video class="preview-video" :src="videoUrl" controls="controls" autoplay="autoplay">
             您的浏览器不支持 video
         </video>

+ 3 - 0
src/styles/app/element.scss

@@ -32,6 +32,9 @@
 .el-button + .el-button {
     margin-left: 20px;
 }
+.el-button--small + .el-button--small {
+    margin-left: 5px;
+}
 
 //单选框、多选框
 .el-checkbox.size-xl .el-checkbox__inner,

+ 2 - 7
src/styles/gauge/station.scss

@@ -1,13 +1,8 @@
 .hc-layout-box {
     position: relative;
-    height: calc(100% - 60px);
-    padding: 0 24px 24px;
-    .hc-card-header {
-        position: relative;
-        font-size: initial;
-        font-weight: initial;
-    }
+    height: 100%;
 }
+
 .hc-import-modal-box {
     .tip-box {
         position: relative;

+ 17 - 15
src/views/data-fill/components/WbsTree.vue

@@ -27,7 +27,7 @@
 import {ref,nextTick,watch} from "vue";
 import {hIconJs} from "~src/plugins/renderele";
 import dataFillQuery from '~api/data-fill/query';
-import {isItem,getArrValue} from "vue-utils-plus"
+import {isItem,getArrValue,getIndex} from "vue-utils-plus"
 import {NDropdown} from 'naive-ui';
 
 //参数
@@ -204,20 +204,22 @@ const ElTreeLabelContextMenu = (e,data,node) => {
 
 //设置菜单标记状态
 const setMenuMarkVal = (rows,item) => {
-    for (let i = 0; i < rows.length; i++) {
-        if (rows[i].key === 'mark' || rows[i].key === 'cancel_mark') {
-            if (item.isFirst) {
-                menusData.value[i].label = '取消标记为首件';
-                menusData.value[i].key = 'cancel_mark';
-                menusData.value[i].icon = hIconJs({
-                    name: 'grade', fill: true
-                });
-            } else {
-                menusData.value[i].label = '标记为首件';
-                menusData.value[i].key = 'mark';
-                menusData.value[i].icon = hIconJs({name: 'grade'});
-            }
-            break;
+    let indexs = getIndex(rows, 'key', 'mark')
+    if (indexs === -1) {
+        indexs = getIndex(rows, 'key', 'cancel_mark')
+    }
+    const index = indexs
+    if (index !== -1) {
+        if (item.isFirst === true) {
+            menusData.value[index].label = '取消标记为首件';
+            menusData.value[index].key = 'cancel_mark';
+            menusData.value[index].icon = hIconJs({
+                name: 'grade', fill: true
+            });
+        } else {
+            menusData.value[index].label = '标记为首件';
+            menusData.value[index].key = 'mark';
+            menusData.value[index].icon = hIconJs({name: 'grade'});
         }
     }
 }

+ 117 - 18
src/views/data-fill/query.vue

@@ -149,12 +149,12 @@ import {useAppStore} from "~src/store/index";
 import WbsTree from "./components/WbsTree.vue"
 import HcTreeData from "./components/HcTreeData.vue"
 import {getStoreData, setStoreData} from '~src/utils/storage'
-import {isType, deepClone, formValidate} from "vue-utils-plus"
+import {isType, downloadBlob} from "vue-utils-plus"
 import queryApi from '~api/data-fill/query';
 
 //变量
 const useAppState = useAppStore()
-const {getObjNullValue, getObjValue, getArrValue} = isType()
+const {getObjValue, getArrValue, isObjNull} = isType()
 const projectId = ref(useAppState.getProjectId);
 const contractId = ref(useAppState.getContractId);
 const projectInfo = ref(useAppState.getProjectInfo);
@@ -307,7 +307,7 @@ const betweenTimeUpdate = ({val,arr}) => {
 const keyUpEvent = (e) => {
     if (e.key === "Enter") {
         searchForm.value.current = 1;
-        getLogTableData()
+        getTableData()
     }
 }
 
@@ -355,7 +355,6 @@ const tableSelectionChange = (rows) => {
     tableCheckedKeys.value = rows.filter((item) => {
         return (item??'') !== '';
     })
-    console.log(rows)
 }
 
 //上报
@@ -373,10 +372,7 @@ const reportModalClick = () => {
     if (result) {
         //const info = nodeDataInfo.value;
         const row = getObjValue(rows[0])
-        //拼接ID
-        reportIds.value = rows.map((obj) => {
-            return obj.id;
-        }).join(",")
+        reportIds.value = rowsToId(rows)
         //设置任务名称
         reportTaskName.value = rows.length > 1 ? `${row.name}等${rows.length}个文件` : row.name
         //reportAddition.value = {contractIdRelation: info['contractIdRelation']}
@@ -391,35 +387,138 @@ const showReportFinish = () => {
     getTableData()
 }
 
+
 //下载
 const downloadLoading = ref(false)
-const batchDownload = () => {
-
+const batchDownload = async () => {
+    const rows = tableCheckedKeys.value;
+    const ids = rowsToId(rows)
+    //批量下载
+    downloadLoading.value = true
+    const { error, disposition, res } = await queryApi.batchDownloadFileToZip({ids: ids})
+    //处理数据
+    downloadLoading.value = false
+    if (!error) {
+        if (disposition) {
+            downloadBlob(res,disposition)
+        } else {
+            window.$message?.error('数据异常')
+        }
+    }
 }
 
 //打印
 const printLoading = ref(false)
-const batchPrint = () => {
-
+const batchPrint = async () => {
+    const rows = tableCheckedKeys.value;
+    const ids = rowsToId(rows)
+    //批量下载
+    printLoading.value = true
+    const { error, code, data } = await queryApi.batchPrint({ids: ids})
+    //处理数据
+    printLoading.value = false
+    if (!error && code === 200) {
+        console.log(data)
+        if (isObjNull(data)) {
+            window.$message?.error('数据异常')
+        } else {
+            //待写
+        }
+    }
 }
 
 //废除
-const batchAbolishClick = () => {
-
+const batchAbolishClick = async () => {
+    const rows = tableCheckedKeys.value;
+    //判断是否满足条件
+    const result = rows.every(({status})=> {
+        return status !== 0 && status !== 3
+    })
+    //判断状态
+    if (result) {
+        //拼接ID
+        const ids = rowsToId(rows)
+        window?.$messageBox?.alert('是否废除勾选的已上报文件?', '废除文件', {
+            showCancelButton: true,
+            confirmButtonText: '确定废除',
+            cancelButtonText: '取消',
+            callback: (action) => {
+                if (action === 'confirm') {
+                    batchAbolishSave(ids)
+                }
+            }
+        })
+    } else {
+        window.$message?.warning('未上报的文件不能废除')
+    }
+}
+//废除勾选的已上报文件
+const batchAbolishSave = async (ids) => {
+    const { error, code } = await queryApi.batchAbolish({ids: ids})
+    //处理数据
+    if (!error && code === 200) {
+        window.$message?.success('批量废除成功')
+        tableCheckedKeys.value = []
+        getTableData()
+    }
 }
 
 //本地验签
 const localLoading = ref(false)
-const batchLocal = () => {
-
+const batchLocal = async () => {
+    const rows = tableCheckedKeys.value;
+    //判断是否满足条件
+    const result = rows.every(({status})=> {
+        return status === 2
+    })
+    //判断状态
+    if (result) {
+        const ids = rowsToId(rows)
+        //请求数据
+        localLoading.value = true
+        const { error, code, data } = await queryApi.localVerify({
+            ids: ids
+        })
+        //处理数据
+        localLoading.value = false
+        if (!error && code === 200) {
+            console.log(data)
+        }
+    } else {
+        window.$message?.warning('存在未审批或未上报数据')
+    }
 }
 
 //在线验签
 const onlineLoading = ref(false)
-const batchOnline = () => {
-
+const batchOnline = async () => {
+    const rows = tableCheckedKeys.value;
+    if (rows.length > 1) {
+        window.$message?.warning('在线验签只能勾选一条数据进行验签')
+        return;
+    }
+    if (rows[0].status !== 2) {
+        window.$message?.warning('存在未审批或未上报数据')
+        return;
+    }
+    //发起
+    onlineLoading.value = true
+    const { error, code, data } = await queryApi.onlineVerify({
+        ids: rows[0]['id']
+    })
+    //处理数据
+    localLoading.value = false
+    if (!error && code === 200) {
+        console.log(data)
+    }
 }
 
+//拼接ID
+const rowsToId = (rows) => {
+    return rows.map((obj) => {
+        return obj.id;
+    }).join(",")
+}
 
 
 //左右拖动,改变树形结构宽度

+ 0 - 545
src/views/data-fill/query_bak.vue

@@ -1,545 +0,0 @@
-<template>
-    <n-divider dashed title-placement="left">资料查询</n-divider>
-    <div class="hc-layout-box">
-        <div class="hc-layout-left-box" :style="'width:' + leftWidth + 'px;'">
-            <div class="hc-project-box">
-                <div class="text-xl text-cut project-alias-box">
-                    <i class="hcicon-xiangmu"/>
-                    <span class="ml-2">{{projectInfo['projectAlias']}}</span>
-                </div>
-                <div class="text-xs text-cut project-name">{{projectInfo['name']}}</div>
-            </div>
-            <div class="hc-el-tree-box">
-                <div class="search-tree-val">
-                    <n-input-group>
-                        <n-input v-model:value="searchTreeVal" type="text" placeholder="请输入名称关键词检索" clearable  @keyup="searchTreeKeyUp"/>
-                        <n-button type="primary" @click="searchTreeClick">搜索</n-button>
-                    </n-input-group>
-                </div>
-                <template v-if="isSearchTree">
-                    <HcTreeData :datas="searchTreeData" :params="treeParams" :props="wbsElTreeProps" isColor @node-click="wbsElTreeClick"/>
-                </template>
-                <template v-else>
-                    <HcTree type="data-fill-query" :params="treeParams" :props="wbsElTreeProps" lazy isColor @node-click="wbsElTreeClick"/>
-                </template>
-            </div>
-            <div class="hc-tree-foot-tip-box">
-                <div class="dot-view green">已审批</div>
-                <div class="dot-view black">未填报</div>
-                <div class="dot-view orange">已填报-待审批</div>
-                <div class="dot-view blue">已填报-未上报</div>
-            </div>
-            <!--左右拖动-->
-            <div class="horizontal-drag-line" @mousedown="onmousedown"/>
-        </div>
-        <div class="hc-layout-content-box">
-            <n-card class="hc-card-overflow-box" :segmented="{content: true}">
-                <template #header>
-                    <div class="hc-card-header flex items-center">
-                        <div class="w-40">
-                            <n-select v-model:value="searchForm.taskStatus" :options="processStatusData" placeholder="流程状态" clearable/>
-                        </div>
-                        <div class="w-40 ml-5">
-                            <n-select v-model:value="searchForm.fileUserIdAndName" :options="reportingPersonData" placeholder="填报人" clearable/>
-                        </div>
-                        <div class="w-40 ml-5">
-                            <n-select v-model:value="searchForm.sourceType" :options="fileTypeData" placeholder="文件类型" clearable/>
-                        </div>
-                        <div class="w-40 ml-5">
-                            <n-select v-model:value="searchForm.reportNumber" :options="reportBatchData" placeholder="上报批次" clearable/>
-                        </div>
-                        <div class="w-96 ml-5">
-                            <n-date-picker v-model:formatted-value="betweenTime" value-format="yyyy-MM-dd HH:mm:ss" type="datetimerange" clearable @update:value="betweenTimeUpdate"/>
-                        </div>
-                        <div class="w-60 ml-5">
-                            <n-input v-model:value="searchForm.queryValue" type="text" placeholder="请输入名称关键词检索" clearable @keyup="keyUpEvent">
-                                <template #suffix>
-                                    <span class="_icon-search hc-input-search-icon"/>
-                                </template>
-                            </n-input>
-                        </div>
-                        <n-button type="primary" class="ml-2" @click="searchChange">搜索</n-button>
-                    </div>
-                </template>
-                <div class="hc-sticky-box p-6">
-                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_report?.textInfo" v-if="btn_report">
-                        <template #trigger>
-                            <n-button type="primary" class="px-8" @click="reportModalClick">上报</n-button>
-                        </template>
-                        <span>{{btn_report?.textInfo}}</span>
-                    </n-popover>
-                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_download?.textInfo" v-if="btn_download">
-                        <template #trigger>
-                            <n-button type="primary" strong secondary class="px-8 ml-6" :loading="batchDownloadLoading" @click="batchDownload">下载</n-button>
-                        </template>
-                        <span>{{btn_download?.textInfo}}</span>
-                    </n-popover>
-                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_print?.textInfo" v-if="btn_print">
-                        <template #trigger>
-                            <n-button type="primary" strong secondary class="px-8 ml-6" :loading="batchPrintLoading" @click="batchPrint">打印</n-button>
-                        </template>
-                        <span>{{btn_print?.textInfo}}</span>
-                    </n-popover>
-                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_abolish?.textInfo" v-if="btn_abolish">
-                        <template #trigger>
-                            <n-button type="primary" strong secondary class="px-8 ml-6" @click="batchAbolishClick">废除</n-button>
-                        </template>
-                        <span>{{btn_abolish?.textInfo}}</span>
-                    </n-popover>
-                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_online?.textInfo" v-if="btn_online">
-                        <template #trigger>
-                            <n-button type="primary" strong secondary class="px-8 ml-6" :loading="batchOnlineLoading" @click="batchOnline">在线验签</n-button>
-                        </template>
-                        <span>{{btn_online?.textInfo}}</span>
-                    </n-popover>
-                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_local?.textInfo" v-if="btn_local">
-                        <template #trigger>
-                            <n-button type="primary" strong secondary class="px-8 ml-6" :loading="batchLocalLoading" @click="batchLocal">本地验签</n-button>
-                        </template>
-                        <span>{{btn_local?.textInfo}}</span>
-                    </n-popover>
-                </div>
-                <div class="p-6 pt-0">
-                    <n-data-table :columns="tableColumns" :data="tableData" :row-key="row => row.id" @update:checked-row-keys="tableHandleCheck" :single-line="false" striped/>
-                </div>
-                <template #action>
-                    <HcPage :pages="searchForm" @change="pageChange"/>
-                </template>
-            </n-card>
-        </div>
-    </div>
-    <!--批量上报审批-->
-    <HcReportModal  title="批量上报审批" url="informationWriteQuery/batchTask" :show="showReportModal" :projectId="projectId" :contractId="contractId"
-                    :taskName="reportTaskName" :ids="reportIds" @hide="showReportModal = false" @finish="showReportFinish"/>
-</template>
-
-<script setup>
-import {ref,watch,onMounted} from "vue";
-import {useAppStore} from "~src/store/index";
-import HcTree from "~com/plugins/element/HcTree.vue"
-import HcPage from "~com/plugins/naive/HcPage.vue"
-import HcTreeData from "./components/HcTreeData.vue"
-import dataFillQuery from '~api/data-fill/query';
-import HcReportModal from "~com/reportModal/index.vue"
-import {deepClone} from "~src/utils/lib/util";
-import {download} from '~src/utils/lib/tools';
-
-//变量
-const useAppState = useAppStore()
-const projectId = ref(useAppState.getProjectId);
-const contractId = ref(useAppState.getContractId);
-const projectInfo = ref(useAppState.getProjectInfo);
-
-//按钮气泡开关
-const bubbleVal = ref(useAppState.getBubble);
-//监听
-watch(() => [
-    useAppState.getProjectId,
-    useAppState.getContractId,
-    useAppState.getProjectInfo,
-    useAppState.getBubble,
-], ([UserProjectId, UserContractId,UserProjectInfo,Bubble]) => {
-    //项目合同数据
-    projectId.value = UserProjectId
-    contractId.value = UserContractId
-    projectInfo.value = UserProjectInfo
-    //按钮气泡开关
-    bubbleVal.value = Bubble
-})
-
-//获取气泡数据
-const getButtonsVal = (value) => {
-    return useAppState.getButtonsVal(value)
-}
-
-//气泡数据
-const btn_report = ref(getButtonsVal('query_report'))
-const btn_download = ref(getButtonsVal('query_download'))
-const btn_print = ref(getButtonsVal('query_print'))
-const btn_local = ref(getButtonsVal('query_local_attestation'))
-const btn_abolish = ref(getButtonsVal('query_abolish'))
-const btn_online = ref(getButtonsVal('query_online_attestation'))
-
-const processStatusData = ref([])   //流程状态
-const reportingPersonData = ref([]) //填报人
-const fileTypeData = ref([])        //文件类型
-const reportBatchData = ref([])     //上报批次
-
-//搜索表单
-const betweenTime = ref(null)
-const searchForm = ref({
-    taskStatus: null, fileUserIdAndName: null, sourceType: null, reportNumber: null,
-    queryValue: null, betweenTime: null, wbsId: null, current: 1, size: 20, total: 0
-})
-
-//树数据
-const wbsElTreeProps = {label: 'title', children: 'children', isLeaf: 'notExsitChild'}
-const treeParams = ref({contractId: contractId.value})
-//树被点击
-const wbsElTreeClick = ({data}) => {
-    searchForm.value.wbsId = data['contractIdRelation'] ? data['id'] : data['primaryKeyId']
-    searchForm.value.contractIdRelation = data['contractIdRelation']
-    searchForm.value.current = 1;
-    getTableData()
-}
-
-//树搜索
-const isSearchTree = ref(false)
-const searchTreeVal = ref('')
-const searchTreeData = ref([])
-console.log(isSearchTree.value)
-//回车
-const searchTreeKeyUp = (e) => {
-    if (e.key === "Enter") {
-        searchTreeClick()
-    }
-}
-const searchTreeClick = () => {
-    if (searchTreeVal.value) {
-        isSearchTree.value = true
-        dataFillQuery.searchContractTree({
-            contractId: contractId.value,
-            queryValue: searchTreeVal.value
-        }).then(({data}) => {
-            searchTreeData.value = data?.data || []
-        }).catch(() => {
-            searchTreeData.value = []
-        })
-    } else {
-        isSearchTree.value = false
-    }
-}
-
-//渲染完成
-onMounted(() => {
-    getFileUser()
-    getReportNumber()
-    getDictBizClassify('flowTaskStatus')
-    getDictBizClassify('fileType')
-})
-
-//获取所有填报人
-const getFileUser = () => {
-    dataFillQuery.getFileUser({
-        contractId: contractId.value
-    }).then(({data}) => {
-        let res = data?.data || [], userArr = [];
-        res.forEach(item => {
-            userArr.push({
-                label: item?.userName,
-                value: `${item?.userId}-${item?.userName}`
-            })
-        })
-        reportingPersonData.value = userArr
-    })
-}
-
-//获取所有填报人
-const getReportNumber = () => {
-    dataFillQuery.getReportNumber({
-        contractId: contractId.value
-    }).then(({data}) => {
-        let res = data?.data || [];
-    })
-}
-
-//获取流程状态分类和文件类型分类
-const getDictBizClassify = (code) => {
-    dataFillQuery.getDictBizClassify({
-        contractId: contractId.value,
-        code: code
-    }).then(({data}) => {
-        let res = data?.data || [], typeArr = [];
-        res.forEach((key) => {
-            typeArr.push({
-                label: key?.dictValue,
-                value: key?.dictKey
-            })
-        })
-        if (code === 'flowTaskStatus') {
-            processStatusData.value = typeArr
-        } else if (code === 'fileType') {
-            fileTypeData.value = typeArr
-        }
-    })
-}
-
-//重新搜索数据
-const searchChange = () => {
-    searchForm.value.current = 1
-    getTableData()
-}
-
-//回车搜索
-const keyUpEvent = (e) => {
-    if (e.key === "Enter") {
-        searchForm.value.current = 1;
-        getTableData()
-    }
-}
-
-//日期时间被选择
-const betweenTimeUpdate = (_,res) => {
-    res = res || []
-    if (res.length > 0) {
-        searchForm.value.betweenTime = res[0] + '~' + res[1]
-    } else {
-        searchForm.value.betweenTime = null
-    }
-    searchForm.value.current = 1;
-    getTableData()
-}
-
-//分页被点击
-const pageChange = (res) => {
-    searchForm.value.current = res.current;
-    searchForm.value.size = res.size;
-    getTableData()
-}
-
-//获取数据
-const getTableData = () => {
-    if (!!searchForm.value.wbsId) {
-        dataFillQuery.getPageData({
-            projectId: projectId.value,
-            contractId: contractId.value,
-            ...searchForm.value
-        }).then(({data}) => {
-            let res = data['data'] || {}
-            tableData.value = res['records'] || []
-            searchForm.value.total = res.total || 0
-        })
-    } else {
-        window?.$message?.warning('请先选择一个树节点')
-    }
-}
-
-//表格表头
-const tableColumns = [
-    {type: 'selection'},
-    {title: '序号', key: 'key', width: 80, align: 'center',
-        render(_, index) {
-            return index + 1
-        }
-    },
-    {title: '文件名称', key: 'name'},
-    {title: '开始时间', key: 'startTime'},
-    {title: '流程状态', key: 'taskStatusStr'},
-    {title: '上报批次', key: 'reportNumber', width: 120, align: 'center'},
-    {title: '填报人', key: 'fileUserIdAndName'},
-    {title: '任务人', key: 'tesk'}
-]
-//表格数据
-const tableData = ref([]);
-//表格勾选
-const checkedRowsRef = ref([])
-const tableHandleCheck = (_,rows) => {
-    checkedRowsRef.value = rows.filter((item) => {
-        return (item??'') !== '';
-    })
-}
-
-//批量上报
-const reportIds = ref('')
-const reportTaskName = ref('')
-const showReportModal = ref(false)
-const reportModalClick = () => {
-    const rows = checkedRowsRef.value;
-    if (rows.length > 0) {
-        let ids = '', report = true;
-        for (let i = 0; i < rows.length; i++) {
-            ids += `${ids?`,${rows[i]['id']}`:rows[i]['id']}`
-            if (rows[i].status !== 0 && rows[i].status !== 3) {
-                report = false
-                break;
-            }
-        }
-        //判断状态
-        if (report) {
-            reportIds.value = ids
-            reportTaskName.value = rows.length > 1?`${rows[0].name}等${rows.length}个文件`:rows[0].name
-            showReportModal.value = true
-        } else {
-            window.$message?.warning('已上报的文件不能进行再次上报,若要重新上报,要先撤回之前的上报,再重新上报')
-        }
-    } else {
-        window.$message?.warning('请先勾选要上报的数据')
-    }
-}
-
-//上报完成
-const showReportFinish = () => {
-    showReportModal.value = false
-    checkedRowsRef.value = []
-    getTableData()
-}
-
-//批量废除
-const batchAbolishClick = () => {
-    const rows = deepClone(checkedRowsRef.value)
-    if (rows.length > 0) {
-        let report = true, ids = '';
-        for (let i = 0; i < rows.length; i++) {
-            ids += `${ids?`,${rows[i]['id']}`:rows[i]['id']}`
-            if (rows[i].status === 0 || rows[i].status === 3) {
-                report = false
-                break;
-            }
-        }
-        //判断状态
-        if (report) {
-            window?.$dialog?.warning({
-                title: "确认操作",
-                content: "是否废除勾选的已上报文件?",
-                positiveText: "确定废除",
-                negativeText: "取消",
-                onPositiveClick: () => {
-                    batchAbolishSave(ids)
-                }
-            });
-        } else {
-            window.$message?.warning('未上报的文件不能废除')
-        }
-    } else {
-        window.$message?.warning('请先勾选要废除的数据')
-    }
-}
-
-//废除勾选的已上报文件
-const batchAbolishSave = (ids) => {
-    if (ids) {
-        dataFillQuery.batchAbolish({
-            ids: ids
-        }).then(({data}) => {
-            if (data.code === 200) {
-                window.$message?.success('批量废除成功')
-                checkedRowsRef.value = []
-                getTableData()
-            } else {
-                window.$message?.error(data.msg || '批量废除失败')
-            }
-        })
-    } else {
-        window.$message?.warning('请先勾选要废除的数据')
-    }
-}
-
-//批量下载
-const batchDownloadLoading = ref(false)
-const batchDownload = () => {
-    const rows = checkedRowsRef.value;
-    if (rows.length > 0) {
-        let ids = '';
-        for (let i = 0; i < rows.length; i++) {
-            ids += `${ids?`,${rows[i]['id']}`:rows[i]['id']}`
-        }
-        //批量下载
-        batchDownloadLoading.value = true
-        dataFillQuery.batchDownloadFileToZip({
-            ids: ids
-        }).then((res) => {
-            batchDownloadLoading.value = false
-            download(res)   //下载文件
-        })
-    } else {
-        window.$message?.warning('请先勾选要下载的数据')
-    }
-}
-
-//批量打印
-const batchPrintLoading = ref(false)
-const batchPrint = () => {
-    const rows = checkedRowsRef.value;
-    if (rows.length > 0) {
-        let ids = '';
-        for (let i = 0; i < rows.length; i++) {
-            ids += `${ids?`,${rows[i]['id']}`:rows[i]['id']}`
-        }
-        //发起
-        batchPrintLoading.value = true
-        dataFillQuery.batchPrint({
-            ids: ids
-        }).then(({data}) => {
-            console.log(data)
-            batchPrintLoading.value = false
-        })
-    } else {
-        window.$message?.warning('请先勾选要下载的数据')
-    }
-}
-
-//本地验签
-const batchLocalLoading = ref(false)
-const batchLocal = () => {
-    const rows = checkedRowsRef.value;
-    if (rows.length <= 0) {
-        window.$message?.warning('请先勾选要下载的数据')
-    } else {
-        let report = true, ids = '';
-        for (let i = 0; i < rows.length; i++) {
-            ids += `${ids?`,${rows[i]['id']}`:rows[i]['id']}`
-            if (rows[i].status !== 2) {
-                report = false
-                break;
-            }
-        }
-        //判断状态
-        if (report) {
-            batchLocalLoading.value = true
-            dataFillQuery.localVerify({
-                ids: ids
-            }).then(({data}) => {
-                console.log(data)
-                batchLocalLoading.value = false
-            })
-        } else {
-            window.$message?.warning('存在未审批或未上报数据')
-        }
-    }
-}
-
-//在线验签
-const batchOnlineLoading = ref(false)
-const batchOnline = () => {
-    const rows = checkedRowsRef.value;
-    if (rows.length <= 0) {
-        window.$message?.warning('请先勾选要下载的数据')
-        return;
-    }
-    if (rows.length > 1) {
-        window.$message?.warning('在线验签只能勾选一条数据进行验签')
-        return;
-    }
-    if (rows[0].status !== 2) {
-        window.$message?.warning('存在未审批或未上报数据')
-        return;
-    }
-    //发起
-    batchOnlineLoading.value = true
-    dataFillQuery.onlineVerify({
-        ids: rows[0]['id']
-    }).then(({data}) => {
-        console.log(data)
-        batchOnlineLoading.value = false
-    })
-}
-
-//左右拖动,改变树形结构宽度
-const leftWidth = ref(382);
-const onmousedown = () => {
-    document.onmousemove = (ve) => {
-        let diffVal = ve.clientX + 2;
-        if(diffVal >= 310 && diffVal <= 900) {
-            leftWidth.value = diffVal;
-        }
-    }
-    document.onmouseup = () => {
-        document.onmousemove = null;
-        document.onmouseup = null;
-    }
-}
-</script>
-
-<style lang="scss" scoped>
-@import "../../styles/data-fill/query.scss";
-</style>

+ 358 - 360
src/views/gauge/station.vue

@@ -1,81 +1,122 @@
 <template>
-    <n-divider dashed title-placement="left">测站点</n-divider>
     <div class="hc-layout-box">
-        <n-card class="hc-card-overflow-p-box" :segmented="{content: true}">
+        <HcCard :scrollbar="false" actionSize="lg">
             <template #header>
-                <div class="hc-card-header flex items-center">
-                    <div class="w-60">
-                        <n-input v-model:value="searchForm.name" type="text" placeholder="请输入测站点或关键字进行搜索" clearable/>
-                    </div>
-                    <n-button type="primary" class="px-5 ml-3" @click="searchChange">搜索</n-button>
-                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_add?.textInfo" v-if="btn_add">
-                        <template #trigger>
-                            <n-button type="primary" strong secondary class="px-5 ml-10" @click="AddRowClick">新增</n-button>
-                        </template>
-                        <span>{{btn_add?.textInfo}}</span>
-                    </n-popover>
-                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_import?.textInfo" v-if="btn_import">
-                        <template #trigger>
-                            <n-button type="primary" strong secondary class="px-5 ml-3" @click="importModalClick">导入</n-button>
-                        </template>
-                        <span>{{btn_import?.textInfo}}</span>
-                    </n-popover>
-                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_export?.textInfo" v-if="btn_export">
-                        <template #trigger>
-                            <n-button type="primary" strong secondary class="px-5 ml-3" @click="exportModalClick">导出</n-button>
-                        </template>
-                        <span>{{btn_export?.textInfo}}</span>
-                    </n-popover>
+                <HcTooltip keys="gauge-station-add">
+                    <el-button type="primary" hc-btn @click="AddRowClick">
+                        <HcIcon name="drive_folder_upload"/>
+                        <span>新增</span>
+                    </el-button>
+                </HcTooltip>
+                <HcTooltip keys="gauge-station-import">
+                    <el-button hc-btn @click="importModalClick">
+                        <HcIcon name="download"/>
+                        <span>导入</span>
+                    </el-button>
+                </HcTooltip>
+                <HcTooltip keys="gauge-station-export">
+                    <el-button hc-btn :loading="downloadLoading" @click="exportModalClick">
+                        <HcIcon name="print"/>
+                        <span>导出</span>
+                    </el-button>
+                </HcTooltip>
+                <div class="w-60 ml-6">
+                    <el-input v-model="searchForm.name" size="large" placeholder="请输入测站点或关键字进行搜索" clearable @keyup="keyUpEvent"/>
+                </div>
+                <div class="ml-2">
+                    <el-button type="primary" size="large" @click="searchClick">搜索</el-button>
                 </div>
             </template>
-            <template #header-extra>
-                <HcTabs :datas="tabsTypeData" :keys="tabsTypeKey" @change="tabsTypeChange"/>
+            <template #extra>
+                <HcNewSwitch :datas="tabsTypeData" :keys="tabsTypeKey" @change="tabsTypeChange"/>
             </template>
-            <div v-if="tabsTypeKey==='1'">
-                <n-data-table :columns="traverseColumns" :data="traverseTable" :pagination="false" :row-key="row => row.name" :single-line="false" striped/>
-            </div>
-            <div v-if="tabsTypeKey==='0'">
-                <n-data-table :columns="levelColumns" :data="levelTable" :pagination="false" :row-key="row => row.name" :single-line="false" striped/>
-            </div>
+            <el-scrollbar>
+                <div class="hc-table-ref-box" v-if="tabsTypeKey === '0'">
+                    <el-table ref="recycleTableRef" hc :data="levelTable" :loading="tableLoading" stripe>
+                        <el-table-column prop="num" label="序号" width="80">
+                            <template #default="scope">
+                                {{scope.$index + 1}}
+                            </template>
+                        </el-table-column>
+                        <el-table-column prop="name" label="测站点名称" />
+                        <el-table-column prop="h" label="高程(m)"/>
+                        <el-table-column prop="level" label="等级"/>
+                        <el-table-column prop="remark" label="备注"/>
+                        <el-table-column label="操作" align="center" width="130">
+                            <template #default="scope">
+                                <HcTooltip keys="gauge-station-edit">
+                                    <el-button type="primary" size="small" text @click="handleLevelEdit(scope.row)">编辑</el-button>
+                                </HcTooltip>
+                                <HcTooltip keys="gauge-station-del">
+                                    <el-button type="danger" size="small" text @click="handleLevelDelete(scope.row)">删除</el-button>
+                                </HcTooltip>
+                            </template>
+                        </el-table-column>
+                    </el-table>
+                </div>
+                <div class="hc-table-ref-box" v-if="tabsTypeKey === '1'">
+                    <el-table ref="recycleTableRef" hc :data="traverseTable" :loading="tableLoading" stripe>
+                        <el-table-column prop="num" label="序号" width="80">
+                            <template #default="scope">
+                                {{scope.$index + 1}}
+                            </template>
+                        </el-table-column>
+                        <el-table-column prop="name" label="测站点名称" />
+                        <el-table-column prop="x" label="X坐标(m)"/>
+                        <el-table-column prop="y" label="Y坐标(m)"/>
+                        <el-table-column prop="h" label="高程(m)"/>
+                        <el-table-column prop="level" label="等级"/>
+                        <el-table-column prop="remark" label="备注"/>
+                        <el-table-column label="操作" align="center" width="130">
+                            <template #default="scope">
+                                <HcTooltip keys="gauge-station-edit">
+                                    <el-button type="primary" size="small" text @click="handleTraverseEdit(scope.row)">编辑</el-button>
+                                </HcTooltip>
+                                <HcTooltip keys="gauge-station-del">
+                                    <el-button type="danger" size="small" text @click="handleTraverseDelete(scope.row)">删除</el-button>
+                                </HcTooltip>
+                            </template>
+                        </el-table-column>
+                    </el-table>
+                </div>
+            </el-scrollbar>
             <template #action>
-                <HcPage :pages="searchForm" @change="pageChange"/>
+                <HcPages :pages="searchForm" @change="pageChange"/>
             </template>
-        </n-card>
-    </div>
-    <!--新增/编辑 弹框-->
-    <n-modal v-model:show="showRowModal">
-        <n-card class="w-750" :title="rowModalTitle()" :segmented="{content: true}">
-            <n-form ref="formRowRef" :model="formRowValue" :rules="rulesRow" label-placement="left" label-width="auto" size="large">
-                <n-form-item label="点名称" path="name">
-                    <n-input class="flex-1" v-model:value="formRowValue.name" placeholder="请输入点名称"/>
-                </n-form-item>
-                <n-form-item label="X坐标(m)" path="x" v-if="tabsTypeKey === '1'">
-                    <n-input class="flex-1" v-model:value="formRowValue.x" placeholder="请输入X坐标(m)"/>
-                </n-form-item>
-                <n-form-item label="Y坐标(m)" path="y" v-if="tabsTypeKey === '1'">
-                    <n-input class="flex-1" v-model:value="formRowValue.y" placeholder="请输入Y坐标(m)"/>
-                </n-form-item>
-                <n-form-item label="高程(m)" path="h">
-                    <n-input class="flex-1" v-model:value="formRowValue.h" placeholder="请输入高程(m)"/>
-                </n-form-item>
-                <n-form-item label="等级">
-                    <n-select class="flex-1" v-model:value="formRowValue.level" :options="personData" placeholder="请选择等级"/>
-                </n-form-item>
-                <n-form-item label="备注">
-                    <n-input v-model:value="formRowValue.remark" placeholder="请输入文字说明" type="textarea" :autosize="{minRows: 3,maxRows: 5}"/>
-                </n-form-item>
-            </n-form>
-            <template #action>
-                <div class="text-center">
-                    <n-button class="px-5" @click="showRowModal = false">取消</n-button>
-                    <n-button type="primary" class="px-5 ml-4" :loading="saveFormLoading" @click="saveFormClick">保存</n-button>
+        </HcCard>
+        <!--新增/编辑 弹框-->
+        <el-dialog v-model="showRowModal" :title="`${formRowValue?.id ? '编辑' : '新增'}${tabsTypeKey==='1'?'导线点':'水准点'}`" width="47rem" custom-class="hc-modal-border">
+            <el-form ref="formRowRef" :model="formRowValue" :rules="rulesRow" label-width="auto" size="large">
+                <el-form-item label="点名称" prop="name">
+                    <el-input v-model="formRowValue.name" placeholder="请输入点名称"/>
+                </el-form-item>
+                <el-form-item label="X坐标(m)" prop="x" v-if="tabsTypeKey === '1'">
+                    <el-input v-model="formRowValue.x" placeholder="请输入X坐标(m)"/>
+                </el-form-item>
+                <el-form-item label="Y坐标(m)" prop="y" v-if="tabsTypeKey === '1'">
+                    <el-input v-model="formRowValue.y" placeholder="请输入Y坐标(m)"/>
+                </el-form-item>
+                <el-form-item label="高程(m)" prop="h">
+                    <el-input v-model="formRowValue.h" placeholder="请输入高程(m)"/>
+                </el-form-item>
+                <el-form-item label="等级">
+                    <el-select v-model="formRowValue.level" block>
+                        <el-option v-for="item in personData" :label="item.label" :value="item.value" placeholder="请选择等级"/>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="备注">
+                    <el-input type="textarea" v-model="formRowValue.remark" placeholder="请输入文字说明" :autosize="{ minRows: 3, maxRows: 5 }"/>
+                </el-form-item>
+            </el-form>
+            <template #footer>
+                <div class="dialog-footer">
+                    <el-button size="large" @click="showRowModal = false">取消</el-button>
+                    <el-button type="primary" hc-btn :loading="saveFormLoading" @click="saveFormClick">提交</el-button>
                 </div>
             </template>
-        </n-card>
-    </n-modal>
-    <!--导入 弹框-->
-    <n-modal v-model:show="showImportModal">
-        <n-card class="w-750" :title="'导入' + getModalTitle()" :segmented="{content: true}">
+        </el-dialog>
+        <!--导入 弹框-->
+        <el-dialog v-model="showImportModal" :title="`导入${tabsTypeKey==='1'?'导线点':'水准点'}`" width="47rem" custom-class="hc-modal-border">
             <div class="hc-import-modal-box">
                 <div class="tip-box">
                     <span>请先下载导入模板(</span>
@@ -84,9 +125,12 @@
                     <span> ),按模板样式编辑测站点后,再点击"选择文件"按钮选择编辑好的文件,并点击底部的"确认导入"按钮即可导入成功!</span>
                 </div>
                 <div class="upload-box">
-                    <n-upload ref="uploadRef" :action="action" :headers="getTokenHeader()" :data="upData" :max="1" :accept="accept" :default-upload="false" multiple @change="handleUploadChange" @finish="uploadFinish">
-                        <n-button type="primary" class="px-4">选择文件</n-button>
-                    </n-upload>
+                    <el-upload ref="uploadRef" :action="action" :headers="getTokenHeader()" :accept="accept" :data="addition" :limit="1" :auto-upload="false" v-model:file-list="fileList"
+                               :on-exceed="handleUploadExceed" :on-progress="handleUploadProgress" :on-success="handleUploadFinish" :on-error="handleUploadError">
+                        <template #trigger>
+                            <el-button type="primary" :loading="importLoading">选择文件</el-button>
+                        </template>
+                    </el-upload>
                 </div>
                 <div class="text-orange">导入模板格式示例:</div>
                 <div class="demo-img-box" v-if="tabsTypeKey==='1'">
@@ -96,396 +140,350 @@
                     <img src="../../assets/view/152211@2x.png" alt="">
                 </div>
             </div>
-            <template #action>
-                <div class="text-center">
-                    <n-button class="px-4" @click="showImportModal = false">取消</n-button>
-                    <n-button type="primary" :disabled="!fileListLength" :loading="importLoading" class="px-4 ml-4" @click="handleImportClick">确认导入</n-button>
+            <template #footer>
+                <div class="dialog-footer">
+                    <el-button size="large" @click="showImportModal = false">取消</el-button>
+                    <el-button type="primary" hc-btn :disabled="fileList.length <= 0" :loading="importLoading" @click="handleImportClick">确认导入</el-button>
                 </div>
             </template>
-        </n-card>
-    </n-modal>
+        </el-dialog>
+    </div>
 </template>
 
 <script setup>
-import {ref,watch,onMounted} from "vue";
+import {ref,onMounted} from "vue";
+import {useRouter, useRoute} from 'vue-router'
 import {useAppStore} from "~src/store/index";
-import HcTabs from "~com/plugins/naive/HcTabs.vue"
-import HcPage from "~com/plugins/naive/HcPage.vue"
-//import {renderTableEditDelButton} from "~src/plugins/renderele";
+import stationApi from '~api/gauge/station';
 import {getTokenHeader} from '~src/api/request/header';
-import station from '~api/gauge/station';
-import {download} from "~src/utils/lib/tools";
+import {getArrValue, downloadBlob, formValidate} from "vue-utils-plus"
+import { genFileId } from 'element-plus'
 
 //初始变量
+const router = useRouter()
+const useRoutes = useRoute()
 const useAppState = useAppStore()
-const projectId = ref(useAppState.getProjectId);
-const contractId = ref(useAppState.getContractId);
 
-//按钮气泡开关
-const bubbleVal = ref(useAppState.getBubble);
+//路由参数
+const routerQuery = useRoutes?.query;
+const typeName = routerQuery?.type || '0'
 
-//监听
-watch(() => [
-    useAppState.getProjectId,
-    useAppState.getContractId,
-    useAppState.getBubble,
-], ([UserProjectId,UserContractId,Bubble]) => {
-    projectId.value = UserProjectId
-    contractId.value = UserContractId
-    //按钮气泡开关
-    bubbleVal.value = Bubble
-})
-
-//获取气泡数据
-const getButtonsVal = (value) => {
-    return useAppState.getButtonsVal(value)
-}
-
-//气泡数据
-const btn_add = ref(getButtonsVal('gauge-station-add'))
-const btn_import = ref(getButtonsVal('gauge-station-import'))
-const btn_export = ref(getButtonsVal('gauge-station-export'))
-const btn_edit = ref(getButtonsVal('gauge-station-edit'))
-const btn_del = ref(getButtonsVal('gauge-station-del'))
-
-//搜索表单
-const searchForm = ref({
-    projectId: projectId.value,
-    contractId: contractId.value,
-    name: null, type: '1',
-    current: 1, size: 20, total: 0
-})
+//全局变量
+const projectId = ref(useAppState.getProjectId);
+const contractId = ref(useAppState.getContractId);
 
-//结构类型tab数据和相关处理
-const tabsTypeKey = ref('1')
+//类型tab数据和相关处理
+const tabsTypeKey = ref(typeName)
 const tabsTypeData = ref([
     {key:'0',  name: '水准点'},
     {key:'1', name: '导线点'}
 ]);
-const tabsTypeChange = (value) => {
-    tabsTypeKey.value = value;
-    searchForm.value.type = value;
+const tabsTypeChange = (item) => {
+    tabsTypeKey.value = item?.key
+    searchForm.value.type = item?.key
     searchForm.value.current = 1
     getTableData()
+    //路由跳转
+    router.push({
+        path: useRoutes.path,
+        query: {
+            type: item?.key
+        }
+    })
 }
-
 //渲染完成
 onMounted(() => {
+    searchForm.value.type = typeName
     getTableData()
 })
 
-//新增编辑
-const showRowModal = ref(false)
-const formRowRef = ref(null)
-const formRowValue = ref({
-    projectId: projectId.value,
-    contractId: contractId.value,
-    type: tabsTypeKey.value,
-    name: '', x: '', y: '', h: '', level: null, remark: null
+//搜索表单
+const searchForm = ref({
+    projectId: projectId.value, contractId: contractId.value, name: null, type: '0',
+    current: 1, size: 20, total: 0
 })
+
+//回车搜索
+const keyUpEvent = (e) => {
+    if (e.key === "Enter") {
+        searchForm.value.current = 1;
+        getTableData()
+    }
+}
+
+//重新搜索数据
+const searchClick = () => {
+    searchForm.value.current = 1
+    getTableData()
+}
+
+//分页被点击
+const pageChange = ({current, size}) => {
+    searchForm.value.current = current
+    searchForm.value.size = size
+    getTableData()
+}
+
+//获取数据
+const traverseTable = ref([])   //导线点
+const levelTable = ref([])      //水准点
+const tableLoading = ref(false)
+const getTableData = async () => {
+    tableLoading.value = true
+    const { error, code, data } = await stationApi.queryListData({
+        projectId: projectId.value,
+        contractId: contractId.value,
+        ...searchForm.value
+    })
+    //处理数据
+    tableLoading.value = false
+    if (!error && code === 200) {
+        let records = getArrValue(data['records'])
+        if (tabsTypeKey.value === '0') {
+            levelTable.value = records
+        } else if (tabsTypeKey.value === '1') {
+            traverseTable.value = records
+        }
+        searchForm.value.total = data.total || 0
+    } else {
+        levelTable.value = []
+        traverseTable.value = []
+        searchForm.value.total = 0
+    }
+}
+
+//等级
 const personData = ref([
     {label: "一级", value: "一级"}, {label: "二级", value: "二级"},
     {label: "三级", value: "三级"}, {label: "四级", value: "四级"}
 ])
+
+//新增 / 编辑 配置
+const showRowModal = ref(false)
+const formRowRef = ref(null)
+const formRowValue = ref({name: '', x: '', y: '', h: '', level: null, remark: null})
 const rulesRow = {
     name: {
         required: true,
-        trigger: ["blur", "input"],
+        trigger: "blur",
         message: "请输入测站点名称"
     },
     x: {
         required: true,
-        trigger: ["blur", "input"],
+        trigger: "blur",
         message: "请输入X坐标(m)"
     },
     y: {
         required: true,
-        trigger: ["blur", "input"],
+        trigger: "blur",
         message: "请输入Y坐标(m)"
     },
     h: {
         required: true,
-        trigger: ["blur", "input"],
+        trigger: "blur",
         message: "请输入高程(m)"
     }
 }
 
-//卡片弹窗标题
-const rowModalTitle = () => {
-    let formType = '新增', tabType = '异常了';
-    if (formRowValue.value.id) {
-        formType = '编辑'
-    }
-    if (tabsTypeKey.value === '1') {
-        tabType = '导线点'
-    } else if (tabsTypeKey.value === '0') {
-        tabType = '水准点'
-    }
-    return formType + tabType
-}
-
-//导线点的 表格表头
-const createTraverseColumns = ({edit,del}) => {
-    return [
-        {title: '序号', key: 'num', width: 80, align: 'center',
-            render(_, index) {
-                return index + 1
-            }
-        },
-        {title: '测站点名称', key: 'name'},
-        {title: 'X坐标(m)', key: 'x'},
-        {title: 'Y坐标(m)', key: 'y'},
-        {title: '高程(m)', key: 'h'},
-        {title: '等级', key: 'level'},
-        {title: '备注', key: 'remark'},
-        {title: "操作", key: "actions", width: 160, align: 'center',
-            render(row) {
-                /*return renderTableEditDelButton({
-                    bubble: bubbleVal.value,
-                    btn_edit: btn_edit.value,
-                    btn_del: btn_del.value,
-                    edit_event: edit,
-                    del_event: del,
-                    row:row
-                })*/
-            }
-        }
-    ];
-};
-const traverseColumns = createTraverseColumns({
-    edit(row) {
-        let form = JSON.parse(JSON.stringify(row));
-        let mile = ['name', 'x', 'y', 'h', 'level', 'remark']
-        mile.forEach((key) => {
-            formRowValue.value[key] = form[key] + '';
-        })
-        formRowValue.value['id'] = form.id;
-        formRowValue.value['projectId'] = projectId.value;
-        formRowValue.value['contractId'] = contractId.value;
-        showRowModal.value = true
-    },
-    del(row) {
-        station.delData({
-            ids: row.id
-        }).then(({data}) => {
-            if (data.code === 200) {
-                window?.$message?.success('删除成功')
-                getTableData()
-            } else {
-                window?.$message?.error('删除失败')
-            }
-        })
-    },
-})
-const traverseTable = ref([]);
-
-//水准点的 表格表头
-const createLevelColumns = ({edit,del}) => {
-    return [
-        {title: '序号', key: 'num', width: 80, align: 'center',
-            render(_, index) {
-                return index + 1
-            }
-        },
-        {title: '测站点名称', key: 'name'},
-        {title: '高程(m)', key: 'h'},
-        {title: '等级', key: 'level'},
-        {title: '备注', key: 'remark'},
-        {title: "操作", key: "actions", width: 160, align: 'center',
-            render(row) {
-                /*return renderTableEditDelButton({
-                    bubble: bubbleVal.value,
-                    btn_edit: btn_edit.value,
-                    btn_del: btn_del.value,
-                    edit_event: edit,
-                    del_event: del,
-                    row:row
-                })*/
-            }
-        }
-    ];
-};
-const levelColumns = createLevelColumns({
-    edit(row) {
-        let form = JSON.parse(JSON.stringify(row));
-        let mile = ['name', 'h', 'level', 'remark'];
-        mile.forEach((key) => {
-            formRowValue.value[key] = form[key] + '';
-        })
-        formRowValue.value['id'] = form.id;
-        formRowValue.value['projectId'] = projectId.value;
-        formRowValue.value['contractId'] = contractId.value;
-        showRowModal.value = true
-    },
-    del(row) {
-        station.delData({
-            ids: row.id
-        }).then(({data}) => {
-            if (data.code === 200) {
-                window?.$message?.success('删除成功')
-                getTableData()
-            } else {
-                window?.$message?.error('删除失败')
-            }
-        })
-    },
-})
-//表格数据
-const levelTable = ref([]);
-
 //新增
 const AddRowClick = () => {
-    if (tabsTypeKey.value === '0') {
-        formRowValue.value = {
-            projectId: projectId.value,
-            contractId: contractId.value,
-            type: tabsTypeKey.value,
-            name: '', h: '', level: null, remark: null
-        }
-    } else if (tabsTypeKey.value === '1') {
-        formRowValue.value = {
-            projectId: projectId.value,
-            contractId: contractId.value,
-            type: tabsTypeKey.value,
-            name: '', x: '', y: '', h: '', level: null, remark: null
-        }
+    const type = tabsTypeKey.value
+    const obj = {
+        projectId: projectId.value,
+        contractId: contractId.value,
+        type: tabsTypeKey.value,
+        name: '', h: '', level: null, remark: null
     }
+    if (type === '0') {
+        formRowValue.value = obj
+    } else if (type === '1') {
+        formRowValue.value = {...obj, x: '', y: ''}
+    }
+    saveFormLoading.value = false
     showRowModal.value = true
 }
 
-//保存表单
+//新增/编辑 保存
 const saveFormLoading = ref(false)
-const saveFormClick = () => {
-    const form = formRowValue.value
-    if (!!form.id) {
-        saveFormLoading.value = true
-        station.updateSave(formRowValue.value).then(({data}) => {
+const saveFormClick = async () => {
+    const validate = await formValidate(formRowRef.value)
+    if (validate) {
+        const form = formRowValue.value
+        if (!!form.id) {
+            saveFormLoading.value = true
+            const {error, code} = await stationApi.updateSave(form,false)
+            //判断状态
             saveFormLoading.value = false
-            if (data.code === 200) {
-                getTableData()
+            if (!error && code === 200) {
                 showRowModal.value = false
                 window?.$message?.success('保存成功')
+                getTableData()
             } else {
                 window?.$message?.error('保存失败')
             }
-        }).catch(() => {
-            saveFormLoading.value = false
-        })
-    } else {
-        saveFormLoading.value = true
-        station.addSave(formRowValue.value).then(({data}) => {
+        } else {
+            saveFormLoading.value = true
+            const {error, code} = await stationApi.addSave(form,false)
+            //判断状态
             saveFormLoading.value = false
-            if (data.code === 200) {
-                getTableData()
+            if (!error && code === 200) {
                 showRowModal.value = false
                 window?.$message?.success('新增成功')
+                getTableData()
             } else {
                 window?.$message?.error('新增失败')
             }
-        }).catch(() => {
-            saveFormLoading.value = false
-        })
+        }
     }
 }
 
-//导入弹窗
+//导入配置
 const showImportModal = ref(false)
-const fileListLength = ref(0);
-const uploadRef = ref(null);
 const importLoading = ref(false)
+
+//上传配置
+const uploadRef = ref(null)
+const addition = ref({})
+const fileList = ref([])
 const action = '/api/blade-business/dap/import';
 const accept = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel';
-const upData = ref({
-    projectId: projectId.value,
-    contractId: contractId.value,
-    type: tabsTypeKey.value
-})
 
-const importModalClick  = () => {
-    upData.value = {
+//导入
+const importModalClick = () => {
+    addition.value = {
         projectId: projectId.value,
         contractId: contractId.value,
         type: tabsTypeKey.value
     }
+    importLoading.value = false
     showImportModal.value = true
 }
 
-const handleUploadChange = (options) => {
-    fileListLength.value = options.fileList.length;
+//上传一个文件时,重置
+const handleUploadExceed = (files) => {
+    uploadRef.value?.clearFiles()
+    const file = files[0]
+    file.uid = genFileId()
+    uploadRef.value?.handleStart(file)
 }
+
+//确认导入
 const handleImportClick = () => {
+    uploadRef.value?.submit()
+}
+//上传中
+const handleUploadProgress = () => {
     importLoading.value = true
-    uploadRef.value?.submit();
 }
 //上传完成
-const uploadFinish = ({event}) => {
+const handleUploadFinish = () => {
     importLoading.value = false
-    let res = JSON.parse(event?.target?.response);
-    if (res.code === 200) {
-        window?.$message?.success('导入成功')
-        showImportModal.value = false
-        getTableData()
-    } else {
-        window?.$message?.error(res.msg||'导入失败')
-    }
+    showImportModal.value = false
+    window?.$message?.success('导入成功')
+    uploadRef.value?.clearFiles()
+    getTableData()
 }
-
-//卡片弹窗标题
-const getModalTitle = () => {
-    let tabType = '异常了';
-    if (tabsTypeKey.value === '1') {
-        tabType = '导线点'
-    } else if (tabsTypeKey.value === '0') {
-        tabType = '水准点'
-    }
-    return tabType
+//上传失败
+const handleUploadError = () => {
+    importLoading.value = false
+    window?.$message?.error('导入失败')
 }
 
-//导出弹窗
-const exportModalClick  = () => {
-    window?.$dialog?.warning({
-        title: "导出数据",
-        content: "将导出当前所有数据",
-        positiveText: "确定导出",
-        negativeText: "取消",
-        onPositiveClick: () => {
-            station.getExportExcel({
-                projectId: projectId.value,
-                contractId: contractId.value,
-                type: tabsTypeKey.value,
-                search: searchForm.value['name'] || ''
-            }).then(res => {
-                download(res)
-            })
+//导出
+const exportModalClick = () => {
+    window?.$messageBox?.alert('将导出当前所有数据?', '导出数据', {
+        showCancelButton: true,
+        confirmButtonText: '确定导出',
+        cancelButtonText: '取消',
+        callback: (action) => {
+            if (action === 'confirm') {
+                getExportExcel()
+            }
         }
-    });
+    })
 }
-
-//重新搜索数据
-const searchChange = () => {
-    searchForm.value.current = 1
-    getTableData()
+//确定导出
+const downloadLoading = ref(false)
+const getExportExcel = async () => {
+    //批量下载
+    downloadLoading.value = true
+    const { error, disposition, res } = await stationApi.getExportExcel({
+        projectId: projectId.value,
+        contractId: contractId.value,
+        type: tabsTypeKey.value,
+        search: searchForm.value['name'] || ''
+    })
+    //处理数据
+    downloadLoading.value = false
+    if (!error) {
+        if (disposition) {
+            downloadBlob(res,disposition)
+        } else {
+            window.$message?.error('数据异常')
+        }
+    }
 }
 
-//分页被点击
-const pageChange = (res) => {
-    searchForm.value.current = res.current;
-    searchForm.value.size = res.size;
-    getTableData()
+//水准点
+const handleLevelEdit = (row) => {
+    formRowValue.value = {
+        ...row,
+        projectId: projectId.value,
+        contractId: contractId.value,
+        type: tabsTypeKey.value
+    }
+    saveFormLoading.value = false
+    showRowModal.value = true
+}
+const handleLevelDelete = (row) => {
+    window?.$messageBox?.alert('是否删除当前数据?', '删除提醒', {
+        showCancelButton: true,
+        confirmButtonText: '确定删除',
+        cancelButtonText: '取消',
+        callback: (action) => {
+            if (action === 'confirm') {
+                delData(row.id)
+            }
+        }
+    })
 }
 
-//获取数据
-const getTableData = () => {
-    station.queryListData(searchForm.value).then(({data}) => {
-        let res = data['data'] || {}
-        if (tabsTypeKey.value === '0') {
-            levelTable.value = res['records'] || []
-        } else if (tabsTypeKey.value === '1') {
-            traverseTable.value = res['records'] || []
+//导线点
+const handleTraverseEdit = (row) => {
+    formRowValue.value = {
+        ...row,
+        projectId: projectId.value,
+        contractId: contractId.value,
+        type: tabsTypeKey.value
+    }
+    saveFormLoading.value = false
+    showRowModal.value = true
+}
+const handleTraverseDelete = (row) => {
+    window?.$messageBox?.alert('是否删除当前数据?', '删除提醒', {
+        showCancelButton: true,
+        confirmButtonText: '确定删除',
+        cancelButtonText: '取消',
+        callback: (action) => {
+            if (action === 'confirm') {
+                delData(row.id)
+            }
         }
-        searchForm.value.total = res.total || 0
     })
 }
+
+//删除请求
+const delData = async (id) => {
+    const {error, code} = await stationApi.delData({ids: id},false)
+    //判断状态
+    if (!error && code === 200) {
+        window?.$message?.success('删除成功')
+        getTableData()
+    } else {
+        window?.$message?.error('删除失败')
+    }
+}
+
 </script>
 
 <style lang="scss" scoped>

+ 493 - 0
src/views/gauge/station_a.vue

@@ -0,0 +1,493 @@
+<template>
+    <n-divider dashed title-placement="left">测站点</n-divider>
+    <div class="hc-layout-box">
+        <n-card class="hc-card-overflow-p-box" :segmented="{content: true}">
+            <template #header>
+                <div class="hc-card-header flex items-center">
+                    <div class="w-60">
+                        <n-input v-model:value="searchForm.name" type="text" placeholder="请输入测站点或关键字进行搜索" clearable/>
+                    </div>
+                    <n-button type="primary" class="px-5 ml-3" @click="searchChange">搜索</n-button>
+                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_add?.textInfo" v-if="btn_add">
+                        <template #trigger>
+                            <n-button type="primary" strong secondary class="px-5 ml-10" @click="AddRowClick">新增</n-button>
+                        </template>
+                        <span>{{btn_add?.textInfo}}</span>
+                    </n-popover>
+                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_import?.textInfo" v-if="btn_import">
+                        <template #trigger>
+                            <n-button type="primary" strong secondary class="px-5 ml-3" @click="importModalClick">导入</n-button>
+                        </template>
+                        <span>{{btn_import?.textInfo}}</span>
+                    </n-popover>
+                    <n-popover trigger="hover" :disabled="!bubbleVal || !btn_export?.textInfo" v-if="btn_export">
+                        <template #trigger>
+                            <n-button type="primary" strong secondary class="px-5 ml-3" @click="exportModalClick">导出</n-button>
+                        </template>
+                        <span>{{btn_export?.textInfo}}</span>
+                    </n-popover>
+                </div>
+            </template>
+            <template #header-extra>
+                <HcTabs :datas="tabsTypeData" :keys="tabsTypeKey" @change="tabsTypeChange"/>
+            </template>
+            <div v-if="tabsTypeKey==='1'">
+                <n-data-table :columns="traverseColumns" :data="traverseTable" :pagination="false" :row-key="row => row.name" :single-line="false" striped/>
+            </div>
+            <div v-if="tabsTypeKey==='0'">
+                <n-data-table :columns="levelColumns" :data="levelTable" :pagination="false" :row-key="row => row.name" :single-line="false" striped/>
+            </div>
+            <template #action>
+                <HcPage :pages="searchForm" @change="pageChange"/>
+            </template>
+        </n-card>
+    </div>
+    <!--新增/编辑 弹框-->
+    <n-modal v-model:show="showRowModal">
+        <n-card class="w-750" :title="rowModalTitle()" :segmented="{content: true}">
+            <n-form ref="formRowRef" :model="formRowValue" :rules="rulesRow" label-placement="left" label-width="auto" size="large">
+                <n-form-item label="点名称" path="name">
+                    <n-input class="flex-1" v-model:value="formRowValue.name" placeholder="请输入点名称"/>
+                </n-form-item>
+                <n-form-item label="X坐标(m)" path="x" v-if="tabsTypeKey === '1'">
+                    <n-input class="flex-1" v-model:value="formRowValue.x" placeholder="请输入X坐标(m)"/>
+                </n-form-item>
+                <n-form-item label="Y坐标(m)" path="y" v-if="tabsTypeKey === '1'">
+                    <n-input class="flex-1" v-model:value="formRowValue.y" placeholder="请输入Y坐标(m)"/>
+                </n-form-item>
+                <n-form-item label="高程(m)" path="h">
+                    <n-input class="flex-1" v-model:value="formRowValue.h" placeholder="请输入高程(m)"/>
+                </n-form-item>
+                <n-form-item label="等级">
+                    <n-select class="flex-1" v-model:value="formRowValue.level" :options="personData" placeholder="请选择等级"/>
+                </n-form-item>
+                <n-form-item label="备注">
+                    <n-input v-model:value="formRowValue.remark" placeholder="请输入文字说明" type="textarea" :autosize="{minRows: 3,maxRows: 5}"/>
+                </n-form-item>
+            </n-form>
+            <template #action>
+                <div class="text-center">
+                    <n-button class="px-5" @click="showRowModal = false">取消</n-button>
+                    <n-button type="primary" class="px-5 ml-4" :loading="saveFormLoading" @click="saveFormClick">保存</n-button>
+                </div>
+            </template>
+        </n-card>
+    </n-modal>
+    <!--导入 弹框-->
+    <n-modal v-model:show="showImportModal">
+        <n-card class="w-750" :title="'导入' + getModalTitle()" :segmented="{content: true}">
+            <div class="hc-import-modal-box">
+                <div class="tip-box">
+                    <span>请先下载导入模板(</span>
+                    <a class="text-link" href="https://bladex-test-info.oss-cn-chengdu.aliyuncs.com//upload/20220614/a4b08ea228dbf74db1c049c4d878fbe7.xlsx" target="_blank" v-if="tabsTypeKey==='1'">导线点导入模板</a>
+                    <a class="text-link" href="https://bladex-test-info.oss-cn-chengdu.aliyuncs.com//upload/20220629/5fa2abeaa1ad553ee4adf64118df4e2a.xlsx" target="_blank" v-if="tabsTypeKey==='0'">水准点导入模板</a>
+                    <span> ),按模板样式编辑测站点后,再点击"选择文件"按钮选择编辑好的文件,并点击底部的"确认导入"按钮即可导入成功!</span>
+                </div>
+                <div class="upload-box">
+                    <n-upload ref="uploadRef" :action="action" :headers="getTokenHeader()" :data="upData" :max="1" :accept="accept" :default-upload="false" multiple @change="handleUploadChange" @finish="uploadFinish">
+                        <n-button type="primary" class="px-4">选择文件</n-button>
+                    </n-upload>
+                </div>
+                <div class="text-orange">导入模板格式示例:</div>
+                <div class="demo-img-box" v-if="tabsTypeKey==='1'">
+                    <img src="../../assets/view/152221@2x.png" alt="">
+                </div>
+                <div class="demo-img-box" v-if="tabsTypeKey==='0'">
+                    <img src="../../assets/view/152211@2x.png" alt="">
+                </div>
+            </div>
+            <template #action>
+                <div class="text-center">
+                    <n-button class="px-4" @click="showImportModal = false">取消</n-button>
+                    <n-button type="primary" :disabled="!fileListLength" :loading="importLoading" class="px-4 ml-4" @click="handleImportClick">确认导入</n-button>
+                </div>
+            </template>
+        </n-card>
+    </n-modal>
+</template>
+
+<script setup>
+import {ref,watch,onMounted} from "vue";
+import {useAppStore} from "~src/store/index";
+import HcTabs from "~com/plugins/naive/HcTabs.vue"
+import HcPage from "~com/plugins/naive/HcPage.vue"
+import {renderTableEditDelButton} from "~src/plugins/renderele";
+import {getTokenHeader} from '~src/api/request/header';
+import station from '~api/gauge/station';
+import {download} from "~src/utils/lib/tools";
+
+//初始变量
+const useAppState = useAppStore()
+const projectId = ref(useAppState.getProjectId);
+const contractId = ref(useAppState.getContractId);
+
+//按钮气泡开关
+const bubbleVal = ref(useAppState.getBubble);
+
+//监听
+watch(() => [
+    useAppState.getProjectId,
+    useAppState.getContractId,
+    useAppState.getBubble,
+], ([UserProjectId,UserContractId,Bubble]) => {
+    projectId.value = UserProjectId
+    contractId.value = UserContractId
+    //按钮气泡开关
+    bubbleVal.value = Bubble
+})
+
+//获取气泡数据
+const getButtonsVal = (value) => {
+    return useAppState.getButtonsVal(value)
+}
+
+//气泡数据
+const btn_add = ref(getButtonsVal('gauge-station-add'))
+const btn_import = ref(getButtonsVal('gauge-station-import'))
+const btn_export = ref(getButtonsVal('gauge-station-export'))
+const btn_edit = ref(getButtonsVal('gauge-station-edit'))
+const btn_del = ref(getButtonsVal('gauge-station-del'))
+
+//搜索表单
+const searchForm = ref({
+    projectId: projectId.value,
+    contractId: contractId.value,
+    name: null, type: '1',
+    current: 1, size: 20, total: 0
+})
+
+//结构类型tab数据和相关处理
+const tabsTypeKey = ref('1')
+const tabsTypeData = ref([
+    {key:'0',  name: '水准点'},
+    {key:'1', name: '导线点'}
+]);
+const tabsTypeChange = (value) => {
+    tabsTypeKey.value = value;
+    searchForm.value.type = value;
+    searchForm.value.current = 1
+    getTableData()
+}
+
+//渲染完成
+onMounted(() => {
+    getTableData()
+})
+
+//新增编辑
+const showRowModal = ref(false)
+const formRowRef = ref(null)
+const formRowValue = ref({
+    projectId: projectId.value,
+    contractId: contractId.value,
+    type: tabsTypeKey.value,
+    name: '', x: '', y: '', h: '', level: null, remark: null
+})
+const personData = ref([
+    {label: "一级", value: "一级"}, {label: "二级", value: "二级"},
+    {label: "三级", value: "三级"}, {label: "四级", value: "四级"}
+])
+const rulesRow = {
+    name: {
+        required: true,
+        trigger: ["blur", "input"],
+        message: "请输入测站点名称"
+    },
+    x: {
+        required: true,
+        trigger: ["blur", "input"],
+        message: "请输入X坐标(m)"
+    },
+    y: {
+        required: true,
+        trigger: ["blur", "input"],
+        message: "请输入Y坐标(m)"
+    },
+    h: {
+        required: true,
+        trigger: ["blur", "input"],
+        message: "请输入高程(m)"
+    }
+}
+
+//卡片弹窗标题
+const rowModalTitle = () => {
+    let formType = '新增', tabType = '异常了';
+    if (formRowValue.value.id) {
+        formType = '编辑'
+    }
+    if (tabsTypeKey.value === '1') {
+        tabType = '导线点'
+    } else if (tabsTypeKey.value === '0') {
+        tabType = '水准点'
+    }
+    return formType + tabType
+}
+
+//导线点的 表格表头
+const createTraverseColumns = ({edit,del}) => {
+    return [
+        {title: '序号', key: 'num', width: 80, align: 'center',
+            render(_, index) {
+                return index + 1
+            }
+        },
+        {title: '测站点名称', key: 'name'},
+        {title: 'X坐标(m)', key: 'x'},
+        {title: 'Y坐标(m)', key: 'y'},
+        {title: '高程(m)', key: 'h'},
+        {title: '等级', key: 'level'},
+        {title: '备注', key: 'remark'},
+        {title: "操作", key: "actions", width: 160, align: 'center',
+            render(row) {
+                return renderTableEditDelButton({
+                    bubble: bubbleVal.value,
+                    btn_edit: btn_edit.value,
+                    btn_del: btn_del.value,
+                    edit_event: edit,
+                    del_event: del,
+                    row:row
+                })
+            }
+        }
+    ];
+};
+const traverseColumns = createTraverseColumns({
+    edit(row) {
+        let form = JSON.parse(JSON.stringify(row));
+        let mile = ['name', 'x', 'y', 'h', 'level', 'remark']
+        mile.forEach((key) => {
+            formRowValue.value[key] = form[key] + '';
+        })
+        formRowValue.value['id'] = form.id;
+        formRowValue.value['projectId'] = projectId.value;
+        formRowValue.value['contractId'] = contractId.value;
+        showRowModal.value = true
+    },
+    del(row) {
+        station.delData({
+            ids: row.id
+        }).then(({data}) => {
+            if (data.code === 200) {
+                window?.$message?.success('删除成功')
+                getTableData()
+            } else {
+                window?.$message?.error('删除失败')
+            }
+        })
+    },
+})
+const traverseTable = ref([]);
+
+//水准点的 表格表头
+const createLevelColumns = ({edit,del}) => {
+    return [
+        {title: '序号', key: 'num', width: 80, align: 'center',
+            render(_, index) {
+                return index + 1
+            }
+        },
+        {title: '测站点名称', key: 'name'},
+        {title: '高程(m)', key: 'h'},
+        {title: '等级', key: 'level'},
+        {title: '备注', key: 'remark'},
+        {title: "操作", key: "actions", width: 160, align: 'center',
+            render(row) {
+                return renderTableEditDelButton({
+                    bubble: bubbleVal.value,
+                    btn_edit: btn_edit.value,
+                    btn_del: btn_del.value,
+                    edit_event: edit,
+                    del_event: del,
+                    row:row
+                })
+            }
+        }
+    ];
+};
+const levelColumns = createLevelColumns({
+    edit(row) {
+        let form = JSON.parse(JSON.stringify(row));
+        let mile = ['name', 'h', 'level', 'remark'];
+        mile.forEach((key) => {
+            formRowValue.value[key] = form[key] + '';
+        })
+        formRowValue.value['id'] = form.id;
+        formRowValue.value['projectId'] = projectId.value;
+        formRowValue.value['contractId'] = contractId.value;
+        showRowModal.value = true
+    },
+    del(row) {
+        station.delData({
+            ids: row.id
+        }).then(({data}) => {
+            if (data.code === 200) {
+                window?.$message?.success('删除成功')
+                getTableData()
+            } else {
+                window?.$message?.error('删除失败')
+            }
+        })
+    },
+})
+//表格数据
+const levelTable = ref([]);
+
+//新增
+const AddRowClick = () => {
+    if (tabsTypeKey.value === '0') {
+        formRowValue.value = {
+            projectId: projectId.value,
+            contractId: contractId.value,
+            type: tabsTypeKey.value,
+            name: '', h: '', level: null, remark: null
+        }
+    } else if (tabsTypeKey.value === '1') {
+        formRowValue.value = {
+            projectId: projectId.value,
+            contractId: contractId.value,
+            type: tabsTypeKey.value,
+            name: '', x: '', y: '', h: '', level: null, remark: null
+        }
+    }
+    showRowModal.value = true
+}
+
+//保存表单
+const saveFormLoading = ref(false)
+const saveFormClick = () => {
+    const form = formRowValue.value
+    if (!!form.id) {
+        saveFormLoading.value = true
+        station.updateSave(formRowValue.value).then(({data}) => {
+            saveFormLoading.value = false
+            if (data.code === 200) {
+                getTableData()
+                showRowModal.value = false
+                window?.$message?.success('保存成功')
+            } else {
+                window?.$message?.error('保存失败')
+            }
+        }).catch(() => {
+            saveFormLoading.value = false
+        })
+    } else {
+        saveFormLoading.value = true
+        station.addSave(formRowValue.value).then(({data}) => {
+            saveFormLoading.value = false
+            if (data.code === 200) {
+                getTableData()
+                showRowModal.value = false
+                window?.$message?.success('新增成功')
+            } else {
+                window?.$message?.error('新增失败')
+            }
+        }).catch(() => {
+            saveFormLoading.value = false
+        })
+    }
+}
+
+//导入弹窗
+const showImportModal = ref(false)
+const fileListLength = ref(0);
+const uploadRef = ref(null);
+const importLoading = ref(false)
+const action = '/api/blade-business/dap/import';
+const accept = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel';
+const upData = ref({
+    projectId: projectId.value,
+    contractId: contractId.value,
+    type: tabsTypeKey.value
+})
+
+const importModalClick  = () => {
+    upData.value = {
+        projectId: projectId.value,
+        contractId: contractId.value,
+        type: tabsTypeKey.value
+    }
+    showImportModal.value = true
+}
+
+const handleUploadChange = (options) => {
+    fileListLength.value = options.fileList.length;
+}
+const handleImportClick = () => {
+    importLoading.value = true
+    uploadRef.value?.submit();
+}
+//上传完成
+const uploadFinish = ({event}) => {
+    importLoading.value = false
+    let res = JSON.parse(event?.target?.response);
+    if (res.code === 200) {
+        window?.$message?.success('导入成功')
+        showImportModal.value = false
+        getTableData()
+    } else {
+        window?.$message?.error(res.msg||'导入失败')
+    }
+}
+
+//卡片弹窗标题
+const getModalTitle = () => {
+    let tabType = '异常了';
+    if (tabsTypeKey.value === '1') {
+        tabType = '导线点'
+    } else if (tabsTypeKey.value === '0') {
+        tabType = '水准点'
+    }
+    return tabType
+}
+
+//导出弹窗
+const exportModalClick  = () => {
+    window?.$dialog?.warning({
+        title: "导出数据",
+        content: "将导出当前所有数据",
+        positiveText: "确定导出",
+        negativeText: "取消",
+        onPositiveClick: () => {
+            station.getExportExcel({
+                projectId: projectId.value,
+                contractId: contractId.value,
+                type: tabsTypeKey.value,
+                search: searchForm.value['name'] || ''
+            }).then(res => {
+                download(res)
+            })
+        }
+    });
+}
+
+//重新搜索数据
+const searchChange = () => {
+    searchForm.value.current = 1
+    getTableData()
+}
+
+//分页被点击
+const pageChange = (res) => {
+    searchForm.value.current = res.current;
+    searchForm.value.size = res.size;
+    getTableData()
+}
+
+//获取数据
+const getTableData = () => {
+    station.queryListData(searchForm.value).then(({data}) => {
+        let res = data['data'] || {}
+        if (tabsTypeKey.value === '0') {
+            levelTable.value = res['records'] || []
+        } else if (tabsTypeKey.value === '1') {
+            traverseTable.value = res['records'] || []
+        }
+        searchForm.value.total = res.total || 0
+    })
+}
+</script>
+
+<style lang="scss" scoped>
+@import '../../styles/gauge/station.scss';
+</style>

+ 40 - 40
yarn.lock

@@ -105,10 +105,10 @@
   resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
   integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
 
-"@types/web-bluetooth@^0.0.14":
-  version "0.0.14"
-  resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz#94e175b53623384bff1f354cdb3197a8d63cdbe5"
-  integrity sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==
+"@types/web-bluetooth@^0.0.15":
+  version "0.0.15"
+  resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.15.tgz#d60330046a6ed8a13b4a53df3813c44942ebdf72"
+  integrity sha512-w7hEHXnPMEZ+4nGKl/KDRVpxkwYxYExuHOYXyzIzCDzEZ9ZCGMAewulr9IqJu2LR4N37fcnb1XVeuZ09qgOxhA==
 
 "@vitejs/plugin-vue@^3.0.3":
   version "3.0.3"
@@ -210,25 +210,25 @@
   resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.37.tgz#8e6adc3f2759af52f0e85863dfb0b711ecc5c702"
   integrity sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==
 
-"@vueuse/core@^8.7.5":
-  version "8.9.4"
-  resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-8.9.4.tgz#c7db40f19390b3c9f4ff9294a30461497f62ec19"
-  integrity sha512-B/Mdj9TK1peFyWaPof+Zf/mP9XuGAngaJZBwPaXBvU3aCTZlx3ltlrFFFyMV4iGBwsjSCeUCgZrtkEj9dS2Y3Q==
+"@vueuse/core@^9.1.0":
+  version "9.1.0"
+  resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-9.1.0.tgz#f0fb13fd99768c0eb617169a2d2c1cbd5f5a52eb"
+  integrity sha512-BIroqvXEqt826aE9r3K5cox1zobuPuAzdYJ36kouC2TVhlXvFKIILgFVWrpp9HZPwB3aLzasmG3K87q7TSyXZg==
   dependencies:
-    "@types/web-bluetooth" "^0.0.14"
-    "@vueuse/metadata" "8.9.4"
-    "@vueuse/shared" "8.9.4"
+    "@types/web-bluetooth" "^0.0.15"
+    "@vueuse/metadata" "9.1.0"
+    "@vueuse/shared" "9.1.0"
     vue-demi "*"
 
-"@vueuse/metadata@8.9.4":
-  version "8.9.4"
-  resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-8.9.4.tgz#a4132db33e4c1b1023636acfa20aa7b37ab3d978"
-  integrity sha512-IwSfzH80bnJMzqhaapqJl9JRIiyQU0zsRGEgnxN6jhq7992cPUJIRfV+JHRIZXjYqbwt07E1gTEp0R0zPJ1aqw==
+"@vueuse/metadata@9.1.0":
+  version "9.1.0"
+  resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-9.1.0.tgz#194d4bd47f7acb91e348c0f436e678ddf7ee235b"
+  integrity sha512-8OEhlog1iaAGTD3LICZ8oBGQdYeMwByvXetOtAOZCJOzyCRSwqwdggTsmVZZ1rkgYIEqgUBk942AsAPwM21s6A==
 
-"@vueuse/shared@8.9.4":
-  version "8.9.4"
-  resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-8.9.4.tgz#c9741c30ffb666b50d62f0dd80b76119fd47573e"
-  integrity sha512-wt+T30c4K6dGRMVqPddexEVLa28YwxW5OFIPmzUHICjphfAuBFTTdDoyqREZNDOFJZ44ARH1WWQNCUK8koJ+Ag==
+"@vueuse/shared@9.1.0":
+  version "9.1.0"
+  resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-9.1.0.tgz#d8459a45324f32fb05a2a56ed754637c3d0efaeb"
+  integrity sha512-pB/3njQu4tfJJ78ajELNda0yMG6lKfpToQW7Soe09CprF1k3QuyoNi1tBNvo75wBDJWD+LOnr+c4B5HZ39jY/Q==
   dependencies:
     vue-demi "*"
 
@@ -475,10 +475,10 @@ electron-to-chromium@^1.4.202:
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.206.tgz#580ff85b54d7ec0c05f20b1e37ea0becdd7b0ee4"
   integrity sha512-h+Fadt1gIaQ06JaIiyqPsBjJ08fV5Q7md+V8bUvQW/9OvXfL2LRICTz2EcnnCP7QzrFTS6/27MRV6Bl9Yn97zA==
 
-element-plus@^2.2.13:
-  version "2.2.13"
-  resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-2.2.13.tgz#9ec3a9fa6587c93a87bb0d30c200ac8ee4f69c8b"
-  integrity sha512-dKQ7BPZC8deUPhv+6s4GgOL0GyGj3KpUarywxm6s1nWnHjH6FqeZlUcxPqBvJd7W/d81POayx3B13GP+rfkG9g==
+element-plus@^2.2.14:
+  version "2.2.14"
+  resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-2.2.14.tgz#161f2cbf2c12608a570af303f8191c7d7eae725b"
+  integrity sha512-V5Pis0OHhePg1RgVogZrcefaVl8vjVn4Pn9Qsh/t2CbFgjg9kKOYFqf/tuP3ObSXGm3X89hpe0W+nLVAsaFnpw==
   dependencies:
     "@ctrl/tinycolor" "^3.4.1"
     "@element-plus/icons-vue" "^2.0.6"
@@ -486,7 +486,7 @@ element-plus@^2.2.13:
     "@popperjs/core" "npm:@sxzz/popperjs-es@^2.11.7"
     "@types/lodash" "^4.14.182"
     "@types/lodash-es" "^4.17.6"
-    "@vueuse/core" "^8.7.5"
+    "@vueuse/core" "^9.1.0"
     async-validator "^4.2.5"
     dayjs "^1.11.3"
     escape-html "^1.0.3"
@@ -791,10 +791,10 @@ js-md5@^0.7.3:
   resolved "https://registry.yarnpkg.com/js-md5/-/js-md5-0.7.3.tgz#b4f2fbb0b327455f598d6727e38ec272cd09c3f2"
   integrity sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ==
 
-js-web-screen-shot@^1.7.1:
-  version "1.7.2"
-  resolved "https://registry.yarnpkg.com/js-web-screen-shot/-/js-web-screen-shot-1.7.2.tgz#45fef1b9da5f3a7eca7032c2d04ec5acfe65a668"
-  integrity sha512-A3OtE7EYdl2iXJsBJ0szurOC6PA/O88kGQNflih5ZTYgM5pttue0ffinRgeqTIKGYD/Y4vdhIvDpMQXCBcTDxQ==
+js-web-screen-shot@^1.7.3:
+  version "1.7.3"
+  resolved "https://registry.yarnpkg.com/js-web-screen-shot/-/js-web-screen-shot-1.7.3.tgz#031c553330e9fe1693a34bfeac98ad55a70444cd"
+  integrity sha512-j9Gyjhj1yEIJu/tNHA0P54o/VMouAbBgpi+oqhVHJ4Inh5hei500gycj1NEO8qqLbsm8TcNWvIFv3ytLzZ+caw==
   dependencies:
     html2canvas "^1.0.0-rc.7"
 
@@ -999,10 +999,10 @@ pify@^2.3.0:
   resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
   integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
 
-pinia@^2.0.19:
-  version "2.0.19"
-  resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.0.19.tgz#1ee8b521ab0fdac16b727151f7761674a04875e1"
-  integrity sha512-Q/UQrmFLDMdlCkLfM5rGw1Ug0A7dy0G7NtBusMQSK+TNjf3CV/pO0RqblNIfuurWl42byTjM6HIemCWOfo8KXA==
+pinia@^2.0.20:
+  version "2.0.20"
+  resolved "https://registry.yarnpkg.com/pinia/-/pinia-2.0.20.tgz#3b7f1a5a660282fab6a0c83bae62c48ee0b1bc1f"
+  integrity sha512-fdHHumXW/0U5HhxmY1emo3I4z85p8NJPdbtFQSlmJXFe3ktuF0pYNVgVtk2q+j2zCtTufY763xzaEMx0t6T59g==
   dependencies:
     "@vue/devtools-api" "^6.2.1"
     vue-demi "*"
@@ -1130,10 +1130,10 @@ run-parallel@^1.1.9:
   dependencies:
     queue-microtask "^1.2.2"
 
-sass@^1.54.4:
-  version "1.54.4"
-  resolved "https://registry.yarnpkg.com/sass/-/sass-1.54.4.tgz#803ff2fef5525f1dd01670c3915b4b68b6cba72d"
-  integrity sha512-3tmF16yvnBwtlPrNBHw/H907j8MlOX8aTBnlNX1yrKx24RKcJGPyLhFUwkoKBKesR3unP93/2z14Ll8NicwQUA==
+sass@^1.54.5:
+  version "1.54.5"
+  resolved "https://registry.yarnpkg.com/sass/-/sass-1.54.5.tgz#93708f5560784f6ff2eab8542ade021a4a947b3a"
+  integrity sha512-p7DTOzxkUPa/63FU0R3KApkRHwcVZYC0PLnLm5iyZACyp15qSi32x7zVUhRdABAATmkALqgGrjCJAcWvobmhHw==
   dependencies:
     chokidar ">=3.0.0 <4.0.0"
     immutable "^4.0.0"
@@ -1334,10 +1334,10 @@ vfonts@^0.0.3:
   resolved "https://registry.yarnpkg.com/vfonts/-/vfonts-0.0.3.tgz#999d66fecea18efee3f2b966c81101ae8ce01a29"
   integrity sha512-nguyw8L6Un8eelg1vQ31vIU2ESxqid7EYmy8V+MDeMaHBqaRSkg3dTBToC1PR00D89UzS/SLkfYPnx0Wf23IQQ==
 
-vite@^3.0.8:
-  version "3.0.8"
-  resolved "https://registry.yarnpkg.com/vite/-/vite-3.0.8.tgz#aa095ad8e3e5da46d9ec7e878f262678965d6531"
-  integrity sha512-AOZ4eN7mrkJiOLuw8IA7piS4IdOQyQCA81GxGsAQvAZzMRi9ZwGB3TOaYsj4uLAWK46T5L4AfQ6InNGlxX30IQ==
+vite@^3.0.9:
+  version "3.0.9"
+  resolved "https://registry.yarnpkg.com/vite/-/vite-3.0.9.tgz#45fac22c2a5290a970f23d66c1aef56a04be8a30"
+  integrity sha512-waYABTM+G6DBTCpYAxvevpG50UOlZuynR0ckTK5PawNVt7ebX6X7wNXHaGIO6wYYFXSM7/WcuFuO2QzhBB6aMw==
   dependencies:
     esbuild "^0.14.47"
     postcss "^8.4.16"