shuhao před 7 měsíci
rodič
revize
cf156bae43
38 změnil soubory, kde provedl 4056 přidání a 69 odebrání
  1. 4 1
      package.json
  2. binární
      src/assets/images/common/edit-icon.png
  3. binární
      src/assets/images/common/sub-title.png
  4. binární
      src/assets/images/components/close.png
  5. binární
      src/assets/images/foster-home/area-bg.png
  6. binární
      src/assets/images/foster-home/btn-bg.png
  7. binární
      src/assets/images/foster-home/firend-icon.png
  8. binární
      src/assets/images/foster-home/garden-img.png
  9. binární
      src/assets/images/foster-home/honour-bg.png
  10. binární
      src/assets/images/foster-home/image.png
  11. binární
      src/assets/images/foster-home/list/0.png
  12. binární
      src/assets/images/foster-home/list/1.png
  13. binární
      src/assets/images/foster-home/list/2.png
  14. binární
      src/assets/images/foster-home/list/3.png
  15. binární
      src/assets/images/foster-home/list/4.png
  16. binární
      src/assets/images/foster-home/list/5.png
  17. binární
      src/assets/images/foster-home/list/6.png
  18. binární
      src/assets/images/foster-home/list/7.png
  19. binární
      src/assets/images/foster-home/list/8.png
  20. binární
      src/assets/images/foster-home/recode.png
  21. binární
      src/assets/images/foster-home/tree-icon.png
  22. binární
      src/assets/images/foster-home/tree-item.png
  23. binární
      src/assets/images/foster-home/tree.png
  24. binární
      src/assets/images/foster-home/video.png
  25. binární
      src/assets/images/foster-home/water-icon.png
  26. binární
      src/assets/images/foster-home/wind-icon.png
  27. 124 0
      src/components/common/upload.vue
  28. 45 0
      src/utils/upliadFile.js
  29. 259 0
      src/views/home/components/foster/addressList.vue
  30. 502 0
      src/views/home/components/foster/adoptList.vue
  31. 348 0
      src/views/home/components/foster/applyList.vue
  32. 588 0
      src/views/home/components/foster/clientList.vue
  33. 175 0
      src/views/home/components/foster/tablePopup.vue
  34. 420 0
      src/views/home/components/homeFile - 副本.vue
  35. 12 12
      src/views/home/components/homeFile.vue
  36. 1075 0
      src/views/home/index - 副本.vue
  37. 56 38
      src/views/home/index.vue
  38. 448 18
      yarn.lock

+ 4 - 1
package.json

@@ -57,7 +57,10 @@
     "vuex": "^4.0.2",
     "xe-utils": "^3.5.4",
     "yarn": "^1.22.22",
