UE+EarthSDK2.0+Cesium学习指南(使用VScode)

EarthSDK2.0快速入门文档:‌​​​​​‬​​‬⁠⁠‬​​​​​⁠⁠‌⁠​​​‌​​​​‌‍⁠​‬​‌​‌‍​⁠​‌​​​EarthSDK2.0快速入门教程 - 飞书云文档 (feishu.cn)

EarthSDK2 JS API文档:EarthSDK2 JS API文档 (wolai.com)

EarthSDK2 官方示例:示例首页 (earthsdk.com)

Cesium示例:Hello World - Cesium Sandcastle

B站视频链接(地球可视化实验室):https://www.bilibili.com/video/BV16x421277N?vd_source=0f546fec3e50c4412e6098c8166be74a

环境搭建

webpack:如何引入EartrhSDK_哔哩哔哩_bilibili

npm i esobjs-xe2-plugin

npm i vue-xe2-plugin

vite:vite项目搭建好后,先安装XE2依赖esobjs-xe2-plugin,两个插件vite-plugin-externals 和 vite-plugin-static-copy。示例地址:earthsdk-demos: 基于earthsdk开发的用户交互界面,以及几个最小的和vue配合的示例 - Gitee.com

vue基础环境搭建:‬​‌​​‬‬​​‍⁠​‬‬⁠⁠‍​​​​‍‌‍​‍​​​​​‌​⁠‍​​‌⁠​​VUE基础环境搭建 - 飞书云文档 (feishu.cn)

安装配置ESSS信令服务器:如果要启动像素流服务,那么要求机器上最少有 nvidia 2060 以上的显卡,显卡配置太低,可能无法正确启动服务。ESSS信令服务器下载地址:https://bjxbsj.cn/esss.html或者 https://bjxbsj.cn/downcenter.html

安装成功之后 ,桌面图标运行,会在默认浏览器里打开 http://localhost:8086/login.html

默认用户名:admin,默认密码: admin1234

新版本使用分布式和官方文档步骤有变化,只需要将压缩包地址添加进编辑里面就行了

本地更新里面添加

代码演示:

<template>
    <div style="width: 100%; height: 100%;" ref="xe2Container"></div>
    <div class="header">
    <select v-model="onlineUrl" @change="switchOnlineImage(onlineUrl)">
      <option value="https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}">谷歌</option>
      <option value="https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}">高德</option>
      <option value="https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}">Arcgis</option>
    </select>
    <button @click="createESLocationMeasurement()">点位测量</button>
    <button @click="createESDistanceMeasurement()">距离测量</button>
    <button @click="createESHeightMeasurement()">高度测量</button>
    <button @click="createESAreaMeasurement()">面积测量</button>
    <button @click="createESDirectionMeasurement()">方位角测量</button>
    <button @click="destroyMeasurement()">清除测量</button>
    </div>
    <div class="switch">
      <button @click="switchCesiumViewer">切换Cesium视口</button>
      <button @click="switchUEViewer">切换UE视口</button>
      <button @click="flyIn([114.05565611710809, 32.23032890173555, 550640.6629355564], [349.4892794691355, -50.19016063219766, 0.0023330016021228077], 2)">初始位置</button>
    </div>
    <div class="mode">
        <select name="" id="" @change="createESPolygonFence($event)">
            <option value="danger">围栏样式1</option>
            <option value="checkerboard">围栏样式2</option>
            <option value="warning">围栏样式3</option>
            <option value="cord">围栏样式4</option>
            <option value="scanline">围栏样式5</option>
            <option selected value="honeycomb">围栏样式6</option>
        </select>
        <button @click="destroyfence()">清除围栏</button>

        <select name="" id="" @change="createESPipeFence($event)">
            <option value="purple">紫色</option>
            <option selected value="blue">蓝色</option>
        </select>

        <select name="" id="" @change="createESPath($event)">
            <option value="singleArrow">单箭头路径</option>
            <option selected value="multipleArrows">多箭头路径</option>
        </select>
        <button @click="destroyPath()">清除路径</button>

        <select name="" id="" @change="createESAlarm($event)">
            <option value="cylinder">柱状</option>
            <option selected value="circle">圆形</option>
        </select>
        <button @click="destroyAlarm()">清除警告</button>

        <select name="" id="" @change="createESHuman($event)">
            <option value="worker">工人</option>
            <option selected value="police">警察</option>
            <option selected value="pedestrian">路人</option>
        </select>

        <label for="">人员跟随</label><input type="checkbox" v-model="follow">

        <button @click="createESImageLabel()">图片标签</button>
        <button @click="createESGeoPolygon()">贴地多边形</button>
        <button @click="createESApertureEffect()">光圈特效</button>
    </div>
    <div class="weather">
        <div class="control-group">
            <label for="">时间线</label>
            <input type="range" min="0" max="1" step="0.01" @input="changeCurrentTime($event)">
        </div>
        <div class="control-group">
           <label for="">云</label>
           <input type="range" min="0" max="1" step="0.01" @input="changeCloud($event)"> 
        </div>
        <div class="control-group">
            <label for="">雨</label>
            <input type="range" min="0" max="1" step="0.01" @input="changeRain($event)">
        </div>
        <div class="control-group">
            <label for="">雪</label>
            <input type="range" min="0" max="1" step="0.01" @input="changeSnow($event)">
        </div>
        <div class="control-group">
            <label for="">大气</label>
            <input type="checkbox" value="true" @change="changeAtmosphere()">
        </div>
    </div> 
    <div class="tile">
        <!-- <button v-for="(item, index) in tileData" :key="item.id" @click="flyToById(item.id)">{{ item.name }}</button> -->
        <button v-for="(item) in tileData" :key="item.id" @click="flyToById(item.id)">{{ item.name }}</button>
    </div>
    <div>

    </div>

    </template>
    
    <!-- 1.创建dom元素用来加载视口
         2.创建ESObjectManager对象管理器
         3.创建视口对象
         4.加载影像
    -->
    <script setup>
    import { ESApertureEffect, ESLocationMeasurement, ESObjectsManager } from 'esobjs-xe2-plugin/dist-node/esobjs-xe2-plugin-main';
    import { PickedInfo } from 'xbsj-xe2/dist-node/xe2-base-objects'
    import { ref, onMounted, onBeforeUnmount } from 'vue'
    import { ESApertureEffect, ESPipeFence, ESGeoPolygon, ESHuman, ESImageLabel, ESPath, ESImageryLayer, ESTerrainLayer, ES3DTileset, ESAlarm, ESPolygonFence, ESDistanceMeasurement, ESHeightMeasurement, ESAreaMeasurement, ESDirectionMeasurement } from 'esobjs-xe2-plugin/dist-node/esobjs-xe2-plugin-main';
    //ESLocationMeasurement出错

    // //VUE3和EarthSDK2双向绑定
    // import { createVueDisposer, toVueRef } from 'vue-xe2-plugin/dist-node/components/xe2/tools'
    // const d = createVueDisposer(onBeforeUnmount)

    const objm = new ESObjectsManager();
    const onlineUrl = ref("https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}")
    
    window.g_objm = objm  //控制台打印
    const xe2Container = ref(null)

    const follow = ref(false)
    let humanArr = []

    onMounted(() => {
        const dom = xe2Container.value;
        if (!dom) return;

        //监听每个视口创建
        objm.viewerCreatedEvent.don((viewer) => {
            //监听点击事件
            viewer.clickEvent.don(e => {
                console.log(e)
                if(e.screenPosition && follow.value) {
                    viewer.pickPosition(e.screenPosition).then(position => {
                        humanArr.forEach(h => {
                            h.animation="walking"
                            h.smoothMove(position, 5)
                        })
                    })
                }
            })

            viewer.hoverEvent.don((e) => {
                viewer.pick(e.screenPosition, "hover").then(res => {
                    if (res && res.sceneObject) {
                        res.sceneObject.show = false
                    }
                })
            })
            viewer.mouseMoveEvent.don((e) => {
                // eslint-disable-next-line @typescript-eslint/no-empty-function
                viewer.pick(e.screenPosition, "mouseMove").then(res => {

                })
            })

        })
    
        //创建一个cesium视口,并且绑定一个div容器
        objm.createCesiumViewer(dom)

        //监听视口状态
        objm.activeViewer.statusChanged.don((val) => {
            console.log('监听视口的变化', val)
            if(val == 'Created') {
                //视口加载成功,飞行到视口位置
                flyIn([114.05565611710809, 32.23032890173555, 550640.6629355564], [349.4892794691355, -50.19016063219766, 0.0023330016021228077], 2)
            }
        })
       
        //json用来初始化基础场景
        objm.jsonLoadingEvent.don((e) => {
              switch (e.type) {
                case "init":
                 console.log('json加载初始化')
                 break;
                case "loading":
                 console.log('json正在加载')
                 break;
                case "loaded":
                 console.log('json加载完成')
                 break;
                default:
                  break;
              }
            }),
        
            objm.json =
            {
            "asset": {
                "type": "ESObjectsManager",
                "version": "0.1.0",
                "createdTime": "2022-06-17T05:54:41.744Z",
                "modifiedTime": "2024-08-15T03:55:36.741Z",
                "name": "图层管理"
            },
            "viewers": [
                {
                    "id": "dffeff37-9e5f-4b4a-b6be-ff45866ec9d0",
                    "type": "ESCzmViewer",
                    "show": true,
                    "globeShow": true,
                    "ionAccessToken": "",
                    "apiKey": "",
                    "apiUrl": "",
                    "secretKey": "",
                    "speechVoiceMode": "",
                    "hoverTime": 2,
                    "debug": false,
                    "lonLatFormat": "DECIMAL_DEGREE",
                    "fov": 60,
                    "currentTime": 1723694400000,
                    "simulationTime": 1723651200000,
                    "timeSync": false,
                    "rain": 0,
                    "snow": 0,
                    "cloud": 0,
                    "fog": 0,
                    "depthOfField": 0,
                    "atmosphere": true,
                    "sun": true,
                    "moon": true,
                    "name": "undefined_ined"
                }
            ],
            "sceneTree": {
                "root": {
                    "children": [
                        {
                            "name": "新建场景",
                            "children": [
                                {
                                    "name": "全球影像",
                                    "sceneObj": {
                                        "id": "ae103185-08c7-4ed0-b6d4-15ad77bbbf66",
                                        "type": "ESImageryLayer",
                                        "url": "https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
                                        "rectangle": [
                                            -180,
                                            -90,
                                            180,
                                            90
                                        ],
                                        "maximumLevel": 18,
                                        "name": "全球影像",
                                        "allowPicking": true
                                    },
                                    "children": []
                                }
                            ]
                        },
                        {
                            "name": "白色多边形",
                            "sceneObj": {
                                "id": "ae8a1669-7a96-444c-be98-52271882b096",
                                "type": "ESGeoPolygon",
                                "name": "白色多边形",
                                "collision": false,
                                "allowPicking": true,
                                "filled": true,
                                "points": [
                                    [
                                        92.30165158602695,
                                        37.73367318112731,
                                        0
                                    ],
                                    [
                                        96.7317906007983,
                                        31.18275916765977,
                                        -3.1324159463573503e-9
                                    ],
                                    [
                                        108.61925826702146,
                                        38.78492432980533,
                                        -1.3969838619232178e-9
                                    ],
                                    [
                                        109.40519719194107,
                                        38.646291090285246,
                                        2.1339280972982942e-9
                                    ]
                                ]
                            },
                            "children": []
                        },
                        {
                            "name": "红色多边形",
                            "sceneObj": {
                                "id": "47f0cb3a-c41e-45e5-aca3-c856229906c6",
                                "type": "ESGeoPolygon",
                                "name": "红色多边形",
                                "collision": false,
                                "allowPicking": true,
                                "filled": true,
                                "fillStyle": {
                                    "color": [
                                        1,
                                        0,
                                        0,
                                        1
                                    ],
                                    "material": "",
                                    "materialParams": {},
                                    "ground": false
                                },
                                "points": [
                                    [
                                        119.44521014612961,
                                        49.984659637438604,
                                        -1.3969838619232178e-9
                                    ],
                                    [
                                        108.18857245543923,
                                        45.58726924876385,
                                        0
                                    ],
                                    [
                                        129.56630372382782,
                                        38.28146324973777,
                                        1.6130980174698654e-9
                                    ],
                                    [
                                        139.05473862053634,
                                        46.04777650297759,
                                        -2.7152485655831642e-9
                                    ],
                                    [
                                        139.05473862053634,
                                        46.04777650297759,
                                        -2.7152485655831642e-9
                                    ]
                                ]
                            },
                            "children": []
                        },
                        {
                            "name": "蓝色相机",
                            "sceneObj": {
                                "id": "660dd9b8-4971-477b-95b7-6094114772eb",
                                "type": "ESImageLabel",
                                "position": [
                                    94.03816148546012,
                                    44.18957674755954,
                                    -5.276388813417216e-9
                                ],
                                "name": "蓝色相机",
                                "allowPicking": true,
                                "renderMode": 4
                            },
                            "children": []
                        }
                    ]
                }
            },
            "viewCollection": [],
            "lastView": {
                "position": [
                    110.83065300892005,
                    34.521990035435024,
                    11467536.204733359
                ],
                "rotation": [
                    3.053332494204976e-13,
                    -89.8898693403468,
                    0
                ]
            }
        }
    
        //Cesium加载官方地形需要ionAccessToken
        objm.activeViewer.ionAccessToken = "自己的token";
    
        //添加地形图形
        addTerrainLayer()
        //添加影像图层
        addImageLayer()
    
        //监听当前激活视口变化
        objm.activeViewerChanged.don((viewer)=> {
            if (viewer.typeName == "ESUeViewer") {
                viewer.sunSkyControlled = true
            }
        }) 

        // create3DTileset()

        //加载3dtilset
        init3Dtiles()
    })
    
    //切换Cesium视口
    const switchCesiumViewer = () => {
      const dom = xe2Container.value;
      if (!dom) return;
      objm.switchToCesiumViewer(dom)
    }
    
    //切换UE视口
    const switchUEViewer = () => {
      const dom = xe2Container.value;
      if (!dom) return;
      objm.switchToUEViewer(dom, "http://localhost:8086/", "demo")
    }
    
    //加载影像图层
    const addTerrainLayer = () => {
      const sceneObj = objm.createSceneObject(ESTerrainLayer,'image123')
      if (sceneObj) return
      sceneObj.url = "ion://1"
      
    }

    //添加影像图层
    const addImageLayer = () => {
      const sceneObj = objm.createSceneObject(ESImageryLayer)
      if (!sceneObj) return
      sceneObj.url = "https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
      //设置层级关系
      sceneObj.zIndex = 10
    }
    
    //任意切换在线影像
    const switchOnlineImage = (url) => {
      //获取影像图层
      const imageLayer = objm.getSceneObjectById('image123')
      //设置图层的url地址
      if (!imageLayer) return
      imageLayer.url = url
    }

    //根据位置和姿态信息飞行定位
    const flyIn = (position, rotation, duration) => {
        objm.activeViewer.flyIn(position, rotation, duration)
    }

    let startTime = 1710864010000
    let endTime = 1710950410000
    const changeCurrentTime = ($event) => {
        objm.activeViewer.currentTime = Number($event.target.value) * (endTime - startTime) + startTime
    }

    const changeCloud = ($event) => {
        objm.activeViewer.cloud = Number($event.target.value)
    }

    const changeRain = ($event) => {
        objm.activeViewer.rain = Number($event.target.value)
    }

    const changeSnow = ($event) => {
        objm.activeViewer.snow = Number($event.target.value)
    }

    const changeAtmosphere = () => {
        objm.activeViewer.atmosphere = !objm.activeViewer.atmosphere
    }

    //创建3DTileset
    const create3DTileset = () => {
        const tileset = objm.createSceneObject(ES3DTileset)
        if (!tileset) return

        tileset.url = "https://image.giiiis.com/shanghai/tileset.json"
        tileset.materialMode = 'technology'
        tileset.editing = true
        window.tileset = tileset
        //3dtileset需要先加载,做一个延迟
        setTimeout(() => {
            tileset.flyTo()
        },2000)
    }

    const tileData = ref([
        {
            id: "tile1",
            name: "倾斜数据",
            url: "https://image.giiiis.com/dayanta/tileset.json"
        }, {
            id: "tile2",
            name: "白模数据",
            url: "https://image.giiiis.com/shanghai/tileset.json"
        }, {
            id: "tile3",
            name: "点云数据",
            url: "https://image.giiiis.com/dianyun/tileset.json"
        }, {
            id: "tile4",
            name: "BIM数据",
            url: "https://image.giiiis.com/bim/tileset.json"
        }, {
            id: "tile5",
            name: "人工建模",
            url: "https://image.giiiis.com/changfang/tileset.json"
        }, {
            id: "tile6",
            name: "管线数据",
            url: "https://www.pipeser.com/3dtiles/phipxrow1/tileset.json"
        }
    ])

    //初始化3DTileset数据
    const init3Dtiles = () => {
        tileData.value.forEach(item => {
            const tileset = objm.createSceneObject(ES3DTileset, item.id)
            if(tileset) {
                tileset.url = item.url
            }
        })
    }
    

    //3DTileset根据id进行飞行定位
    const flyToById = (id) => {
        const tileset = objm.getSceneObjectById(id)
        if (tileset) {
            tileset.flyTo()
        }
    }

    let measurementArr = []
    //点位测量
    const createESLocationMeasurement = () => {
        const sceneObj = objm.createSceneObject(ESLocationMeasurement)
        if(!sceneObj) return
        sceneObj.editing = true
        measurementArr.push(sceneObj)
    }

    //距离测量
    const createESDistanceMeasurement = () => {
        const sceneObj = objm.createSceneObject(ESDistanceMeasurement)
        if(!sceneObj) return
        sceneObj.editing = true
        measurementArr.push(sceneObj)
    }

    //高度测量
    const createESHeightMeasurement = () => {
        const sceneObj = objm.createSceneObject(ESHeightMeasurement)
        if(!sceneObj) return
        sceneObj.editing = true
        measurementArr.push(sceneObj)
    }

    //面积测量
    const createESAreaMeasurement = () => {
        const sceneObj = objm.createSceneObject(ESAreaMeasurement)
        if(!sceneObj) return
        sceneObj.editing = true
        measurementArr.push(sceneObj)
    }

    //方位角测量
    const createESDirectionMeasurement = () => {
        const sceneObj = objm.createSceneObject(ESDirectionMeasurement)
        if(!sceneObj) return
        sceneObj.editing = true
        measurementArr.push(sceneObj)
    }
    //清除测量
    const destroyMeasurement = () => {
        measurementArr.forEach(item => {
            objm.destroySceneObject(item)
            item = undefined
        })
    }

    let fenceArr = []
    //创建电子围栏
    const createESPolygonFence = ($event) => {
        const sceneObj = objm.createSceneObject(ESPolygonFence)
        if (!sceneObj) return
        sceneObj.materialMode = $event.target.value
        sceneObj.height = 30
        sceneObj.editing = true
        fenceArr.push(sceneObj)
        // window.fence = sceneObj
    }
    //清除围栏
    const destroyfence = () => {
        fenceArr.forEach(item => {
            objm.destroySceneObject(item)
            item = undefined
        })
    }

    let pathArr = []
    //创建路径
    const createESPath = ($event) => {
        const sceneObj = objm.createSceneObject(ESPath)
        if (!sceneObj) return
        sceneObj.materialMode = $event.target.value
        //线样式设置,在父类中
        sceneObj.stroked = true
        sceneObj.strokeWidth = 10
        sceneObj.speed = 40
        sceneObj.editing = true
        pathArr.push(sceneObj)
        window.path = sceneObj
    }
    //清除路径
    const destroyPath = () => {
        pathArr.forEach(item => {
            objm.destroySceneObject(item)
            item = undefined
        })
    }

    let alarmArr = []
    //创建警告
    const createESAlarm = ($event) => {
        const sceneObj = objm.createSceneObject(ESAlarm)
        if (!sceneObj) return
        sceneObj.mode = $event.target.value
        sceneObj.radius = 100
        sceneObj.editing = true
        alarmArr.push(sceneObj)
    }
    const destroyAlarm = () => {
        alarmArr.forEach(item => {
            objm.destroySceneObject(item)
            item = undefined
        })
    }

    let imageArr = []
    //创建图片标签
    const createESImageLabel = () => {
        const sceneObj = objm.createSceneObject(ESImageLabel)
        if (!sceneObj) return
        sceneObj.editing = true
        window.image = sceneObj
        imageArr.push(sceneObj)
    }

    //创建人员
    const createESHuman = ($event) => {
        const sceneObj = objm.createSceneObject(ESHuman)
        if (!sceneObj) return
        sceneObj.editing = true
        //人员样式设置
        sceneObj.mode = $event.target.value
        humanArr.push(sceneObj)
    }

    //创建贴地多边形
    const createESGeoPolygon = () => {
        const sceneObj = objm.createSceneObject(ESGeoPolygon)
        if (!sceneObj) return
        sceneObj.editing = true
        sceneObj.filled = true
        sceneObj.fillColor = [1, 1, 1, 1]
        sceneObj.fillGround = true
        window.p = sceneObj
        sceneObj.pickedEvent.don((e) => {
            const result = PickedInfo.getFinalAttachedInfo(e)
            switch (result) {
                case 'hover':
                    sceneObj.fillColor = [0, 1, 0, 1]
                    break;
                case 'mouseMove':
                    sceneObj.fillColor = [1, 1, 1, 1]
                break;
                default:
                    sceneObj.fillColor = [1, 0, 0, 1]
                    break;
            }
        })
    }

    //管道电子围栏
    const createESPipeFence = ($event) => {
        const sceneObj = objm.createSceneObject(ESPipeFence)
        if (!sceneObj) return
        sceneObj.editing = true
        //样式设置
        sceneObj.materialMode = $event.target.value
        sceneObj.width = 30
        sceneObj.height = 30
    }

    const createESApertureEffect = () => {
        const sceneObj = objm.createSceneObject(ESApertureEffect)
        if(!sceneObj) return
        sceneObj.editing = true
        //半径设置
        sceneObj.radius = 500
        window.aperture = sceneObj
    }

