开发者工作台

开发者服务统一工作台,切换开发配置、接口文档、小程序、离线下载、CDN 与插件等区块。

1. 页面信息

2. 功能说明

3. 业务说明

权限要求

配置前置

在完成开发者基本信息配置前,切换其他区块会被提示「请先配置完成基本信息后再试」。

平台限制

小程序工作台可用平台取决于账号允许的平台范围;开发版及以上会员不受平台校验限制。

接口与 API 的最低会员档位

「接口文档服务」中的 API 能力按会员版本开放:通过 API 获取作品信息(读)、管理全景作品(写)、提交素材制作全景、接收制作结果通知等接口,均在企业版及以上版本开放(开发版不含)。各版本具体权益以 VIP 会员服务页的权益矩阵实时口径为准。

界面可选值

可选值 取值 说明
开发初始配置 — —
接口文档服务 — —
小程序工作台 — —
全景离线下载 — —
自定义CDN素材 — —
全景插件服务 — —
微信小程序 weixin —
快手小程序 kuaishou —
百度小程序 baidu —
字节小程序 toutiao —
QQ小程序 qq —

<!-- public-api:start -->

开发者公开 API 参考(10 项)

以下为面向开发者公开的正式接口能力,接口地址、请求参数、返回字段与多语言调用示例均来自官方公开文档。运行示例前请把 EXAMPLE_API_KEY / YOUR_WORK_ID / YOUR_MEDIA_ID 等占位符替换为你自己的合法值;POST 接口会产生写入副作用,请勿使用他人密钥或他人作品 ID 反复调用。

1. 使用Api获取作品列表(getVrList())

接口地址
GET https://develop.9kvr.cn/api/develop/listd.html?key=apiKey
请求参数
参数名 类型 必填 说明
key string 是 开发者API密钥
响应示例
{
  "info": {
    "total": 310,
    "per_page": 12,
    "current_page": 1,
    "last_page": 26,
    "data": [
      {
        "work_name": "示例作品",
        "work_profile": "",
        "work_thumb": "https://cdn.example.com/example-pano.jpg",
        "work_createtime": "2025-07-15 22:53:05",
        "work_status": 2,
        "work_makes": 2,
        "work_type": 1,
        "work_viewid": "YOUR_WORK_ID",
        "work_looks": 6,
        "mark_douyin_title": null,
        "mark_kuaishou_title": null,
        "mark_recommend": null,
        "mark_boutique": null,
        "work_xls_id": 1,
        "location_name": null,
        "location_address": null,
        "location_latitude": null,
        "location_longitude": null,
        "work_play": "https://develop.9kvr.cn/tour/index?id=YOUR_WORK_ID&key=EXAMPLE_API_KEY",
        "work_thumb_last": "https://cdn.example.com/example-pano.jpg",
        "mount_title": "示例作品"
      }
    ]
  },
  "msg": "获取成功",
  "code": 1,
  "sparrow": 0,
  "time": 104,
  "ip": "127.0.0.1",
  "version": 2
}
响应参数说明
分页信息 (info)
参数名 类型 说明
total number 总记录数
per_page number 每页显示数量
current_page number 当前页码
last_page number 最后一页页码
data array 作品数据列表
作品信息 (data)
参数名 类型 说明
work_name string 作品名称
work_profile string 作品描述
work_thumb string 作品缩略图
work_createtime string 作品创建时间
work_status number 作品状态
work_makes number 制作状态
work_type number 作品类型
work_viewid string 作品唯一ID
work_looks number 浏览次数
mark_douyin_title string 抖音标题标记
mark_kuaishou_title string 快手标题标记
mark_recommend string 推荐标记
mark_boutique string 精品标记
work_xls_id number 作品关联ID
location_name string 位置名称
location_address string 位置地址
location_latitude string 纬度坐标
location_longitude string 经度坐标
work_play string 作品播放链接
work_thumb_last string 最后缩略图
mount_title string 挂载标题
响应状态
参数名 类型 说明
msg string 响应消息
code number 响应状态码 (1: 成功, 0: 失败)
sparrow number 系统标识
time number 响应时间(毫秒)
ip string 请求IP地址
version number API版本号
状态码说明
状态码 说明
1 成功
0 失败
使用说明
  1. 请确保已获取有效的API密钥
  2. 该接口返回用户的所有全景作品列表
  3. 支持分页查询,默认每页12条记录
  4. 返回数据包含完整的分页信息和作品详情
  5. 作品播放链接可直接用于webview打开

2. 使用Api获取作品详情(getVrDetail())

接口地址
GET https://develop.9kvr.cn/api/develop/info.html?key=apiKey&id=全景ID
请求参数
参数名 类型 必填 说明
key string 是 开发者API密钥
id string 是 全景作品ID
响应示例
{
  "info": {
    "work_name": "示例作品",
    "work_profile": "",
    "work_thumb": "https://cdn.example.com/example-pano.jpg",
    "work_createtime": "2025-07-15 22:53:05",
    "work_status": 2,
    "work_makes": 2,
    "work_type": 1,
    "work_viewid": "YOUR_WORK_ID",
    "work_looks": 6,
    "mark_douyin_title": null,
    "mark_kuaishou_title": null,
    "mark_recommend": null,
    "mark_boutique": null,
    "work_xls_id": 1,
    "location_name": null,
    "location_address": null,
    "location_latitude": null,
    "location_longitude": null,
    "work_play": "https://develop.9kvr.cn/tour/index?id=YOUR_WORK_ID&key=EXAMPLE_API_KEY",
    "work_thumb_last": "https://cdn.example.com/example-pano.jpg",
    "mount_title": "示例作品"
  },
  "msg": "获取成功",
  "code": 1,
  "sparrow": 0,
  "time": 28,
  "ip": "127.0.0.1",
  "version": 2
}
响应参数说明
作品信息 (info)
参数名 类型 说明
work_name string 作品名称
work_profile string 作品描述
work_thumb string 作品缩略图
work_createtime string 作品创建时间
work_status number 作品状态
work_makes number 制作状态
work_type number 作品类型
work_viewid string 作品唯一ID
work_looks number 浏览次数
mark_douyin_title string 抖音标题标记
mark_kuaishou_title string 快手标题标记
mark_recommend string 推荐标记
mark_boutique string 精品标记
work_xls_id number 作品关联ID
location_name string 位置名称
location_address string 位置地址
location_latitude string 纬度坐标
location_longitude string 经度坐标
work_play string 作品播放链接
work_thumb_last string 最后缩略图
mount_title string 挂载标题
响应状态
参数名 类型 说明
msg string 响应消息
code number 响应状态码 (1: 成功, 0: 失败)
sparrow number 系统标识
time number 响应时间(毫秒)
ip string 请求IP地址
version number API版本号
状态码说明
状态码 说明
1 成功
0 失败
使用说明
  1. 通过作品ID获取单个全景作品的详细信息
  2. 包含作品的完整信息,包括基本信息、状态、位置、播放链接等
  3. 可用于小程序或H5页面展示全景内容
  4. 作品播放链接可直接用于webview打开
  5. 支持获取作品的地理位置信息(如果已设置)

3. Webview打开单个全景链接(openWebview())

链接格式
https://develop.9kvr.cn/tour/index?id=作品ID&key=apiKey
参数说明
参数名 类型 必填 说明
id string 是 全景作品ID
key string 是 开发者API密钥
使用场景
  1. 小程序Webview组件:在小程序中使用webview组件打开全景页面
  2. H5页面跳转:在H5页面中直接跳转到全景播放页面
  3. 分享链接:生成可分享的全景查看链接
注意事项
示例代码
// 小程序webview使用示例
<webview src="https://develop.9kvr.cn/tour/index?id=123456&key=your_api_key"></webview>

4. 使用API制作VR全景(createVrPanorama())

接口地址
POST https://develop.9kvr.cn/api/develop/makeTour.html?key=apiKey
请求参数
基础参数
参数名 类型 必填 说明
key string 是 开发者KEY(在开发者配置页面获取)
notifier number 否 是否接受微信模板消息通知, 1 接收, 0 不接收
作品信息 (work) - json 格式
参数名 类型 必填 说明
work_name string 是 作品名称
work_profile string 否 作品介绍
work_private number 否 是否私有, 1 公开, 0 私有
work_password string 否 访问密码, 必须设置为私有才可设置访问密码
素材信息 (media)- json 格式
参数名 类型 必填 说明
imgs_location string 是 VR素材CDN地址
imgs_filename string 是 VR素材名称(最大支持15个字符)
imgs_description string 否 素材介绍(最大支持60个字符)

注意: media数组最大支持20组素材

配置信息 (config) - json 格式
参数名 类型 必填 说明
set_more_menu number 否 显示更多菜单按钮, 1显示(默认), 0 不显示
set_hide_right number 否 隐藏右侧整体导航条, 1显示(默认), 0 不显示
set_title_mask number 否 芊云全景版权小尾巴, 1显示(默认), 0 不显示
work_music string 否 作品全局背景音乐(仅限mp3文件)
入参示例
{
  "work": {
    "work_name": "示例作品",
    "work_profile": "作品介绍",
    "work_private": "是否私有,1 公开 0私有",
    "work_password": "访问密码, 必须设置为私有才可设置访问密码"
  },
  "key": "开发者KEY(在开发者配置页面获取)",
  "media": [
    {
      "imgs_location": "VR素材CDN地址",
      "imgs_filename": "VR素材名称",
      "imgs_description": "素材介绍"
    },
    {
      "imgs_location": "... media数组最大支持20组素材",
      "imgs_filename": "... VR素材名称(名称最大支持15个字符)",
      "imgs_description": "... VR素材介绍(名称最大支持60个字符)"
    }
  ],
  "notifier": "是否接受微信模板消息通知, 1 接收, 0 不接收",
  "config": {
    "set_more_menu": "显示更多菜单按钮; 1显示(默认), 0 不显示",
    "set_hide_right": "隐藏右侧整体导航条; 1显示(默认), 0 不显示",
    "set_title_mask": "芊云全景版权小尾巴: 1显示(默认), 0 不显示",
    "work_music": "作品全局背景音乐(仅限mp3文件)"
  }
}
调用示例代码
Node.js 示例
const axios = require('axios');
const FormData = require('form-data');

async function makeTour() {
  const apiKey = 'your_api_key_here';
  const url = `https://develop.9kvr.cn/api/develop/makeTour.html?key=${apiKey}`;

  const formData = new FormData();

  // 作品信息
  const work = {
    work_name: '我的VR作品',
    work_profile: '这是一个测试VR作品',
    work_private: '1'
  };
  formData.append('work', JSON.stringify(work));

  // 素材信息
  const media = [
    {
      imgs_location: 'https://cdn.example.com/example-pano.jpg',
      imgs_filename: '全景图1',
      imgs_description: '第一个全景场景'
    },
    {
      imgs_location: 'https://cdn.example.com/pano2.jpg',
      imgs_filename: '全景图2',
      imgs_description: '第二个全景场景'
    }
  ];
  formData.append('media', JSON.stringify(media));

  // 通知设置
  formData.append('notifier', '1');

  // 配置信息
  const config = {
    set_more_menu: '1',
    set_hide_right: '1',
    set_title_mask: '1'
  };
  formData.append('config', JSON.stringify(config));

  try {
    const response = await axios.post(url, formData, {
      headers: {
        ...formData.getHeaders(),
        'Origin': 'https://your-domain.com'
      }
    });

    console.log('成功:', response.data);
    return response.data;
  } catch (error) {
    console.error('失败:', error.response ? error.response.data : error.message);
    throw error;
  }
}

makeTour();
PHP 示例
<?php

function makeTour() {
    $apiKey = 'your_api_key_here';
    $url = 'https://develop.9kvr.cn/api/develop/makeTour.html?key=' . $apiKey;

    // 准备表单数据
    $postData = [
        // 作品信息
        'work' => json_encode([
            'work_name' => '我的VR作品',
            'work_profile' => '这是一个测试VR作品',
            'work_private' => '1'
        ]),
        // 素材信息
        'media' => json_encode([
            [
                'imgs_location' => 'https://cdn.example.com/example-pano.jpg',
                'imgs_filename' => '全景图1',
                'imgs_description' => '第一个全景场景'
            ],
            [
                'imgs_location' => 'https://cdn.example.com/pano2.jpg',
                'imgs_filename' => '全景图2',
                'imgs_description' => '第二个全景场景'
            ]
        ]),
        // 通知设置
        'notifier' => '1',
        // 配置信息
        'config' => json_encode([
            'set_more_menu' => '1',
            'set_hide_right' => '1',
            'set_title_mask' => '1'
        ])
    ];

    // 初始化 cURL
    $ch = curl_init();

    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($postData),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Origin: https://your-domain.com',
            'Content-Type: application/x-www-form-urlencoded'
        ]
    ]);

    // 执行请求
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    if (curl_errno($ch)) {
        echo '请求错误: ' . curl_error($ch);
        curl_close($ch);
        return false;
    }

    curl_close($ch);

    // 解析响应
    $result = json_decode($response, true);

    if ($httpCode === 200) {
        echo "成功: \n";
        print_r($result);
        return $result;
    } else {
        echo "失败: HTTP {$httpCode}\n";
        print_r($result);
        return false;
    }
}

makeTour();
?>
Python 示例
import requests

def make_tour():
    import json

    api_key = 'your_api_key_here'
    url = f'https://develop.9kvr.cn/api/develop/makeTour.html?key={api_key}'

    # 准备表单数据
    data = {
        # 作品信息
        'work': json.dumps({
            'work_name': '我的VR作品',
            'work_profile': '这是一个测试VR作品',
            'work_private': '1'
        }),
        # 素材信息
        'media': json.dumps([
            {
                'imgs_location': 'https://cdn.example.com/example-pano.jpg',
                'imgs_filename': '全景图1',
                'imgs_description': '第一个全景场景'
            },
            {
                'imgs_location': 'https://cdn.example.com/pano2.jpg',
                'imgs_filename': '全景图2',
                'imgs_description': '第二个全景场景'
            }
        ]),
        # 通知设置
        'notifier': '1',
        # 配置信息
        'config': json.dumps({
            'set_more_menu': '1',
            'set_hide_right': '1',
            'set_title_mask': '1'
        })
    }

    # 设置请求头
    headers = {
        'Origin': 'https://your-domain.com'
    }

    try:
        # 发送 POST 请求
        response = requests.post(url, data=data, headers=headers)
        response.raise_for_status()

        # 解析响应
        result = response.json()
        print('成功:', result)
        return result

    except requests.exceptions.RequestException as e:
        print(f'请求失败: {e}')
        if hasattr(e, 'response') and e.response is not None:
            print('响应内容:', e.response.text)
        return None

if __name__ == '__main__':
    make_tour()
Java 示例
import com.google.gson.Gson;
import okhttp3.*;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MakeTourExample {

    private static final String API_KEY = "your_api_key_here";
    private static final String API_URL = "https://develop.9kvr.cn/api/develop/makeTour.html?key=" + API_KEY;

    public static void main(String[] args) {
        try {
            makeTour();
        } catch (IOException e) {
            System.err.println("请求失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    public static void makeTour() throws IOException {
        Gson gson = new Gson();

        // 作品信息
        Map<String, String> work = new HashMap<>();
        work.put("work_name", "我的VR作品");
        work.put("work_profile", "这是一个测试VR作品");
        work.put("work_private", "1");
        String workJson = gson.toJson(work);

        // 素材信息
        Map<String, String> media1 = new HashMap<>();
        media1.put("imgs_location", "https://cdn.example.com/example-pano.jpg");
        media1.put("imgs_filename", "全景图1");
        media1.put("imgs_description", "第一个全景场景");

        Map<String, String> media2 = new HashMap<>();
        media2.put("imgs_location", "https://cdn.example.com/pano2.jpg");
        media2.put("imgs_filename", "全景图2");
        media2.put("imgs_description", "第二个全景场景");

        List<Map<String, String>> mediaList = Arrays.asList(media1, media2);
        String mediaJson = gson.toJson(mediaList);

        // 配置信息
        Map<String, String> config = new HashMap<>();
        config.put("set_more_menu", "1");
        config.put("set_hide_right", "1");
        config.put("set_title_mask", "1");
        String configJson = gson.toJson(config);

        // 构建表单数据
        RequestBody formBody = new FormBody.Builder()
                .add("work", workJson)
                .add("media", mediaJson)
                .add("notifier", "1")
                .add("config", configJson)
                .build();

        // 创建请求
        Request request = new Request.Builder()
                .url(API_URL)
                .post(formBody)
                .addHeader("Origin", "https://your-domain.com")
                .build();

        // 发送请求
        OkHttpClient client = new OkHttpClient();
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful() && response.body() != null) {
                String responseBody = response.body().string();
                System.out.println("成功: " + responseBody);

                // 解析响应
                @SuppressWarnings("unchecked")
                Map<String, Object> result = gson.fromJson(responseBody, Map.class);
                System.out.println("返回码: " + result.get("code"));
                System.out.println("消息: " + result.get("msg"));
            } else {
                System.err.println("请求失败: HTTP " + response.code());
                if (response.body() != null) {
                    System.err.println("响应内容: " + response.body().string());
                }
            }
        }
    }
}

依赖配置 (Maven):

<dependencies>
    <!-- OkHttp -->
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.12.0</version>
    </dependency>

    <!-- Gson -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.10.1</version>
    </dependency>
</dependencies>

依赖配置 (Gradle):

dependencies {
    implementation 'com.squareup.okhttp3:okhttp:4.12.0'
    implementation 'com.google.code.gson:gson:2.10.1'
}
返回示例
成功响应
{
  "info": {
    "work_id": "作品Id"
  },
  "msg": "投递成功",
  "code": 1
}
失败响应
{
  "info": {},
  "msg": "投递失败的原因",
  "code": 0
}
回调通知
成功回调
{
  "info": {
    "work_id": "作品Id",
    "media": {
      "imgs_filename": "素材名称",
      "imgs_thumb": "素材预览图",
      "imgs_id": "素材ID",
      "imgs_web_link": "素材预览链接",
      "imgs_mini_link": "小程序预览链接"
    },
    "link": {
      "web": "网页链接",
      "mini": "小程序链接"
    },
    "work": {
      "work_thumb": "全景作品封面",
      "work_uid": "开发者 UID",
      "work_viewid": "YOUR_WORK_ID"
    }
  },
  "msg": "全景制作完成",
  "code": 1
}
失败回调
{
  "info": {},
  "msg": "全景制作失败的原因",
  "code": 0
}
注意事项

⚠️ 重要提醒:

状态码说明
状态码 说明
1 成功
0 失败

5. 发布全景素材(makeMedia())

接口地址
POST https://develop.9kvr.cn/api/develop/makeMedia.html?key=apiKey
请求参数
基础参数
参数名 类型 必填 说明
key string 是 开发者KEY(在开发者配置页面获取)
素材信息 (media) - json 格式
参数名 类型 必填 说明
imgs_location string 是 VR素材CDN地址
imgs_filename string 否 VR素材名称(最大支持15个字符, 默认"来自API素材")
imgs_description string 否 素材介绍(最大支持60个字符, 默认"来自API素材")

注意: media 可传单个对象或数组, 数组最大支持20组素材 注意: 仅生成素材, 不创建全景作品, 如需制作作品请使用 使用API制作VR全景

入参示例
单个素材
{
  "media": {
    "imgs_location": "https://cdn.example.com/pano.jpg",
    "imgs_filename": "全景素材1",
    "imgs_description": "我的第一个全景素材"
  }
}
多个素材
{
  "media": [
    {
      "imgs_location": "https://cdn.example.com/pano1.jpg",
      "imgs_filename": "全景素材1",
      "imgs_description": "第一个全景素材"
    },
    {
      "imgs_location": "https://cdn.example.com/pano2.jpg",
      "imgs_filename": "全景素材2",
      "imgs_description": "第二个全景素材"
    }
  ]
}
调用示例代码
Node.js 示例
const axios = require('axios');

async function makeMedia() {
  const apiKey = 'your_api_key_here';
  const url = `https://develop.9kvr.cn/api/develop/makeMedia.html?key=${apiKey}`;

  const formData = new FormData();

  // 素材信息(单个对象或数组)
  const media = [
    {
      imgs_location: 'https://cdn.example.com/pano1.jpg',
      imgs_filename: '全景素材1',
      imgs_description: '第一个全景素材'
    },
    {
      imgs_location: 'https://cdn.example.com/pano2.jpg',
      imgs_filename: '全景素材2',
      imgs_description: '第二个全景素材'
    }
  ];
  formData.append('media', JSON.stringify(media));

  try {
    const response = await axios.post(url, formData, {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    });
    console.log('成功:', response.data);
    return response.data;
  } catch (error) {
    console.error('失败:', error.response ? error.response.data : error.message);
    throw error;
  }
}

makeMedia();
Python 示例
import requests
import json

def make_media():
    api_key = 'your_api_key_here'
    url = f'https://develop.9kvr.cn/api/develop/makeMedia.html?key={api_key}'

    # 素材信息(单个对象或数组)
    media = [
        {
            'imgs_location': 'https://cdn.example.com/pano1.jpg',
            'imgs_filename': '全景素材1',
            'imgs_description': '第一个全景素材'
        }
    ]

    data = {
        'media': json.dumps(media, ensure_ascii=False)
    }

    try:
        response = requests.post(url, data=data)
        response.raise_for_status()
        result = response.json()
        print('成功:', result)
        return result
    except requests.exceptions.RequestException as e:
        print(f'请求失败: {e}')
        return None

if __name__ == '__main__':
    make_media()
返回示例
成功响应
{
  "code": 1,
  "msg": "发布素材成功",
  "info": {
    "media_id": [10001]
  }
}
失败响应
{
  "code": 0,
  "msg": "发布素材失败的原因",
  "info": {}
}
注意事项

⚠️ 重要提醒:

状态码说明
状态码 说明
1 成功
0 失败

6. 通过素材库制作VR全景(makeTourByMedia())

接口地址
POST https://develop.9kvr.cn/api/develop/makeTourByMedia.html?key=apiKey
请求参数
基础参数
参数名 类型 必填 说明
key string 是 开发者KEY(在开发者配置页面获取)
作品信息 (work) - json 格式
参数名 类型 必填 说明
work_name string 是 作品名称
work_profile string 否 作品介绍
work_music string 否 作品全局背景音乐(仅限mp3文件)
素材信息 (media) - json 格式
参数名 类型 必填 说明
imgs_workid string 是 素材ID(来自 发布全景素材 或 查询素材列表)

注意:

  • media 可传单个对象或数组, 数组最大支持20组素材
  • 素材必须是当前开发者账号下已发布的素材, 且素材制作已完成
  • 该接口直接使用素材库已有的成品素材制作作品, 无需再传CDN地址
入参示例
{
  "work": {
    "work_name": "示例作品",
    "work_profile": "作品介绍"
  },
  "key": "开发者KEY(在开发者配置页面获取)",
  "media": [
    {
      "imgs_workid": "YOUR_MEDIA_ID"
    },
    {
      "imgs_workid": "YOUR_MEDIA_ID"
    }
  ]
}
调用示例代码
Node.js 示例
const axios = require('axios');

