{"_id":"@cqsjjb/website-platform-sdk","_rev":"6-be83e70a01e5b36678071d7efc222aac","name":"@cqsjjb/website-platform-sdk","dist-tags":{"beta":"1.0.0","latest":"1.0.5"},"versions":{"1.0.0":{"name":"@cqsjjb/website-platform-sdk","version":"1.0.0","author":"","license":"ISC","_id":"@cqsjjb/website-platform-sdk@1.0.0","maintainers":[{"name":"cqjjb","email":"995934055@qq.com"}],"dist":{"shasum":"8dafac23e40eaec8f80efe27f3be493560ca5c6f","tarball":"https://registry.npmjs.org/@cqsjjb/website-platform-sdk/-/website-platform-sdk-1.0.0.tgz","fileCount":30,"integrity":"sha512-wDavTQuPjSnvW4eKq4Ult+QAHjFEPr7BJFx0yexpF3RdRJ99RHNxB1DhLyuYyFq2EIPYpB0mANefLMd64fe8Wg==","signatures":[{"sig":"MEUCIQDVDyuAtpqC3M1B7kLxjsEhLRqxXluqnPhsV29N61sLHAIgRLu/drz0+O2ww+T5CTHKcQK4eIArWu8a2zBGEJet3Ps=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":312895},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"f49d7fb87dd228b6cfeba5aa5c397637f12c606e","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"rimraf dist && tsc --emitDeclarationOnly && esbuild src/index.ts --bundle --format=esm --platform=browser --sourcemap --outfile=dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"cqjjb","email":"995934055@qq.com"},"repository":{"url":"http://192.168.1.242:10985/jjb.web/cqsjjb/website-platform-sdk.git","type":"git"},"_npmVersion":"10.8.2","description":"Website platform iframe SDK (open auth, SM2 config)","directories":{},"_nodeVersion":"20.19.0","dependencies":{"sm-crypto":"^0.3.13"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rimraf":"^6.0.1","esbuild":"^0.25.0","typescript":"~5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/website-platform-sdk_1.0.0_1776248916994_0.12419035331046913","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@cqsjjb/website-platform-sdk","version":"1.0.1","author":"","license":"ISC","_id":"@cqsjjb/website-platform-sdk@1.0.1","maintainers":[{"name":"cqjjb","email":"995934055@qq.com"}],"dist":{"shasum":"dd2ae1fcb2523c0e66dfa8b25155382a7b13e417","tarball":"https://registry.npmjs.org/@cqsjjb/website-platform-sdk/-/website-platform-sdk-1.0.1.tgz","fileCount":30,"integrity":"sha512-sMmUZnbalM3yNzjh7d4UqO1w37hpEEHHg54coCfwyUOCQCrBTwCDvS6vDYzcGRYX4w2GyMbFJ7/bu+aWVAcMvw==","signatures":[{"sig":"MEQCIE5FYq3L0zlepSp/kpT559UKU5r4+Rbc3uPizUMgV1rNAiA9g7HrBCW8LdIHj6G6M5OxQjYSqLczUhK8YEiQ3nQraA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":313715},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"c8a31f4318e98738137268c1739669f506c81b34","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"rimraf dist && tsc --emitDeclarationOnly && esbuild src/index.ts --bundle --format=esm --platform=browser --sourcemap --outfile=dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"cqjjb","email":"995934055@qq.com"},"repository":{"url":"http://192.168.1.242:10985/15023122306/website-platform-sdk","type":"git"},"_npmVersion":"10.8.2","description":"Website platform iframe SDK (open auth, SM2 config)","directories":{},"_nodeVersion":"20.19.0","dependencies":{"sm-crypto":"^0.3.13"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rimraf":"^6.0.1","esbuild":"^0.25.0","typescript":"~5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/website-platform-sdk_1.0.1_1776303854217_0.029522726138792255","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@cqsjjb/website-platform-sdk","version":"1.0.2","author":"","license":"ISC","_id":"@cqsjjb/website-platform-sdk@1.0.2","maintainers":[{"name":"cqjjb","email":"995934055@qq.com"}],"dist":{"shasum":"e266bdffddce959c2002b1e796195a5cc82e44f7","tarball":"https://registry.npmjs.org/@cqsjjb/website-platform-sdk/-/website-platform-sdk-1.0.2.tgz","fileCount":30,"integrity":"sha512-A9X6KlqVzZtdeOVVilvKoghBlx9axBEt3Tz6DhmgtdEWrktN9bs5uRK9nU/4ThEgkyEr8Tz/a3EInhyDlr0CYw==","signatures":[{"sig":"MEUCIBf863JKf/o6Vkj0LuaYdR6dtCCFQkjzSLVdtRI0cQd+AiEAzF5yM0vxsOOoTWroUgyH7PryWlGQini058+KGvF3Pgo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":315158},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"2c9a080457facc2fc730635ab70b4fb495be5952","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"rimraf dist && tsc --emitDeclarationOnly && esbuild src/index.ts --bundle --format=esm --platform=browser --sourcemap --outfile=dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"cqjjb","email":"995934055@qq.com"},"repository":{"url":"http://192.168.1.242:10985/15023122306/website-platform-sdk","type":"git"},"_npmVersion":"10.8.2","description":"Website platform iframe SDK (open auth, SM2 config)","directories":{},"_nodeVersion":"20.19.0","dependencies":{"sm-crypto":"^0.3.13"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rimraf":"^6.0.1","esbuild":"^0.25.0","typescript":"~5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/website-platform-sdk_1.0.2_1776735796063_0.3679373891136688","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@cqsjjb/website-platform-sdk","version":"1.0.3","author":"","license":"ISC","_id":"@cqsjjb/website-platform-sdk@1.0.3","maintainers":[{"name":"cqjjb","email":"995934055@qq.com"}],"dist":{"shasum":"f43db2b7b85bee6d7f3c11b84487f2fdc112b363","tarball":"https://registry.npmjs.org/@cqsjjb/website-platform-sdk/-/website-platform-sdk-1.0.3.tgz","fileCount":30,"integrity":"sha512-xixeUkD1QLouJORMtUMzNzpLFsxah9eehCybsn5OxwiTjt1dSvNIOWqvLN8dtlu+c53AhKkcLtF29EDv0onizg==","signatures":[{"sig":"MEUCIDskJSVoNdGEH2E8fub2CaftO0qE+7+PTozba/b2nLUNAiEAnCALLClsmjwsw1/lBL5LQwfHgoin4aSU5eQdONIRAVU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":315178},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"048611a4220cb4eb1f6242f45a12d238cec06016","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"rimraf dist && tsc --emitDeclarationOnly && esbuild src/index.ts --bundle --format=esm --platform=browser --sourcemap --outfile=dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"cqjjb","email":"995934055@qq.com"},"repository":{"url":"http://192.168.1.242:10985/15023122306/website-platform-sdk","type":"git"},"_npmVersion":"10.8.2","description":"Website platform iframe SDK (open auth, SM2 config)","directories":{},"_nodeVersion":"20.19.0","dependencies":{"sm-crypto":"^0.3.13"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rimraf":"^6.0.1","esbuild":"^0.25.0","typescript":"~5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/website-platform-sdk_1.0.3_1776762123210_0.3232683023988687","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@cqsjjb/website-platform-sdk","version":"1.0.4","author":"","license":"ISC","_id":"@cqsjjb/website-platform-sdk@1.0.4","maintainers":[{"name":"cqjjb","email":"995934055@qq.com"}],"dist":{"shasum":"f58ce107d823f34aac409545d1d9f213454c8632","tarball":"https://registry.npmjs.org/@cqsjjb/website-platform-sdk/-/website-platform-sdk-1.0.4.tgz","fileCount":30,"integrity":"sha512-VDUk8jNB62ol31WJ0LCezwQPP0A48NG+8fH7u0Ymls6yUOxgZRrblVgMxrd9e3AZNbuIB8FyifiTx5GgX8Sqcw==","signatures":[{"sig":"MEUCIQDUAlLEgyZFYOuJqkmQS39UW51qa6KLEJgwVLLdEXUoGwIgEabtyBfR8hhrWk/78fxs3pl7+blOfzHMuD21DMu1MWo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":319471},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"e40542e24efbdf92470ab676d6d8efeb0ebdcf2d","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"rimraf dist && tsc --emitDeclarationOnly && esbuild src/index.ts --bundle --format=esm --platform=browser --sourcemap --outfile=dist/index.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"cqjjb","email":"995934055@qq.com"},"repository":{"url":"http://192.168.1.242:10985/15023122306/website-platform-sdk","type":"git"},"_npmVersion":"10.8.2","description":"Website platform iframe SDK (open auth, SM2 config)","directories":{},"_nodeVersion":"20.19.0","dependencies":{"sm-crypto":"^0.3.13"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"rimraf":"^6.0.1","esbuild":"^0.25.0","typescript":"~5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/website-platform-sdk_1.0.4_1776910757270_0.01328819914732482","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@cqsjjb/website-platform-sdk","version":"1.0.5","description":"Website platform iframe SDK (open auth, SM2 config)","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"scripts":{"build":"rimraf dist && tsc --emitDeclarationOnly && esbuild src/index.ts --bundle --format=esm --platform=browser --sourcemap --outfile=dist/index.js","prepublishOnly":"npm run build","test":"echo \"Error: no test specified\" && exit 1"},"repository":{"type":"git","url":"http://192.168.1.242:10985/15023122306/website-platform-sdk"},"author":"","license":"ISC","publishConfig":{"access":"public"},"dependencies":{"sm-crypto":"^0.3.13"},"devDependencies":{"esbuild":"^0.25.0","rimraf":"^6.0.1","typescript":"~5.7.2"},"_id":"@cqsjjb/website-platform-sdk@1.0.5","gitHead":"14bd616dc41bdd9015173c42f598d7ae059a3784","_nodeVersion":"20.19.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-thfQYkxS0lDef5hKZaMPtopfomMc7W2FUTkdfIR2urwythxtv+iLaCNCzqH5tzOMJNL++RrzI/eZiZTEKwHdJA==","shasum":"382b8abc3d08bebd9c8e11030e95ef80541f23b0","tarball":"https://registry.npmjs.org/@cqsjjb/website-platform-sdk/-/website-platform-sdk-1.0.5.tgz","fileCount":30,"unpackedSize":331956,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFo+Gb+tmkQALr6+PlQKSLR6EnYJMnk1XXmmswsZioycAiEAmJ4ttJWw4LpNH2Ox2qU4IDAXr/WmbEaInG35NbUl7FU="}]},"_npmUser":{"name":"cqjjb","email":"995934055@qq.com"},"directories":{},"maintainers":[{"name":"cqjjb","email":"995934055@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/website-platform-sdk_1.0.5_1776998186828_0.2148414140570989"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-15T10:28:36.933Z","modified":"2026-04-24T02:36:27.109Z","1.0.0":"2026-04-15T10:28:37.146Z","1.0.1":"2026-04-16T01:44:14.355Z","1.0.2":"2026-04-21T01:43:16.205Z","1.0.3":"2026-04-21T09:02:03.355Z","1.0.4":"2026-04-23T02:19:17.418Z","1.0.5":"2026-04-24T02:36:26.987Z"},"license":"ISC","repository":{"type":"git","url":"http://192.168.1.242:10985/15023122306/website-platform-sdk"},"description":"Website platform iframe SDK (open auth, SM2 config)","maintainers":[{"name":"cqjjb","email":"995934055@qq.com"}],"readme":"# @cqsjjb/website-platform-sdk\r\n\r\n在业务页面中嵌入**建站站点**（建站系统页面）的浏览器端 SDK：通过开放账号接口完成用户鉴权（含 SM2 加密 `config`），并在页面容器内挂载 `iframe`，加载建站预览页；新用户会先出现**授权确认**，再继续创建账号。\r\n\r\n---\r\n\r\n## 特性\r\n\r\n- **ESM**：适用于 Vite、Webpack 5、Create React App（配合配置）等现代打包工具，或原生 `<script type=\"module\">`。\r\n- **TypeScript**：提供类型声明，便于在 TS 项目中获得提示。\r\n- **开放账号流程**：`getUserInfo` →（无用户数据则）**授权弹窗** → `createUser` → 拼接 iframe 地址并挂载。\r\n- **事件回调**：鉴权各阶段、授权确认/取消、挂载/卸载均可订阅。\r\n- **依赖**：`sm-crypto` 会随本包安装，用于对 `config` 做 SM2 加密，无需再单独引入 CDN 版本。\r\n\r\n---\r\n\r\n## 环境要求\r\n\r\n- **浏览器**（需 `fetch`、`document`、iframe 等 DOM API）。\r\n- 建议使用 **HTTPS** 或与接口同策略的部署环境；跨域与 Cookie 策略由后端与浏览器共同决定。\r\n\r\n---\r\n\r\n## 安装\r\n\r\n```bash\r\nnpm install @cqsjjb/website-platform-sdk\r\n```\r\n\r\n安装后请确保工程能解析 **ESM**（主流前端脚手架默认支持）。**不要用 `file://` 直接打开本地 HTML**，否则 ES 模块可能被浏览器拦截；本地预览请使用 dev server（如 `npm run dev`）或 `npx serve` 等。\r\n\r\n---\r\n\r\n## 使用示例\r\n\r\n以下示例中，`platformOrigin`、`appkey`、`config`、`host` 请替换为**与后端约定**的实际值（`platformOrigin` 为建站站点根地址，开放账号接口与嵌入页同源）。\r\n\r\n### React（函数组件 + Hooks）\r\n\r\n```tsx\r\nimport { useEffect, useRef } from 'react';\r\nimport { createWebSite } from '@cqsjjb/website-platform-sdk';\r\nimport type { Website } from '@cqsjjb/website-platform-sdk';\r\n\r\nexport function WebsitePlatformEmbed() {\r\n  const containerRef = useRef<HTMLDivElement>(null);\r\n  const websiteRef = useRef<Website | null>(null);\r\n\r\n  useEffect(() => {\r\n    const el = containerRef.current;\r\n    if (!el) return;\r\n\r\n    const website = createWebSite({\r\n      platformOrigin: 'https://你的建站站点根地址',\r\n      appkey: '你的 appkey',\r\n      sm2PublicKeyDerHex: '基座提供的 SM2 公钥 DER（十六进制）',\r\n      config: {\r\n        username: 'user001',\r\n        tenantId: '租户 ID',\r\n        clientId: '客户端 ID',\r\n        siteId: '站点 ID',\r\n        // 其余字段与后端约定一致\r\n      },\r\n      host: typeof window !== 'undefined' ? window.location.origin : '',\r\n    });\r\n\r\n    website.on('mount', () => {\r\n      console.log('iframe 已挂载');\r\n    });\r\n    website.on('getUserInfo:error', (_w, detail) => {\r\n      console.error('获取用户信息失败', detail?.err);\r\n    });\r\n\r\n    website.mount(el, {\r\n      width: '100%',\r\n      height: '600px',\r\n      style: { border: 'none' },\r\n    });\r\n\r\n    websiteRef.current = website;\r\n\r\n    return () => {\r\n      website.unmount();\r\n      websiteRef.current = null;\r\n    };\r\n  }, []);\r\n\r\n  return <div ref={containerRef} style={{ width: '100%', minHeight: 400 }} />;\r\n}\r\n```\r\n\r\n要点：\r\n\r\n- 用 **`ref` 拿到挂载容器**，在 `useEffect` 里调用 `mount`，避免重复创建实例时可把 `createWebSite` 放进 effect 或配合 `useMemo`/`useRef` 存实例。\r\n- 在 **effect 清理函数**里调用 `website.unmount()`，防止路由切换或组件卸载后残留 iframe 与监听。\r\n\r\n---\r\n\r\n### Vue 3（`<script setup>`）\r\n\r\n```vue\r\n<template>\r\n  <div ref=\"containerRef\" class=\"embed-wrap\"></div>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref, onMounted, onBeforeUnmount } from 'vue';\r\nimport { createWebSite } from '@cqsjjb/website-platform-sdk';\r\nimport type { Website } from '@cqsjjb/website-platform-sdk';\r\n\r\nconst containerRef = ref<HTMLDivElement | null>(null);\r\nlet website: Website | null = null;\r\n\r\nonMounted(() => {\r\n  const el = containerRef.value;\r\n  if (!el) return;\r\n\r\n  website = createWebSite({\r\n    platformOrigin: 'https://你的建站站点根地址',\r\n    appkey: '你的 appkey',\r\n    sm2PublicKeyDerHex: '基座提供的 SM2 公钥 DER（十六进制）',\r\n    config: {\r\n      username: 'user001',\r\n      tenantId: '租户 ID',\r\n      clientId: '客户端 ID',\r\n      siteId: '站点 ID',\r\n    },\r\n    host: typeof window !== 'undefined' ? window.location.origin : '',\r\n  });\r\n\r\n  website.on('mount', () => {\r\n    console.log('iframe 已挂载');\r\n  });\r\n  website.on('getUserInfo:error', (_w, detail) => {\r\n    console.error('获取用户信息失败', detail?.err);\r\n  });\r\n\r\n  website.mount(el, {\r\n    width: '100%',\r\n    height: '600px',\r\n    style: { border: 'none' },\r\n  });\r\n});\r\n\r\nonBeforeUnmount(() => {\r\n  website?.unmount();\r\n  website = null;\r\n});\r\n</script>\r\n\r\n<style scoped>\r\n.embed-wrap {\r\n  width: 100%;\r\n  min-height: 400px;\r\n}\r\n</style>\r\n```\r\n\r\n要点：\r\n\r\n- 在 **`onMounted`** 中执行 `mount`，此时模板已渲染，`ref` 已指向 DOM。\r\n- 在 **`onBeforeUnmount`** 中调用 `unmount()`，与页面或组件生命周期对齐。\r\n\r\n---\r\n\r\n### 传统 HTML（原生 ES Module）\r\n\r\n页面需通过 **HTTP/HTTPS** 访问（本地可用任意静态服务）。在页面中增加容器，并用 `type=\"module\"` 的脚本从 `node_modules` 引入（路径按实际安装位置调整，打包到静态资源后也可用相对路径）。\r\n\r\n```html\r\n<!DOCTYPE html>\r\n<html lang=\"zh\">\r\n<head>\r\n  <meta charset=\"UTF-8\" />\r\n  <title>建站站点嵌入示例</title>\r\n</head>\r\n<body>\r\n  <div id=\"embed-root\" style=\"width:100%;height:600px;border:1px solid #ccc;\"></div>\r\n\r\n  <script type=\"module\">\r\n    import { createWebSite } from './node_modules/@cqsjjb/website-platform-sdk/dist/index.js';\r\n\r\n    const container = document.getElementById('embed-root');\r\n    if (!container) throw new Error('找不到容器');\r\n\r\n    const website = createWebSite({\r\n      platformOrigin: 'https://你的建站站点根地址',\r\n      appkey: '你的 appkey',\r\n      sm2PublicKeyDerHex: '基座提供的 SM2 公钥 DER（十六进制）',\r\n      config: {\r\n        username: 'user001',\r\n        tenantId: '租户 ID',\r\n        clientId: '客户端 ID',\r\n        siteId: '站点 ID',\r\n      },\r\n      host: window.location.origin,\r\n    });\r\n\r\n    website.on('mount', () => console.log('iframe 已挂载'));\r\n    website.on('getUserInfo:error', (_w, d) => console.error(d?.err));\r\n\r\n    website.mount(container, {\r\n      width: '100%',\r\n      height: '100%',\r\n      style: { border: 'none' },\r\n    });\r\n\r\n    // 若需要在离开页面前卸载，可绑定 beforeunload 或你自己的导航逻辑：\r\n    // window.addEventListener('beforeunload', () => website.unmount());\r\n  </script>\r\n</body>\r\n</html>\r\n```\r\n\r\n若使用 **Vite / Webpack** 等多文件打包，通常不写死 `node_modules` 路径，而是在入口 JS 里写 `import { createWebSite } from '@cqsjjb/website-platform-sdk'`，由打包器解析，再引入打包后的单文件脚本。\r\n\r\n---\r\n\r\n## API 说明\r\n\r\n### `createWebSite(options: WebsiteOptions): Website`\r\n\r\n创建 `Website` 实例。\r\n\r\n| 字段 | 类型 | 说明 |\r\n|------|------|------|\r\n| `platformOrigin` | `string` | **必填**。建站站点根地址（与开放账号接口、iframe 嵌入页同源），如 `https://platform.example.com`。末尾 `/` 可写可不写，SDK 会规范化。 |\r\n| `appkey` | `string` | **必填**。开放应用 appkey。 |\r\n| `sm2PublicKeyDerHex` | `string` | **必填**。SM2 公钥的 X.509 DER **十六进制串**（与后端解密用私钥对应），用于加密 `config`。 |\r\n| `config` | `Record<string, unknown>` | 可选。业务配置，将 **JSON 序列化后经 SM2 加密** 传给开放接口（字段名与后端约定一致）。嵌入建站预览页时还需 **`siteId`**、**`tenantId`** 等，与 `buildPlatformIframeSrc` 规则一致。 |\r\n| `host` | `string` | 可选。请求体中的 `host`，一般填当前业务站点或后端认可的来源地址。 |\r\n\r\n---\r\n\r\n### `website.mount(container, options?)`\r\n\r\n将 SDK 挂到 **一个 DOM 容器**上，内部会异步请求开放接口并在成功后插入 `iframe`。\r\n\r\n**参数**\r\n\r\n- `container`：`HTMLElement | null`。一般为 `div` 等块级容器；为 `null` 时会在控制台报错并中止。\r\n- `options`：`MountOptions`，可选：\r\n\r\n| 字段 | 类型 | 说明 |\r\n|------|------|------|\r\n| `style` | `Record<string, string>` | 应用到 `iframe` 的 CSS 行内样式（如 `border: 'none'`）。 |\r\n| `width` | `string` | `iframe` 宽度，如 `'100%'`、`'800px'`。 |\r\n| `height` | `string` | `iframe` 高度。 |\r\n| `attrs` | `Record<string, string>` | 额外 HTML 属性（如 `id`、`title`）。 |\r\n\r\n**流程概要**\r\n\r\n1. 展示「正在获取用户信息…」Loading。\r\n2. 调用 `getUserInfo`；失败则触发 `getUserInfo:error` 并结束。\r\n3. 若返回中 **没有用户数据**（`!res.data`）：关闭 Loading → 展示 **授权确认**（确认 / 取消）。\r\n   - **确认**：触发 `auth:confirm`，再 Loading「正在创建用户…」，调用 `createUser`。\r\n   - **取消**：在容器内展示「您已取消授权」文案，触发 `auth:cancel`，**不再**创建用户、不挂 iframe。\r\n4. 若有用户数据或 `createUser` 成功拿到 `data`：根据 `data` 与 `config` 拼接建站预览页 URL（见 `buildPlatformIframeSrc`），插入 `iframe`，`mounted = true`，触发 `mount`。\r\n\r\n---\r\n\r\n### `website.unmount()`\r\n\r\n卸载 iframe 并清空与本次挂载相关的内部状态；触发 `unmount` 事件。若当前未成功挂载 iframe，会在控制台提示错误。\r\n\r\n---\r\n\r\n### 实例属性（赋值即更新 iframe）\r\n\r\n在 **iframe 已存在** 时，以下 setter 会同步到 DOM。\r\n\r\n| 属性 | 说明 |\r\n|------|------|\r\n| `website.width` | 字符串，如 `'100%'`。 |\r\n| `website.height` | 字符串。 |\r\n| `website.style` | 行内样式对象。 |\r\n| `website.attrs` | HTML 属性对象。 |\r\n\r\n---\r\n\r\n### `buildPlatformIframeSrc(data, platformOrigin, config?): string`\r\n\r\n根据开放接口返回的 **用户态** 与创建实例时的 **`config`** 生成建站预览页 URL（与 SDK 内部挂载 iframe 时一致）。第二参数可与 `createWebSite` 时一致，或传 **`website.platformOrigin`**；第三参数与 **`createWebSite({ config })`** 一致，可省略（默认 `{}`），但预览路径需要 **`config.siteId`**、**`config.tenantId`** 等字段。\r\n\r\n- **路径**：`{platformOrigin}/official-website-design/container/Preview/{clientId}/{tenantId}/{siteId}`\r\n- **`clientId`**：`data.clientId` 与 `config.clientId` 取其一或合并（与实现一致）。\r\n- **查询参数**：附带 `token`（来自 `data.token`）。\r\n\r\n适用于需要**自行打开新窗口或预校验 URL** 的场景。\r\n\r\n### `normalizePlatformOrigin(origin): string`\r\n\r\n去掉首尾空白与末尾 `/`，与 SDK 内部拼接开放接口、iframe 地址时的规范化规则一致；若你在配置中心存的是带尾斜杠的 URL，可先经此函数再传入 `platformOrigin`（也可直接传入，构造函数内会再次规范化）。\r\n\r\n---\r\n\r\n## 事件\r\n\r\n使用 `website.on(eventName, callback)` 订阅。回调签名为 **`(website, detail?)`**（第一个参数为当前 `Website` 实例）。\r\n\r\n| 事件名 | 触发时机 | `detail` 大致内容 |\r\n|--------|----------|-------------------|\r\n| `getUserInfo:start` | 即将请求 `getUserInfo` | `{ authOpts }` |\r\n| `getUserInfo:success` | `getUserInfo` HTTP 成功且已解析 JSON | `{ res, authOpts }` |\r\n| `getUserInfo:error` | `getUserInfo` 抛错或 HTTP 非 2xx | `{ err, authOpts }` |\r\n| `auth:confirm` | 用户点击「确认授权」后、请求 `createUser` 前 | `{ authOpts }` |\r\n| `auth:cancel` | 用户点击「取消」 | `{ authOpts }` |\r\n| `createUser:start` | 即将请求 `createUser` | `{ authOpts }` |\r\n| `createUser:success` | `createUser` 成功 | `{ res1, authOpts }` |\r\n| `createUser:error` | `createUser` 失败 | `{ err, authOpts }` |\r\n| `mount` | iframe 已插入容器并完成绑定 | 无额外载荷（回调第一个参数仍为 `Website` 实例） |\r\n| `heartbeat:start` | iframe 挂载后心跳定时器启动（仅当 token 存在时） | 无额外载荷 |\r\n| `token:expired` | 心跳检测到 token 失效 | 无额外载荷（会同步隐藏 iframe 并弹出「重新授权」对话框） |\r\n| `unmount` | 调用 `unmount()` 并完成清理 | 无额外载荷 |\r\n\r\n使用 `website.off(eventName)` 可移除对应监听。\r\n\r\n---\r\n\r\n## TypeScript\r\n\r\n包导出类型包括：`WebsiteOptions`、`MountOptions`、`AuthOpts`、`WebsiteUserData`、`OpenAccountEnvelope` 等。\r\n\r\n```ts\r\nimport {\r\n  createWebSite,\r\n  buildPlatformIframeSrc,\r\n  normalizePlatformOrigin,\r\n  type WebsiteOptions,\r\n} from '@cqsjjb/website-platform-sdk';\r\n\r\nconst origin = normalizePlatformOrigin('https://platform.example.com/');\r\nconst url = buildPlatformIframeSrc(userData, origin, {\r\n  tenantId: '租户 ID',\r\n  siteId: '站点 ID',\r\n  clientId: '客户端 ID',\r\n});\r\n```\r\n\r\n---\r\n\r\n## 与后端约定\r\n\r\n- **`platformOrigin`** 决定开放账号接口与 iframe 的基址，须与当前环境**建站站点**部署地址一致（测试 / 生产分别配置）。\r\n- **`config` 字段**须与后端解密、验签规则一致（SM2 加密由本包在浏览器侧完成）。\r\n- 若贵司接口在 HTTP 层之外还有业务错误码约定，请在业务代码中根据返回体自行处理（例如统一提示）。\r\n\r\n---\r\n\r\n## 常见问题\r\n\r\n**1. 页面里 `import` 报错 / 模块找不到**  \r\n请通过 **开发服务器或静态站点** 访问页面，不要使用 `file://` 打开含 ES Module 的 HTML。\r\n\r\n**2. 安装后没有类型提示**  \r\n确认已正确安装依赖，且 IDE 使用的是包内的类型入口（由 `package.json` 的 `\"types\"` 字段指定）。\r\n\r\n**3. 新用户一直停在 Loading**  \r\n检查网络、开放接口是否可达，以及 `platformOrigin` / `appkey` / `config` / `host` 是否与当前环境一致。\r\n\r\n**4. 授权成功但无法显示**\r\n这可能是跨域问题导致，需要联系技术人员处理。\r\n\r\n---\r\n\r\n## 开源协议\r\n\r\nISC（见发布包内 `package.json` 的 `license` 字段）。\r\n","readmeFilename":"README.md"}