</script> 
<style>
    body,
    html,
    #app,
    .container {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      overflow: hidden;
    }
    .switch {
      position: absolute;
      right: 10px;
      top: 20px;
    }
    .header {
      color: azure;
      position: absolute;
      left: 8px;
      top: 50px;
    }
    .mode {
      color: azure;
      position: absolute;
      left: 502px;
      top: 50px;
    }
    .weather {
      background-color:white;
      position: absolute;
      right: 10px;
      top: 150px;
      display: flex;  
      flex-direction: column;   
      align-items: flex-start;
    }
    .control-group {  
      display: flex;   
      align-items: center; 
      margin-bottom: 10px;
    }
    .tile {  
    display: flex;  
    flex-direction: column; 
    align-items: flex-start; 
    position: absolute;  
    left: 10px; 
    top: 100px;    
    padding: 10px;  
    
}  
</style>
    
包含下面内容:
JSON初始化场景
UE和Cesium视口切换
地形影像加载
根据位置飞行定位
实现环境和天气系统
加载3DTileset
VUE和EarthSDK双向绑定
测量分析
多边形电子围栏
实现路径
实现报警
数字孪生三维可视化
实现人员定位,平滑移动
实现贴地多边形
拾取事件和自定义拾取事件
管道电子围栏
光圈特效
  • 37
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SteveJi666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值