async function makeTourByMedia() {
  const apiKey = 'your_api_key_here';
  const url = `https://develop.9kvr.cn/api/develop/makeTourByMedia.html?key=${apiKey}`;

  const formData = new FormData();
  formData.append('work', JSON.stringify({
    work_name: '我的作品',
    work_profile: '作品介绍'
  }));
  // 素材ID列表(来自素材列表接口, 值为 imgs_workid)
  formData.append('media', JSON.stringify([
    { imgs_workid: 'YOUR_MEDIA_ID' },
    { imgs_workid: 'YOUR_MEDIA_ID' }
  ]));

  try {
    const response = await axios.post(url, formData, {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    });
    console.log('成功:', response.data);
    return response.data;
  } catch (error) {
    console.error('失败:', error.response ? error.response.data : error.message);
    throw error;
  }
}

makeTourByMedia();
返回示例
成功响应
{
  "code": 1,
  "msg": "制作成功",
  "info": "作品viewid"
}
失败响应
{
  "code": 0,
  "msg": "发布失败的原因",
  "info": []
}
注意事项

⚠️ 重要提醒:

7. 查询素材列表(getMediaList())

接口地址
POST https://develop.9kvr.cn/api/develop/getMediaList.html?key=apiKey
请求参数
基础参数
参数名 类型 必填 说明
key string 是 开发者KEY(在开发者配置页面获取)
page number 否 页码, 默认1
limit number 否 每页数量, 默认12
status number 否 素材状态, 0全部(默认), 1制作中, 2制作完成
keyword string 否 素材名称关键词搜索
入参示例
POST ?key=apiKey&page=1&limit=12&status=0
调用示例代码
Node.js 示例
const axios = require('axios');

async function getMediaList() {
  const apiKey = 'your_api_key_here';
  const url = `https://develop.9kvr.cn/api/develop/getMediaList.html?key=${apiKey}`;

  const formData = new FormData();
  formData.append('page', '1');
  formData.append('limit', '12');
  formData.append('status', '0');

  try {
    const response = await axios.post(url, formData, {
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    });
    console.log('成功:', response.data);
    return response.data;
  } catch (error) {
    console.error('失败:', error.response ? error.response.data : error.message);
    throw error;
  }
}

getMediaList();
返回示例
成功响应
{
  "code": 1,
  "msg": "获取成功",
  "info": {
    "list": [
      {
        "id": "YOUR_MEDIA_ID",
        "imgs_workid": "YOUR_MEDIA_ID",
        "imgs_filename": "客厅全景",
        "imgs_description": "客厅裸眼全景图",
        "imgs_location": "https://cdn.example.com/panorama.jpg",
        "imgs_thumb": "https://cdn.example.com/example-pano.jpg",
        "imgs_size": 2.5,
        "imgs_width": 8400,
        "imgs_height": 4100,
        "imgs_status": 2,
        "imgs_type": 1,
        "imgs_version": 1,
        "imgs_slice_type": 1,
        "imgs_createtime": "2026-08-08 10:00:00"
      }
    ],
    "page": 1,
    "limit": 12,
    "total": 30,
    "total_page": 3
  }
}
失败响应
{
  "code": 0,
  "msg": "权限验证失败,请检查key是否正确",
  "info": []
}
返回字段说明
字段 类型 说明
id string 素材ID(与 imgs_workid 相同, 制作作品时使用)
imgs_workid string 素材对外ID(无规律字符串)
imgs_filename string 素材名称
imgs_description string 素材介绍
imgs_thumb string 素材缩略图(可直接访问的完整URL)
imgs_size number 素材大小(M)
imgs_width number 素材宽度
imgs_height number 素材高度
imgs_status number 素材状态, 1制作中, 2制作完成
imgs_type number 素材类型, 1全景图片
imgs_version number 素材版本
imgs_slice_type number 素材切片类型
imgs_createtime string 素材创建时间
注意事项

⚠️ 重要提醒:

8. 使用小程序跳转打开全景(navigateToMiniProgram())

平台介绍

芊云全景作为一个开放性较强的全景开发平台,我们也赋予了平台一直开发者支持。下面简单介绍一下其他小程序打开芊云全景小程序的方案。

兼容性说明
基础库支持
小程序信息
信息类型 值 说明
AppID wx9f77d65eb4eff65b 芊云全景小程序AppID
环境版本 release 正式环境
页面路径
页面类型 路径 说明
小程序首页 pages/index/index 小程序主页面
全景加载页面 pages/tour/wait?id=全景ID 全景加载等待页面
全景播放器详情页 pages/tour/index?id=全景ID 全景播放器页面
个人主页 pages/index/home?id=自己UID 用户个人主页
跳转方式
基础跳转
wx.navigateToMiniProgram({
  appId: 'wx9f77d65eb4eff65b',
  path: 'pages/index/index',
  extraData: {},
  envVersion: 'release',
  success(res) {
    console.log('打开成功');
  },
  fail(err) {
    console.error('打开失败', err);
  }
});
带参数跳转(当前暂未启用)

⚠️ 注意: 当前暂未启用,也许在后续某个版本启用

直接打开播放器详情页面,需要携带芊云全景提供的 secretKey 参数,否则即使打开,也会强制跳转到加载页面。

wx.navigateToMiniProgram({
  appId: 'wx9f77d65eb4eff65b',
  path: 'pages/tour/wait?id=全景ID',
  extraData: {
    secretKey: '开发者服务页面获取',
    appName: '您自己小程序名称'
  },
  envVersion: 'release',
  success(res) {
    console.log('打开成功');
  },
  fail(err) {
    console.error('打开失败', err);
  }
});
参数说明
跳转参数 (extraData)
参数名 类型 必填 说明
secretKey string 否 开发者服务页面获取的密钥(当前暂未启用)
appName string 否 您自己小程序名称,携带后若返回小程序则显示来源小程序名称,否则只显示"返回来源小程序"
返回参数 (extraData)
参数名 类型 说明
comeBack string 固定值 'vr29'
id string 打开全景的ID
返回来源小程序
芊云全景逻辑处理

若是来自其他小程序,等待页面的"返回"或者"查看更多全景"将变为"返回来源小程序",返回来源小程序后携带参数如下:

wx.navigateBackMiniProgram({
  extraData: {
    comeBack: 'vr29',
    id: '打开全景的ID'
  },
  success(res) {
    console.log('返回成功');
  },
  fail(err) {
    console.error('返回失败', err);
  }
});
开发者集成
获取来源参数

开发者可以自行在自己小程序的生命周期内获取来源参数!

// 在小程序页面中获取来源参数
onLoad(options) {
  if (options.comeBack === 'vr29') {
    console.log('来自芊云全景小程序');
    console.log('全景ID:', options.id);
  }
}
注意事项
  1. 需要在小程序后台配置跳转关系
  2. 确保secretKey有效且具有跳转权限(当前暂未启用)
  3. 建议在跳转前检查用户登录状态
  4. 支持传递自定义参数到全景页面
  5. 注意基础库版本兼容性
  6. 开发者可以自行处理返回参数
相关文档

9. 芊云全景打开半屏小程序VR(openEmbeddedMiniProgram())

功能说明

在芊云全景H5页面中,可以打开半屏小程序来展示VR内容,提供更好的用户体验。

重要提醒

⚠️ 注意: 自己小程序打开芊云全景为半屏小程序目前可以免费使用。 但是若直接打开全景播放器(pages/tour/index)有广告,跳转其他页面无广告。 开通 VIP 可去除所有广告,其他流程均不受影响。

配置步骤
1. 添加小程序权限

在小程序后台申请半屏能力,添加芊云全景小程序。

2. 搜索并添加小程序
小程序页面路径
页面类型 路径 说明
小程序首页 pages/index/index 小程序主页面
全景加载页面 pages/tour/wait?id=全景ID 全景加载等待页面
全景播放器详情页 pages/tour/index?id=全景ID 全景播放器页面
个人主页 pages/index/home?id=自己UID 用户个人主页
接入代码示例
打开半屏小程序
wx.openEmbeddedMiniProgram({
  appId: 'wx9f77d65eb4eff65b',
  path: 'pages/tour/index?id=全景ID',
  extraData: {
    secretKey: '开发者服务页面获取',
    appName: '您自己小程序名称'
  },
  envVersion: 'release',
  success(res) {
    console.log('打开半屏小程序成功');
  },
  fail(err) {
    console.error('打开失败', err);
  }
});
返回来源小程序
wx.navigateBackMiniProgram({
  extraData: {
    comeBack: 'vr29',
    id: '打开全景的ID'
  },
  success(res) {
    console.log('返回成功');
  },
  fail(err) {
    console.error('返回失败', err);
  }
});
参数说明
打开参数 (extraData)
参数名 类型 必填 说明
secretKey string 是 开发者服务页面获取的密钥
appName string 否 您自己小程序名称,携带后若返回小程序则显示来源小程序名称,否则只显示"返回来源小程序"
返回参数 (extraData)
参数名 类型 说明
comeBack string 固定值 'vr29'
id string 打开全景的ID
获取参数方法
如何获取全景ID

打开任意一个作品获取 id=xxx,其中的 xxx 就是全景ID

如何获取 secretKey

在芊云开发者服务平台获取开发者密钥