-    "zdog": "^1.1.3"
+    "zdog": "^1.1.3",
+    "vant": "^4.9.19",
+    "ali-oss": "^6.20.0"
+
   },
   "devDependencies": {
     "@babel/eslint-parser": "^7.18.2",

binární
src/assets/images/common/edit-icon.png


binární
src/assets/images/common/sub-title.png


binární
src/assets/images/components/close.png


binární
src/assets/images/foster-home/area-bg.png


binární
src/assets/images/foster-home/btn-bg.png


binární
src/assets/images/foster-home/firend-icon.png


binární
src/assets/images/foster-home/garden-img.png


binární
src/assets/images/foster-home/honour-bg.png


binární
src/assets/images/foster-home/image.png


binární
src/assets/images/foster-home/list/0.png


binární
src/assets/images/foster-home/list/1.png


binární
src/assets/images/foster-home/list/2.png


binární
src/assets/images/foster-home/list/3.png


binární
src/assets/images/foster-home/list/4.png


binární
src/assets/images/foster-home/list/5.png


binární
src/assets/images/foster-home/list/6.png


binární
src/assets/images/foster-home/list/7.png


binární
src/assets/images/foster-home/list/8.png


binární
src/assets/images/foster-home/recode.png


binární
src/assets/images/foster-home/tree-icon.png


binární
src/assets/images/foster-home/tree-item.png


binární
src/assets/images/foster-home/tree.png


binární
src/assets/images/foster-home/video.png


binární
src/assets/images/foster-home/water-icon.png


binární
src/assets/images/foster-home/wind-icon.png


+ 124 - 0
src/components/common/upload.vue

@@ -0,0 +1,124 @@
+<template>
+    <div class="upload-wrap">
+        <el-upload
+            v-model:file-list="fileList"
+            action="#"
+            :limit="3"
+            :http-request="uploading"
+            :auto-upload="true"
+            list-type="picture-card"
+            class="upload"
+        >
+            <el-icon><Plus /></el-icon>
+            <template #file="{ file }">
+                <div>
+                    <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
+                    <span class="el-upload-list__item-actions">
+                        <span class="el-upload-list__item-delete" @click="handleRemove(file)">
+                            <img src="@/assets/images/components/close.png" alt="" />
+                        </span>
+                    </span>
+                </div>
+            </template>
+        </el-upload>
+    </div>
+</template>
+
+<script setup>
+import { onMounted, ref} from "vue";
+import eventBus from "@/api/eventBus";
+import { base_img_url2 } from "@/api/config";
+import { getFileExt } from "@/utils/util";
+import UploadFile from "@/utils/upliadFile";
+// import { useStore } from "vuex";
+
+// const props = defineProps({
+ 
+// })
+
+// const store = useStore();
+// const miniUserId = store.state.home.miniUserId;
+const miniUserId = 81881;
+
+//上传照片
+const fileList = ref([]);
+const imgArr = ref([])
+const uploadFileObj = new UploadFile();
+//上传中
+const uploading = (option) => {
+    let file = option.file;
+    let ext = getFileExt(file.name);
+    let key = `birdseye-look-mini/${miniUserId}/${new Date().getTime()}.${ext}`;
+    uploadFileObj.put(key, file).then((resFilename) => {
+        let index = fileList.value.findIndex((item) => item.name == file.name);
+        fileList.value[index].url = base_img_url2 + resFilename;
+        imgArr.value[index] = resFilename
+        eventBus.emit('upload:change',fileList.value)
+        eventBus.emit('upload:changeArr',imgArr.value)
+    });
+};
+
+//删除图片
+const handleRemove = (uploadFile) => {
+    const index = fileList.value.findIndex((f) => f.uid === uploadFile.uid); // 通过 uid 来识别
+    if (index !== -1) {
+        fileList.value.splice(index, 1);
+        imgArr.value.splice(index, 1);
+        eventBus.emit('upload:change',fileList.value)
+        eventBus.emit('upload:changeArr',imgArr.value)
+    }
+};
+
+function uploadReset(){
+    fileList.value = []
+    imgArr.value = []
+}
+
+onMounted(()=>{
+    eventBus.off('upload:reset',uploadReset)
+    eventBus.on('upload:reset',uploadReset)
+})
+</script>
+
+<style lang="scss" scoped>
+.upload-wrap {
+    ::v-deep {
+        .el-select__wrapper:hover {
+            box-shadow: 0 0 0 1px #dcdfe6 inset;
+        }
+    }
+    .upload {
+        position: relative;
+        .el-upload-list__item-delete {
+            position: absolute;
+            display: block;
+            right: -8px;
+            top: -10px;
+            img {
+                width: 22px;
+            }
+        }
+        .el-upload-list--picture-card .el-upload-list__item-actions {
+            opacity: 1;
+            background-color: transparent;
+        }
+        ::v-deep {
+            .el-upload--picture-card {
+                width: 70px;
+                height: 70px;
+            }
+            .el-upload-list--picture-card .el-upload-list__item {
+                width: 70px;
+                height: 70px;
+                overflow: visible;
+                margin-bottom: 0;
+            }
+            .el-upload-list--picture-card .el-upload-list__item-thumbnail {
+                width: 70px;
+                height: 70px;
+                object-fit: cover;
+            }
+        }
+    }
+}
+</style>

+ 45 - 0
src/utils/upliadFile.js

@@ -0,0 +1,45 @@
+import OSS from "ali-oss"
+import { ElMessage } from "element-plus";
+
+class UploadFile {
+  constructor() {
+    this.bucket = 'birdseye';
+    this.region = 'oss-cn-guangzhou'
+    this.credentials = null;
+    this.ossClient = null
+    this.getCredential()
+  }
+
+  async put(fileName, file){
+    if(!this.credentials){
+      alert("初始化失败!")
+      return;
+    }
+    let result = await this.ossClient.put(fileName, file)
+    return result.name;
+  }
+  //获取授权
+  getCredential() {
+    let that = this;
+    return VE_API.ali.credential()
+        .then( ({data})=> {
+          that.credentials = data;
+          that.initOSSClient()
+        })
+  }
+  //初始化oss对象
+  initOSSClient() {
+    let that = this;
+    const { accessKeyId, accessKeySecret, securityToken } = this.credentials;
+    this.ossClient = new OSS({
+      accessKeyId: accessKeyId,
+      accessKeySecret: accessKeySecret,
+      stsToken: securityToken,
+      bucket: that.bucket,
+      region: that.region
+    });
+  }
+}
+
+
+export default UploadFile;

+ 259 - 0
src/views/home/components/foster/addressList.vue

@@ -0,0 +1,259 @@
+<template>
+    <div class="address-list">
+        <div class="list-wrap">
+            <div class="list-item" v-for="(item, index) in addressList" :key="index">
+                <div class="item-info">
+                    <div class="tree-icon">
+                        <div class="tree-tag" v-show="item.status === 0">待确认</div>
+                        <div class="tree-tag done" v-show="item.status === 1">已确认</div>
+                        <img class="tree-img" src="@/assets/images/foster-home/tree-item.png" alt="" />
+                        <div class="tree-type-name-tag">白糖罂</div>
+                    </div>
+                    <div class="item-center">
+                        <div class="center-t">
+                            BTY-A25
+                            <span class="type-tag">综合:94分</span>
+                            <span class="type-tag">生态:92分</span>
+                            <span class="type-tag">树龄:5年</span>
+                        </div>
+                        <div class="center-item">单价:<span>12元/斤</span></div>
+                        <div class="center-item">预计成熟时间:<span>2025.05.30</span></div>
+                    </div>
+                </div>
+
+                <div v-if="item.status === 1" class="address-wrap">
+                    <div class="info" v-for="(user, userI) in 3" :key="userI">
+                        <div class="avatar">
+                            <el-avatar
+                                :size="53"
+                                src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
+                            />
+                            <div class="name">刘浩浩</div>
+                        </div>
+                        <el-divider class="divider" direction="vertical" />
+                        <div class="cont">
+                            <div class="li">发货时间<span>2025.03.22</span></div>
+                            <div class="li">认养斤数<span>50斤</span></div>
+                            <div class="li">收货电话<span>19871533165</span></div>
+                            <div class="li">收货地址<span>湖北省武汉市富丽长信园1520室</span></div>
+                        </div>
+                    </div>
+                </div>
+                <div v-else class="user-wrap">
+                    <div class="user-title">权属人</div>
+                    <div class="user-item">
+                      <div class="user-detail" v-for="(owner, oI) in item.owners" :key="oI">
+                        {{ owner.userName }}({{ owner.value }}斤)
+                        <span v-show="oI<item.owners.length-1">/</span>
+                      </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <!-- 渐变主色按钮 -->
+        <div class="center-btn" @click="showExport">导出</div>
+        <!-- 导出表格 -->
+        <table-popup :showPopupParent="showPopupParent"></table-popup>
+    </div>
+</template>
+
+<script setup>
+import { onMounted, ref } from "vue";
+import tablePopup from "./tablePopup.vue"
+
+const addressList = ref([
+  { status: 0, price: 16, owners: [{userName: "王丽丽", value: 50}, {userName: "张山", value: 30}, {userName: "刘珊珊", value: 30}] },
+  { status: 0, price: 16, owners: [{userName: "王丽丽", value: 50}, {userName: "张山", value: 30}, {userName: "刘珊珊", value: 30}]  },
+  { status: 1, price: 16, owners: [{userName: "王丽丽", value: 50}, {userName: "张山", value: 30}, {userName: "刘珊珊", value: 30}] },
+  { status: 1, price: 16, owners: [{userName: "王丽丽", value: 50}, {userName: "张山", value: 30}, {userName: "刘珊珊", value: 30}]  },
+]);
+onMounted(() => {});
+
+// 导出
+function showExport() {
+    showPopupParent.value = !showPopupParent.value
+}
+
+const showPopupParent = ref(false)
+</script>
+
+<style lang="scss" scoped>
+.address-list {
+    height: 100%;
+    overflow: auto;
+
+    .type-tag {
+        color: #ffd489;
+        background: rgba(255, 212, 137, 0.06);
+        padding: 2px 4px;
+        font-size: 10px;
+        margin-left: 4px;
+        border-radius: 4px;
+    }
+    .list-wrap {
+        .list-item {
+            background: rgba(255, 255, 255, 0.08);
+            padding: 8px 10px;
+            border-radius: 5px;
+            .item-info {
+                display: flex;
+                justify-content: space-between;
+                align-items: center;
+            }
+            .tree-icon {
+                position: relative;
+                .tree-tag {
+                    position: absolute;
+                    left: 0;
+                    top: 0;
+                    background: #ed9e1e;
+                    border-radius: 5px 0 5px 0;
+                    color: #fff;
+                    padding: 1px 6px;
+                    font-size: 10px;
+                    &.done {
+                        background: #5c5c5c;
+                    }
+                }
+                .tree-type-name-tag {
+                    position: absolute;
+                    left: 0;
+                    bottom: 0;
+                    background: rgba(0, 0, 0, 0.6);
+                    border-radius: 0 5px 5px 0;
+                    font-size: 10px;
+                    width: 100%;
+                    text-align: center;
+                    padding: 1px;
+                    backdrop-filter: blur(2px);
+                }
+                .tree-img {
+                    width: 63px;
+                    height: 63px;
+                    border-radius: 5px;
+                    object-fit: cover;
+                }
+            }
+            .item-center {
+                flex: 1;
+                padding: 0 12px;
+                color: #fff;
+                .center-t {
+                    font-size: 14px;
+                }
+                .center-item {
+                    color: #6c6c6c;
+                    font-size: 12px;
+                    padding-top: 2px;
+                    span {
+                        color: #fff;
+                    }
+                }
+            }
+        }
+        .list-item + .list-item {
+            margin-top: 8px;
+        }
+
+        .address-wrap {
+          padding-top: 12px;
+            .info {
+                border-radius: 4px;
+                background: rgba(255, 255, 255, 0.04);
+                padding: 6px 2px 6px 10px;
+                border: 1px solid rgba(255, 255, 255, 0.1);
+                display: flex;
+                align-items: center;
+                margin-top: 8px;
+                box-sizing: border-box;
+                .avatar {
+                    text-align: center;
+                    .name {
+                        background: #fff;
+                        border-radius: 20px;
+                        font-size: 12px;
+                        color: #0d0d0d;
+                        padding: 1px 2px;
+                        position: relative;
+                        z-index: 2;
+                        margin-top: -12px;
+                    }
+                }
+                .divider {
+                    border-color: rgba(252, 252, 252, 0.3);
+                    margin: 0 14px;
+                    height: 50px;
+                }
+                .cont {
+                    .li {
+                        color: #6c6c6c;
+                        position: relative;
+                        margin-left: 10px;
+                        display: flex;
+                        align-items: center;
+                        font-size: 12px;
+                        &::before {
+                            content: "";
+                            position: absolute;
+                            top: 7px;
+                            left: -10px;
+                            width: 4px;
+                            height: 4px;
+                            border-radius: 50%;
+                            background: #6c6c6c;
+                        }
+                        span {
+                            color: #ffffff;
+                            margin-left: 5px;
+                            flex: 1;
+                        }
+                    }
+                }
+            }
+        }
+        .user-wrap {
+          margin-top: 12px;
+          padding: 5px 10px;
+          background: linear-gradient( 90deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0));
+          border-radius: 30px 0 0 30px;
+          width: 100%;
+          display: flex;
+          font-size: 12px;
+          .user-title {
+            color: rgba(255, 255, 255, 0.56);
+            padding-right: 5px;
+          }
+          .user-item {
+            display: flex;
+            align-items: center;
+            color: #FFD489;
+          }
+        }
+    }
+    .unit {
+        padding-left: 5px;
+        color: #fff;
+    }
+    .p-t-2 {
+        padding-top: 2px;
+    }
+    
+    .center-btn {
+        position: absolute;
+        bottom: 64px;
+        left: 50%;
+        transform: translateX(-50%);
+        color: #000000;
+        border-radius: 20px;
+        font-size: 14px;
+        padding: 7px 10px;
+        cursor: pointer;
+        border: 1px solid #fff;
+        background: linear-gradient(180deg, #ffd887, #ed9e1e);
+        width: 194px;
+        box-sizing: border-box;
+        text-align: center;
+    }
+}
+</style>

+ 502 - 0
src/views/home/components/foster/adoptList.vue

@@ -0,0 +1,502 @@
+<template>
+    <div class="adopt-list" :class="{ 'has-btn': isManySetting }">
+        <div class="select-wrap">
+            <el-select class="select-item" v-model="areaVal" placeholder="全区" style="width: 116px">
+                <el-option v-for="item in areaOptions" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+            <el-select class="select-item" v-model="typeVal" placeholder="全部品类" style="width: 116px">
+                <el-option v-for="item in typeOptions" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+            <el-select class="select-item" v-model="ageVal" placeholder="树龄" style="width: 116px">
+                <el-option v-for="item in ageOptions" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+        </div>
+        <div class="select-wrap select-b">
+            <el-select class="select-item" v-model="allVal" placeholder="综合评分" style="width: 116px">
+                <el-option v-for="item in allOptions" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+            <el-select class="select-item" v-model="ecologyVal" placeholder="生态评分" style="width: 116px">
+                <el-option v-for="item in ecologyOptions" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+            <el-select class="select-item" v-model="statusVal" placeholder="全部状态" style="width: 116px">
+                <el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
+            </el-select>
+        </div>
+
+        <div class="many-setting select-wrap" v-show="isManySetting">
+            <el-select class="select-item many-select" v-model="settingType" placeholder="选中设置项" style="width: 96px">
+                <template #label="{ label, value }">
+                    <span v-show="value!=='total'">设置</span>
+                    <span>{{ label }}</span>
+                </template>
+                <el-option v-for="(item, index) in settingTypeOptions" :key="index" :label="item.name" :value="item.value" />
+            </el-select>
+            <el-input-number
+                style="width: 174px"
+                placeholder="请输入"
+                class="number-input"
+                :controls="false"
+                v-model="unifyPrice"
+                :min="0"
+                @change="setManyPrice"
+            />
+            <span class="unit">{{settingType === "price" ? "元/斤" : settingType === "age" ? "年" : "斤"}}</span>
+        </div>
+
+        <div class="list-wrap">
+            <div class="list-item" v-for="(item, index) in displayedAdoptList" :key="index">
+                <div class="list-info">
+                    <div class="tree-icon">
+                        <div class="tree-tag" v-show="item.status === 0">{{ ROLE == 1 ? "未定价" : "可团购"}}</div>
+                        <div class="tree-tag wait" v-show="item.status === 1">{{ ROLE == 1 ? "待认养" : "可团购"}}</div>
+                        <div class="tree-tag done" v-show="item.status === 2">{{ ROLE == 1 ? "已认养" : "已认养"}}</div>
+                        <!-- <img class="tree-img" src="@/assets/images/foster-home/tree-item.png" alt="" /> -->
+                        <img class="tree-img" :src="require(`@/assets/images/foster-home/list/${index < 7 ? index : 0}.png`)" alt="" />
+                        <div class="tree-type-name-tag">白糖罂</div>
+                    </div>
+                    <div class="item-center">
+                        <div class="center-t">
+                            {{item.bm ? item.bm : "BTY-A3"+index}}
+                            <span class="type-tag">综合:{{item.zh||94}}分</span>
+                            <span class="type-tag">生态:{{item.st||92}}分</span>
+                        </div>
+                        <!-- 批量设置单价 -->
+                        <div class="center-item" v-show="isManySetting && settingType !== 'price'">单价:<span class="unit">{{item.price||12}}元/斤</span></div>
+                        
+                        <!-- 批量设置树龄或单项设置 -->
+                        <div class="center-item p-t-2 has-input" v-show="(isManySetting && settingType === 'age') || item.settingPrice">
+                            <span class="edit-label">树龄:</span>
+                            <el-input-number @change="settingSinglePrice" class="number-input" :controls="false" v-model="item.age" :min="0" />
+                            <span class="unit">年</span>
+                        </div>
+                        <!-- 不是编辑状态 -->
+                        <div class="center-item p-t-2 age-line" v-show="!isManySetting && !item.settingPrice">
+                            <div class="age-wrap">
+                                <div class="has-age">
+                                    <div class="age">树龄:<span class="unit">5年</span></div>
+                                </div>
+                                <div class="sort-line"></div>
+                            </div>
+                            单价:<span class="unit">{{item.status === 0 ? "--" : item.price||12}}元/斤</span>
+                        </div>
+                        <div class="center-item p-t-2 has-input" v-show="(isManySetting && settingType === 'price') || item.settingPrice">
+                            <span class="edit-label">单价:</span>
+                            <el-input-number @change="settingSinglePrice" class="number-input" :controls="false" v-model="item.price" :min="0" />
+                            <span class="unit">元/斤</span>
+                        </div>
+                        <div class="center-item" v-show="isManySetting && settingType !== 'age'">树龄:<span class="unit">{{item.age||5}}年</span></div>
+                        <div class="center-item" v-show="!item.settingPrice && !isManySetting && ROLE == 1">总认养斤数:<span class="unit">{{item.total||212}}斤</span></div>
+                        <div class="center-item" v-show="(isManySetting && settingType !== 'total' && ROLE == 1)">总认养斤数:<span class="unit">{{item.total||212}}斤</span></div>
+                        
+                        <div class="center-item p-t-2 has-input" v-show="(isManySetting && settingType === 'total') || item.settingPrice">
+                            <span class="edit-label">总认养斤数:</span>
+                            <el-input-number @change="settingSinglePrice" class="number-input" :controls="false" v-model="item.total" :min="0" />
+                            <span class="unit">斤</span>
+                        </div>
+                        <!-- 团长角色 -->
+                        <div class="center-item p-t-2 progress-wrap" v-show="ROLE==2 && item.status !== 2">
+                            剩余可购:
+                            <el-progress :percentage="60" color="#FFD887"><span class="progress-text"><span class="over">150</span>/215斤</span></el-progress>
+                        </div>
+                        <div class="center-item p-t-2 progress-wrap" v-show="ROLE==2 && item.status === 2">
+                            权属人:
+                            <span class="unit">
+                                <div class="user-item">
+                                    <div class="user-detail" v-for="(owner, oI) in owners" :key="oI">
+                                        {{ owner.userName }}({{ owner.value }}斤)
+                                        <span v-show="oI<owners.length-1">/</span>
+                                    </div>
+                                </div>
+                            </span>
+                        </div>
+                    </div>
+                    <div v-show="!isManySetting && !item.settingPrice && ROLE == 1" @click="toSettingSinglePrice(index, true)">
+                        <img src="@/assets/images/common/edit-icon.png" alt="" />
+                    </div>
+                </div>
+                <div v-show="item.settingPrice" class="btn-group edit-one">
+                    <!-- 渐变主色按钮 -->
+                    <div class="btn cancel-btn" @click="toSettingSinglePrice(index, false)">取消</div>
+                    <div class="btn edit-btn" @click="toSettingSinglePrice(index, false)">确认修改</div>
+                </div>
+            </div>
+        </div>
+
+        <!-- 渐变主色按钮 -->
+        <div class="center-btn" v-show="!isManySetting" @click="manySetPrice">批量定价</div>
+        <!-- 渐变主色按钮 -->
+        <div class="btn-group list-btn" v-show="isManySetting">
+            <div class="btn cancel-btn" @click="saveManySetting(0)">取消</div>
+            <div class="btn edit-btn" @click="saveManySetting(1)">保存</div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { onMounted, ref } from "vue";
+import { useStore } from "vuex";
+let store = useStore();
+
+const ROLE = store.state.home.userRole;
+
+const areaVal = ref(0);
+const areaOptions = ref([
+    { label: "全区", value: 0 },
+    { label: "1区", value: 1 },
+    { label: "2区", value: 2 },
+]);
+const typeVal = ref(0);
+const typeOptions = ref([
+    { label: "全部品类", value: 0 },
+    { label: "白糖罂", value: 1 },
+    { label: "井岗红糯", value: 2 },
+]);
+const ageVal = ref(0);
+const ageOptions = ref([
+    { label: "全部树龄", value: 0 },
+    { label: "0-10年", value: 1 },
+    { label: "10-20年", value: 2 },
+]);
+const allVal = ref(0);
+const allOptions = ref([
+    { label: "全部评分", value: 0 },
+    { label: "0-10年", value: 1 },
+    { label: "10-20年", value: 2 },
+]);
+const ecologyVal = ref(0);
+const ecologyOptions = ref([
+    { label: "生态评分", value: 0 },
+    { label: "0-10年", value: 1 },
+    { label: "10-20年", value: 2 },
+]);
+const statusVal = ref(0);
+const statusOptions = ref([
+    { label: "全部状态", value: 0 },
+    { label: "0-10年", value: 1 },
+    { label: "10-20年", value: 2 },
+]);
+
+const adoptList = ref([
+    { status: 0, price: 10, bm: "BTY-A21", pz: "白糖罂", zh: 94, st: 92, sl: 5, total: 215 },
+    { status: 0, price: 12, bm: "BTY-A22", pz: "白糖罂", zh: 92, st: 94, sl: 6, total: 201 },
+    { status: 0, price: 8, bm: "BTY-A25", pz: "白糖罂", zh: 92, st: 94, sl: 4, total: 220 },
+    { status: 1, price: 13, bm: "BTY-A31", pz: "白糖罂", zh: 90, st: 92, sl: 6, total: 202 },
+    { status: 1, price: 10, bm: "BTY-A33", pz: "白糖罂", zh: 90, st: 96, sl: 7, total: 190 },
+    { status: 1, price: 16 },
+    { status: 1, price: 16 },
+    { status: 2, price: 16 },
+    { status: 2, price: 16 },
+]);
+
+const owners = ref([{userName: "王丽丽", value: 50}, {userName: "张山", value: 30}])
+
+const displayedAdoptList = ref([...adoptList.value]); // 初始时显示完整列表
+
+onMounted(() => {});
+
+// 批量定价
+const unifyPrice = ref(null);
+const isManySetting = ref(false);
+const settingTypeOptions = [
+    {name: "单价", value: "price"},
+    {name: "树龄", value: "age"},
+    {name: "认养斤数", value: "total"},
+]
+const settingType = ref("price")
+function manySetPrice() {
+    isManySetting.value = true;
+    displayedAdoptList.value = adoptList.value.filter((item) => item.status === 0);
+}
+function saveManySetting(isToSave) {
+    isManySetting.value = false;
+    displayedAdoptList.value = [...adoptList.value]; // 显示完整列表
+    if (isToSave) {
+        // 保存
+    }
+}
+
+function setManyPrice(v) {
+  displayedAdoptList.value.map(item => item.price = v)
+}
+
+// 设置单棵树单价
+
+function toSettingSinglePrice(i, val) {
+  console.log('tototot');
+  displayedAdoptList.value[i].settingPrice = val
+}
+function settingSinglePrice() {
+  console.log('sss');
+}
+</script>
+
+<style lang="scss" scoped>
+.adopt-list {
+    height: 100%;
+    overflow: auto;
+    &.has-btn {
+        height: calc(100% - 60px);
+    }
+    .type-tag {
+        color: #ffd489;
+        background: rgba(255, 212, 137, 0.06);
+        padding: 2px 4px;
+        font-size: 10px;
+        margin-left: 4px;
+        border-radius: 4px;
+    }
+    .select-wrap {
+        display: flex;
+        align-items: center;
+        ::v-deep {
+            .el-select__wrapper {
+                background: rgba(255, 212, 137, 0.06);
+                box-shadow: 0 0 0 1px rgba(255, 212, 137, 0.3) inset;
+                font-size: 13px;
+                .el-select__input {
+                    color: #ffd489;
+                }
+                .el-select__placeholder {
+                    color: #ffd489;
+                    text-align: center;
+                }
+                .el-select__suffix {
+                    color: #ffd489;
+                }
+            }
+        }
+        .select-item + .select-item {
+            margin-left: 5px;
+        }
+    }
+    .select-b {
+        margin-top: 8px;
+    }
+    .list-wrap {
+        padding: 12px 0;
+        .list-item {
+            background: rgba(255, 255, 255, 0.08);
+            padding: 8px 10px;
+            border-radius: 5px;
+            .list-info {
+                display: flex;
+                justify-content: space-between;
+                align-items: center;
+            }
+            .edit-one {
+                margin-top: 12px;
+                border-top: 1px solid #444444;
+                &.btn-group {
+                    padding: 12px 0;
+                    .btn {
+                        flex: 1;
+                        text-align: center;
+                        padding: 5px;
+                        &.cancel-btn {
+                            border-color: #363636;
+                            color: #FFFFFF;
+                        }
+                    }
+                }
+            }
+            .tree-icon {
+                align-self: baseline;
+                position: relative;
+                .tree-tag {
+                    position: absolute;
+                    left: 0;
+                    top: 0;
+                    background: #0accbf;
+                    border-radius: 5px 0 5px 0;
+                    color: #fff;
+                    padding: 1px 6px;
+                    font-size: 10px;
+                    &.wait {
+                        background: #f0ac37;
+                    }
+                    &.done {
+                        background: #757575;
+                    }
+                }
+                .tree-type-name-tag {
+                    position: absolute;
+                    left: 0;
+                    bottom: 0;
+                    background: rgba(0, 0, 0, 0.6);
+                    border-radius: 0 5px 5px 0;
+                    font-size: 10px;
+                    width: 100%;
+                    text-align: center;
+                    padding: 1px;
+                    backdrop-filter: blur(2px);
+                }
+                .tree-img {
+                    width: 63px;
+                    height: 63px;
+                    border-radius: 5px;
+                    object-fit: cover;
+                }
+            }
+            .item-center {
+                flex: 1;
+                padding: 0 12px;
+                color: #fff;
+                .center-t {
+                    font-size: 14px;
+                }
+                .center-item {
+                    color: #6c6c6c;
+                    font-size: 12px;
+                    padding-top: 2px;
+                }
+                
+                .progress-wrap {
+                    display: flex;
+                    align-items: center;
+                    .user-item {
+                        display: flex;
+                        align-items: center;
+                    }
+                    .progress-text {
+                        font-size: 12px;
+                        color: #999999;
+                        .over {
+                            color: #FFD489;
+                        }
+                    }
+                    ::v-deep {
+                        .el-progress-bar__outer {
+                            width: 100px;
+                            background: rgba(242, 243, 245, 0.23);
+                        }
+                    }
+                }
+                .age-line {
+                    display: flex;
+                    align-items: center;
+                    .age-wrap {
+                        display: flex;
+                        align-items: center;
+                        .sort-line {
+                            margin: 0 10px;
+                            height: 10px;
+                            width: 1px;
+                            background: #6C6C6C;
+                        }
+                    }
+                }
+                .edit-label {
+                    display: inline-block;
+                    width: 76px;
+                }
+                .has-input {
+                    padding: 4px 0;
+                    .unit {
+                        padding-left: 5px;
+                    }
+                }
+                .small-btn-group {
+                  display: flex;
+                  font-size: 12px;
+                }
+            }
+        }
+        .list-item + .list-item {
+            margin-top: 8px;
+        }
+    }
+    .unit {
+        padding-left: 5px;
+        color: #fff;
+    }
+    .many-setting {
+        background: rgba(255, 212, 137, 0.08);
+        border: 1px solid rgba(255, 212, 137, 0.3);
+        border-radius: 6px;
+        color: #ffd489;
+        padding: 12px 8px;
+        margin-top: 12px;
+        .many-select {
+            ::v-deep {
+                .el-select__wrapper {
+                    padding: 4px;
+                    box-shadow: none;
+                }
+            }
+        }
+    }
+    .number-input {
+        margin: 0 12px;
+        ::v-deep {
+            &.el-input-number {
+                width: 80px;
+                background: rgba(255, 212, 137, 0.08);
+                border: 1px solid #ffd489;
+                border-radius: 5px;
+            }
+            .el-input__wrapper {
+                background: transparent;
+                box-shadow: none;
+            }
+            .el-input-number.is-without-controls .el-input__wrapper {
+                padding: 0 8px;
+            }
+            .el-input__inner {
+                color: #ffd489;
+            }
+        }
+    }
+    .p-t-2 {
+        padding-top: 2px;
+    }
+    .center-btn {
+        position: absolute;
+        bottom: 64px;
+        left: 50%;
+        transform: translateX(-50%);
+        color: #000000;
+        border-radius: 20px;
+        font-size: 14px;
+        padding: 7px 10px;
+        cursor: pointer;
+        border: 1px solid #fff;
+        background: linear-gradient(180deg, #ffd887, #ed9e1e);
+        width: 194px;
+        box-sizing: border-box;
+        text-align: center;
+    }
+
+    .list-btn {
+        position: absolute;
+        bottom: 0;
+        right: 0;
+    }
+    .btn-group {
+        display: flex;
+        align-items: center;
+        justify-content: end;
+        background: #232323;
+        width: 100%;
+        padding: 10px 12px;
+        box-sizing: border-box;
+        border-radius: 0 0 8px 8px;
+        .btn {
+            cursor: pointer;
+            padding: 12px 36px;
+            font-size: 14px;
+            border-radius: 4px;
+            border: 1px solid #ffd489;
+        }
+        .cancel-btn {
+            color: #ffd489;
+        }
+        .edit-btn {
+            background: #ffd489;
+            color: #000000;
+        }
+        .btn + .btn {
+            margin-left: 12px;
+        }
+    }
+}
+</style>

+ 348 - 0
src/views/home/components/foster/applyList.vue

@@ -0,0 +1,348 @@
+<template>
+    <div class="apply-list">
+        <div class="list-wrap">
+            <div class="list-item" v-for="(item, index) in 10" :key="index">
+              <div class="item-info">
+                <div class="tree-icon">
+                    <img class="tree-img" src="@/assets/images/foster-home/tree-item.png" alt="" />
+                    <div class="tree-type-name-tag">白糖罂</div>
+                </div>
+                <div class="item-center">
+                    <div class="center-t">
+                        BTY-A25
+                        <span class="type-tag">综合:94分</span>
+                        <span class="type-tag">生态:92分</span>
+                    </div>
+
+                    <div class="center-item p-t-2 age-line">
+                        <div class="age-wrap">
+                            <div class="has-age">
+                                <div class="age">树龄:<span class="unit">5年</span></div>
+                            </div>
+                            <div class="sort-line"></div>
+                        </div>
+                        单价:<span class="unit">{{item.status === 0 ? "--" : item.price||12}}元/斤</span>
+                    </div>
+
+                    <div class="center-item">截至分配时间:<span>2025.05.15</span></div>
+                </div>
+              </div>
+
+              <div class="apply-wrap" v-show="ROLE == 1">
+                <div class="apply-item" v-for="(item, index) in 2" :key="index">
+                    <div class="apply-users">
+                        <div class="user-item">
+                            <el-avatar :size="32" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" />
+                            <div class="user-name">华国伟</div>
+                        </div>
+                        <div class="user-item">
+                            <el-avatar :size="32" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" />
+                            <div class="user-name">华国伟</div>
+                        </div>
+                        <div class="user-item">
+                            <el-avatar :size="32" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" />
+                            <div class="user-name">华国伟</div>
+                        </div>
+                    </div>
+                    <div class="apply-time">2025.03.29</div>
+                    <div class="apply-btn">
+                        确认分配
+                    </div>
+                </div>
+              </div>
+
+              <!-- 团长 -->
+              <div class="team-wrap" v-show="ROLE == 2">
+                <div class="team-box">
+                    <div class="team-apply">
+                        <div class="apply-total">已分配给15人</div>
+                        <div class="apply-tooltip">
+                            <el-tooltip
+                                class="box-item"
+                                effect="dark"
+                                content="Top Center prompts info"
+                                placement="top"
+                            >
+                            <template #content>
+                                <div class="user-wrap">
+                                    <div class="user-detail" v-for="(owner, oI) in owners" :key="oI">
+                                        {{ owner.userName }}
+                                        <span v-show="oI<owners.length-1">/</span>
+                                    </div>
+                                </div>
+                            </template>
+                            <div class="tooltip-user-item">
+                                <div class="user-detail" v-for="(owner, oI) in owners" :key="oI">
+                                    {{ owner.userName }}
+                                    <span v-show="oI<owners.length-1">/</span>
+                                </div>
+                            </div>
+                            </el-tooltip>
+                        </div>
+                    </div>
+                    
+                    <div class="progress-wrap" v-show="ROLE==2 && item.status !== 2">
+                        剩余可购:
+                        <el-progress :percentage="60" color="#FFD887"><span class="progress-text"><span class="over">150</span>/215斤</span></el-progress>
+                    </div>
+                </div>
+
+                <div class="team-users apply-wrap">
+                    <div class="apply-item" v-for="(item, index) in 2" :key="index">
+                    <div class="apply-users">
+                        <div class="user-item">
+                            <el-avatar :size="32" src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" />
+                        </div>
+                        <div class="team-info">
+                            <div class="team-name">华国伟</div>
+                            <div class="team-time">3/25<span>10:08:32</span></div>
+                        </div>
+                    </div>
+                    <div class="apply-time">购买<span class="main-unit">15斤</span></div>
+                    <div class="apply-btn">
+                        确认分配
+                    </div>
+                </div>
+                </div>
+              </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { onMounted, ref } from "vue";
+import { useStore } from "vuex";
+let store = useStore();
+
+const owners = ref([{userName: "王丽丽", value: 50}, {userName: "张山", value: 30}, {userName: "刘珊珊", value: 30}, {userName: "张山2", value: 30}, {userName: "刘珊珊2", value: 30}])
+
+const ROLE = store.state.home.userRole;
+
+onMounted(() => {console.log('ROLE', ROLE);});
+</script>
+
+<style lang="scss" scoped>
+.apply-list {
+    height: 100%;
+    overflow: auto;
+
+    .type-tag {
+        color: #ffd489;
+        background: rgba(255, 212, 137, 0.06);
+        padding: 2px 4px;
+        font-size: 10px;
+        margin-left: 4px;
+        border-radius: 4px;
+    }
+    .list-wrap {
+        .list-item {
+            background: rgba(255, 255, 255, 0.08);
+            padding: 8px 10px;
+            border-radius: 5px;
+            .item-info {
+              display: flex;
+              justify-content: space-between;
+              align-items: center;
+            }
+            .tree-icon {
+                position: relative;
+                .tree-type-name-tag {
+                    position: absolute;
+                    left: 0;
+                    bottom: 0;
+                    background: rgba(0, 0, 0, 0.6);
+                    border-radius: 0 5px 5px 0;
+                    font-size: 10px;
+                    width: 100%;
+                    text-align: center;
+                    padding: 1px;
+                    backdrop-filter: blur(2px);
+                }
+                .tree-img {
+                    width: 63px;
+                    height: 63px;
+                    border-radius: 5px;
+                    object-fit: cover;
+                }
+            }
+            .item-center {
+                flex: 1;
+                padding: 0 12px;
+                color: #fff;
+                .center-t {
+                    font-size: 14px;
+                }
+                .center-item {
+                    color: #6c6c6c;
+                    font-size: 12px;
+                    padding-top: 2px;
+                    span {
+                        color: #fff;
+                    }
+                }
+                
+                .age-line {
+                    display: flex;
+                    align-items: center;
+                    .age-wrap {
+                        display: flex;
+                        align-items: center;
+                        .sort-line {
+                            margin: 0 10px;
+                            height: 10px;
+                            width: 1px;
+                            background: #6C6C6C;
+                        }
+                    }
+                }
+            }
+        }
+        .list-item + .list-item {
+            margin-top: 8px;
+        }
+    }
+    .unit {
+        padding-left: 5px;
+        color: #fff;
+    }
+
+    .apply-wrap {
+        padding-top: 12px;
+        .apply-item {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            background: rgba(255, 255, 255, 0.04);
+            .apply-users {
+                display: flex;
+                .user-item {
+                    .user-name {
+                        color: #fff;
+                        font-size: 14px;
+                    }
+                }
+                .user-item + .user-item {
+                    padding-left: 6px;
+                }
+            }
+            .apply-time {
+                flex: 1;
+                text-align: center;
+                font-size: 14px;
+                color: #999999;
+                .main-unit {
+                    color: #FFD489;
+                }
+            }
+            .apply-btn {
+                padding: 4px 7px;
+                border: 1px solid #FFD489;
+                border-radius: 20px;
+                color: #FFD489;
+                font-size: 12px;
+                cursor: pointer;
+            }
+        }
+        
+        .apply-item + .apply-item {
+            margin-top: 8px;
+        }
+
+        &.team-users {
+            margin-top: 8px;
+            background: rgba(255, 255, 255, 0.04);
+            border-radius: 8px;
+            .apply-item {
+                background: none;
+                padding: 6px 8px;
+            }
+            .apply-users {
+                .team-info {
+                    padding-left: 8px;
+                    .team-name {
+                        color: #fff;
+                        font-size: 14px;
+                    }
+                    .team-time {
+                        color: #999999;
+                        font-size: 12px;
+                        span {
+                            padding-left: 4px;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    .p-t-2 {
+        padding-top: 2px;
+    }
+
+    .team-wrap {
+        padding-top: 12px;
+        .team-box {
+            padding: 5px 12px;
+            background: rgba(255, 255, 255, 0.04);
+        }
+        .team-apply {
+            display: flex;
+            align-items: center;
+            .apply-total {
+                color: #F2D677;
+                font-size: 14px;
+                padding-right: 10px;
+            }
+            .apply-tooltip {
+                padding: 0px 10px;
+                border-radius: 20px;
+                background: #3B3B3B;
+                .tooltip-user-item {
+                    display: inline-block;
+                    font-size: 12px;
+                    color: #F2D677;
+                    max-width: 182px;
+                    white-space: nowrap;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+                    height: 26px;
+                    line-height: 30px;
+                }
+                .user-detail {
+                    display: inline-block;
+                }
+            }
+        }
+        
+                
+        .progress-wrap {
+            padding-top: 8px;
+            display: flex;
+            align-items: center;
+            font-size: 12px;
+            .user-item {
+                display: flex;
+                align-items: center;
+            }
+            .progress-text {
+                font-size: 12px;
+                color: #999999;
+                .over {
+                    color: #FFD489;
+                }
+            }
+            ::v-deep {
+                .el-progress-bar__outer {
+                    width: 160px;
+                    background: rgba(242, 243, 245, 0.23);
+                }
+            }
+        }
+    }
+}
+
+                    
+.user-wrap {
+    display: flex;
+}
+</style>

+ 588 - 0
src/views/home/components/foster/clientList.vue

@@ -0,0 +1,588 @@
+<template>
+    <div class="list-wrap">
+        <div class="list-header">
+            <el-input class="search" v-model="input" placeholder="搜索">
+                <template #prefix>
+                    <el-icon><search /></el-icon>
+                </template>
+            </el-input>
+            <div class="button" @click="handlePerson('add')">
+                <img src="@/assets/images/foster-home/firend-icon.png" alt="" />
+                新增客户
+            </div>
+        </div>
+        <div class="list-content" :class="{'max-height':!isManage}">
+            <collapse v-model="activeNames">
+                <collapse-item :name="index" v-for="(item, index) in list" :key="index" :is-link="false">
+                    <template #title>
+                        <el-icon class="icon"><CaretRight /></el-icon>
+                        {{ item.name }}
+                        <span class="span">{{ item.children.length }}</span>
+                    </template>
+                    <template #value>
+                        <div @click.stop="hadnleManage(item,index)" class="text">{{isManage?'管理':'取消管理'}}</div>
+                    </template>
+                    <div class="list-item" :class="{active:ele.checked}" v-for="(ele, idx) in item.children" :key="idx + ele.id">
+                      <checkbox class="checkbox" @change="changeCheck" v-show="setingShow" v-model="ele.checked"></checkbox>
+                        <div class="item-flex">
+                            <img class="photo" src="@/assets/images/foster-home/image.png" alt="" />
+                            <div class="item-text">
+                                <div class="name">
+                                    <span>{{ ele.name }}</span>
+                                    <el-icon class="icon" @click.stop="handlePerson('edit')" color="#FFD489" size="16" ><Edit /></el-icon>
+                                </div>
+                                <div>电话:19875236548</div>
+                                <div>地址:湖北省武汉市富里唱鑫园5023</div>
+                            </div>
+                        </div>
+                    </div>
+                </collapse-item>
+            </collapse>
+        </div>
+        <div class="list-footer">
+          <div class="settings" v-show="!isSetting && isManage" @click="handleGroup">新增分组</div>
+          <div class="settings" v-show="!isSetting && !isManage" @click="handleSetting">批量设置</div>
+          <div class="operation flex" v-show="isSetting && !setingShow">
+            <div class="delete" @click="handleDelete">删除分组</div>
+            <div class="btn-group flex">
+              <div class="add" @click="handleAdd">添加</div>
+              <div class="remove" @click="handleRemove">移除</div>
+            </div>
+          </div>
+          <div class="controls flex" v-show="isSetting && setingShow">
+            <div class="personnel flex">
+              <div class="circle flex" v-show="filterList.length"><el-icon color="#000" size="11"><ArrowUpBold /></el-icon></div>
+              <div class="text van-ellipsis">
+                <template v-for="(item,index) in filterList" :key="index">
+                  {{item.name}}<span v-show="filterList.length - 1 !== index">/</span>
+                </template>
+              </div>
+            </div>
+            <div class="delete" @click="handleGroup" v-show="listType==='other'">设置分组</div>
+            <div class="delete" @click="handleOperation" v-show="listType!=='other'">{{operationType==='add'?'添加':'移出'}}({{filterList.length}})</div>
+          </div>
+        </div>
+    </div>
+  <!-- 添加分组 -->
+  <popup v-model:show="showGroup" closeable round class="popup-custom" :close-on-click-overlay="false">
+    <div class="popup-title">添加分组</div>
+    <div class="popup-content">
+      <el-input class="input" v-model="inputVal" size="large" placeholder="请输入名称" />
+    </div>
+    <div class="popup-footer">
+      <div class="cancel" @click="handleCancel">取消</div>
+      <div @click="handleAddGroup">添加</div>
+    </div>
+  </popup>
+  <!-- 新增客户、编辑客户 -->
+  <popup v-model:show="showClient" closeable round class="popup-custom" :close-on-click-overlay="false">
+    <div class="popup-title">{{typePopup==='add'?'新增客户':'编辑客户'}}</div>
+    <div class="popup-content">
+      <el-form
+        ref="ruleFormRef"
+        :model="ruleForm"
+        :rules="rules"
+        label-width="auto"
+        class="rule-form"
+        size="large"
+      >
+        <el-form-item label="姓名" prop="name">
+          <el-input class="input" v-model="ruleForm.name" size="large" placeholder="请输入姓名" />
+        </el-form-item>
+        <el-form-item label="电话" prop="tel">
+          <el-input class="input" v-model="ruleForm.tel" size="large" placeholder="请输入电话号码" />
+        </el-form-item>
+        <el-form-item label="地址" prop="adress">
+          <el-input class="input" v-model="ruleForm.adress" size="large" placeholder="请输入地址" />
+        </el-form-item>
+        <el-form-item label="头像" prop="photo">
+          <!-- <upload></upload> -->
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="popup-footer">
+      <div class="cancel" @click="resetForm">取消</div>
+      <div @click="submitForm">添加</div>
+    </div>
+  </popup>
+</template>
+
+<script setup>
+import { ref,reactive } from "vue";
+import { Collapse, CollapseItem,Checkbox,Popup,showConfirmDialog } from "vant";
+import { useRouter } from "vue-router";
+import { ElMessage } from 'element-plus'
+import { deepClone } from "@/common/commonFun";
+import upload from "@/components/common/upload.vue";
+const router = useRouter();
+
+//新建分组
+const showGroupPopup = ref(false);
+const showPopup = () => {
+  showGroupPopup.value = true;
+};
+const input = ref("");
+const distributionShow = ref(false);
+
+// 果树选中的监听事件
+const checkedList = ref([])
+const changeActive = (arr) =>{
+  checkedList.value = arr
+}
+
+const isManage = ref(true)
+// const curIndex = ref(0)
+const listType = ref('')
+// 管理
+const hadnleManage = (value,index) => {
+  // console.log('val',value);
+  listType.value = 'often'
+  isSetting.value = true
+  if(value.name==='未分组列表'){
+    listType.value = 'other'
+    isSetting.value = false
+  }
+  // curIndex.value = index
+  isManage.value = !isManage.value
+  if(!isManage.value){
+    list.value = deepClone([defalutList.value[index]])
+  }else{
+    resetList()
+  }
+};
+
+const resetList = () =>{
+  
+  list.value = deepClone(defalutList.value)
+  setingShow.value = false
+  isSetting.value = false
+  isManage.value = true
+}
+
+const isSetting = ref(false)
+//设置
+const handleSetting = () =>{
+  isSetting.value = true
+  if(listType.value==='other'){
+    setingShow.value = true
+  }
+}
+
+const operationType = ref('')
+//添加
+const handleAdd = () =>{
+  operationType.value = 'add'
+  setingShow.value = true
+}
+
+//移除
+const setingShow = ref(false)
+const handleRemove = () =>{
+  operationType.value = 'remove'
+  setingShow.value = true
+}
+
+const filterList = ref([]);
+const changeCheck = () =>{
+  filterList.value = list.value[0].children.filter((item) => item.checked);
+}
+
+//设置分组
+const showGroup = ref(false)
+const inputVal = ref('')
+const handleGroup = () =>{
+  // if(filterList.value.length<1) return ElMessage.warning('请选择用户')
+  showGroup.value = true
+}
+
+//添加分组
+const handleAddGroup = () =>{
+  if(inputVal.value.length<1) return ElMessage.warning('请输入名称')
+  handleCancel()
+  ElMessage.success('添加成功')
+}
+const handleCancel = () =>{
+  showGroup.value = false
+  inputVal.value = ''
+}
+
+//删除分组
+const handleDelete = () =>{
+  showConfirmDialog({
+    title: '提示',
+    message:'是否删除该分组!',
+  })
+  .then(() => {
+    // on confirm
+  })
+  .catch(() => {
+    // on cancel
+  });
+}
+
+//新增客户
+const typePopup = ref('')
+const handlePerson = (type) =>{
+  typePopup.value = type
+  showClient.value = true
+}
+
+//移出、添加
+const handleOperation = () =>{
+  if(filterList.value.length<1) return ElMessage.warning('请选择用户')
+  if(operationType.value === 'add'){
+    ElMessage.success('添加成功')
+  }else{
+    ElMessage.success('移出成功')
+  }
+  resetList()
+}
+
+const showClient = ref(false)
+const ruleForm = reactive({
+  name:'',
+  tel:'',
+  adress:''
+})
+const rules = reactive({
+  name: { required: true, message: '请输入用户名称', trigger: ['blur','change'] },
+  tel: { required: true, message: '请输入电话号码', trigger: ['blur','change'] },
+})
+
+const ruleFormRef = ref(null)
+const submitForm = async () =>{
+  if (!ruleFormRef.value) return
+  await ruleFormRef.value.validate((valid, fields) => {
+    if (valid) {
+      ElMessage.success('添加成功')
+      showClient.value = false
+    } else {
+      console.log('error submit!')
+    }
+  })
+}
+
+const resetForm = () =>{
+  if (!ruleFormRef.value) return
+  ruleFormRef.value.resetFields()
+  showClient.value = false
+}
+
+const defalutList = ref([
+    {
+        name: "常用列表",
+        id: "1",
+        isGroup: 0,
+        children: [
+            {
+                id: "3",
+                name: "周浩",
+                checked: false,
+            },
+            {
+                id: "4",
+                name: "王丽丽",
+                checked: false,
+            },
+        ],
+    },
+    {
+        name: "未分组列表",
+        id: "2",
+        isGroup: 1,
+        children: [
+            {
+                id: "5",
+                name: "李莉",
+                checked: false,
+            },
+            {
+                id: "6",
+                name: "陈林",
+                checked: false,
+            },
+        ],
+    },
+])
+const list = ref(deepClone(defalutList.value));
+
+const activeNames = ref([0]);
+
+</script>
+
+<style lang="scss" scoped>
+.list-wrap {
+    width: 100%;
+    height: 100%;
+    .list-header {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        .search {
+            width: 90px;
+            margin-right: 10px;
+            --el-input-placeholder-color: rgba(255, 212, 137, 0.6);
+            ::v-deep {
+                .el-input__wrapper {
+                    box-shadow: none;
+                    border: 1px solid rgba(255, 212, 137, 0.6);
+                    background: transparent;
+                }
+                .el-input__prefix,
+                .el-input__inner {
+                    color: rgba(255, 212, 137, 0.6);
+                }
+            }
+        }
+        .button {
+            width: calc(100% - 100px);
+            color: #FFD489;
+            background: rgba(255, 212, 137, 0.06);
+            border: 1px solid rgba(255, 212, 137, 0.3);
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            padding: 8px;
+            border-radius: 5px;
+            cursor: pointer;
+            img {
+                width: 20px;
+                height: 17px;
+                margin-right: 6px;
+            }
+        }
+    }
+    .list-content {
+        width: 100%;
+        height: calc(100% - 50px);
+        margin-top: 12px;
+        &.max-height{
+          height: calc(100% - 50px - 55px);
+        }
+        .text {
+            color: #FFD489;
+            cursor: pointer;
+        }
+        ::v-deep {
+            .van-cell:after,.van-collapse-item--border:after,.van-hairline--top-bottom:after{
+              border: none !important;
+            }
+            .van-cell {
+                border-radius: 5px 5px 0 0;
+                justify-content: space-between;
+                background: rgba(255, 255, 255, 0.08);
+                color: #fff;
+                .van-cell__value {
+                    flex: none;
+                }
+                .van-cell__title {
+                    display: flex;
+                    align-items: center;
+                    .icon {
+                        margin-right: 3px;
+                        color: #bfbfbf;
+                        font-size: 16px;
+                    }
+                    .span {
+                        color: rgba(255, 255, 255, 0.4);
+                        margin-left: 10px;
+                    }
+                }
+            }
+            .van-collapse-item__content{
+              background: transparent;
+              padding: 10px 0 0 0;
+            }
+            .van-collapse-item__title--expanded {
+                .van-cell__title {
+                    .icon {
+                        transform: rotate(90deg);
+                    }
+                }
+            }
+            .van-collapse-item + .van-collapse-item {
+                margin-top: 12px;
+            }
+
+            .van-checkbox__icon--checked .van-icon{
+              background-color: #F7BE5A;
+              border-color: #F7BE5A;
+              color: #000;
+            }
+        }
+        .list-item {
+            border-radius: 6px;
+            position: relative;
+            display: flex;
+            align-items: center;
+            background: rgba(255, 255, 255, 0.08);
+            border: 1px solid transparent;
+            padding: 8px 10px;
+            &.active{
+              background: rgba(243, 193, 29, 0.1);
+              border-color: #FFD489;
+            }
+            .checkbox{
+              margin-right: 12px;
+            }
+            .item-flex {
+                display: flex;
+                align-items: center;
+            }
+            .photo {
+                width: 68px;
+                height: 68px;
+                border-radius: 8px;
+                margin-right: 12px;
+            }
+            .item-text {
+                color: #999999;
+                font-size: 12px;
+                line-height: 1.6;
+                .name {
+                    display: flex;
+                    align-items: center;
+                    span {
+                        font-size: 15px;
+                        color: #FFFFFF;
+                        font-weight: 500;
+                        margin-right: 5px;
+                    }
+                    .icon{
+                      cursor: pointer;
+                    }
+                }
+            }
+        }
+        .list-item + .list-item {
+            margin-top: 12px;
+        }
+    }
+    .list-footer{
+      position: absolute;
+      bottom: 0;
+      left: 0;
+      width: 100%;
+      background: rgba(255, 255, 255, 0.08);
+      display: flex;
+      justify-content: center;
+      box-sizing: border-box;
+      padding: 11px;
+      .settings{
+        background: rgba(255, 255, 255, 0.1);
+        border-radius: 4px;
+        padding: 8px 36px;
+        color: #fff;
+        cursor: pointer;
+      }
+      .flex{
+        display: flex;
+        align-items: center;
+      }
+      .delete{
+        border: 1px solid #FFD489;
+        border-radius: 4px;
+        padding: 8px 19px;
+        color: #FFD489;
+        cursor: pointer;
+      }
+      .operation{
+        width: 100%;
+        justify-content: space-between;
+        .btn-group{
+          div{
+            background: rgba(255, 255, 255, 0.1);
+            padding: 8px 19px;
+            border-radius: 4px;
+            cursor: pointer;
+          }
+          .add{
+            margin-right: 10px;
+          }
+        }
+      }
+      .controls{
+        width: 100%;
+        justify-content: space-between;
+        .personnel{
+          width: calc(100% - 100px);
+          .circle{
+            width: 16px;
+            height: 16px;
+            background: #FFD489;
+            border-radius: 50%;
+            justify-content: center;
+            margin-right: 8px;
+          }
+          .text{
+            width: 90%;
+          }
+        }
+        .delete{
+          background: #FFD489;
+          color: #000;
+          width: 85px;
+          box-sizing: border-box;
+          text-align: center;
+          padding: 8px;
+        }
+      }
+    }
+}
+.popup-custom{
+  // width: 24%;
+  width: 504px;
+  padding: 31px 25px;
+  box-sizing: border-box;
+  background: #232323;
+  ::v-deep{
+    .van-popup__close-icon{
+      color: #FFFFFF;
+    }
+  }
+  .popup-title{
+    text-align: center;
+    color: #FFFFFF;
+    font-size: 24px;
+    margin-bottom: 15px;
+  }
+  .popup-content{
+    width: 100%;
+    ::v-deep {
+      .el-form-item__label {
+        color: rgba(255, 255, 255, 0.4);
+      }
+      .el-input__wrapper {
+        background: transparent;
+        box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.46) inset;
+      }
+    }
+    .input{
+      height: 46px;
+      font-size: 16px;
+    }
+  }
+  .popup-footer{
+    width: 100%;
+    display: flex;
+    border-top: 1px solid rgba(0, 0, 0,0.1);
+    margin-top: 30px;
+    padding-top: 25px;
+    div{
+      flex: 1;
+      background: linear-gradient(120deg,#FFD887,#ED9E1E);
+      border-radius: 6px;
+      padding: 13px;
+      font-size: 20px;
+      color: #fff;
+      text-align: center;
+      cursor: pointer;
+    }
+    .cancel{
+      color: #000;
+      background: #F3F3F3;
+      margin-right: 30px;
+    }
+  }
+}
+</style>

+ 175 - 0
src/views/home/components/foster/tablePopup.vue

@@ -0,0 +1,175 @@
+<template>
+    <Popup v-model:show="showPopup" class="table-popup">
+        <div class="table-content">
+            <el-table :data="tableData" border :span-method="objectSpanMethod">
+                <el-table-column prop="id" label="果树id" />
+                <el-table-column prop="name" label="客户姓名" />
+                <el-table-column prop="value" label="认养斤数" />
+                <el-table-column prop="tel" label="收货电话" />
+                <el-table-column prop="time" label="发货时间" />
+                <el-table-column prop="address" label="收货地址" />
+            </el-table>
+        </div>
+        <div class="table-btn-group">
+            <div class="btn cancel-btn" @click="showPopup = false">取消</div>
+            <div class="btn edit-btn" @click="showPopup = false">保存</div>
+        </div>
+    </Popup>
+</template>
+
+<script setup>
+import { Popup } from "vant";
+import { ref, watch } from "vue";
+const props = defineProps({
+    showPopupParent: {
+        type: Boolean,
+        default: false,
+    },
+});
+
+const showPopup = ref(false);
+
+const tableData = [
+    {
+        id: "BTY-001",
+        name: "陈依依",
+        value: "50",
+        tel: "13855556564",
+        time: "2025.06.15",
+        address: "广东省广州市番禺区小谷谷围街中山大学东校 区116号之五",
+    },
+    {
+        id: "BTY-001",
+        name: "谢可资",
+        value: "50",
+        tel: "13855556564",
+        time: "2025.06.15",
+        address: "广东省广州市番禺区小谷谷围街中山大学东校 区116号之五",
+    },
+    {
+        id: "BTY-002",
+        name: "陈五五",
+        value: "50",
+        tel: "13855556564",
+        time: "2025.06.15",
+        address: "广东省广州市番禺区小谷谷围街中山大学东校 区116号之五",
+    },
+    {
+        id: "BTY-003",
+        name: "黎依依",
+        value: "50",
+        tel: "13855556564",
+        time: "2025.06.15",
+        address: "广东省广州市番禺区小谷谷围街中山大学东校 区116号之五",
+    },
+    {
+        id: "BTY-003",
+        name: "李依依",
+        value: "50",
+        tel: "13855556564",
+        time: "2025.06.15",
+        address: "广东省广州市番禺区小谷谷围街中山大学东校 区116号之五",
+    },
+    {
+        id: "BTY-004",
+        name: "潘依依",
+        value: "50",
+        tel: "13855556564",
+        time: "2025.06.15",
+        address: "广东省广州市番禺区小谷谷围街中山大学东校 区116号之五",
+    },
+];
+
+// 预先计算合并信息
+const spanMap = {};
+tableData.forEach((item, index) => {
+    if (!spanMap[item.id]) {
+        spanMap[item.id] = {
+            count: 1,
+            startIndex: index,
+        };
+    } else {
+        spanMap[item.id].count++;
+    }
+});
+
+const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => {
+    if (columnIndex === 0) {
+        const id = row.id;
+        if (rowIndex === spanMap[id].startIndex) {
+            return {
+                rowspan: spanMap[id].count,
+                colspan: 1,
+            };
+        } else {
+            return {
+                rowspan: 0,
+                colspan: 0,
+            };
+        }
+    }
+};
+
+watch(
+    () => props.showPopupParent,
+    (newValue, oldValue) => {
+        showPopup.value = !showPopup.value;
+    }
+);
+</script>
+
+<style lang="scss" scoped>
+.table-content {
+    ::v-deep {
+        .el-table {
+            --el-table-border-color: rgba(255, 255, 255, 0.1);
+            --el-table-text-color: #FFFFFF;
+            --el-table-header-text-color: rgba(255, 255, 255, 0.6);
+            --el-table-row-hover-bg-color: transparent;
+            --el-table-current-row-bg-color: transparent;
+            --el-table-header-bg-color: transparent;
+            --el-table-bg-color: rgba(255, 255, 255, 0.04);
+            --el-table-tr-bg-color: transparent;
+        }
+        .el-table tr {
+            background: transparent;
+        }
+        .el-table th.el-table__cell {
+            background: transparent;
+
+        }
+    }
+}
+.table-btn-group {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding-top: 28px;
+    .btn {
+        cursor: pointer;
+        padding: 9px 80px;
+        font-size: 12px;
+        border-radius: 4px;
+        border: 1px solid #ffd489;
+    }
+    .cancel-btn {
+        color: #ffd489;
+    }
+    .edit-btn {
+        background: #ffd489;
+        color: #000000;
+    }
+    .btn + .btn {
+        margin-left: 8px;
+    }
+}
+</style>
+<style lang="less">
+.table-popup {
+    background: #232323;
+    padding: 24px 16px 28px 16px;
+    width: 66%;
+    border: 1px solid #666666;
+    border-radius: 8px;
+}
+</style>

+ 420 - 0
src/views/home/components/homeFile - 副本.vue

@@ -0,0 +1,420 @@
+<template>
+    <div class="file-wrap yes-events"  ref="draggable" @mousedown="startDrag" :style="{ left: position.x + 'px', top: position.y + 'px' }">
+
+        <!-- 箭头 -->
+        <!-- <div class="arrow" @click="handleShrink('bottom')">
+            <el-icon class="icon" color="#141414"><DArrowLeft /></el-icon>
+        </div> -->
+        <div class="file-title">
+            <img src="@/assets/images/common/chart-yellow.png" alt="" />
+            果园档案
+        </div>
+
+        <div class="box-wrap">
+            <div class="overview-file">
+                <div class="box-title">总体档案</div>
+                <div class="base-data">
+                    <div
+                        class="base-item"
+                        v-for="(item, index) in photoBaseData"
+                        :key="item.label"
+                        @click.stop="toggleFileItem(item.label, index)"
+                    >
+                        <span class="label">{{ item.label }}</span>
+                        <div v-if="index === 0" class="value">
+                            <el-select
+                                v-model="item.speciesItemId"
+                                size="small"
+                                @change="changeSelect"
+                                class="type-select"
+                            >
+                                <el-option
+                                    v-for="item in selectOptions"
+                                    :key="item.speciesItemId"
+                                    :label="item.speciesItemName"
+                                    :value="item.speciesItemId"
+                                />
+                            </el-select>
+                        </div>
+                        <div v-else class="value">{{ item.value }}</div>
+                    </div>
+                </div>
+                <div class="list">
+                    <div class="list-item" v-for="item in photoList" :key="item.key">
+                        <div class="list-name">
+                            <img src="@/assets/images/common/title-icon.png" alt="" />
+                            {{ item.key }}
+                        </div>
+                        {{ item.statement }}
+                    </div>
+                </div>
+            </div>
+
+            <div class="box-r">
+                <div class="overview-file">
+                    <div class="box-title">产量信息</div>
+                    <div class="box-wrap">
+                        <div
+                            class="box-item"
+                            v-for="(item, index) in outputBox"
+                            :key="index"
+                            @click="toggleAcitve(item.name, item.field)"
+                            :class="{ active: activeOuput === item.name }"
+                        >
+                            <div class="item-name">{{ item.name }}</div>
+                            <div class="item-val">
+                                {{ item.value }}<span>{{ item.unit }}</span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="overview-file">
+                    <div class="box-title">生态评估</div>
+                    <div class="box-wrap">
+                        <div
+                            class="box-item"
+                            v-for="(item, index) in qualityBox"
+                            :key="index"
+                            @click="toggleAcitve(item.name, item.field)"
+                            :class="{ active: activeOuput === item.name }"
+                        >
+                            <div class="item-name">{{ item.name }}</div>
+                            <div class="item-val">
+                                {{ item.value }}<span>{{ item.unit }}</span>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import eventBus from "@/api/eventBus";
+import { onMounted, ref, onBeforeUnmount, reactive } from "vue";
+const outputBox = ref([
+    { id: 1, name: "产量估计", field: "cl", value: "--", unit: "斤/亩" },
+    { id: 2, name: "高质果率", field: "spgl", value: "--", unit: "%" },
+    { id: 3, name: "挂果数", field: "zuoguo_ratio",value: "--", unit: "颗/枝条" },
+]);
+
+const qualityBox = ref([
+    { id: 5, name: "通风率", field: "tfl", value: "--", unit: "%" },
+    { id: 6, name: "透光率", field: "tgl", value: "--", unit: "%" },
+    { id: 7, name: "病虫比例", value: "--", unit: "%" },
+]);
+
+const photoBaseData = ref([
+    {
+        label: "品种",
+        value: "--",
+    },
+    {
+        label: "冠幅平均表面积",
+        value: "--",
+    },
+    {
+        label: "平均总枝条",
+        value: "--",
+    },
+    {
+        label: "平均树龄",
+        value: "--",
+    },
+]);
+
+const photoList = ref([
+    { key: "物候", statement: "--" },
+    { key: "病虫", statement: "--" },
+    { key: "异常", statement: "--" },
+    { key: "农事", statement: "--" },
+]);
+
+const activeOuput = ref(1);
+
+// 品种
+const farmId = ref(null);
+onMounted(() => {
+    eventBus.off("area:id", toggleAreaId);
+    eventBus.on("area:id", toggleAreaId);
+    farmId.value = sessionStorage.getItem("farmId");
+
+    eventBus.off("resetFileActive", resetActive2);
+    eventBus.on("resetFileActive", resetActive2);
+});
+function resetActive2(name) {
+    activeOuput.value = name
+    console.log('222resetActive2', name);
+}
+
+const selectOptions = ref([]);
+const getSpeciesItemList = (farmId, regionId) => {
+    VE_API.farm.getSpeciesItemList({ farmId, regionId }).then((res) => {
+        selectOptions.value = res.data;
+        selectOptions.value.unshift({ speciesItemId: "0", speciesItemName: "全部" });
+        photoBaseData.value[0].speciesItemId = res.data[0].speciesItemId;
+    });
+};
+
+function changeSelect(e) {
+    console.log("eee", e);
+    setFileData(e);
+}
+
+function toggleFileItem(name, index) {
+    if (index !== 0) {
+        toggleAcitve(name);
+    }
+}
+
+// 产量详情
+function toggleAcitve(name, field) {
+    activeOuput.value = name;
+    console.log("产量详情产量详情产量详情", name);
+    // eventBus.emit("change:mapPoint", name)
+    if (name === "透光率" || name === "通风率") {
+        eventBus.emit("handleTabItem", name)
+        eventBus.emit("handleActive", { name, key: "生态指标", index: 1, isFile: name === "通风率" ? true : false });
+        // eventBus.emit('handleTab',"透光率")
+    } else {
+        eventBus.emit("change:mapPoint", field);
+    }
+}
+
+const regionId = ref(null);
+function toggleAreaId({ areaId, farmId }) {
+    regionId.value = areaId;
+    getSpeciesItemList(farmId, areaId);
+    getFileData(farmId, areaId);
+}
+
+const allTypeData = ref([]);
+function getFileData(farmId, regionId) {
+    VE_API.farm.getFarmFiles({ farmId, regionId: regionId ? regionId : undefined }).then(({ data }) => {
+        allTypeData.value = data;
+        console.log("getFileData", allTypeData.value);
+        setFileData(photoBaseData.value[0].speciesItemId);
+    });
+}
+
+function setFileData(type_id) {
+  const res = allTypeData.value.find((item) => item.type_id == type_id);
+
+  photoBaseData.value[1].value = res.meta_info.avg_crown + "平方米";
+    photoBaseData.value[2].value = res.meta_info.avg_branch_num;
+    photoBaseData.value[3].value = res.meta_info.avg_age + "年";
+    photoList.value[0].key = res.meta_info.phenology_info.key;
+    photoList.value[0].statement = res.meta_info.phenology_info.statement;
+    photoList.value[1].key = res.meta_info.dp_alert_info.key;
+    photoList.value[1].statement = res.meta_info.dp_alert_info.statement;
+    photoList.value[2].key = res.meta_info.grow_alert_info.key;
+    photoList.value[2].statement = res.meta_info.grow_alert_info.statement;
+    photoList.value[3].key = res.meta_info.prescription_info.key;
+    photoList.value[3].statement = res.meta_info.prescription_info.statement;
+    // if(res.production_info.production){
+    //   res.production_info.production = (res.production_info.production * 1.3).toFixed(1)
+    // }
+    outputBox.value[0].value = res.production_info.production;
+    outputBox.value[1].value = res.production_info.quality.toFixed(0);
+    if(res.production_info.zuoguo_ratio){
+      outputBox.value[2].name = "坐果率";
+      outputBox.value[2].value = res.production_info.zuoguo_ratio.toFixed(0);
+    }else{
+      outputBox.value[2].name = "雌花率";
+      outputBox.value[2].value = res.production_info.cihua_ratio.toFixed(0);
+    }
+    qualityBox.value[0].value = res.ecology_info.ventilation;
+    qualityBox.value[1].value = res.ecology_info.transmittance;
+    qualityBox.value[2].value = res.ecology_info.dp_situation;
+}
+
+// 可拖拽
+const position = reactive({ x: 0, y: window.innerHeight - 322 });
+const isDragging = ref(false);
+const offset = reactive({ x: 0, y: 0 });
+const draggable = ref(null);
+function startDrag(event) {
+  isDragging.value = true;
+  offset.x = event.clientX - position.x;
+  offset.y = event.clientY - position.y;
+  document.addEventListener('mousemove', onDrag);
+  document.addEventListener('mouseup', stopDrag);
+}
+
+function onDrag(event) {
+  if (!isDragging.value) return;
+  position.x = event.clientX - offset.x;
+  position.y = event.clientY - offset.y;
+}
+
+function stopDrag() {
+  isDragging.value = false;
+  document.removeEventListener('mousemove', onDrag);
+  document.removeEventListener('mouseup', stopDrag);
+}
+</script>
+
+<style lang="scss" scoped>
+.file-wrap {
+    margin-top: 16px;
+    background: url("@/assets/images/home/file-bg-w.png") no-repeat top center / 100% 100%;
+    margin-left: 12px;
+    padding: 12px 18px 20px 16px;
+    position: absolute;
+
+    .file-title {
+        font-size: 20px;
+        color: #ffd489;
+    }
+    .box-wrap {
+        display: flex;
+        .box-r {
+            padding-left: 24px;
+        }
+    }
+    .overview-file {
+        padding-top: 20px;
+        .box-title {
+            font-size: 16px;
+            padding-left: 13px;
+            margin-bottom: 16px;
+            position: relative;
+            display: flex;
+            justify-content: space-between;
+            color: #fff;
+            &::before {
+                content: "";
+                position: absolute;
+                left: 0;
+                top: 3px;
+                width: 3px;
+                height: 16px;
+                background: #fff;
+                border-radius: 11px;
+            }
+        }
+        .title {
+            color: #f3c11d;
+            font-size: 16px;
+            font-family: "PangMenZhengDao";
+            margin-bottom: 20px;
+            .big {
+                width: 13px;
+                height: 13px;
+                margin: -10px 0 0 4px;
+            }
+            .small {
+                width: 7px;
+                height: 7px;
+                margin-left: -3px;
+            }
+        }
+        .base-data {
+            background: rgba(207, 207, 207, 0.1);
+            border-radius: 4px;
+            padding: 6px 0;
+            display: flex;
+            .base-item {
+                // flex: 1;
+                text-align: center;
+                padding: 0 14px;
+                .label {
+                    font-size: 12px;
+                    color: #666666;
+                    width: max-content;
+                    display: block;
+                    margin: 0 auto;
+                    padding-bottom: 2px;
+                }
+                .value {
+                    padding-top: 2px;
+                    font-size: 16px;
+                    color: #ffffff;
+                    width: max-content;
+                    margin: 0 auto;
+                }
+                .type-select {
+                    width: 72px;
+                    ::v-deep {
+                        .el-select__wrapper {
+                            background: rgba(247, 190, 90, 0.1);
+                            box-shadow: 0 0 0 1px #f7be5a inset;
+                            color: #ffd489;
+                        }
+                        .el-select__placeholder {
+                            color: #ffd489;
+                        }
+                    }
+                }
+            }
+            .base-item + .base-item {
+                border-left: 1px solid rgba(102, 102, 102, 0.42);
+            }
+        }
+        .list {
+            margin-top: 15px;
+            width: max-content;
+            font-size: 14px;
+            .list-item {
+                color: #bbbbbb;
+                display: flex;
+                margin-bottom: 8px;
+                .list-name {
+                    color: #f3c11d;
+                    margin-right: 6px;
+                    img {
+                        width: 17px;
+                        height: 13px;
+                    }
+                }
+            }
+        }
+    }
+    .overview-file + .overview-file {
+        margin-top: 8px;
+    }
+    .box-wrap {
+        display: flex;
+        .box-item {
+            box-sizing: border-box;
+            min-width: 110px;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+            padding: 6px 16px;
+            background: rgba(207, 207, 207, 0.1);
+            border-radius: 4px;
+            border: 1px solid rgba(207, 207, 207, 0.1);
+            cursor: pointer;
+            .item-name {
+                font-size: 12px;
+                color: #666666;
+                width: max-content;
+            }
+            .item-val {
+                font-size: 18px;
+                color: #fff;
+                width: max-content;
+                padding-top: 3px;
+                span {
+                    font-size: 12px;
+                    padding-left: 2px;
+                }
+            }
+            &.active {
+                background: rgba(255, 212, 137, 0.16);
+                border: 1px solid #ffd489;
+                .item-name {
+                    color: #bbbbbb;
+                }
+            }
+        }
+        .box-item + .box-item {
+            margin-left: 8px;
+        }
+    }
+}
+</style>

+ 12 - 12
src/views/home/components/homeFile.vue

@@ -95,9 +95,9 @@
 import eventBus from "@/api/eventBus";
 import { onMounted, ref, onBeforeUnmount, reactive } from "vue";
 const outputBox = ref([
-    { id: 1, name: "产量估计", field: "cl", value: "--", unit: "斤/亩" },
-    { id: 2, name: "高质果率", field: "spgl", value: "--", unit: "%" },
-    { id: 3, name: "挂果数", field: "zuoguo_ratio",value: "--", unit: "颗/枝条" },
+    { id: 1, name: "种植面积", field: "area", value: "6800", unit: "亩" },
+    { id: 2, name: "亩产估计", field: "cl", value: "1610", unit: "斤/亩" },
+    { id: 3, name: "产量估计", field: "zuoguo_ratio",value: "1094.8", unit: "万斤" },
 ]);
 
 const qualityBox = ref([
@@ -216,15 +216,15 @@ function setFileData(type_id) {
     // if(res.production_info.production){
     //   res.production_info.production = (res.production_info.production * 1.3).toFixed(1)
     // }
-    outputBox.value[0].value = res.production_info.production;
-    outputBox.value[1].value = res.production_info.quality.toFixed(0);
-    if(res.production_info.zuoguo_ratio){
-      outputBox.value[2].name = "坐果率";
-      outputBox.value[2].value = res.production_info.zuoguo_ratio.toFixed(0);
-    }else{
-      outputBox.value[2].name = "雌花率";
-      outputBox.value[2].value = res.production_info.cihua_ratio.toFixed(0);
-    }
+    // outputBox.value[0].value = res.production_info.production;
+    // outputBox.value[1].value = res.production_info.quality.toFixed(0);
+    // if(res.production_info.zuoguo_ratio){
+    //   outputBox.value[2].name = "坐果率";
+    //   outputBox.value[2].value = res.production_info.zuoguo_ratio.toFixed(0);
+    // }else{
+    //   outputBox.value[2].name = "雌花率";
+    //   outputBox.value[2].value = res.production_info.cihua_ratio.toFixed(0);
+    // }
     qualityBox.value[0].value = res.ecology_info.ventilation;
     qualityBox.value[1].value = res.ecology_info.transmittance;
     qualityBox.value[2].value = res.ecology_info.dp_situation;

+ 1075 - 0
src/views/home/index - 副本.vue

@@ -0,0 +1,1075 @@
+<template>
+    <div class="base-container no-events">
+        <fnHeader showDate></fnHeader>
+        <div class="content">
+            <navigation @handleTab="handleTab"></navigation>
+            <div class="left yes-events">
+                <tool-list direction="left" :list="leftToolList" @handleActive="handleActiveLeft"></tool-list>
+                <component :is="components[currentComponent]" />
+                <!-- 箭头 -->
+                <div class="arrow" @click="handleShrink('left')">
+                    <el-icon class="icon" color="#141414"><DArrowLeft /></el-icon>
+                </div>
+            </div>
+            <div class="home-bottom">
+                <div class="garden-file" :class="{ isShrink: isShrink }">
+                    <home-file></home-file>
+                </div>
+            </div>
+            <div class="right yes-events">
+                <div class="list album-r">
+                    <chart-box name="农事列表" arrow="arrow-left" :class="{ 'list-wrap': rightIndex === 0 }">
+                        <template v-if="rightIndex === 0">
+                            <album></album>
+                            <!-- <img class="tabs" src="@/assets/images/home/ns-tabs.png" alt="">
+              <div class="img-box">
+                <img @click="handleAct(item)" v-for="item in 2" :key="item" :src="require(`@/assets/images/home/0${act<=2&&act==item?item+'-act':item}.png`)" alt="">
+              </div> -->
+                        </template>
+                        <template v-if="rightIndex === 1">
+                            <div class="img-box1">
+                                <img src="@/assets/images/home/fh01.png" alt="" />
+                                <img src="@/assets/images/home/fh02.png" alt="" />
+                            </div>
+                        </template>
+                        <template v-if="rightIndex === 2">
+                            <div class="btn-wrap">
+                                <div :class="{ active: btnIndex === 0 }" @click="handleBtn(0)">
+                                    {{ btnIndex === 0 && btnName != "" ? "采样分区:" + btnName : "选择采样分区" }}
+                                </div>
+                                <div :class="{ active: btnIndex === 1 }" @click="handleBtn(1)">
+                                    {{ btnIndex === 1 && btnName != "" ? "单树编号:" + btnName : "选择树" }}
+                                </div>
+                            </div>
+                            <div class="img-box2" v-show="showPoint">
+                                <img v-if="showType === 'point'" src="@/assets/images/home/line-chart.png" alt="" />
+                                <img v-else src="@/assets/images/home/line-chart2.png" alt="" />
+                                <img src="@/assets/images/home/fh01.png" alt="" />
+                            </div>
+                            <div class="img-box2" v-show="!showPoint">
+                                <img v-if="showType === 'point'" src="@/assets/images/home/line-chart1.png" alt="" />
+                                <img v-else src="@/assets/images/home/line-chart3.png" alt="" />
+                                <img src="@/assets/images/home/fh02.png" alt="" />
+                            </div>
+                        </template>
+                    </chart-box>
+                </div>
+                <tool-list direction="right" :list="rightToolList" @handleActive="handleActiveRight"></tool-list>
+            </div>
+
+            <!-- 图例 -->
+            <!-- <img class="legend yes-events" src="@/assets/images/home/legend-img.png" alt="" /> -->
+            <div v-if="legendArr && legendArr.length" class="map-bg map-legend yes-events">
+                <div class="item" v-for="(legend, legendI) in legendArr" :key="legendI">
+                    <span class="legend-block" :style="{background: legend.color}"></span>
+                    {{ legend.name }}
+                </div>
+            </div>
+            <div v-else class="map-bg map-legend yes-events">
+                <div class="item">
+                    <img src="@/assets/images/map/status/status-bh.png" alt="" />
+                    病害异常
+                </div>
+                <div class="item">
+                    <img src="@/assets/images/map/status/status-ch.png" alt="" />
+                    虫害异常
+                </div>
+                <div class="item">
+                    <img src="@/assets/images/map/status/status-zc.png" alt="" />
+                    正常
+                </div>
+                <!-- <div class="item">
+                    <img src="@/assets/images/map/status/defalut-icon.png" alt="" />
+                    无照片
+                </div> -->
+            </div>
+        </div>
+    </div>
+    <div ref="mapRef" class="bottom-map"></div>
+
+    <!-- 图片弹窗 -->
+    <PicturePreview :imageUrl="urls" :curIndex="urlsIndex"></PicturePreview>
+    <album-carousel></album-carousel>
+    <PdfDialog title="果园报告"></PdfDialog>
+
+    <!-- 对比 -->
+    <compareDialog></compareDialog>
+
+    <div class="compare-start-btn yes-events" v-show="showCompareBtn" @click="showCompare">
+        <img src="@/assets/images/home/compare-btn.png" alt="" />
+    </div>
+
+    <!-- 果树档案 -->
+    <div class="file-wrap map-file" id="popup-file">
+        <div class="file-title">
+            <img src="@/assets/images/common/chart-yellow.png" alt="" />
+            果树档案
+            <span id="tag-nh" class="tag">小农户</span>
+        </div>
+        <div class="overview-file">
+            <div class="box-title">总体档案</div>
+            <div class="base-data" id="file-overview">
+            </div>
+            <div class="list" id="file-text">
+                <div class="list-item" v-for="item in photoList" :key="item.key">
+                    <div class="list-name">
+                        <img src="@/assets/images/common/title-icon.png" alt="" />
+                        {{ item.key }}
+                    </div>
+                    {{ item.statement }}
+                </div>
+            </div>
+        </div>
+
+        <div class="overview-file">
+            <div class="box-title">产量信息</div>
+            <div class="box-wrap" id="file-output">
+                <div class="box-item">
+                    <div class="item-name"></div>
+                    <div class="item-val"></div>
+                </div>
+            </div>
+        </div>
+
+        <div class="overview-file">
+            <div class="box-title">生态评估</div>
+            <div class="box-wrap" id="file-quality">
+                <div class="box-item">
+                    <div class="item-name"></div>
+                    <div class="item-val"></div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { onMounted, onUnmounted, ref } from "vue";
+import config from "@/api/config.js";
+import timeLine from "@/components/timeLine.vue";
+import PicturePreview from "@/components/PicturePreview.vue";
+import fnHeader from "@/components/fnHeader.vue";
+import navigation from "@/components/navigation.vue";
+import chartBox from "@/components/chartBox.vue";
+import toolList from "@/components/toolList.vue";
+import fileBar from "@/components/fileBar.vue";
+import HomeMap from "./map/homeMap";
+import homePage from "./components/homePage.vue";
+import weatherPage from "./components/weatherPage.vue";
+import phenologyPage from "./components/phenologyPage.vue";
+import indicatorChart from "./components/indicatorChart.vue";
+import homeFile from "./components/homeFile.vue";
+import { useRouter } from "vue-router";
+import SamplePointLayer from "./map/samplePointLayer";
+import { useStore } from "vuex";
+import RegionLayer from "./map/regionLayer";
+import BlueRegionLayer from "./map/blueRegionLayer";
+import eventBus from "@/api/eventBus";
+import AlbumCarousel from "./album_compoents/albumCarousel.vue";
+import compareDialog from "./album_compoents/compareDialog.vue";
+import album from "./album/index.vue";
+import PdfDialog from "../../components/PdfDialog";
+import StaticMapLayers from "@/components/static_map_change/Layers.js"
+let store = useStore();
+const components = {
+    homePage,
+    weatherPage,
+    phenologyPage,
+};
+//当前农场
+const currentFarm = {
+    id: store.getters.userinfo.curFarmId,
+    name: store.getters.userinfo.curFarmName,
+};
+//当前区域
+const currentRegion = {
+    id: null,
+    name: null,
+};
+let homeMap = new HomeMap();
+let staticMapLayers = null;
+let samplePointLayer = null;
+let regionLayer = null;
+let blueRegionLayer = null;
+const router = useRouter();
+const mapRef = ref();
+onMounted(() => {
+    homeMap.initMap("POINT(113.61448114737868 23.585550924763083)", mapRef.value);
+    // homeMap.initMap(store.getters.userinfo.location, mapRef.value);
+    // regionLayer = new RegionLayer(homeMap.kmap.map, currentFarm, currentRegion)
+    samplePointLayer = new SamplePointLayer(homeMap.kmap);
+    VE_API.warning.fetchWarningLayer({
+      k: "feiniao_static_map",
+      resultType: "json",
+    }).then(({data}) => {
+      staticMapLayers = new StaticMapLayers(homeMap.kmap, data)
+    })
+    blueRegionLayer = new BlueRegionLayer(homeMap.kmap);
+    function changeStaticMapLayers(e){
+      // staticMapLayers.
+    }
+
+    getYellow();
+    // getFarmLog()
+
+    //区域切换监听事件
+    eventBus.on("area:id", areaId);
+    //选项卡子项事件监听
+    // eventBus.on("handleTabItem", handleTabItem);
+    // 是否开启指标对比
+    eventBus.on("compareTree", handleCompare)
+    eventBus.on("clickToCompare:point", toggleCompare);
+});
+
+onUnmounted(() => {
+    eventBus.off("area:id", areaId);
+    // eventBus.off("handleTabItem", handleTabItem);
+    eventBus.off("compareTree", handleCompare)
+    eventBus.off("clickToCompare:point", toggleCompare);
+});
+
+
+function handleCompare(v) {
+    isShrink.value = v
+    if (v === false) {
+        showCompareBtn.value = v
+    }
+}
+
+const blueList = ref([]);
+const getBlueRegionList = (callback) => {
+    let selectAll = undefined;
+    if (regionId.value === 0) {
+        selectAll = 1;
+    }
+    const areaId = selectAll ? undefined : regionId.value;
+    VE_API.farm.blueRegionList({ farmId: organId.value, regionId: areaId, selectAll }).then(({ data }) => {
+        blueList.value = data.map((item) => {
+            let color = "rgba(255, 255, 255, 0.5)"; //失效区域
+            if (item.status === 2) {
+                //物候期风险
+                // color = "rgba(63, 255, 53, 0.5)";
+                color = "#2BFE00";
+            }
+            if (item.status === 3) {
+                //生长异常
+                // color = "rgba(255, 252, 61, 0.5)";
+                color = "#FF7410";
+            }
+            if (item.status === 4) {
+                //病虫害
+                // color = "rgba(255, 73, 73, 0.5)";
+                color = "#F82121";
+            }
+            return {
+                ...item,
+                color,
+            };
+        });
+        blueRegionLayer.initData(blueList.value);
+        callback && callback();
+    });
+};
+// 图例
+const legendArr = ref([])
+
+const organId = ref(null);
+const regionId = ref(null);
+const tabName = ref("");
+const tabId = ref(0);
+eventBus.off("changePointLegend", toggleLegend)
+eventBus.on("changePointLegend", toggleLegend)
+function toggleLegend({colorObj}) {
+    legendArr.value = colorObj?.list
+}
+//选项卡事件监听
+const handleTab = async ({ name, id, isUpdate, params, legend, colorObj }) => {
+    eventBus.emit("changePointType", {legend, colorObj})
+    legendArr.value = colorObj?.list
+    console.log('name, id, isUpdate, params', name, id, isUpdate, params, legend, colorObj);
+    tabName.value = name;
+    tabId.value = id;
+    if (id === 0) {
+        getBlueRegionList(() => {
+            if (isUpdate) {
+                handleTabItem(params);
+            }
+        });
+    } else {
+        getFarmIndexReport(() => {
+            if (isUpdate) {
+                handleTabItem(params);
+            }
+        });
+    }
+    // 切换点位数据
+    // samplePointLayer.changePointType(name, params)
+};
+
+//区域切换监听事件
+function areaId({ areaId, farmId }) {
+    organId.value = farmId;
+    regionId.value = areaId;
+    samplePointLayer.initData(farmId, areaId);
+    if (tabId.value === 0) {
+        getBlueRegionList();
+    } else {
+        getFarmIndexReport();
+    }
+}
+
+//选项卡子项事件监听
+const handleTabItem = (e) => {
+    console.log('eeeeeeeeee', e, reportData.value);
+    // if (reportData.value.blueZoneList) {
+    //     const index = reportData.value.blueZoneList.findIndex((item) => item.key === e);
+    //     let arr = [];
+    //     if (reportData.value.blueZoneList.length) {
+    //         arr = blueListConvert(reportData.value.blueZoneList[index].obj, index);
+    //     }
+    //     blueRegionLayer.initData(arr, "87");
+    // }
+};
+
+const reportData = ref({});
+const blueListConvert = (data, index) => {
+    const list = [];
+    for (let key in data) {
+        const filterData = reportData.value.blueZoneLegendList[index].list.filter((item) => item.val === key);
+        const arr = data[key];
+        arr.forEach((item) => {
+            const listObj = blueList.value.filter((ele) => ele.blueZoneCode === item);
+            const updateList = listObj.map((ele) => {
+                return {
+                    ...ele,
+                    level: key,
+                    name: filterData[0].name,
+                    color: filterData[0].color,
+                };
+            });
+            list.push(...updateList);
+        });
+    }
+    return list;
+};
+
+const getFarmIndexReport = (callback) => {
+    // const params = { farmId:organId.value,regionId:regionId.value, type: tabName.value };
+    //   VE_API.farm.farmIndexReport(params).then(({data,code}) => {
+    //     if (code === 0) {
+    //         reportData.value = data || {};
+    //         let arr = []
+    //         if(data.blueZoneList.length){
+    //           arr = blueListConvert(data.blueZoneList[0].obj,0)
+    //         }
+    //         blueRegionLayer.initData(arr,'87')
+    //         callback && callback()
+    //     }
+    // });
+};
+
+const indicatorChartData = ref({});
+const blueZone = ref("ws0y1meyhxp4");
+
+const getFarmLog = () => {
+    console.log("getfarmlog");
+    const params = {
+        id: null,
+        farmId: 766,
+        blueZone: blueZone.value,
+    };
+    VE_API.warning.fetchFarmLog(params).then(({ data }) => {
+        indicatorChartData.value = data || {};
+        eventBus.emit("chart:updateOption", data);
+    });
+};
+
+const urls = ref([]);
+const urlsIndex = ref(0);
+const getYellow = () => {
+    VE_API.home.getYellowList().then((res) => {
+        // urls.value = res.data.map(item =>{
+        //   return {
+        //     ...item,
+        //     imgPath:config.base_img_url2+item.cloudFilename
+        //   }
+        // })
+        // urls.value = [
+        //   "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-07.jpg",
+        //   "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-08.jpg",
+        //   "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-09.jpg",
+        //   "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-10.jpg",
+        //   "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-11.jpg",
+        //   "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-12.jpg",
+        //   "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-13.jpg",
+        // ]
+    });
+};
+
+const btnIndex = ref(null);
+const btnName = ref("");
+const handleBtn = (e) => {
+    btnName.value = "";
+    btnIndex.value = e;
+    eventBus.emit("clear:area");
+    samplePointLayer.updateAreaStatus(e === 0 ? true : false);
+    regionLayer.resetData();
+    samplePointLayer.resetPoint();
+};
+
+//点击果园日志
+const handleSelectArea = () => {
+    btnName.value = "";
+    btnIndex.value = null;
+    eventBus.emit("clear:area");
+    regionLayer.resetData();
+    samplePointLayer.resetPoint();
+    samplePointLayer.updateAreaStatus(true);
+};
+
+//农事点击高亮
+const act = ref(null);
+const handleAct = (v) => {
+    act.value = v;
+    samplePointLayer.resetPoint();
+    if (v === 1) {
+        regionLayer.selectAreaMultiple([
+            { value: 2, color: "blue" },
+            { value: 4, color: "blue1" },
+            { value: 5, color: "blue2" },
+            { value: 7, color: "blue" },
+            { value: 13, color: "blue2" },
+        ]);
+    }
+    if (v === 2) {
+        regionLayer.selectAreaMultiple([
+            { value: 1, color: "blue" },
+            { value: 2, color: "blue1" },
+            { value: 9, color: "blue2" },
+            { value: 12, color: "blue2" },
+        ]);
+    }
+};
+
+//柱状图点击事件监听
+eventBus.on("echart:barClick", (e) => {
+    btnName.value = "";
+    btnIndex.value = null;
+    eventBus.emit("clear:area");
+    samplePointLayer.updateAreaStatus(false);
+    const arr = ["花穗伸长", "啃食虫害", "毛毡病"];
+    const isDraw = arr.includes(e);
+    const index = arr.indexOf(e);
+    if (isDraw) {
+        if (index === 0) {
+            regionLayer.selectAreaMultiple([
+                { value: 0, color: "green" },
+                { value: 1, color: "green" },
+                { value: 2, color: "green" },
+                { value: 3, color: "green1" },
+                { value: 4, color: "green1" },
+                { value: 5, color: "green2" },
+                { value: 6, color: "green1" },
+                { value: 7, color: "green2" },
+                { value: 8, color: "green2" },
+                { value: 9, color: "green" },
+                { value: 10, color: "green" },
+                { value: 11, color: "green1" },
+                { value: 12, color: "green2" },
+                { value: 13, color: "green" },
+                { value: 14, color: "green2" },
+            ]);
+        } else if (index === 1) {
+            regionLayer.selectAreaMultiple([{ value: 6, color: "red" }]);
+        } else {
+            regionLayer.selectAreaMultiple([
+                { value: 12, color: "red2" },
+                { value: 10, color: "red" },
+                { value: 1, color: "red" },
+            ]);
+        }
+    }
+});
+
+//黄板点击事件监听
+eventBus.on("click:yellowBlock", (e) => {
+    const arr = ["113.61396985128522", "113.61390710255375", "113.61491218688275"];
+    if (arr[0] == e) {
+        urls.value = ["HB-ws0y1menggxv"];
+        urlsIndex.value = 0;
+    }
+    if (arr[1] == e) {
+        urls.value = ["HB-ws0y1mg0pvd"];
+        urlsIndex.value = 3;
+    }
+    if (arr[2] == e) {
+        urls.value = ["HB-ws0y1mg9wpcp"];
+        urlsIndex.value = 6;
+    }
+    eventBus.emit("dialog:show", true);
+});
+
+const showPoint = ref(true);
+const showType = ref("point");
+
+eventBus.on("click:updateArea", (e) => {
+    blueZone.value = e.value;
+    btnName.value = e.name;
+    regionLayer.selectArea(e.name * 1 === 0 ? 0 : e.name * 1 - 1, "blue");
+    //getFarmLog()
+});
+
+const currentComponent = ref("homePage");
+const handleActiveLeft = (e) => {
+    currentComponent.value = e.componentName;
+    if (e.title === "首页") {
+        router.push("/warningHome");
+    }
+};
+const leftToolList = [
+    {
+        title: "首页",
+        name: "home",
+        componentName: "homePage",
+    },
+    {
+        title: "气象预警",
+        componentName: "weatherPage",
+    },
+    {
+        title: "物候调节",
+        componentName: "phenologyPage",
+    },
+    {
+        title: "病虫测报",
+    },
+    {
+        title: "营养评估",
+    },
+];
+
+const rightIndex = ref(0);
+const handleActiveRight = ({ index }) => {
+    rightIndex.value = index;
+    btnIndex.value = null;
+    btnName.value = "";
+    samplePointLayer.updateAreaStatus(false);
+    regionLayer.resetData();
+    samplePointLayer.resetPoint();
+    if (index !== 0) {
+        act.value = null;
+    }
+};
+const hanleRightIndex = (num) => {
+    rightIndex.value = num;
+    eventBus.emit("tool:updateAct", num);
+};
+const rightToolList = [
+    {
+        title: "农事列表",
+        index: 0,
+    },
+    {
+        title: "处方分析",
+        index: 2,
+    },
+    {
+        title: "复核对比",
+        index: 1,
+    },
+];
+
+// 跳转果园档案
+const toFilePage = () => {
+    router.push("/garden-file");
+};
+
+// 地图图例
+const showMapLegend = ref(true);
+const handleLegend = (e) => {
+    blueRegionLayer.toggleLayer(e);
+};
+
+// 对比
+const compareData = ref([]);
+const showCompareBtn = ref(false);
+function toggleCompare(arr) {
+    // eventBus.emit("clickToCompare:point",{farmId:fs.get("farmId"),sampleId:fs.get("sampleId"), data: fs.getProperties()})
+    compareData.value = [];
+    arr.map((fs) => {
+        compareData.value.push({ farmId: fs.get("farmId"), sampleId: fs.get("id"), data: fs.getProperties() });
+    });
+    console.log("compareData", compareData.value);
+    showCompareBtn.value = compareData.value.length > 1 ? true : false;
+}
+function showCompare() {
+    eventBus.emit("showCompareDialog", compareData.value);
+}
+
+const isShrink = ref(false);
+const isLeftShrink = ref(false);
+const isRightShrink = ref(false);
+const handleShrink = (position) => {
+    switch (position) {
+        case "bottom":
+            isShrink.value = !isShrink.value;
+            break;
+        case "left":
+            isLeftShrink.value = !isLeftShrink.value;
+            break;
+        case "rigth":
+            isRightShrink.value = !isRightShrink.value;
+            break;
+    }
+};
+
+const photoList = ref([
+    {key: "病虫", statement: "病虫 2025年02月19日,发现毛毡病异常1级"},
+    {key: "异常", statement: "2025年03月17日,发现花量大异常3级"},
+    {key: "营养", statement: "无营养异常"},
+]);
+
+</script>
+
+<style lang="scss" scoped>
+.base-container {
+    width: 100%;
+    height: 100vh;
+    color: #fff;
+    position: absolute;
+    box-sizing: border-box;
+    z-index: 1;
+
+    .content {
+        width: 100%;
+        height: calc(100% - 74px - 48px);
+        display: flex;
+        justify-content: space-between;
+        box-sizing: border-box;
+        .left,
+        .right {
+            width: calc(376px + 54px);
+            height: 100%;
+            margin-top: 10px;
+            box-sizing: border-box;
+            display: flex;
+            position: relative;
+        }
+        .left {
+            background: #101010;
+            border-radius: 4px;
+            border: 1px solid #444444;
+            .arrow {
+                position: absolute;
+                right: -16px;
+                top: calc(50% - 40px);
+                background: #fff;
+                width: 16px;
+                height: 80px;
+                line-height: 80px;
+                border-radius: 0 5px 5px 0;
+                text-align: center;
+                cursor: pointer;
+            }
+        }
+        .right {
+            width: calc(376px + 54px + 10px);
+            .album-r {
+                .list-wrap {
+                    width: 375px;
+                }
+            }
+            .list {
+                width: 100%;
+                height: 100%;
+                .btn-wrap {
+                    width: 100%;
+                    height: 25px;
+                    line-height: 25px;
+                    margin: 10px 0;
+                    display: flex;
+                    align-items: center;
+                    justify-content: space-between;
+                    div {
+                        width: 48%;
+                        height: 100%;
+                        color: #ffd489;
+                        border: 1px solid rgba(255, 213, 137, 0.6);
+                        border-radius: 2px;
+                        text-align: center;
+                        font-size: 12px;
+                        cursor: pointer;
+                        &.active {
+                            background: #ffd489;
+                            color: #000;
+                        }
+                    }
+                }
+                .img-box {
+                    width: 100%;
+                    height: calc(100% - 35px);
+                    overflow: auto;
+                }
+                .img-box1 {
+                    width: 100%;
+                    height: calc(100% - 10px);
+                    overflow: auto;
+                    margin-top: 10px;
+                }
+                .img-box2 {
+                    width: 100%;
+                    height: calc(100% - 45px);
+                    overflow: auto;
+                    margin-top: 10px;
+                }
+                img {
+                    width: 100%;
+                    height: auto;
+                    object-fit: cover;
+                    margin-bottom: 12px;
+                    cursor: pointer;
+                }
+                .mt {
+                    margin-top: -12px;
+                }
+                .list-wrap {
+                    ::v-deep {
+                        .chart-content {
+                            padding: 16px 0 0 0;
+                        }
+                    }
+                }
+            }
+        }
+        .overflow {
+            overflow: auto;
+        }
+        .home-bottom {
+            display: flex;
+            align-items: flex-end;
+            width: calc(100% - 20px - 430px * 2);
+            height: 152px;
+            align-self: flex-end;
+            .time-wrap {
+                height: 85px;
+            }
+            .fly-icon {
+                width: 148px;
+                height: 100%;
+                margin-left: 27px;
+            }
+            .log-box {
+                height: 34%;
+                width: calc(100% - 340px - 28px);
+                margin-right: 28px;
+                .box-name {
+                    width: 89px;
+                    height: 22px;
+                    text-align: center;
+                    line-height: 22px;
+                    border-radius: 20px;
+                    margin: 10px 0 5px 6px;
+                    cursor: pointer;
+                    background: linear-gradient(0deg, #bba269 0%, #3d3523 100%);
+                }
+                .log-content {
+                    font-size: 12px;
+                    line-height: 1.5;
+                    padding: 0 18px;
+                }
+                .chart-wrap {
+                    width: 100%;
+                    height: calc(100% - 50px);
+                    .line {
+                        margin-top: 10px;
+                        margin-bottom: 12px;
+                    }
+                    img {
+                        width: 100%;
+                        margin-bottom: 10px;
+                    }
+                }
+            }
+
+            .garden-file {
+                position: relative;
+                top: 10px;
+                // height: 30%;
+                // min-height: 210px;
+                // width: 640px;
+                transition: all 0.3s;
+                // width: 800px;
+                // height: 320px;
+                width: 100vw;
+                height: 100vh;
+                overflow: hidden;
+                &.isShrink {
+                    height: 66px;
+                    width: 450px;
+                    overflow: hidden;
+                    .arrow {
+                        .icon {
+                            transform: rotate(90deg);
+                        }
+                    }
+                }
+                .arrow {
+                    position: absolute;
+                    right: 56px;
+                    top: 36px;
+                    background: #fff;
+                    height: 16px;
+                    width: 80px;
+                    line-height: 16px;
+                    border-radius: 0 0 5px 5px;
+                    text-align: center;
+                    cursor: pointer;
+                    .icon {
+                        transform: rotate(270deg);
+                    }
+                }
+            }
+
+            .file-box {
+                height: 25%;
+                min-height: 210px;
+                width: 340px;
+                position: relative;
+                img {
+                    width: 100%;
+                    margin-top: 12px;
+                }
+                .arrow-icon {
+                    top: -32px;
+                    left: 50%;
+                    position: absolute;
+                    background: #fff;
+                    width: 16px;
+                    height: 80px;
+                    line-height: 80px;
+                    border-radius: 5px 0 0 5px;
+                    text-align: center;
+                    transform: translateX(-50%) rotate(270deg);
+                }
+                .edit-btn {
+                    padding: 2px 24px;
+                    background: #ffd489;
+                    border-radius: 4px;
+                    color: #000;
+                }
+            }
+        }
+        .legend {
+            position: fixed;
+            bottom: 8px;
+            right: 64px;
+            // width: 525px;
+            height: 20px;
+        }
+        .map-bg {
+            position: fixed;
+            z-index: 2;
+            background: rgba(35, 35, 35, 0.8);
+            border-radius: 18px;
+            padding: 7px 16px;
+            right: 460px;
+        }
+        .map-btn {
+            top: 19px;
+            cursor: pointer;
+        }
+        .map-legend {
+            bottom: 34px;
+            .item {
+                display: flex;
+                align-items: center;
+                font-size: 14px;
+                img {
+                    width: 16px;
+                    margin-right: 6px;
+                }
+                .legend-block {
+                    width: 16px;
+                    height: 16px;
+                    box-sizing: border-box;
+                    border-radius: 50%;
+                    border: 2px solid #fff;
+                    margin-right: 6px;
+                }
+            }
+            .legend-title {
+                border-bottom: 1px solid rgba(102, 102, 102, 0.35);
+            }
+            .item + .item {
+                padding-top: 10px;
+            }
+        }
+    }
+}
+.bottom-map {
+    width: 100%;
+    height: 100vh;
+    position: absolute;
+    z-index: 0;
+}
+
+.compare-start-btn {
+    position: absolute;
+    z-index: 2;
+    left: 50%;
+    transform: translateX(-50%);
+    cursor: pointer;
+    bottom: 106px;
+    // right: 445px;
+    img {
+        height: 55px;
+    }
+}
+</style>
+
+<style lang="less">
+.file-wrap {
+    &.map-file {
+        width: 367px;
+        position: relative;
+        background: url("@/assets/images/home/file-bg.png") no-repeat top center / 100% 100%;
+        margin-left: 12px;
+        padding: 12px;
+        .file-title {
+            font-size: 20px;
+            color: #ffd489;
+            .tag {
+                border: 1px solid #FFD489;
+                border-radius: 4px;
+                font-size: 12px;
+                display: inline-block;
+                width: 44px;
+                height: 20px;
+                text-align: center;
+                line-height: 18px;
+                margin-left: 8px;
+                padding: 1px 4px;
+            }
+        }
+        .overview-file {
+            padding-top: 20px;
+            .box-title {
+                font-size: 16px;
+                padding-left: 13px;
+                margin-bottom: 16px;
+                position: relative;
+                display: flex;
+                justify-content: space-between;
+                color: #fff;
+                &::before {
+                    content: "";
+                    position: absolute;
+                    left: 0;
+                    top: 3px;
+                    width: 3px;
+                    height: 16px;
+                    background: #fff;
+                    border-radius: 11px;
+                }
+            }
+            .title {
+                color: #f3c11d;
+                font-size: 16px;
+                font-family: "PangMenZhengDao";
+                margin-bottom: 20px;
+                .big {
+                    width: 13px;
+                    height: 13px;
+                    margin: -10px 0 0 4px;
+                }
+                .small {
+                    width: 7px;
+                    height: 7px;
+                    margin-left: -3px;
+                }
+            }
+            .base-data {
+                background: rgba(207, 207, 207, 0.1);
+                border-radius: 4px;
+                padding: 6px 0;
+                display: flex;
+                .base-item {
+                    flex: 1;
+                    text-align: center;
+                    .label {
+                        font-size: 12px;
+                        color: #666666;
+                    }
+                    .value {
+                        padding-top: 2px;
+                        font-size: 16px;
+                        color: #ffffff;
+                    }
+                }
+                .base-item + .base-item {
+                    border-left: 1px solid rgba(102, 102, 102, 0.42);
+                }
+            }
+            .list {
+                margin-top: 15px;
+                width: max-content;
+                font-size: 14px;
+                .list-item {
+                    color: #bbbbbb;
+                    display: flex;
+                    margin-bottom: 8px;
+                    .list-name {
+                        color: #f3c11d;
+                        margin-right: 6px;
+                        img {
+                            width: 17px;
+                            height: 13px;
+                        }
+                    }
+                }
+            }
+        }
+        .overview-file + .overview-file {
+            margin-top: 8px;
+        }
+        .box-wrap {
+            display: flex;
+            .box-item {
+                // flex: 1;
+                min-width: 109px;
+                display: flex;
+                flex-direction: column;
+                justify-content: center;
+                align-items: center;
+                padding: 6px;
+                box-sizing: border-box;
+                background: rgba(207, 207, 207, 0.1);
+                border-radius: 4px;
+                border: 1px solid rgba(207, 207, 207, 0.1);
+                cursor: pointer;
+                .item-name {
+                    font-size: 12px;
+                    color: #666666;
+                    width: max-content;
+                }
+                .item-val {
+                    font-size: 18px;
+                    color: #fff;
+                    width: max-content;
+                    padding-top: 3px;
+                }
+                &.active {
+                    background: rgba(255, 212, 137, 0.16);
+                    border: 1px solid #ffd489;
+                    .item-name {
+                        color: #bbbbbb;
+                    }
+                }
+            }
+            .box-item + .box-item {
+                margin-left: 8px;
+            }
+        }
+    }
+}
+</style>

+ 56 - 38
src/views/home/index.vue

@@ -17,44 +17,24 @@
                 </div>
             </div>
             <div class="right yes-events">
-                <div class="list album-r">
-                    <chart-box name="农事列表" arrow="arrow-left" :class="{ 'list-wrap': rightIndex === 0 }">
-                        <template v-if="rightIndex === 0">
-                            <album></album>
-                            <!-- <img class="tabs" src="@/assets/images/home/ns-tabs.png" alt="">
-              <div class="img-box">
-                <img @click="handleAct(item)" v-for="item in 2" :key="item" :src="require(`@/assets/images/home/0${act<=2&&act==item?item+'-act':item}.png`)" alt="">
-              </div> -->
-                        </template>
-                        <template v-if="rightIndex === 1">
-                            <div class="img-box1">
-                                <img src="@/assets/images/home/fh01.png" alt="" />
-                                <img src="@/assets/images/home/fh02.png" alt="" />
-                            </div>
-                        </template>
-                        <template v-if="rightIndex === 2">
-                            <div class="btn-wrap">
-                                <div :class="{ active: btnIndex === 0 }" @click="handleBtn(0)">
-                                    {{ btnIndex === 0 && btnName != "" ? "采样分区:" + btnName : "选择采样分区" }}
-                                </div>
-                                <div :class="{ active: btnIndex === 1 }" @click="handleBtn(1)">
-                                    {{ btnIndex === 1 && btnName != "" ? "单树编号:" + btnName : "选择树" }}
-                                </div>
-                            </div>
-                            <div class="img-box2" v-show="showPoint">
-                                <img v-if="showType === 'point'" src="@/assets/images/home/line-chart.png" alt="" />
-                                <img v-else src="@/assets/images/home/line-chart2.png" alt="" />
-                                <img src="@/assets/images/home/fh01.png" alt="" />
-                            </div>
-                            <div class="img-box2" v-show="!showPoint">
-                                <img v-if="showType === 'point'" src="@/assets/images/home/line-chart1.png" alt="" />
-                                <img v-else src="@/assets/images/home/line-chart3.png" alt="" />
-                                <img src="@/assets/images/home/fh02.png" alt="" />
-                            </div>
-                        </template>
-                    </chart-box>
-                </div>
-                <tool-list direction="right" :list="rightToolList" @handleActive="handleActiveRight"></tool-list>
+              <div class="list adopt-list-wrap">
+                <chart-box name="认养管理" arrow="">
+                  <el-tabs v-model="activeName" class="demo-tabs">
+                    <el-tab-pane label="认养列表" name="认养列表">
+                      <adopt-list></adopt-list>
+                    </el-tab-pane>
+                    <el-tab-pane label="客户列表" name="客户列表">
+                      <client-list></client-list>
+                    </el-tab-pane>
+                    <el-tab-pane label="认养申请" name="认养申请">
+                      <apply-list></apply-list>
+                    </el-tab-pane>
+                    <el-tab-pane label="确认地址" name="确认地址">
+                      <address-list></address-list>
+                    </el-tab-pane>
+                  </el-tabs>
+                </chart-box>
+              </div>
             </div>
 
             <!-- 图例 -->
@@ -170,6 +150,10 @@ import compareDialog from "./album_compoents/compareDialog.vue";
 import album from "./album/index.vue";
 import PdfDialog from "../../components/PdfDialog";
 import StaticMapLayers from "@/components/static_map_change/Layers.js"
+import adoptList from "./components/foster/adoptList.vue";
+import clientList from "./components/foster/clientList.vue";
+import applyList from "./components/foster/applyList.vue";
+import addressList from "./components/foster/addressList.vue";
 let store = useStore();
 const components = {
     homePage,
@@ -181,6 +165,7 @@ const currentFarm = {
     id: store.getters.userinfo.curFarmId,
     name: store.getters.userinfo.curFarmName,
 };
+const activeName = ref('认养列表')
 //当前区域
 const currentRegion = {
     id: null,
@@ -674,6 +659,39 @@ const photoList = ref([
         }
         .right {
             width: calc(376px + 54px + 10px);
+
+            .adopt-list-wrap {
+              ::v-deep {
+                .el-tabs {
+                  height: 100%;
+                }
+                .el-tabs__content {
+                  height: calc(100% - 40px - 15px);
+                  position: static;
+                }
+                .el-tabs__item {
+                  color: #727272;
+                }
+                .el-tabs__active-bar {
+                  background-color: #FFFFFF;
+                  height: 1px;
+                }
+                .el-tabs__item.is-active {
+                  color: #fff;
+                }
+                .el-tabs__nav-wrap:after {
+                  height: 1px;
+                  background-color: rgba(127, 127, 127, 0.3);
+                }
+                .el-tabs__nav {
+                  left: 50%;
+                  transform: translateX(-50%) !important;
+                }
+                .el-tab-pane {
+                  height: 100%;
+                }
+              }
+            }
             .album-r {
                 .list-wrap {
                     width: 375px;

+ 448 - 18
yarn.lock

@@ -3295,6 +3295,16 @@
   dependencies:
     "@types/node" "*"
 
+"@vant/popperjs@^1.3.0":
+  version "1.3.0"
+  resolved "https://registry.npmjs.org/@vant/popperjs/-/popperjs-1.3.0.tgz#e0eff017124b5b2352ef3b36a6df06277f4400f2"
+  integrity sha512-hB+czUG+aHtjhaEmCJDuXOep0YTZjdlRR+4MSmIFnkCQIxJaXLQdSsR90XWvAI2yvKUI7TCGqR8pQg2RtvkMHw==
+
+"@vant/use@^1.6.0":
+  version "1.6.0"
+  resolved "https://registry.npmjs.org/@vant/use/-/use-1.6.0.tgz#237df3091617255519552ca311ffdfea9de59001"
+  integrity sha512-PHHxeAASgiOpSmMjceweIrv2AxDZIkWXyaczksMoWvKV2YAYEhoizRuk/xFnKF+emUIi46TsQ+rvlm/t2BBCfA==
+
 "@videojs/http-streaming@2.16.2":
   version "2.16.2"
   resolved "https://registry.npmmirror.com/@videojs/http-streaming/-/http-streaming-2.16.2.tgz"
@@ -3701,6 +3711,11 @@
   resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz"
   integrity sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==
 
+"@vue/shared@^3.5.13":
+  version "3.5.14"
+  resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.5.14.tgz#8fcdc6c69661a1163c173cafb6129c3f8ad01122"
+  integrity sha512-oXTwNxVfc9EtP1zzXAlSlgARLXNC84frFYkS0HHz0h3E4WZSP9sywqjqzGCP9Y34M8ipNmd380pVgmMuwELDyQ==
+
 "@vue/vue-loader-v15@npm:vue-loader@^15.9.7":
   version "15.10.0"
   resolved "https://registry.npmmirror.com/vue-loader/-/vue-loader-15.10.0.tgz"
@@ -3952,6 +3967,11 @@ address@^1.1.2:
   resolved "https://registry.npmmirror.com/address/-/address-1.2.0.tgz"
   integrity sha512-tNEZYz5G/zYunxFm7sfhAxkXEuLj3K6BKwv6ZURlsF6yiUQ65z0Q2wZW9L5cPUl9ocofGvXOdFYbFHp0+6MOig==
 
+address@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.npmjs.org/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e"
+  integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==
+
 aes-decrypter@1.0.3:
   version "1.0.3"
   resolved "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-1.0.3.tgz"
@@ -3976,6 +3996,13 @@ agent-base@6, agent-base@^6.0.2:
   dependencies:
     debug "4"
 
+agentkeepalive@^3.4.1:
+  version "3.5.3"
+  resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.3.tgz#c210afce942b4287e2df2fbfe6c0d57eda2ce634"
+  integrity sha512-yqXL+k5rr8+ZRpOAntkaaRgWgE5o8ESAj5DyRmVTCSoZxXmqemb9Dd7T4i5UzwuERdLAJUy6XzR9zFVuf0kzkw==
+  dependencies:
+    humanize-ms "^1.2.1"
+
 agentkeepalive@^4.2.1:
   version "4.6.0"
   resolved "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a"
@@ -4040,6 +4067,37 @@ ajv@^8.0.0:
     require-from-string "^2.0.2"
     uri-js "^4.2.2"
 
+ali-oss@^6.20.0:
+  version "6.23.0"
+  resolved "https://registry.npmjs.org/ali-oss/-/ali-oss-6.23.0.tgz#0bb236428307986ece0bf9243d77d7029d7b6ed2"
+  integrity sha512-FipRmyd16Pr/tEey/YaaQ/24Pc3HEpLM9S1DRakEuXlSLXNIJnu1oJtHM53eVYpvW3dXapSjrip3xylZUTIZVQ==
+  dependencies:
+    address "^1.2.2"
+    agentkeepalive "^3.4.1"
+    bowser "^1.6.0"
+    copy-to "^2.0.1"
+    dateformat "^2.0.0"
+    debug "^4.3.4"
+    destroy "^1.0.4"
+    end-or-error "^1.0.1"
+    get-ready "^1.0.0"
+    humanize-ms "^1.2.0"
+    is-type-of "^1.4.0"
+    js-base64 "^2.5.2"
+    jstoxml "^2.0.0"
+    lodash "^4.17.21"
+    merge-descriptors "^1.0.1"
+    mime "^2.4.5"
+    platform "^1.3.1"
+    pump "^3.0.0"
+    qs "^6.4.0"
+    sdk-base "^2.0.1"
+    stream-http "2.8.2"
+    stream-wormhole "^1.0.4"
+    urllib "^2.44.0"
+    utility "^1.18.0"
+    xml2js "^0.6.2"
+
 ansi-align@^3.0.1:
   version "3.0.1"
   resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz"
@@ -4113,9 +4171,9 @@ ansi-styles@^6.1.0:
   resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz"
   integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
 
-any-promise@^1.0.0:
+any-promise@^1.0.0, any-promise@^1.3.0:
   version "1.3.0"
-  resolved "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz"
+  resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
   integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
 
 anymatch@~3.1.2:
@@ -4460,6 +4518,11 @@ boolbase@^1.0.0:
   resolved "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz"
   integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
 
+bowser@^1.6.0:
+  version "1.9.4"
+  resolved "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz#890c58a2813a9d3243704334fa81b96a5c150c9a"
+  integrity sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==
+
 boxen@7.0.0:
   version "7.0.0"
   resolved "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz"
@@ -4548,6 +4611,11 @@ buffer@^6.0.3:
     base64-js "^1.3.1"
     ieee754 "^1.2.1"
 
+builtin-status-codes@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
+  integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==
+
 builtins@^5.0.0:
   version "5.0.1"
   resolved "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz"
@@ -4622,6 +4690,14 @@ cache-base@^1.0.1:
     union-value "^1.0.0"
     unset-value "^1.0.0"
 
+call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6"
+  integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==
+  dependencies:
+    es-errors "^1.3.0"
+    function-bind "^1.1.2"
+
 call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7:
   version "1.0.7"
   resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz"
@@ -4633,6 +4709,14 @@ call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7:
     get-intrinsic "^1.2.4"
     set-function-length "^1.2.1"
 
+call-bound@^1.0.2:
+  version "1.0.4"
+  resolved "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a"
+  integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==
+  dependencies:
+    call-bind-apply-helpers "^1.0.2"
+    get-intrinsic "^1.3.0"
+
 callsites@^3.0.0:
   version "3.1.0"
   resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
@@ -5136,6 +5220,11 @@ content-disposition@0.5.4:
   dependencies:
     safe-buffer "5.2.1"
 
+content-type@^1.0.2:
+  version "1.0.5"
+  resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
+  integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
+
 content-type@~1.0.4:
   version "1.0.4"
   resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz"
@@ -5170,6 +5259,11 @@ copy-descriptor@^0.1.0:
   resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz"
   integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==
 
+copy-to@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz#2680fbb8068a48d08656b6098092bdafc906f4a5"
+  integrity sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==
+
 copy-webpack-plugin@^9.0.1:
   version "9.1.0"
   resolved "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz"
@@ -5200,9 +5294,9 @@ core-js@^3.23.3, core-js@^3.6.0, core-js@^3.8.3:
   resolved "https://registry.npmmirror.com/core-js/-/core-js-3.23.3.tgz"
   integrity sha512-oAKwkj9xcWNBAvGbT//WiCdOMpb9XQG92/Fe3ABFM/R16BsHgePG00mFOgKf7IsCtfj8tA1kHtf/VwErhriz5Q==
 
-core-util-is@~1.0.0:
+core-util-is@^1.0.2, core-util-is@~1.0.0:
   version "1.0.3"
-  resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz"
+  resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
   integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
 
 cosmiconfig@^7.0.0:
@@ -5436,6 +5530,11 @@ data-view-byte-offset@^1.0.0:
     es-errors "^1.3.0"
     is-data-view "^1.0.1"
 
+dateformat@^2.0.0:
+  version "2.2.0"
+  resolved "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062"
+  integrity sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw==
+
 dayjs@^1.11.3:
   version "1.11.3"
   resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.3.tgz"
@@ -5494,6 +5593,13 @@ default-gateway@^6.0.3:
   dependencies:
     execa "^5.0.0"
 
+default-user-agent@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.npmjs.org/default-user-agent/-/default-user-agent-1.0.0.tgz#16c46efdcaba3edc45f24f2bd4868b01b7c2adc6"
+  integrity sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw==
+  dependencies:
+    os-name "~1.0.3"
+
 defaults@^1.0.3:
   version "1.0.3"
   resolved "https://registry.npmmirror.com/defaults/-/defaults-1.0.3.tgz"
@@ -5566,9 +5672,9 @@ depd@~1.1.2:
   resolved "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz"
   integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
 
-destroy@1.2.0:
+destroy@1.2.0, destroy@^1.0.4:
   version "1.2.0"
-  resolved "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz"
+  resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
   integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
 
 detect-node@^2.0.4:
@@ -5581,6 +5687,11 @@ diff@^5.1.0:
   resolved "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz"
   integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==
 
+digest-header@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.npmjs.org/digest-header/-/digest-header-1.1.0.tgz#e16ab6cf4545bc4eea878c8c35acd1b89664d800"
+  integrity sha512-glXVh42vz40yZb9Cq2oMOt70FIoWiv+vxNvdKdU8CwjLad25qHM3trLxhl9bVjdr6WaslIXhWpn0NO8T/67Qjg==
+
 dir-glob@^3.0.1:
   version "3.0.1"
   resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz"
@@ -5705,6 +5816,15 @@ dotenv@^10.0.0:
   resolved "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz"
   integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
 
+dunder-proto@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
+  integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
+  dependencies:
+    call-bind-apply-helpers "^1.0.1"
+    es-errors "^1.3.0"
+    gopd "^1.2.0"
+
 duplexer@^0.1.2:
   version "0.1.2"
   resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz"
@@ -5733,9 +5853,9 @@ echarts@^5.4.1:
     tslib "2.3.0"
     zrender "5.4.1"
 
-ee-first@1.1.1:
+ee-first@1.1.1, ee-first@~1.1.1:
   version "1.1.1"
-  resolved "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz"
+  resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
   integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
 
 electron-to-chromium@^1.4.251:
@@ -5803,6 +5923,11 @@ end-of-stream@^1.1.0:
   dependencies:
     once "^1.4.0"
 
+end-or-error@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmjs.org/end-or-error/-/end-or-error-1.0.1.tgz#dc7a6210fe78d372fee24a8b4899dbd155414dcb"
+  integrity sha512-OclLMSug+k2A0JKuf494im25ANRBVW8qsjmwbgX7lQ8P82H21PQ1PWkoYwb9y5yMBS69BPlwtzdIFClo3+7kOQ==
+
 enhanced-resolve@^5.9.3:
   version "5.10.0"
   resolved "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz"
@@ -5916,6 +6041,11 @@ es-define-property@^1.0.0:
   dependencies:
     get-intrinsic "^1.2.4"
 
+es-define-property@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
+  integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
+
 es-errors@^1.2.1, es-errors@^1.3.0:
   version "1.3.0"
   resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz"
@@ -5933,6 +6063,13 @@ es-object-atoms@^1.0.0:
   dependencies:
     es-errors "^1.3.0"
 
+es-object-atoms@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1"
+  integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==
+  dependencies:
+    es-errors "^1.3.0"
+
 es-set-tostringtag@^2.0.3:
   version "2.0.3"
   resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz"
@@ -6492,6 +6629,16 @@ form-data@^4.0.0:
     combined-stream "^1.0.8"
     mime-types "^2.1.12"
 
+formstream@^1.1.0:
+  version "1.5.1"
+  resolved "https://registry.npmjs.org/formstream/-/formstream-1.5.1.tgz#b25f8121aa434cc82e8b36cdd765338b7b8df4de"
+  integrity sha512-q7ORzFqotpwn3Y/GBK2lK7PjtZZwJHz9QE9Phv8zb5IrL9ftGLyi2zjGURON3voK8TaZ+mqJKERYN4lrHYTkUQ==
+  dependencies:
+    destroy "^1.0.4"
+    mime "^2.5.2"
+    node-hex "^1.0.1"
+    pause-stream "~0.0.11"
+
 forwarded@0.2.0:
   version "0.2.0"
   resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz"
@@ -6667,6 +6814,35 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@
     has-symbols "^1.0.3"
     hasown "^2.0.0"
 
+get-intrinsic@^1.2.5, get-intrinsic@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
+  integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
+  dependencies:
+    call-bind-apply-helpers "^1.0.2"
+    es-define-property "^1.0.1"
+    es-errors "^1.3.0"
+    es-object-atoms "^1.1.1"
+    function-bind "^1.1.2"
+    get-proto "^1.0.1"
+    gopd "^1.2.0"
+    has-symbols "^1.1.0"
+    hasown "^2.0.2"
+    math-intrinsics "^1.1.0"
+
+get-proto@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
+  integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
+  dependencies:
+    dunder-proto "^1.0.1"
+    es-object-atoms "^1.0.0"
+
+get-ready@^1.0.0, get-ready@~1.0.0:
+  version "1.0.0"
+  resolved "https://registry.npmjs.org/get-ready/-/get-ready-1.0.0.tgz#f91817f1e9adecfea13a562adfc8de883ab34782"
+  integrity sha512-mFXCZPJIlcYcth+N8267+mghfYN9h3EhsDa6JSnbA3Wrhh/XFpuowviFcsDeYZtKspQyWyJqfs4O6P8CHeTwzw==
+
 get-stream@^3.0.0:
   version "3.0.0"
   resolved "https://registry.npmmirror.com/get-stream/-/get-stream-3.0.0.tgz"
@@ -6807,6 +6983,11 @@ gopd@^1.0.1:
   dependencies:
     get-intrinsic "^1.1.3"
 
+gopd@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
+  integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
+
 graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
   version "4.2.9"
   resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz"
@@ -6873,6 +7054,11 @@ has-symbols@^1.0.2, has-symbols@^1.0.3:
   resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz"
   integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
 
+has-symbols@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
+  integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
+
 has-tostringtag@^1.0.0, has-tostringtag@^1.0.2:
   version "1.0.2"
   resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz"
@@ -7155,7 +7341,7 @@ human-signals@^3.0.1:
   resolved "https://registry.npmmirror.com/human-signals/-/human-signals-3.0.1.tgz"
   integrity sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==
 
-humanize-ms@^1.2.1:
+humanize-ms@^1.2.0, humanize-ms@^1.2.1:
   version "1.2.1"
   resolved "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz"
   integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==
@@ -7380,6 +7566,11 @@ is-cidr@^4.0.2:
   dependencies:
     cidr-regex "^3.1.1"
 
+is-class-hotfix@~0.0.6:
+  version "0.0.6"
+  resolved "https://registry.npmjs.org/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz#a527d31fb23279281dde5f385c77b5de70a72435"
+  integrity sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==
+
 is-core-module@^2.8.1:
   version "2.16.1"
   resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4"
@@ -7587,6 +7778,15 @@ is-symbol@^1.0.2, is-symbol@^1.0.3:
   dependencies:
     has-symbols "^1.0.2"
 
+is-type-of@^1.4.0:
+  version "1.4.0"
+  resolved "https://registry.npmjs.org/is-type-of/-/is-type-of-1.4.0.tgz#3ed175a0eee888b1da4983332e7714feb8a8fb2b"
+  integrity sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==
+  dependencies:
+    core-util-is "^1.0.2"
+    is-class-hotfix "~0.0.6"
+    isstream "~0.1.2"
+
 is-typed-array@^1.1.13:
   version "1.1.13"
   resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz"
@@ -7650,6 +7850,11 @@ isobject@^3.0.0, isobject@^3.0.1:
   resolved "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz"
   integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
 
+isstream@~0.1.2:
+  version "0.1.2"
+  resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+  integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==
+
 jackspeak@^3.1.2:
   version "3.4.3"
   resolved "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a"
@@ -7698,7 +7903,7 @@ jquery@^3.6.3:
   resolved "https://registry.npmjs.org/jquery/-/jquery-3.6.3.tgz"
   integrity sha512-bZ5Sy3YzKo9Fyc8wH2iIQK4JImJ6R0GWI9kL1/k7Z91ZBNgkRXE6U0JfHIizZbort8ZunhSI3jw9I6253ahKfg==
 
-js-base64@^2.1.9:
+js-base64@^2.1.9, js-base64@^2.5.2:
   version "2.6.4"
   resolved "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz"
   integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
@@ -7826,6 +8031,11 @@ jspdf@^2.5.1:
     dompurify "^2.2.0"
     html2canvas "^1.0.0-rc.5"
 
+jstoxml@^2.0.0:
+  version "2.2.9"
+  resolved "https://registry.npmjs.org/jstoxml/-/jstoxml-2.2.9.tgz#2eebd5e55383fe66a375022ca0aa88f77bc4fb84"
+  integrity sha512-OYWlK0j+roh+eyaMROlNbS5cd5R25Y+IUpdl7cNdB8HNrkgwQzIS7L9MegxOiWNBj9dQhA/yAxiMwCC5mwNoBw==
+
 jsts@2.7.1:
   version "2.7.1"
   resolved "https://registry.npmjs.org/jsts/-/jsts-2.7.1.tgz"
@@ -8373,6 +8583,11 @@ marchingsquares@^1.3.3:
   resolved "https://registry.npmjs.org/marchingsquares/-/marchingsquares-1.3.3.tgz"
   integrity sha512-gz6nNQoVK7Lkh2pZulrT4qd4347S/toG9RXH2pyzhLgkL5mLkBoqgv4EvAGXcV0ikDW72n/OQb3Xe8bGagQZCg==
 
+math-intrinsics@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
+  integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
+
 mdn-data@2.0.14:
   version "2.0.14"
   resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz"
@@ -8400,6 +8615,11 @@ merge-descriptors@1.0.1:
   resolved "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz"
   integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
 
+merge-descriptors@^1.0.1:
+  version "1.0.3"
+  resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5"
+  integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==
+
 merge-options@1.0.1:
   version "1.0.1"
   resolved "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz"
@@ -8498,6 +8718,11 @@ mime@1.6.0, mime@^1.4.1:
   resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz"
   integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
 
+mime@^2.4.5, mime@^2.5.2:
+  version "2.6.0"
+  resolved "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
+  integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==
+
 mimic-fn@^1.0.0:
   version "1.2.0"
   resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz"
@@ -8567,6 +8792,11 @@ minimatch@^9.0.0, minimatch@^9.0.4:
   dependencies:
     brace-expansion "^2.0.1"
 
+minimist@^1.1.0:
+  version "1.2.8"
+  resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+  integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
 minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
   version "1.2.6"
   resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.6.tgz"
@@ -8685,9 +8915,9 @@ mixin-deep@^1.2.0:
     for-in "^1.0.2"
     is-extendable "^1.0.1"
 
-mkdirp@^0.5.5:
+mkdirp@^0.5.1, mkdirp@^0.5.5:
   version "0.5.6"
-  resolved "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz"
+  resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
   integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
   dependencies:
     minimist "^1.2.6"
@@ -8785,9 +9015,9 @@ mux.js@6.0.1:
     "@babel/runtime" "^7.11.2"
     global "^4.4.0"
 
-mz@^2.4.0:
+mz@^2.4.0, mz@^2.7.0:
   version "2.7.0"
-  resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz"
+  resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
   integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
   dependencies:
     any-promise "^1.0.0"
@@ -8889,6 +9119,11 @@ node-gyp@^9.0.0, node-gyp@^9.3.0:
     tar "^6.1.2"
     which "^2.0.2"
 
+node-hex@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmjs.org/node-hex/-/node-hex-1.0.1.tgz#606208e91f9c02b9b81531b692b9f1da4860fb24"
+  integrity sha512-iwpZdvW6Umz12ICmu9IYPRxg0tOLGmU3Tq2tKetejCj3oZd7b2nUXwP3a7QA5M9glWy8wlPS1G3RwM/CdsUbdQ==
+
 node-releases@^2.0.6:
   version "2.0.8"
   resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz"
@@ -9190,6 +9425,11 @@ object-inspect@^1.12.2, object-inspect@^1.13.1:
   resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz"
   integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
 
+object-inspect@^1.13.3:
+  version "1.13.4"
+  resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213"
+  integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==
+
 object-keys@^1.1.1:
   version "1.1.1"
   resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz"
@@ -9372,6 +9612,21 @@ ora@^5.3.0:
     strip-ansi "^6.0.0"
     wcwidth "^1.0.1"
 
+os-name@~1.0.3:
+  version "1.0.3"
+  resolved "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz#1b379f64835af7c5a7f498b357cb95215c159edf"
+  integrity sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew==
+  dependencies:
+    osx-release "^1.0.0"
+    win-release "^1.0.0"
+
+osx-release@^1.0.0:
+  version "1.1.0"
+  resolved "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz#f217911a28136949af1bf9308b241e2737d3cd6c"
+  integrity sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A==
+  dependencies:
+    minimist "^1.1.0"
+
 p-finally@^1.0.0:
   version "1.0.0"
   resolved "https://registry.npmmirror.com/p-finally/-/p-finally-1.0.0.tgz"
@@ -9608,6 +9863,13 @@ pathe@^1.0.0, pathe@^1.1.0:
   resolved "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz"
   integrity sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==
 
+pause-stream@~0.0.11:
+  version "0.0.11"
+  resolved "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
+  integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==
+  dependencies:
+    through "~2.3"
+
 pbf@3.2.1:
   version "3.2.1"
   resolved "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz"
@@ -9674,6 +9936,11 @@ pkg-types@^1.0.2:
     mlly "^1.1.1"
     pathe "^1.1.0"
 
+platform@^1.3.1:
+  version "1.3.6"
+  resolved "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7"
+  integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
+
 point-in-polygon-hao@^1.1.0:
   version "1.2.4"
   resolved "https://registry.npmjs.org/point-in-polygon-hao/-/point-in-polygon-hao-1.2.4.tgz"
@@ -10198,6 +10465,13 @@ qs@^6.11.0:
   dependencies:
     side-channel "^1.0.6"
 
+qs@^6.4.0:
+  version "6.14.0"
+  resolved "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930"
+  integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==
+  dependencies:
+    side-channel "^1.1.0"
+
 query-string@^4.3.2:
   version "4.3.4"
   resolved "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz"
@@ -10358,6 +10632,19 @@ readable-stream@^2.0.1:
     string_decoder "~1.1.1"
     util-deprecate "~1.0.1"
 
+readable-stream@^2.3.6:
+  version "2.3.8"
+  resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
+  integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
+  dependencies:
+    core-util-is "~1.0.0"
+    inherits "~2.0.3"
+    isarray "~1.0.0"
+    process-nextick-args "~2.0.0"
+    safe-buffer "~5.1.1"
+    string_decoder "~1.1.1"
+    util-deprecate "~1.0.1"
+
 readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0:
   version "3.6.0"
   resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz"
@@ -10734,6 +11021,11 @@ sass@^1.53.0:
     immutable "^4.0.0"
     source-map-js ">=0.6.2 <2.0.0"
 
+sax@>=0.6.0:
+  version "1.4.1"
+  resolved "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f"
+  integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==
+
 sax@^1.2.4:
   version "1.2.4"
   resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz"
@@ -10772,6 +11064,13 @@ scule@^1.0.0:
   resolved "https://registry.npmjs.org/scule/-/scule-1.0.0.tgz"
   integrity sha512-4AsO/FrViE/iDNEPaAQlb77tf0csuq27EsVpy6ett584EcRTp6pTDLoGWVxCD77y5iU5FauOvhsI4o1APwPoSQ==
 
+sdk-base@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.npmjs.org/sdk-base/-/sdk-base-2.0.1.tgz#ba40289e8bdf272ed11dd9ea97eaf98e036d24c6"
+  integrity sha512-eeG26wRwhtwYuKGCDM3LixCaxY27Pa/5lK4rLKhQa7HBjJ3U3Y+f81MMZQRsDw/8SC2Dao/83yJTXJ8aULuN8Q==
+  dependencies:
+    get-ready "~1.0.0"
+
 select-hose@^2.0.0:
   version "2.0.0"
   resolved "https://registry.npmmirror.com/select-hose/-/select-hose-2.0.0.tgz"
@@ -10794,6 +11093,11 @@ semver@7.0.0:
   resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz"
   integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
 
+semver@^5.0.1:
+  version "5.7.2"
+  resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
+  integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
+
 semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
   version "6.3.0"
   resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz"
@@ -10981,6 +11285,35 @@ shell-quote@^1.6.1:
   resolved "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz"
   integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==
 
+side-channel-list@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad"
+  integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==
+  dependencies:
+    es-errors "^1.3.0"
+    object-inspect "^1.13.3"
+
+side-channel-map@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42"
+  integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==
+  dependencies:
+    call-bound "^1.0.2"
+    es-errors "^1.3.0"
+    get-intrinsic "^1.2.5"
+    object-inspect "^1.13.3"
+
+side-channel-weakmap@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea"
+  integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==
+  dependencies:
+    call-bound "^1.0.2"
+    es-errors "^1.3.0"
+    get-intrinsic "^1.2.5"
+    object-inspect "^1.13.3"
+    side-channel-map "^1.0.1"
+
 side-channel@^1.0.4, side-channel@^1.0.6:
   version "1.0.6"
   resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz"
@@ -10991,6 +11324,17 @@ side-channel@^1.0.4, side-channel@^1.0.6:
     get-intrinsic "^1.2.4"
     object-inspect "^1.13.1"
 
+side-channel@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9"
+  integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==
+  dependencies:
+    es-errors "^1.3.0"
+    object-inspect "^1.13.3"
+    side-channel-list "^1.0.0"
+    side-channel-map "^1.0.1"
+    side-channel-weakmap "^1.0.2"
+
 signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
   version "3.0.6"
   resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz"
@@ -11310,11 +11654,27 @@ statuses@2.0.1:
   resolved "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz"
   integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
 
-"statuses@>= 1.4.0 < 2":
+"statuses@>= 1.4.0 < 2", statuses@^1.3.1:
   version "1.5.0"
-  resolved "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz"
+  resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
   integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
 
+stream-http@2.8.2:
+  version "2.8.2"
+  resolved "https://registry.npmjs.org/stream-http/-/stream-http-2.8.2.tgz#4126e8c6b107004465918aa2fc35549e77402c87"
+  integrity sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==
+  dependencies:
+    builtin-status-codes "^3.0.0"
+    inherits "^2.0.1"
+    readable-stream "^2.3.6"
+    to-arraybuffer "^1.0.0"
+    xtend "^4.0.0"
+
+stream-wormhole@^1.0.4:
+  version "1.1.0"
+  resolved "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz#300aff46ced553cfec642a05251885417693c33d"
+  integrity sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==
+
 strict-uri-encode@^1.0.0:
   version "1.1.0"
   resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz"
@@ -11672,9 +12032,9 @@ thread-loader@^3.0.0:
     neo-async "^2.6.2"
     schema-utils "^3.0.0"
 
-through@^2.3.8:
+through@^2.3.8, through@~2.3:
   version "2.3.8"
-  resolved "https://registry.npmmirror.com/through/-/through-2.3.8.tgz"
+  resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
   integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
 
 thunky@^1.0.2:
@@ -11697,6 +12057,11 @@ tinyqueue@^2.0.0, tinyqueue@^2.0.3:
   resolved "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz"
   integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==
 
+to-arraybuffer@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
+  integrity sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==
+
 to-fast-properties@^2.0.0:
   version "2.0.0"
   resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz"
@@ -11925,6 +12290,13 @@ unbox-primitive@^1.0.2:
     has-symbols "^1.0.3"
     which-boxed-primitive "^1.0.2"
 
+unescape@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmjs.org/unescape/-/unescape-1.0.1.tgz#956e430f61cad8a4d57d82c518f5e6cc5d0dda96"
+  integrity sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==
+  dependencies:
+    extend-shallow "^2.0.1"
+
 unicode-canonical-property-names-ecmascript@^2.0.0:
   version "2.0.0"
   resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz"
@@ -12107,6 +12479,24 @@ url-toolkit@^2.1.3, url-toolkit@^2.2.1:
   resolved "https://registry.npmmirror.com/url-toolkit/-/url-toolkit-2.2.5.tgz"
   integrity sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==
 
+urllib@^2.44.0:
+  version "2.44.0"
+  resolved "https://registry.npmjs.org/urllib/-/urllib-2.44.0.tgz#0da4b037550bdc03eb9a408de498fb4025ddc0b4"
+  integrity sha512-zRCJqdfYllRDA9bXUtx+vccyRqtJPKsw85f44zH7zPD28PIvjMqIgw9VwoTLV7xTBWZsbebUFVHU5ghQcWku2A==
+  dependencies:
+    any-promise "^1.3.0"
+    content-type "^1.0.2"
+    default-user-agent "^1.0.0"
+    digest-header "^1.0.0"
+    ee-first "~1.1.1"
+    formstream "^1.1.0"
+    humanize-ms "^1.2.0"
+    iconv-lite "^0.6.3"
+    pump "^3.0.0"
+    qs "^6.4.0"
+    statuses "^1.3.1"
+    utility "^1.16.1"
+
 use@^3.1.0:
   version "3.1.1"
   resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz"
@@ -12130,6 +12520,17 @@ utila@~0.4:
   resolved "https://registry.npmmirror.com/utila/-/utila-0.4.0.tgz"
   integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==
 
+utility@^1.16.1, utility@^1.18.0:
+  version "1.18.0"
+  resolved "https://registry.npmjs.org/utility/-/utility-1.18.0.tgz#af55f62e6d5a272e0cb02b0ab3e7f37c46435f36"
+  integrity sha512-PYxZDA+6QtvRvm//++aGdmKG/cI07jNwbROz0Ql+VzFV1+Z0Dy55NI4zZ7RHc9KKpBePNFwoErqIuqQv/cjiTA==
+  dependencies:
+    copy-to "^2.0.1"
+    escape-html "^1.0.3"
+    mkdirp "^0.5.1"
+    mz "^2.7.0"
+    unescape "^1.0.1"
+
 utils-merge@1.0.1:
   version "1.0.1"
   resolved "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz"
@@ -12167,6 +12568,15 @@ validate-npm-package-name@^5.0.0:
   dependencies:
     builtins "^5.0.0"
 
+vant@^4.9.19:
+  version "4.9.19"
+  resolved "https://registry.npmjs.org/vant/-/vant-4.9.19.tgz#315bebe0e8a58237c8fffaec2d1c162b9f112a23"
+  integrity sha512-fRt32XI0fO0vB3/YGhZOpTnHKjplUiNuA05yZy8rPZntmbQE5GA57Y7iC7jmMDxSOaLebovynhgCvWnyk9zmDw==
+  dependencies:
+    "@vant/popperjs" "^1.3.0"
+    "@vant/use" "^1.6.0"
+    "@vue/shared" "^3.5.13"
+
 vary@~1.1.2:
   version "1.1.2"
   resolved "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz"
@@ -12655,6 +13065,13 @@ wildcard@^2.0.0:
   resolved "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz"
   integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==
 
+win-release@^1.0.0:
+  version "1.1.1"
+  resolved "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209"
+  integrity sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw==
+  dependencies:
+    semver "^5.0.1"
+
 wkt-parser@^1.3.1:
   version "1.3.2"
   resolved "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.3.2.tgz"
@@ -12766,6 +13183,19 @@ xml-utils@^1.0.2:
   resolved "https://registry.npmjs.org/xml-utils/-/xml-utils-1.3.0.tgz"
   integrity sha512-i4PIrX33Wd66dvwo4syicwlwmnr6wuvvn4f2ku9hA67C2Uk62Xubczuhct+Evnd12/DV71qKNeDdJwES8HX1RA==
 
+xml2js@^0.6.2:
+  version "0.6.2"
+  resolved "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499"
+  integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==
+  dependencies:
+    sax ">=0.6.0"
+    xmlbuilder "~11.0.0"
+
+xmlbuilder@~11.0.0:
+  version "11.0.1"
+  resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
+  integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
+
 xtend@^4.0.0:
   version "4.0.2"
   resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz"