收藏
回答

使用visionkit开发AR的平面放置模型时,为什么后面的贴图展示到了前面?

图片上,那几根管子本来应该出现在背面,应该是看不到的。但却出现在了前部。用xr-frame打开模型倒是没事,但用visionkit却不行。

import {
  createScopedThreejs
} from 'threejs-miniprogram'
import {
  registerGLTFLoader
} from '../loaders/gltf-loader'
import cloneGltf from '../loaders/gltf-clone'


const info = wx.getSystemInfoSync()


export default function getBehavior() {
  return Behavior({
    data: {
      width: 375,
      height: 600,
      fps: 0,
      memory: 0,
      cpu: 0,
    },
    methods: {
      onReady() {
        // 使用组件作用域的选择器查询
        this.createSelectorQuery()
          .select('#webgl')
          .node()
          .exec(res => {
            console.log('选择器查询结果:', res)
            
            // 检查是否找到了元素
            if (!res || !res[0] || !res[0].node) {
              console.error('未找到webgl canvas元素')
              this.setData({
                loading: false,
                loadingText: '初始化失败:未找到canvas元素'
              })
              return
            }
            
            this.canvas = res[0].node


            const info = wx.getSystemInfoSync()
            const pixelRatio = info.pixelRatio
            const calcSize = (width, height) => {
              console.log(`canvas size: width = ${width} , height = ${height}`)
              this.canvas.width = width * pixelRatio
              this.canvas.height = height * pixelRatio
              this.setData({
                width,
                height,
              })
            }
            
            // 设置初始尺寸
            const initialWidth = info.windowWidth
            const initialHeight = info.windowHeight * 0.8
            calcSize(initialWidth, initialHeight)


            this.initVK()
          })
      },
      onUnload() {
        if (this._texture) {
          this._texture.dispose()
          this._texture = null
        }
        if (this.renderer) {
          this.renderer.dispose()
          this.renderer = null
        }
        if (this.scene) {
          this.scene.dispose()
          this.scene = null
        }
        if (this.camera) this.camera = null
        if (this.model) this.model = null
        if (this._insertModel) this._insertModel = null
        if (this._insertModels) this._insertModels = null
        if (this.planeBox) this.planeBox = null
        if (this.mixers) {
          this.mixers.forEach(mixer => mixer.uncacheRoot(mixer.getRoot()))
          this.mixers = null
        }
        if (this.clock) this.clock = null


        if (this.THREE) this.THREE = null
        if (this._tempTexture && this._tempTexture.gl) {
          this._tempTexture.gl.deleteTexture(this._tempTexture)
          this._tempTexture = null
        }
        if (this._fb && this._fb.gl) {
          this._fb.gl.deleteFramebuffer(this._fb)
          this._fb = null
        }
        if (this._program && this._program.gl) {
          this._program.gl.deleteProgram(this._program)
          this._program = null
        }
        if (this.canvas) this.canvas = null
        if (this.gl) this.gl = null
        if (this.session) this.session = null
        if (this.anchor2DList) this.anchor2DList = []
      },
      initVK() {
        // 首先检查相机权限
        this.checkCameraPermission().then(() => {
          // 权限获取成功后再初始化AR
          this.initARSession()
        }).catch(err => {
          console.error('相机权限检查失败:', err)
          this.setData({
            loading: false,
            loadingText: '相机权限获取失败,请在设置中开启相机权限'
          })
        })
      },
      
      /**
       * 检查相机权限
       */
      checkCameraPermission() {
        return new Promise((resolve, reject) => {
          wx.getSetting({
            success: (res) => {
              console.log('当前权限状态:', res.authSetting)
              
              if (res.authSetting['scope.camera'] === true) {
                // 已授权
                resolve()
              } else if (res.authSetting['scope.camera'] === false) {
                // 已拒绝,需要引导用户手动开启
                this.showCameraPermissionDialog()
                reject(new Error('相机权限被拒绝'))
              } else {
                // 未询问过,尝试授权
                wx.authorize({
                  scope: 'scope.camera',
                  success: () => {
                    console.log('相机权限获取成功')
                    resolve()
                  },
                  fail: (error) => {
                    console.error('相机权限获取失败:', error)
                    this.showCameraPermissionDialog()
                    reject(error)
                  }
                })
              }
            },
            fail: (error) => {
              console.error('获取权限状态失败:', error)
              reject(error)
            }
          })
        })
      },
      
      /**
       * 显示相机权限对话框
       */
      showCameraPermissionDialog() {
        wx.showModal({
          title: '需要相机权限',
          content: 'AR功能需要使用相机权限,请在设置中开启相机权限后重试',
          confirmText: '去设置',
          cancelText: '取消',
          success: (res) => {
            if (res.confirm) {
              wx.openSetting({
                success: (settingRes) => {
                  if (settingRes.authSetting['scope.camera']) {
                    // 用户开启了权限,重新初始化
                    this.initARSession()
                  } else {
                    // 用户仍未开启权限
                    this.setData({
                      loading: false,
                      loadingText: '需要相机权限才能使用AR功能'
                    })
                  }
                }
              })
            } else {
              // 用户选择取消
              this.setData({
                loading: false,
                loadingText: '需要相机权限才能使用AR功能'
              })
            }
          }
        })
      },
      
      /**
       * 初始化AR会话
       */
      initARSession() {
        this.setData({
          loading: true,
          loadingText: '正在初始化AR系统...'
        })
        
        // 初始化 threejs
        this.initTHREE()
        const THREE = this.THREE


        // 自定义初始化
        if (this.init) this.init()


        console.log('this.gl', this.gl)


        const session = this.session = wx.createVKSession({
          track: {
            plane: {
              mode: 1
            },
          },
          version: 'v1',
          gl: this.gl
        })
        session.start(err => {
          if (err) {
            console.error('VK error: ', err)
            this.setData({
              loading: false,
              loadingText: 'AR系统启动失败,请检查设备是否支持AR功能'
            })
            return
          }


          console.log('@@@@@@@@ VKSession.version', session.version)
          
          // AR启动成功,关闭加载状态
          this.setData({
            loading: false,
            loadingText: ''
          })


          const canvas = this.canvas


          const calcSize = (width, height, pixelRatio) => {
            console.log(`canvas size: width = ${width} , height = ${height}`)
            this.canvas.width = width * pixelRatio
            this.canvas.height = height * pixelRatio
            this.setData({
              width,
              height,
            })
          }


          session.on('resize', () => {
            const info = wx.getSystemInfoSync()
            calcSize(info.windowWidth, info.windowHeight * 0.8, info.pixelRatio)
          })


          const loader = new THREE.GLTFLoader()
          
          // 使用 loadModelById 获取模型URL并加载模型
          if (this.data.modelId) {
            this.loadModelById(this.data.modelId).then(modelUrl => {
              console.log('开始加载模型:', modelUrl)
              loader.load(modelUrl, async (gltf) => {
                console.log('模型加载成功:', gltf)
                
                // 先分析材质信息
                this.analyzeMaterials(gltf.scene)
                
                // 使用异步处理材质,避免卡顿
                await this.processMaterialsAsync(gltf.scene)
                
                this.model = {
                  scene: gltf.scene,
                  animations: gltf.animations,
                }
                this.setData({ loading: false })
              }, undefined, (error) => {
                console.error('模型加载失败:', error)
                this.setData({ 
                  loading: false,
                  loadingText: '模型加载失败'
                })
              })
            }).catch(error => {
              console.error('获取模型URL失败:', error)
              this.setData({ 
                loading: false,
                loadingText: '获取模型信息失败'
              })
            })
          } else {
            // 如果没有 modelId,使用默认的机器人模型
            loader.load('https://dldir1.qq.com/weixin/miniprogram/RobotExpressive_aa2603d917384b68bb4a086f32dabe83.glb', gltf => {
              console.log('默认机器人模型加载成功:', gltf)
              
              // 先分析材质信息(在设置光源之前)
              this.analyzeMaterials(gltf.scene)
              
              // 然后处理材质,解决黑色显示问题
              this.processMaterials(gltf.scene)
              
              this.model = {
                scene: gltf.scene,
                animations: gltf.animations,
              }
            }, undefined, (error) => {
              console.error('默认机器人模型加载失败:', error)
            })
          }


          this.clock = new THREE.Clock()


          loader.load('https://dldir1.qq.com/weixin/miniprogram/reticle_4b6cc19698ca4a08b31fd3c95ce412ec.glb', gltf => {
            const reticle = this.reticle = gltf.scene


            reticle.visible = false
            this.scene.add(reticle)
          })


          // 限制调用帧率
          const fps = 30
          const fpsInterval = 1000 / fps
          let last = Date.now()


          // 逐帧渲染
          const onFrame = timestamp => {
            const now = Date.now()
            const mill = now - last
            // 经过了足够的时间
            if (mill > fpsInterval) {
              last = now - (mill % fpsInterval) // 校正当前时间
              const frame = session.getVKFrame(canvas.width, canvas.height)
              if (frame) {
                this.render(frame)
              }
            }
            session.requestAnimationFrame(onFrame)
          }
          session.requestAnimationFrame(onFrame)
        })
      },
      initTHREE() {
        const THREE = this.THREE = createScopedThreejs(this.canvas)
        registerGLTFLoader(THREE)


        // 相机
        this.camera = new THREE.Camera()


        // 场景
        const scene = this.scene = new THREE.Scene()


        // 根据参数设置光照
        // 1. 环境光
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.4) // 强度 40.0 对应 0.4
        scene.add(ambientLight)


        // 2. 三个方向光
        const light0 = new THREE.DirectionalLight(0xffffff, 1.0) // 强度 100.0 对应 1.0
        light0.position.set(1, 1, 1)
        scene.add(light0)


        const light1 = new THREE.DirectionalLight(0xffffff, 1.0)
        light1.position.set(-1, 1, 1)
        scene.add(light1)


        const light2 = new THREE.DirectionalLight(0xffffff, 1.0)
        light2.position.set(0, 1, -1)
        scene.add(light2)


        // 渲染层
        const renderer = this.renderer = new THREE.WebGLRenderer({
          antialias: true,
          alpha: true
        })
        renderer.gammaOutput = true
        renderer.gammaFactor = 2.2
      },
      updateAnimation() {
        const dt = this.clock.getDelta()
        if (this.mixers) this.mixers.forEach(mixer => mixer.update(dt))
      },
      /**
       * 根据模型ID加载模型
       */
      async loadModelById(modelId) {
        try {
          console.log('开始加载模型:', modelId)
          
          this.setData({ 
            loading: true,
            loadingText: '正在获取模型信息...'
          })


          const result = await wx.cloud.callFunction({
            name: 'modelManager',
            data: {
              action: 'detail',
              data: {
                modelId
              }
            }
          })


          if (!result.result || !result.result.success) {
            throw new Error('获取模型信息失败')
          }


          const model = result.result.data
          console.log('模型信息:', model)


          if (!model.fileInfo || !model.fileInfo.downloadUrl) {
            throw new Error('模型文件信息不完整')
          }


          // 检查文件格式
          const fileType = model.fileInfo.fileType?.toLowerCase() || ''
          const fileName = model.fileInfo.downloadUrl.split('/').pop().toLowerCase()
          
          // 检查是否是已知的可能不兼容的格式
          const needsConversion = (
            fileType.includes('fbx') || 
            fileName.endsWith('.fbx') ||
            fileType.includes('obj') || 
            fileName.endsWith('.obj')
          )


          if (needsConversion) {
          this.setData({
              loadingText: '当前模型格式可能不兼容,建议转换为glTF/GLB格式'
          })
            await new Promise(resolve => setTimeout(resolve, 2000))
          }


          this.setData({
            loadingText: '正在下载模型文件...'
          })


          // 返回模型的下载URL
    const url = model.fileInfo.downloadUrl
    


    
    return url
  } catch (error) {
    console.error('加载模型失败:', error)
    this.setData({ 
      loading: false,
      loadingText: error.message || '加载失败'
    })
    throw error
  }
      },
      copyRobot() {
        const THREE = this.THREE
        const {
          scene,
          animations
        } = cloneGltf(this.model, THREE)
        scene.scale.set(0.5, 0.5, 0.5)


        // 动画混合器
        const mixer = new THREE.AnimationMixer(scene)
        // 播放所有可用动画
        animations.forEach(clip => {
          const action = mixer.clipAction(clip);
          action.play();
        })


        // 如果没有动画,添加提示日志
        if (animations.length === 0) {
          console.warn('模型没有找到任何动画数据');
        }


        this.mixers = this.mixers || []
        this.mixers.push(mixer)


        scene._mixer = mixer
        return scene
      },
      getRobot() {
        const THREE = this.THREE


        const model = new THREE.Object3D()
        model.add(this.copyRobot())


        this._insertModels = this._insertModels || []
        this._insertModels.push(model)


        if (this._insertModels.length > 5) {
          const needRemove = this._insertModels.splice(0, this._insertModels.length - 5)
          needRemove.forEach(item => {
            if (item._mixer) {
              const mixer = item._mixer
              this.mixers.splice(this.mixers.indexOf(mixer), 1)
              mixer.uncacheRoot(mixer.getRoot())
            }
            if (item.parent) item.parent.remove(item)
          })
        }
        return model
      },
      onTouchEnd(evt) {
        if (this.scene && this.model && this.reticle) {
          const model = this.getRobot()
          model.position.copy(this.reticle.position)
          model.rotation.copy(this.reticle.rotation)
          this.scene.add(model)
        }
      },
      /**
       * 分析模型材质类型和光照信息
       */
      analyzeMaterials(scene) {
        const THREE = this.THREE
        console.log('=== 开始分析模型材质信息 ===')
        
        let materialCount = 0
        let meshCount = 0
        const materialTypes = new Map()
        
        scene.traverse((child) => {
          if (child.isMesh) {
            meshCount++
            console.log(`--- Mesh ${meshCount}: ${child.name || 'unnamed'} ---`)
            
            if (child.material) {
              const materials = Array.isArray(child.material) ? child.material : [child.material]
              
              materials.forEach((mat, index) => {
                materialCount++
                console.log(`  材质 ${index + 1}:`)
                console.log(`    类型: ${mat.constructor.name}`)
                console.log(`    UUID: ${mat.uuid}`)
                console.log(`    名称: ${mat.name || '未命名'}`)
                
                // 统计材质类型
                const typeName = mat.constructor.name
                materialTypes.set(typeName, (materialTypes.get(typeName) || 0) + 1)
                
                // 基础属性
                console.log(`    透明度: ${mat.opacity}`)
                console.log(`    透明: ${mat.transparent}`)
                console.log(`    可见: ${mat.visible}`)
                console.log(`    双面: ${mat.side === THREE.DoubleSide ? '双面' : '单面'}`)
                
                // 颜色信息
                if (mat.color) {
                  console.log(`    颜色: rgb(${Math.round(mat.color.r * 255)}, ${Math.round(mat.color.g * 255)}, ${Math.round(mat.color.b * 255)})`)
                  console.log(`    颜色十六进制: #${mat.color.getHexString()}`)
                }
                
                // 自发光信息
                if (mat.emissive) {
                  console.log(`    自发光颜色: rgb(${Math.round(mat.emissive.r * 255)}, ${Math.round(mat.emissive.g * 255)}, ${Math.round(mat.emissive.b * 255)})`)
                  console.log(`    自发光强度: ${mat.emissiveIntensity || 'N/A'}`)
                }
                
                // PBR材质特有属性
                if (mat.isMeshStandardMaterial || mat.isMeshPhysicalMaterial) {
                  console.log(`    金属度: ${mat.metalness}`)
                  console.log(`    粗糙度: ${mat.roughness}`)
                  console.log(`    环境光遮蔽强度: ${mat.aoMapIntensity || 'N/A'}`)
                  console.log(`    法线贴图强度: ${mat.normalScale ? `(${mat.normalScale.x}, ${mat.normalScale.y})` : 'N/A'}`)
                }
                
                // 纹理信息
                console.log(`    纹理信息:`)
                if (mat.map) console.log(`      - 基础纹理: ${mat.map.constructor.name}`)
                if (mat.normalMap) console.log(`      - 法线贴图: ${mat.normalMap.constructor.name}`)
                if (mat.emissiveMap) console.log(`      - 自发光贴图: ${mat.emissiveMap.constructor.name}`)
                if (mat.metalnessMap) console.log(`      - 金属贴图: ${mat.metalnessMap.constructor.name}`)
                if (mat.roughnessMap) console.log(`      - 粗糙度贴图: ${mat.roughnessMap.constructor.name}`)
                if (mat.aoMap) console.log(`      - 环境光遮蔽贴图: ${mat.aoMap.constructor.name}`)
                if (mat.envMap) console.log(`      - 环境贴图: ${mat.envMap.constructor.name}`)
                
                // 检查是否是黑色材质
                const isBlack = mat.color && mat.color.getHex() === 0x000000
                const isDark = mat.color && (mat.color.r + mat.color.g + mat.color.b) < 0.3
                
                // 检查自发光属性
                const emissiveExists = mat.emissive !== undefined
                const hasEmissiveColor = emissiveExists && mat.emissive.getHex() !== 0x000000


                console.log(`    材质分析:`)
                console.log(`      - 是否为黑色: ${isBlack}`)
                console.log(`      - 是否偏暗: ${isDark}`)
                console.log(`      - 自发光属性存在: ${emissiveExists}`)
                console.log(`      - 是否有自发光颜色: ${hasEmissiveColor}`)
                console.log(`      - 是否有基础纹理: ${!!mat.map}`)


                // 关键检查:如果emissive是undefined,这就是黑色的主要原因
                if (mat.emissive === undefined) {
                  console.log(`      - ⚠️ 发现问题: mat.emissive 是 undefined,这是导致黑色显示的主要原因`)
                  console.log(`      - 建议处理: 需要创建自发光属性`)
                } else if (!hasEmissiveColor) {
                  console.log(`      - ⚠️ 发现问题: 自发光颜色为黑色,可能导致显示过暗`)
                }


                console.log(`      - 建议处理: ${mat.emissive === undefined ? '需要创建自发光属性' : '材质正常'}`)
                
                console.log(`    ----------`)
              })
            }
          }
        })
        
        // 输出总结信息
        console.log(`=== 材质分析总结 ===`)
        console.log(`网格数量: ${meshCount}`)
        console.log(`材质总数: ${materialCount}`)
        console.log(`材质类型分布:`)
        materialTypes.forEach((count, type) => {
          console.log(`  ${type}: ${count} 个`)
        })
        
        // 分析光照需求
        console.log(`=== 光照需求分析 ===`)
        const hasBasicMaterial = materialTypes.has('MeshBasicMaterial')
        const hasLambertMaterial = materialTypes.has('MeshLambertMaterial')
        const hasPhongMaterial = materialTypes.has('MeshPhongMaterial')
        const hasStandardMaterial = materialTypes.has('MeshStandardMaterial')
        const hasPhysicalMaterial = materialTypes.has('MeshPhysicalMaterial')
        
        console.log(`基础材质(不需要光照): ${hasBasicMaterial ? '是' : '否'}`)
        console.log(`Lambert材质(需要环境光): ${hasLambertMaterial ? '是' : '否'}`)
        console.log(`Phong材质(需要方向光): ${hasPhongMaterial ? '是' : '否'}`)
        console.log(`Standard材质(需要复杂光照): ${hasStandardMaterial ? '是' : '否'}`)
        console.log(`Physical材质(需要物理光照): ${hasPhysicalMaterial ? '是' : '否'}`)
        
        const needsComplexLighting = hasStandardMaterial || hasPhysicalMaterial
        console.log(`是否需要复杂光照系统: ${needsComplexLighting ? '是' : '否'}`)
        
        if (needsComplexLighting) {
          console.log(`推荐光照配置:`)
          console.log(`  - 环境光强度: 0.6-0.8`)
          console.log(`  - 半球光强度: 0.4-0.6`)
          console.log(`  - 主方向光强度: 0.8-1.0`)
          console.log(`  - 补充光强度: 0.3-0.5`)
        }
        
        console.log(`=== 材质分析完成 ===`)
      },
      /**
       * 安全的材质处理方法,防止卡顿
       */
      processMaterials(scene) {
        const THREE = this.THREE
        console.log('=== 开始安全处理材质 ===')
        
        let processedCount = 0
        let fixedEmissiveCount = 0
        let errorCount = 0
        const maxMaterials = 50  // 限制最大处理材质数量
        
        try {
          scene.traverse((child) => {
            if (child.isMesh && child.material && processedCount < maxMaterials) {
              const material = child.material
              
              // 处理材质数组
              const materials = Array.isArray(material) ? material : [material]
              
              materials.forEach((mat, index) => {
                if (processedCount >= maxMaterials) return
                
                try {
                  processedCount++
                  
                  // // 关键检查:如果emissive是undefined,立即修复
                  // if (mat.emissive === undefined) {
                  //   mat.emissive = new THREE.Color(0x000000)  // 先创建黑色自发光
                  //   fixedEmissiveCount++
                  //   console.log(`修复材质 ${processedCount}: 创建自发光属性`)
                  // }
                  
                  // // 确保材质能够接收光照
                  // if (mat.isMeshStandardMaterial || mat.isMeshPhysicalMaterial) {
                    
                  //   // 处理颜色问题
                  //   if (!mat.color || mat.color.getHex() === 0x000000) {
                  //     mat.color = new THREE.Color(0x888888)
                  //   }
                    
                  //   // 安全设置自发光颜色
                  //   if (mat.emissive && mat.color) {
                  //     mat.emissive.copy(mat.color).multiplyScalar(0.3)
                  //   }
                    
                  //   // 处理自发光贴图(只在必要时)
                  //   if (mat.map && !mat.emissiveMap) {
                  //     mat.emissiveMap = mat.map
                  //   }
                    
                  //   // 设置自发光强度
                  //   if (mat.emissiveIntensity !== undefined) {
                  //     mat.emissiveIntensity = Math.max(0.1, mat.emissiveIntensity || 0)
                  //   }
                    
                  // } else {
                  //   // 对于非PBR材质
                  //   if (!mat.color || mat.color.getHex() === 0x000000) {
                  //     mat.color = new THREE.Color(0x888888)
                  //   }
                  // }
                  
                  // // 强制更新材质
                  // mat.needsUpdate = true
                  
                } catch (error) {
                  errorCount++
                  console.error(`处理材质 ${processedCount} 时出错:`, error)
                }
              })
            }
          })
          
          console.log(`=== 材质处理完成 ===`)
          console.log(`处理材质: ${processedCount} 个`)
          console.log(`修复undefined自发光: ${fixedEmissiveCount} 个`)
          console.log(`错误数量: ${errorCount} 个`)
          
          if (processedCount >= maxMaterials) {
            console.warn(`⚠️ 达到最大处理限制 ${maxMaterials},可能还有未处理的材质`)
          }
          
        } catch (error) {
          console.error('材质处理过程中发生严重错误:', error)
        }
      },
      /**
       * 异步材质处理方法,分批处理避免卡顿
       */
      async processMaterialsAsync(scene) {
        const THREE = this.THREE
        console.log('=== 开始异步处理材质 ===')
        
        let processedCount = 0
        let fixedEmissiveCount = 0
        const batchSize = 5  // 每批处理5个材质
        
        const allMaterials = []
        
        // 收集所有材质
        scene.traverse((child) => {
          if (child.isMesh && child.material) {
            const materials = Array.isArray(child.material) ? child.material : [child.material]
            materials.forEach(mat => allMaterials.push(mat))
          }
        })
        
        console.log(`发现 ${allMaterials.length} 个材质,开始分批处理`)
        
        // 分批处理材质
        for (let i = 0; i < allMaterials.length; i += batchSize) {
          const batch = allMaterials.slice(i, i + batchSize)
          
          batch.forEach((mat, index) => {
            try {
              processedCount++
              
              // 关键修复:undefined自发光
              // if (mat.emissive === undefined) {
              //   mat.emissive = new THREE.Color(0x000000)
              //   fixedEmissiveCount++
              // }
              
              // 处理PBR材质
              if (mat.isMeshStandardMaterial || mat.isMeshPhysicalMaterial) {
                if (!mat.color || mat.color.getHex() === 0x000000) {
                  mat.color = new THREE.Color(0x888888)
                }
                
                if (mat.emissive && mat.color) {
                  mat.emissive.copy(mat.color)
                }
                
                if (mat.map && !mat.emissiveMap) {
                  mat.emissiveMap = mat.map
                }
              }
              
              mat.needsUpdate = true
              
            } catch (error) {
              console.error(`处理材质时出错:`, error)
            }
          })
          
          // 每批处理后暂停一下,避免阻塞
          if (i + batchSize < allMaterials.length) {
            await new Promise(resolve => setTimeout(resolve, 10))
          }
        }
        
        console.log(`=== 异步材质处理完成 ===`)
        console.log(`处理材质: ${processedCount} 个`)
        console.log(`修复undefined自发光: ${fixedEmissiveCount} 个`)
      }
    },
  })
}


回答关注问题邀请回答
收藏
登录 后发表内容