逻辑处理说明
芊云全景逻辑处理

若是来自其他小程序,等待页面的"返回"或者"查看更多全景"将变为"返回来源小程序",返回来源小程序后携带参数如上所示。

注意事项
  1. 半屏小程序需要特殊申请和审核
  2. 建议在小程序中提供返回按钮
  3. 注意半屏小程序的尺寸限制
  4. 确保H5页面和小程序的数据同步
  5. 直接打开播放器详情页面,需要携带芊云全景提供的 secretKey 参数,否则即使打开,也会强制跳转到加载页面
相关文档

10. 使用iframe打开全景(embedIframe())

功能说明

使用iframe标签在网页中嵌入芊云全景播放器,实现无缝的全景展示体验。

基础用法
简单iframe嵌入
<iframe 
  src="https://develop.9kvr.cn/tour/index?id=全景ID&key=apiKey" 
  width="100%" 
  height="600px" 
  frameborder="0">
</iframe>
全屏无边框iframe
<iframe 
  src="https://develop.9kvr.cn/tour/index?id=全景ID&key=apiKey" 
  style="width: 100vw; height: 100vh; border: none; position: fixed; top: 0; left: 0; z-index: 9999;">
</iframe>
参数说明
iframe属性
属性名 类型 必填 说明
src string 是 全景播放器URL
width string 否 宽度,建议使用100%或100vw
height string 否 高度,建议使用100vh实现全屏
frameborder string 否 边框,建议设置为"0"或"no"
scrolling string 否 滚动条,建议设置为"no"
URL参数
参数名 类型 必填 说明
id string 是 全景作品ID
key string 是 开发者API密钥
样式配置
基础样式
.vr-iframe {
  width: 100%;
  height: 600px;
  border: none;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
全屏样式
.vr-iframe-fullscreen {
  width: 100vw;
  height: 100vh;
  border: none;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9999;
  background: #000;
}
响应式样式
.vr-iframe-responsive {
  width: 100%;
  height: 0;
  padding-bottom: 56.25%; /* 16:9 宽高比 */
  position: relative;
  border: none;
}

.vr-iframe-responsive iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
完整示例
HTML结构
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>全景展示</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: Arial, sans-serif;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }

        .vr-iframe {
            width: 100%;
            height: 600px;
            border: none;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        }

        .fullscreen-btn {
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 10000;
            padding: 10px 20px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }

        .fullscreen-iframe {
            width: 100vw;
            height: 100vh;
            border: none;
            position: fixed;
            top: 0;
            left: 0;
            z-index: 9999;
            background: #000;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>全景展示</h1>
        <iframe 
            id="vrIframe"
            class="vr-iframe"
            src="https://develop.9kvr.cn/tour/index?id=全景ID&key=apiKey">
        </iframe>
    </div>

    <button class="fullscreen-btn" onclick="toggleFullscreen()">全屏显示</button>

    <script>
        function toggleFullscreen() {
            const iframe = document.getElementById('vrIframe');
            if (iframe.classList.contains('fullscreen-iframe')) {
                iframe.classList.remove('fullscreen-iframe');
                iframe.classList.add('vr-iframe');
            } else {
                iframe.classList.remove('vr-iframe');
                iframe.classList.add('fullscreen-iframe');
            }
        }

        // 监听ESC键退出全屏
        document.addEventListener('keydown', function(e) {
            if (e.key === 'Escape') {
                const iframe = document.getElementById('vrIframe');
                if (iframe.classList.contains('fullscreen-iframe')) {
                    toggleFullscreen();
                }
            }
        });
    </script>
</body>
</html>
移动端适配
移动端样式
@media screen and (max-width: 768px) {
    .vr-iframe {
        height: 400px;
    }

    .fullscreen-iframe {
        width: 100vw;
        height: 100vh;
    }
}
注意事项

⚠️ 重要提醒:

常见问题
Q: iframe无法加载怎么办?

A: 检查URL参数是否正确,确保网络连接正常,查看浏览器控制台错误信息。

Q: 如何实现自适应高度?

A: 可以使用JavaScript监听iframe内容高度变化,动态调整iframe高度。

Q: 如何去除iframe边框?

A: 设置frameborder="0"和CSS中的border: none。

Q: 全屏模式下如何退出?

A: 可以监听ESC键或添加退出按钮,切换CSS类名即可。

相关文档

<!-- public-api:end -->

4. 使用说明

  1. 登录后进入开发者工作台
  2. 在「开发初始配置」中完成基本信息配置
  3. 切换到接口文档、小程序工作台、离线下载等区块
  4. 如需自定义 CDN 素材,先开通开发版及以上会员

5. 规则与限制

6. 状态与异常

7. 相关文档

目录导航

同目录文档(5)

相关主题

8. 文档信息