{"id":63855,"date":"2026-01-22T13:40:57","date_gmt":"2026-01-22T05:40:57","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/63855.html"},"modified":"2026-01-22T13:40:57","modified_gmt":"2026-01-22T05:40:57","slug":"%e4%bd%bf%e7%94%a8claude-code%e5%bc%80%e5%8f%91%e5%9c%a8%e7%ba%bf%e9%a2%84%e8%a7%88word%e3%80%81excel%e3%80%81ppt%e3%80%81pdf%e7%ad%89%e5%a4%9a%e7%a7%8d%e6%96%87%e4%bb%b6%ef%bc%8c%e5%9f%ba%e4%ba%8eonl","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/63855.html","title":{"rendered":"\u4f7f\u7528claude code\u5f00\u53d1\u5728\u7ebf\u9884\u89c8word\u3001excel\u3001ppt\u3001pdf\u7b49\u591a\u79cd\u6587\u4ef6\uff0c\u57fa\u4e8eonlyoffice\u5b9e\u73b0\u9884\u89c8\uff0conlyoffice\u5305\u542bAI\u63d2\u4ef6\uff0c\u53ef\u4ee5\u5bf9\u6587\u4ef6\u5185\u5bb9\u8fdb\u884c\u5904\u7406"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1079\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122054049-6971b861a333c.png\" width=\"1919\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1073\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122054050-6971b862b1f29.png\" width=\"1919\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1052\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122054051-6971b863d83a9.png\" width=\"1919\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"911\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122054053-6971b8652a455.png\" width=\"1920\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1079\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122054054-6971b866111f3.png\" width=\"1919\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"911\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122054055-6971b867279e5.png\" width=\"1920\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"322\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122054056-6971b8682590f.png\" width=\"727\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"\" height=\"1033\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122054056-6971b8683a416.png\" width=\"1919\" \/><\/p>\n<h2>\u5728\u7ebf\u5730\u5740<\/h2>\n<p>https:\/\/chat.xutongbao.top\/nextjs\/light\/onlyOffice<\/p>\n<h2>page.tsx<\/h2>\n<p>&#039;use client&#039;<\/p>\n<p>import { useState, useRef, useEffect } from &#039;react&#039;<br \/>\nimport Header from &#039;&#064;\/components\/header&#039;<br \/>\nimport {<br \/>\n  ArrowLeft,<br \/>\n  Upload,<br \/>\n  FileText,<br \/>\n  File,<br \/>\n  CheckCircle2,<br \/>\n  AlertCircle,<br \/>\n  Loader2,<br \/>\n  X,<br \/>\n  FolderOpen,<br \/>\n  Sparkles,<br \/>\n  Copy,<br \/>\n  Search,<br \/>\n  BookOpen,<br \/>\n  MessageSquare,<br \/>\n  Wand2,<br \/>\n} from &#039;lucide-react&#039;<br \/>\nimport { useRouter } from &#039;next\/navigation&#039;<br \/>\nimport { Button } from &#039;&#064;\/components\/ui\/button&#039;<br \/>\nimport Script from &#039;next\/script&#039;<br \/>\nimport { cn } from &#039;&#064;\/lib\/utils&#039;<br \/>\nimport Api from &#039;&#064;\/api\/h5Api&#039;<\/p>\n<p>\/\/ \u58f0\u660e\u5168\u5c40 DocsAPI \u7c7b\u578b<br \/>\ndeclare global {<br \/>\n  interface Window {<br \/>\n    DocsAPI?: {<br \/>\n      DocEditor: new (id: string, config: any) &#061;&gt; any<br \/>\n    }<br \/>\n  }<br \/>\n}<\/p>\n<p>\/\/ OnlyOffice Editor \u5b9e\u4f8b\u7c7b\u578b<br \/>\ninterface DocEditorInstance {<br \/>\n  destroyEditor: () &#061;&gt; void<br \/>\n  downloadAs: (format: string) &#061;&gt; void<br \/>\n  requestClose: () &#061;&gt; void<br \/>\n}<\/p>\n<p>\/\/ \u652f\u6301\u7684\u6587\u4ef6\u683c\u5f0f<br \/>\nconst SUPPORTED_FORMATS &#061; {<br \/>\n  documents: [<br \/>\n    &#039;.doc&#039;,<br \/>\n    &#039;.docx&#039;,<br \/>\n    &#039;.docm&#039;,<br \/>\n    &#039;.dot&#039;,<br \/>\n    &#039;.dotx&#039;,<br \/>\n    &#039;.dotm&#039;,<br \/>\n    &#039;.odt&#039;,<br \/>\n    &#039;.fodt&#039;,<br \/>\n    &#039;.ott&#039;,<br \/>\n    &#039;.rtf&#039;,<br \/>\n    &#039;.txt&#039;,<br \/>\n    &#039;.html&#039;,<br \/>\n    &#039;.htm&#039;,<br \/>\n    &#039;.mht&#039;,<br \/>\n    &#039;.pdf&#039;,<br \/>\n    &#039;.djvu&#039;,<br \/>\n    &#039;.fb2&#039;,<br \/>\n    &#039;.epub&#039;,<br \/>\n    &#039;.xps&#039;,<br \/>\n  ],<br \/>\n  spreadsheets: [<br \/>\n    &#039;.xls&#039;,<br \/>\n    &#039;.xlsx&#039;,<br \/>\n    &#039;.xlsm&#039;,<br \/>\n    &#039;.xlt&#039;,<br \/>\n    &#039;.xltx&#039;,<br \/>\n    &#039;.xltm&#039;,<br \/>\n    &#039;.ods&#039;,<br \/>\n    &#039;.fods&#039;,<br \/>\n    &#039;.ots&#039;,<br \/>\n    &#039;.csv&#039;,<br \/>\n  ],<br \/>\n  presentations: [<br \/>\n    &#039;.pps&#039;,<br \/>\n    &#039;.ppsx&#039;,<br \/>\n    &#039;.ppsm&#039;,<br \/>\n    &#039;.ppt&#039;,<br \/>\n    &#039;.pptx&#039;,<br \/>\n    &#039;.pptm&#039;,<br \/>\n    &#039;.pot&#039;,<br \/>\n    &#039;.potx&#039;,<br \/>\n    &#039;.potm&#039;,<br \/>\n    &#039;.odp&#039;,<br \/>\n    &#039;.fodp&#039;,<br \/>\n    &#039;.otp&#039;,<br \/>\n  ],<br \/>\n}<\/p>\n<p>const ALL_FORMATS &#061; [<br \/>\n  &#8230;SUPPORTED_FORMATS.documents,<br \/>\n  &#8230;SUPPORTED_FORMATS.spreadsheets,<br \/>\n  &#8230;SUPPORTED_FORMATS.presentations,<br \/>\n]<\/p>\n<p>interface UploadedFile {<br \/>\n  file: File<br \/>\n  name: string<br \/>\n  size: number<br \/>\n  type: string<br \/>\n  uploadTime: number<br \/>\n  previewUrl?: string<br \/>\n}<\/p>\n<p>\/\/ API \u54cd\u5e94\u7c7b\u578b<br \/>\ninterface ApiResponse {<br \/>\n  code: number<br \/>\n  data?: {<br \/>\n    token?: string<br \/>\n    key?: string<br \/>\n    url?: string<br \/>\n  }<br \/>\n}<\/p>\n<p>export default function OnlyOfficePage() {<br \/>\n  const router &#061; useRouter()<br \/>\n  const [uploadedFile, setUploadedFile] &#061; useState&lt;UploadedFile | null&gt;(null)<br \/>\n  const [isUploading, setIsUploading] &#061; useState(false)<br \/>\n  const [isDragOver, setIsDragOver] &#061; useState(false)<br \/>\n  const [error, setError] &#061; useState&lt;string | null&gt;(null)<br \/>\n  const [isPreviewReady, setIsPreviewReady] &#061; useState(false)<br \/>\n  const [scriptLoaded, setScriptLoaded] &#061; useState(false)<br \/>\n  const [qiniuToken, setQiniuToken] &#061; useState&lt;string&gt;(&#039;&#039;)<br \/>\n  const [uploadProgress, setUploadProgress] &#061; useState&lt;number&gt;(0)<br \/>\n  const fileInputRef &#061; useRef&lt;HTMLInputElement&gt;(null)<br \/>\n  const editorContainerRef &#061; useRef&lt;HTMLDivElement&gt;(null)<br \/>\n  const docEditorRef &#061; useRef&lt;DocEditorInstance | null&gt;(null)<\/p>\n<p>  \/\/ \u9f20\u6807\u4f4d\u7f6e\u8ffd\u8e2a<br \/>\n  const mousePositionRef &#061; useRef({ x: 0, y: 0 })<\/p>\n<p>  \/\/ \u4e0a\u4e0b\u6587\u83dc\u5355\u72b6\u6001<br \/>\n  const [contextMenu, setContextMenu] &#061; useState&lt;{<br \/>\n    visible: boolean<br \/>\n    x: number<br \/>\n    y: number<br \/>\n    selectedText: string<br \/>\n  }&gt;({<br \/>\n    visible: false,<br \/>\n    x: 0,<br \/>\n    y: 0,<br \/>\n    selectedText: &#039;&#039;,<br \/>\n  })<\/p>\n<p>  \/\/ \u683c\u5f0f\u5316\u6587\u4ef6\u5927\u5c0f<br \/>\n  const formatBytes &#061; (bytes: number): string &#061;&gt; {<br \/>\n    if (bytes &#061;&#061;&#061; 0) return &#039;0 B&#039;<br \/>\n    const k &#061; 1024<br \/>\n    const sizes &#061; [&#039;B&#039;, &#039;KB&#039;, &#039;MB&#039;, &#039;GB&#039;]<br \/>\n    const i &#061; Math.floor(Math.log(bytes) \/ Math.log(k))<br \/>\n    return Math.round((bytes \/ Math.pow(k, i)) * 100) \/ 100 &#043; &#039; &#039; &#043; sizes[i]<br \/>\n  }<\/p>\n<p>  \/\/ \u68c0\u67e5\u6587\u4ef6\u683c\u5f0f<br \/>\n  const isFileSupported &#061; (fileName: string): boolean &#061;&gt; {<br \/>\n    const ext &#061; &#039;.&#039; &#043; fileName.split(&#039;.&#039;).pop()?.toLowerCase()<br \/>\n    return ALL_FORMATS.includes(ext)<br \/>\n  }<\/p>\n<p>  \/\/ \u83b7\u53d6\u6587\u4ef6\u7c7b\u578b<br \/>\n  const getFileType &#061; (<br \/>\n    fileName: string,<br \/>\n  ): &#039;word&#039; | &#039;cell&#039; | &#039;slide&#039; | &#039;unknown&#039; &#061;&gt; {<br \/>\n    const ext &#061; &#039;.&#039; &#043; fileName.split(&#039;.&#039;).pop()?.toLowerCase()<br \/>\n    if (SUPPORTED_FORMATS.documents.includes(ext)) return &#039;word&#039;<br \/>\n    if (SUPPORTED_FORMATS.spreadsheets.includes(ext)) return &#039;cell&#039;<br \/>\n    if (SUPPORTED_FORMATS.presentations.includes(ext)) return &#039;slide&#039;<br \/>\n    return &#039;unknown&#039;<br \/>\n  }<\/p>\n<p>  \/\/ \u83b7\u53d6\u4e03\u725b\u4e91\u4e0a\u4f20 token<br \/>\n  useEffect(() &#061;&gt; {<br \/>\n    const fetchQiniuToken &#061; async () &#061;&gt; {<br \/>\n      try {<br \/>\n        const res &#061; (await Api.uploadGetTokenForH5(<br \/>\n          {}<br \/>\n        )) as unknown as ApiResponse<br \/>\n        if (res.code &#061;&#061;&#061; 200 &amp;&amp; res.data?.token) {<br \/>\n          setQiniuToken(res.data.token)<br \/>\n        }<br \/>\n      } catch (error) {<br \/>\n        console.error(&#039;\u83b7\u53d6\u4e0a\u4f20token\u5931\u8d25:&#039;, error)<br \/>\n      }<br \/>\n    }<br \/>\n    fetchQiniuToken()<br \/>\n  }, [])<\/p>\n<p>  \/\/ \u4e0a\u4f20\u6587\u4ef6\u5230\u4e03\u725b\u4e91<br \/>\n  const uploadFileToQiniu &#061; async (file: File): Promise&lt;string&gt; &#061;&gt; {<br \/>\n    if (!qiniuToken) {<br \/>\n      throw new Error(&#039;\u4e0a\u4f20 token \u672a\u83b7\u53d6&#xff0c;\u8bf7\u7a0d\u540e\u91cd\u8bd5&#039;)<br \/>\n    }<\/p>\n<p>    const formData &#061; new FormData()<br \/>\n    const key &#061; &#096;ai\/onlyoffice\/${Date.now()}_${file.name}&#096;<br \/>\n    formData.append(&#039;file&#039;, file)<br \/>\n    formData.append(&#039;token&#039;, qiniuToken)<br \/>\n    formData.append(&#039;key&#039;, key)<\/p>\n<p>    setUploadProgress(10)<\/p>\n<p>    const response &#061; await fetch(&#039;https:\/\/upload-z1.qiniup.com&#039;, {<br \/>\n      method: &#039;POST&#039;,<br \/>\n      body: formData,<br \/>\n    })<\/p>\n<p>    setUploadProgress(80)<\/p>\n<p>    const result &#061; await response.json()<\/p>\n<p>    console.log(&#039;\u4e03\u725b\u4e91\u4e0a\u4f20\u54cd\u5e94:&#039;, result)<\/p>\n<p>    \/\/ \u4e03\u725b\u4e91\u76f4\u63a5\u8fd4\u56de { key: &#034;&#8230;&#034;, hash: &#034;&#8230;&#034; }<br \/>\n    if (result.code &#061;&#061;&#061; 200) {<br \/>\n      const fileUrl &#061; &#096;https:\/\/static.xutongbao.top\/${result.data.key}&#096;<br \/>\n      setUploadProgress(100)<br \/>\n      console.log(&#039;\u4e0a\u4f20\u6210\u529f&#xff0c;\u6587\u4ef6 URL:&#039;, fileUrl)<br \/>\n      return fileUrl<br \/>\n    } else {<br \/>\n      throw new Error(result.error || &#039;\u4e0a\u4f20\u5931\u8d25&#xff0c;\u672a\u8fd4\u56de\u6587\u4ef6\u5730\u5740&#039;)<br \/>\n    }<br \/>\n  }<\/p>\n<p>  \/\/ \u5904\u7406\u6587\u4ef6\u9009\u62e9&#xff08;\u6539\u4e3a\u4e0a\u4f20\u5230\u4e03\u725b\u4e91&#xff09;<br \/>\n  const handleFileSelect &#061; async (file: File) &#061;&gt; {<br \/>\n    setError(null)<br \/>\n    setIsPreviewReady(false)<br \/>\n    setUploadProgress(0)<\/p>\n<p>    if (!isFileSupported(file.name)) {<br \/>\n      setError(<br \/>\n        &#096;\u4e0d\u652f\u6301\u7684\u6587\u4ef6\u683c\u5f0f\u3002\u652f\u6301\u7684\u683c\u5f0f\u5305\u62ec&#xff1a;${ALL_FORMATS.slice(0, 10).join(&#039;, &#039;)} \u7b49&#096;,<br \/>\n      )<br \/>\n      return<br \/>\n    }<\/p>\n<p>    if (!qiniuToken) {<br \/>\n      setError(&#039;\u4e0a\u4f20\u670d\u52a1\u672a\u5c31\u7eea&#xff0c;\u8bf7\u7a0d\u540e\u91cd\u8bd5&#039;)<br \/>\n      return<br \/>\n    }<\/p>\n<p>    setIsUploading(true)<\/p>\n<p>    try {<br \/>\n      \/\/ \u4e0a\u4f20\u6587\u4ef6\u5230\u4e03\u725b\u4e91<br \/>\n      const fileUrl &#061; await uploadFileToQiniu(file)<\/p>\n<p>      const uploadedFileData: UploadedFile &#061; {<br \/>\n        file,<br \/>\n        name: file.name,<br \/>\n        size: file.size,<br \/>\n        type: getFileType(file.name),<br \/>\n        uploadTime: Date.now(),<br \/>\n        previewUrl: fileUrl, \/\/ \u4f7f\u7528\u4e03\u725b\u4e91\u8fd4\u56de\u7684 URL<br \/>\n      }<\/p>\n<p>      setUploadedFile(uploadedFileData)<\/p>\n<p>      \/\/ \u5ef6\u8fdf\u663e\u793a\u9884\u89c8\u51c6\u5907\u5c31\u7eea&#xff0c;useEffect \u4f1a\u81ea\u52a8\u89e6\u53d1 initOnlyOfficeEditor<br \/>\n      setTimeout(() &#061;&gt; {<br \/>\n        setIsPreviewReady(true)<br \/>\n      }, 500)<br \/>\n    } catch (err: any) {<br \/>\n      console.error(&#039;\u4e0a\u4f20\u5931\u8d25:&#039;, err)<br \/>\n      setError(err.message || &#039;\u4e0a\u4f20\u5931\u8d25&#xff0c;\u8bf7\u91cd\u8bd5&#039;)<br \/>\n    } finally {<br \/>\n      setIsUploading(false)<br \/>\n      setUploadProgress(0)<br \/>\n    }<br \/>\n  }<\/p>\n<p>  \/\/ \u521d\u59cb\u5316 OnlyOffice \u7f16\u8f91\u5668<br \/>\n  const initOnlyOfficeEditor &#061; (fileData: any, type?: any) &#061;&gt; {<br \/>\n    if (!editorContainerRef.current || !window.DocsAPI) {<br \/>\n      console.warn(&#039;OnlyOffice API \u672a\u52a0\u8f7d\u6216\u5bb9\u5668\u672a\u51c6\u5907\u597d&#039;)<br \/>\n      return<br \/>\n    }<\/p>\n<p>    \/\/ \u9500\u6bc1\u65e7\u7684\u7f16\u8f91\u5668\u5b9e\u4f8b<br \/>\n    if (docEditorRef.current) {<br \/>\n      try {<br \/>\n        docEditorRef.current.destroyEditor()<br \/>\n        docEditorRef.current &#061; null<br \/>\n        \/\/ \u6e05\u7406\u5bb9\u5668\u5185\u5bb9<br \/>\n        if (editorContainerRef.current) {<br \/>\n          editorContainerRef.current.innerHTML &#061; &#039;&#039;<br \/>\n        }<br \/>\n      } catch (error) {<br \/>\n        console.warn(&#039;\u9500\u6bc1\u65e7\u7f16\u8f91\u5668\u5931\u8d25:&#039;, error)<br \/>\n      }<br \/>\n    }<\/p>\n<p>    \/\/ \u786e\u5b9a\u6587\u4ef6 URL \u548c\u6570\u636e<br \/>\n    let url: string<br \/>\n    let documentType: string<br \/>\n    let fileName: string<br \/>\n    let fileType: string<br \/>\n    let timestamp: number<\/p>\n<p>    \/\/ \u6d4b\u8bd5\u6309\u94ae\u4f7f\u7528\u56fa\u5b9a\u7684\u6d4b\u8bd5\u6587\u4ef6<br \/>\n    if (type &#061;&#061;&#061; &#039;1&#039;) {<br \/>\n      url &#061; &#039;https:\/\/static.xutongbao.top\/ai\/onlyoffice\/1769051991957_%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%8B.docx&#039;<br \/>\n      documentType &#061; &#039;word&#039;<br \/>\n      fileName &#061; &#039;\u6d4b\u8bd5.docx&#039;<br \/>\n      fileType &#061; &#039;docx&#039;<br \/>\n      timestamp &#061; 1768789600204<br \/>\n    } else if (type &#061;&#061;&#061; &#039;2&#039;) {<br \/>\n      url &#061; &#039;https:\/\/static.xutongbao.top\/ai\/onlyoffice\/1769053651678_1.xlsx&#039;<br \/>\n      documentType &#061; &#039;cell&#039;<br \/>\n      fileName &#061; &#039;\u6d4b\u8bd5.xlsx&#039;<br \/>\n      fileType &#061; &#039;xlsx&#039;<br \/>\n      timestamp &#061; 1768789600204<br \/>\n    } else if (type &#061;&#061;&#061; &#039;3&#039;) {<br \/>\n      url &#061; &#039;https:\/\/static.xutongbao.top\/ai\/onlyoffice\/1769053694718_1.pptx&#039;<br \/>\n      documentType &#061; &#039;slide&#039;<br \/>\n      fileName &#061; &#039;\u6d4b\u8bd5.pptx&#039;<br \/>\n      fileType &#061; &#039;pptx&#039;<br \/>\n      timestamp &#061; 1768789600204<br \/>\n    } else {<br \/>\n      \/\/ \u7528\u6237\u4e0a\u4f20\u7684\u6587\u4ef6<br \/>\n      url &#061; fileData.previewUrl || &#039;&#039;<br \/>\n      documentType &#061; fileData.type || &#039;word&#039;<br \/>\n      fileName &#061; fileData.name || &#039;\u672a\u547d\u540d\u6587\u6863&#039;<br \/>\n      fileType &#061; fileName.split(&#039;.&#039;).pop() || &#039;docx&#039;<br \/>\n      timestamp &#061; fileData.uploadTime || Date.now()<br \/>\n    }<\/p>\n<p>    console.log(&#039;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; OnlyOffice \u521d\u59cb\u5316 &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#039;)<br \/>\n    console.log(&#039;\u6587\u6863 URL:&#039;, url)<br \/>\n    console.log(&#039;\u6587\u6863\u7c7b\u578b:&#039;, documentType)<br \/>\n    console.log(&#039;\u6587\u4ef6\u540d:&#039;, fileName)<br \/>\n    console.log(&#039;\u6587\u4ef6\u683c\u5f0f:&#039;, fileType)<br \/>\n    console.log(&#039;\u65f6\u95f4\u6233:&#039;, timestamp)<br \/>\n    console.log(&#039;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#039;)<\/p>\n<p>    if (!url) {<br \/>\n      console.error(&#039;\u6587\u6863 URL \u4e3a\u7a7a&#xff0c;\u65e0\u6cd5\u52a0\u8f7d&#039;)<br \/>\n      setError(&#039;\u6587\u6863\u5730\u5740\u83b7\u53d6\u5931\u8d25&#039;)<br \/>\n      return<br \/>\n    }<\/p>\n<p>    const config &#061; {<br \/>\n      documentType,<br \/>\n      document: {<br \/>\n        fileType,<br \/>\n        key: &#096;${timestamp}-${Math.random().toString(36).substring(7)}&#096;,<br \/>\n        title: fileName,<br \/>\n        url,<br \/>\n      },<br \/>\n      editorConfig: {<br \/>\n        mode: &#039;edit&#039;, \/\/ \u7f16\u8f91\u6a21\u5f0f<br \/>\n        lang: &#039;zh-CN&#039;,<br \/>\n        user: {<br \/>\n          id: &#039;690313ca3814f11a1fb7cbd7&#039;,<br \/>\n          name: &#039;\u5f90\u540c\u4fdd&#039;,<br \/>\n        },<br \/>\n        \/\/ \u542f\u7528\u6587\u672c\u9009\u4e2d\u76d1\u542c\u63d2\u4ef6<br \/>\n        plugins: {<br \/>\n          autostart: [&#039;asc.008&#039;],<br \/>\n        },<br \/>\n      },<br \/>\n      width: &#039;100%&#039;,<br \/>\n      height: &#039;100%&#039;,<br \/>\n      events: {<br \/>\n        onDocumentReady: () &#061;&gt; {<br \/>\n          console.log(&#039;OnlyOffice \u6587\u6863\u52a0\u8f7d\u5b8c\u6210&#039;)<br \/>\n        },<br \/>\n        onAppReady: () &#061;&gt; {<br \/>\n          console.log(&#039;OnlyOffice \u5e94\u7528\u5df2\u51c6\u5907\u5c31\u7eea&#039;)<br \/>\n        },<br \/>\n      },<br \/>\n    }<\/p>\n<p>    const editor &#061; new window.DocsAPI.DocEditor(&#039;onlyoffice-editor&#039;, config)<br \/>\n    docEditorRef.current &#061; editor<br \/>\n  }<\/p>\n<p>  \/\/ \u76d1\u542c OnlyOffice API \u811a\u672c\u52a0\u8f7d\u548c DOM \u51c6\u5907\u5c31\u7eea<br \/>\n  useEffect(() &#061;&gt; {<br \/>\n    if (<br \/>\n      window.DocsAPI &amp;&amp;<br \/>\n      scriptLoaded &amp;&amp;<br \/>\n      uploadedFile &amp;&amp;<br \/>\n      isPreviewReady &amp;&amp;<br \/>\n      editorContainerRef.current<br \/>\n    ) {<br \/>\n      console.log(&#039;useEffect \u89e6\u53d1: \u6240\u6709\u6761\u4ef6\u6ee1\u8db3&#xff0c;\u521d\u59cb\u5316\u7f16\u8f91\u5668&#039;)<br \/>\n      initOnlyOfficeEditor(uploadedFile)<br \/>\n    }<br \/>\n  }, [scriptLoaded, uploadedFile, isPreviewReady])<\/p>\n<p>  \/\/ \u76d1\u542c\u9f20\u6807\u79fb\u52a8&#xff0c;\u8ffd\u8e2a\u9f20\u6807\u5750\u6807<br \/>\n  useEffect(() &#061;&gt; {<br \/>\n    const handleMouseMove &#061; (e: MouseEvent) &#061;&gt; {<br \/>\n      mousePositionRef.current &#061; { x: e.clientX, y: e.clientY }<br \/>\n    }<\/p>\n<p>    window.addEventListener(&#039;mousemove&#039;, handleMouseMove)<br \/>\n    return () &#061;&gt; {<br \/>\n      window.removeEventListener(&#039;mousemove&#039;, handleMouseMove)<br \/>\n    }<br \/>\n  }, [])<\/p>\n<p>  \/\/ \u76d1\u542c\u6765\u81ea OnlyOffice \u7684\u6d88\u606f<br \/>\n  useEffect(() &#061;&gt; {<br \/>\n    const handleMessage &#061; (event: MessageEvent) &#061;&gt; {<br \/>\n      \/\/ \u76d1\u542c\u6765\u81ea OnlyOffice iframe \u7684\u6d88\u606f<br \/>\n      if (event.data &amp;&amp; typeof event.data &#061;&#061;&#061; &#039;object&#039;) {<br \/>\n        \/\/ \u6dfb\u52a0\u5230\u5bf9\u8bdd\u6d88\u606f<br \/>\n        if (event.data.type &#061;&#061;&#061; &#039;ADD_TO_CHAT&#039;) {<br \/>\n          console.log(&#039;\u2713 \u6536\u5230\u6dfb\u52a0\u5230\u5bf9\u8bdd\u8bf7\u6c42:&#039;, event.data.text)<br \/>\n          \/\/ \u8fd9\u91cc\u53ef\u4ee5\u8c03\u7528\u4f60\u7684\u5bf9\u8bdd\u529f\u80fd<br \/>\n          alert(&#096;\u6dfb\u52a0\u5230\u5bf9\u8bdd:\\\\n${event.data.text}&#096;)<br \/>\n        }<\/p>\n<p>        \/\/ \u7ffb\u8bd1\u6d88\u606f<br \/>\n        if (event.data.type &#061;&#061;&#061; &#039;TRANSLATE_TEXT&#039;) {<br \/>\n          console.log(&#039;\u2713 \u6536\u5230\u7ffb\u8bd1\u8bf7\u6c42:&#039;, event.data.text)<br \/>\n          \/\/ \u8fd9\u91cc\u53ef\u4ee5\u8c03\u7528\u4f60\u7684\u7ffb\u8bd1\u529f\u80fd<br \/>\n          alert(&#096;\u7ffb\u8bd1\u6587\u672c:\\\\n${event.data.text}&#096;)<br \/>\n        }<\/p>\n<p>        \/\/ \u6587\u672c\u9009\u4e2d\u6d88\u606f &#8211; \u4f7f\u7528\u7236\u9875\u9762\u6355\u83b7\u7684\u9f20\u6807\u5750\u6807<br \/>\n        if (event.data.type &#061;&#061;&#061; &#039;TEXT_SELECTED&#039;) {<br \/>\n          const mousePos &#061; mousePositionRef.current<br \/>\n          const selectedText &#061; event.data.text<\/p>\n<p>          console.log(&#039;\u2713 \u6536\u5230\u6587\u672c\u9009\u4e2d\u4e8b\u4ef6:&#039;, {<br \/>\n            text: selectedText,<br \/>\n            mousePosition: mousePos,<br \/>\n            timestamp: event.data.timestamp,<br \/>\n          })<\/p>\n<p>          \/\/ \u4fdd\u5b58\u9009\u4e2d\u7684\u6587\u672c\u5230 state \u5e76\u663e\u793a\u60ac\u6d6e\u83dc\u5355&#xff08;\u56fa\u5b9a\u5230\u5c4f\u5e55\u4e2d\u5fc3&#xff09;<br \/>\n          setContextMenu({<br \/>\n            visible: true,<br \/>\n            x: 0, \/\/ \u4e0d\u518d\u4f7f\u7528\u9f20\u6807\u5750\u6807<br \/>\n            y: 0,<br \/>\n            selectedText: selectedText,<br \/>\n          })<\/p>\n<p>          console.log(&#039;\u9009\u4e2d\u6587\u672c\u5df2\u4fdd\u5b58\u5230 state:&#039;, selectedText)<br \/>\n          console.log(&#039;\u60ac\u6d6e\u83dc\u5355\u663e\u793a\u5728\u5750\u6807:&#039;, mousePos)<br \/>\n        }<\/p>\n<p>        \/\/ \u9690\u85cf\u6587\u672c\u9009\u4e2d\u83dc\u5355\u6d88\u606f<br \/>\n        if (event.data.type &#061;&#061;&#061; &#039;HIDE_TEXT_SELECTED&#039;) {<br \/>\n          console.log(&#039;\u2713 \u6536\u5230\u9690\u85cf\u83dc\u5355\u4e8b\u4ef6:&#039;, {<br \/>\n            timestamp: event.data.timestamp,<br \/>\n          })<\/p>\n<p>          setContextMenu({<br \/>\n            visible: false,<br \/>\n            x: 0,<br \/>\n            y: 0,<br \/>\n            selectedText: &#039;&#039;,<br \/>\n          })<\/p>\n<p>          console.log(&#039;\u60ac\u6d6e\u83dc\u5355\u5df2\u9690\u85cf&#039;)<br \/>\n        }<br \/>\n      }<br \/>\n    }<\/p>\n<p>    window.addEventListener(&#039;message&#039;, handleMessage)<br \/>\n    return () &#061;&gt; {<br \/>\n      window.removeEventListener(&#039;message&#039;, handleMessage)<br \/>\n    }<br \/>\n  }, [])<\/p>\n<p>  \/\/ \u76d1\u542c\u5168\u5c40\u70b9\u51fb\u4e8b\u4ef6&#xff0c;\u70b9\u51fb\u83dc\u5355\u5916\u90e8\u65f6\u9690\u85cf\u83dc\u5355<br \/>\n  useEffect(() &#061;&gt; {<br \/>\n    if (!contextMenu.visible) return<\/p>\n<p>    const handleClickOutside &#061; (e: MouseEvent) &#061;&gt; {<br \/>\n      const target &#061; e.target as HTMLElement<br \/>\n      \/\/ \u68c0\u67e5\u70b9\u51fb\u7684\u5143\u7d20\u662f\u5426\u5728\u83dc\u5355\u5185\u90e8<br \/>\n      const menuElement &#061; document.getElementById(&#039;context-menu&#039;)<br \/>\n      if (menuElement &amp;&amp; !menuElement.contains(target)) {<br \/>\n        setContextMenu((prev) &#061;&gt; ({ &#8230;prev, visible: false }))<br \/>\n      }<br \/>\n    }<\/p>\n<p>    \/\/ \u5ef6\u8fdf\u6dfb\u52a0\u4e8b\u4ef6\u76d1\u542c&#xff0c;\u907f\u514d\u83dc\u5355\u521a\u663e\u793a\u5c31\u88ab\u5173\u95ed<br \/>\n    const timer &#061; setTimeout(() &#061;&gt; {<br \/>\n      document.addEventListener(&#039;click&#039;, handleClickOutside)<br \/>\n    }, 100)<\/p>\n<p>    return () &#061;&gt; {<br \/>\n      clearTimeout(timer)<br \/>\n      document.removeEventListener(&#039;click&#039;, handleClickOutside)<br \/>\n    }<br \/>\n  }, [contextMenu.visible])<\/p>\n<p>  \/\/ \u6dfb\u52a0\u5230\u5bf9\u8bdd<br \/>\n  const handleAddToChat &#061; () &#061;&gt; {<br \/>\n    console.log(&#039;\u6dfb\u52a0\u5230\u5bf9\u8bdd &#8211; \u9009\u4e2d\u7684\u6587\u672c:&#039;, contextMenu.selectedText)<br \/>\n    setContextMenu((prev) &#061;&gt; ({ &#8230;prev, visible: false }))<br \/>\n  }<\/p>\n<p>  \/\/ \u7ffb\u8bd1<br \/>\n  const handleTranslateText &#061; () &#061;&gt; {<br \/>\n    console.log(&#039;\u7ffb\u8bd1 &#8211; \u9009\u4e2d\u7684\u6587\u672c:&#039;, contextMenu.selectedText)<br \/>\n    setContextMenu((prev) &#061;&gt; ({ &#8230;prev, visible: false }))<br \/>\n  }<\/p>\n<p>  const handleTest &#061; (type: any) &#061;&gt; {<br \/>\n    setError(null)<\/p>\n<p>    \/\/ \u5148\u9500\u6bc1\u65e7\u7684\u7f16\u8f91\u5668<br \/>\n    if (docEditorRef.current) {<br \/>\n      try {<br \/>\n        docEditorRef.current.destroyEditor()<br \/>\n        docEditorRef.current &#061; null<br \/>\n      } catch (error) {<br \/>\n        console.warn(&#039;\u9500\u6bc1\u65e7\u7f16\u8f91\u5668\u5931\u8d25:&#039;, error)<br \/>\n      }<br \/>\n    }<\/p>\n<p>    \/\/ \u91cd\u7f6e\u72b6\u6001<br \/>\n    setIsPreviewReady(false)<br \/>\n    setIsUploading(false)<br \/>\n    setUploadedFile(null)<\/p>\n<p>    \/\/ \u6839\u636e\u6d4b\u8bd5\u7c7b\u578b\u8bbe\u7f6e\u5b8c\u6574\u7684\u6587\u4ef6\u4fe1\u606f<br \/>\n    let testFileData: UploadedFile<br \/>\n    if (type &#061;&#061;&#061; &#039;1&#039;) {<br \/>\n      testFileData &#061; {<br \/>\n        file: {} as File, \/\/ \u6d4b\u8bd5\u6587\u4ef6\u4e0d\u9700\u8981\u5b9e\u9645 File \u5bf9\u8c61<br \/>\n        name: &#039;\u6d4b\u8bd5\u6587\u6863.docx&#039;,<br \/>\n        size: 245760, \/\/ 240 KB<br \/>\n        type: &#039;word&#039;,<br \/>\n        uploadTime: Date.now(),<br \/>\n        previewUrl:<br \/>\n          &#039;https:\/\/static.xutongbao.top\/ai\/onlyoffice\/1769051991957_%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%8B.docx&#039;,<br \/>\n      }<br \/>\n    } else if (type &#061;&#061;&#061; &#039;2&#039;) {<br \/>\n      testFileData &#061; {<br \/>\n        file: {} as File,<br \/>\n        name: &#039;\u6d4b\u8bd5\u8868\u683c.xlsx&#039;,<br \/>\n        size: 102400, \/\/ 100 KB<br \/>\n        type: &#039;cell&#039;,<br \/>\n        uploadTime: Date.now(),<br \/>\n        previewUrl:<br \/>\n          &#039;https:\/\/static.xutongbao.top\/ai\/onlyoffice\/1769053651678_1.xlsx&#039;,<br \/>\n      }<br \/>\n    } else if (type &#061;&#061;&#061; &#039;3&#039;) {<br \/>\n      testFileData &#061; {<br \/>\n        file: {} as File,<br \/>\n        name: &#039;\u6d4b\u8bd5\u6f14\u793a\u6587\u7a3f.pptx&#039;,<br \/>\n        size: 512000, \/\/ 500 KB<br \/>\n        type: &#039;slide&#039;,<br \/>\n        uploadTime: Date.now(),<br \/>\n        previewUrl:<br \/>\n          &#039;https:\/\/static.xutongbao.top\/ai\/onlyoffice\/1769053694718_1.pptx&#039;,<br \/>\n      }<br \/>\n    } else if (type &#061;&#061;&#061; &#039;4&#039;) {<br \/>\n      testFileData &#061; {<br \/>\n        file: {} as File,<br \/>\n        name: &#039;\u6d4b\u8bd5\u6587\u6863.pdf&#039;,<br \/>\n        size: 1024000, \/\/ 1 MB<br \/>\n        type: &#039;word&#039;, \/\/ PDF \u4f7f\u7528 word \u7c7b\u578b<br \/>\n        uploadTime: Date.now(),<br \/>\n        previewUrl:<br \/>\n          &#039;https:\/\/static.xutongbao.top\/ai\/onlyoffice\/1769054138134_%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%8B.pdf&#039;,<br \/>\n      }<br \/>\n    } else {<br \/>\n      return<br \/>\n    }<\/p>\n<p>    \/\/ \u5ef6\u8fdf\u8bbe\u7f6e\u65b0\u6587\u4ef6&#xff0c;\u786e\u4fdd DOM \u5b8c\u5168\u6e05\u7406<br \/>\n    setTimeout(() &#061;&gt; {<br \/>\n      setUploadedFile(testFileData)<br \/>\n      setTimeout(() &#061;&gt; {<br \/>\n        setIsPreviewReady(true)<br \/>\n      }, 100)<br \/>\n    }, 100)<br \/>\n  }<\/p>\n<p>  \/\/ \u62d6\u62fd\u4e8b\u4ef6\u5904\u7406<br \/>\n  const handleDragOver &#061; (e: React.DragEvent) &#061;&gt; {<br \/>\n    e.preventDefault()<br \/>\n    setIsDragOver(true)<br \/>\n  }<\/p>\n<p>  const handleDragLeave &#061; () &#061;&gt; {<br \/>\n    setIsDragOver(false)<br \/>\n  }<\/p>\n<p>  const handleDrop &#061; (e: React.DragEvent) &#061;&gt; {<br \/>\n    e.preventDefault()<br \/>\n    setIsDragOver(false)<\/p>\n<p>    const file &#061; e.dataTransfer.files[0]<br \/>\n    if (file) {<br \/>\n      handleFileSelect(file)<br \/>\n    }<br \/>\n  }<\/p>\n<p>  \/\/ \u6e05\u9664\u6587\u4ef6<br \/>\n  const handleClearFile &#061; () &#061;&gt; {<br \/>\n    setUploadedFile(null)<br \/>\n    setIsPreviewReady(false)<br \/>\n    setError(null)<br \/>\n    if (fileInputRef.current) {<br \/>\n      fileInputRef.current.value &#061; &#039;&#039;<br \/>\n    }<br \/>\n  }<\/p>\n<p>  return (<br \/>\n    &lt;&gt;<br \/>\n      {\/* \u52a0\u8f7d OnlyOffice API \u811a\u672c *\/}<br \/>\n      &lt;Script<br \/>\n        src&#061;&#039;https:\/\/chat.xutongbao.top\/onlyoffice\/web-apps\/apps\/api\/documents\/api.js&#039;<br \/>\n        \/\/ src&#061;&#039;http:\/\/20.51.117.204\/web-apps\/apps\/api\/documents\/api.js&#039;<br \/>\n        strategy&#061;&#039;afterInteractive&#039;<br \/>\n        onLoad&#061;{() &#061;&gt; {<br \/>\n          console.log(&#039;OnlyOffice API \u52a0\u8f7d\u5b8c\u6210&#039;)<br \/>\n          setScriptLoaded(true)<br \/>\n        }}<br \/>\n        onError&#061;{(e) &#061;&gt; {<br \/>\n          console.error(&#039;OnlyOffice API \u52a0\u8f7d\u5931\u8d25:&#039;, e)<br \/>\n          setError(&#039;OnlyOffice API \u52a0\u8f7d\u5931\u8d25&#xff0c;\u8bf7\u68c0\u67e5\u7f51\u7edc\u8fde\u63a5\u6216\u670d\u52a1\u5668\u914d\u7f6e&#039;)<br \/>\n        }}<br \/>\n      \/&gt;<\/p>\n<p>      &lt;Header \/&gt;<\/p>\n<p>      &lt;main className&#061;&#039;m-only-office min-h-screen bg-gradient-to-br from-primary\/5 via-background to-secondary\/5 relative overflow-hidden&#039;&gt;<br \/>\n        {\/* \u80cc\u666f\u88c5\u9970 *\/}<br \/>\n        &lt;div className&#061;&#039;absolute inset-0 overflow-hidden pointer-events-none&#039;&gt;<br \/>\n          &lt;div className&#061;&#039;absolute top-20 left-1\/4 w-96 h-96 bg-primary\/5 rounded-full blur-3xl animate-pulse-slow&#039; \/&gt;<br \/>\n          &lt;div<br \/>\n            className&#061;&#039;absolute bottom-20 right-1\/4 w-96 h-96 bg-secondary\/5 rounded-full blur-3xl animate-pulse-slow&#039;<br \/>\n            style&#061;{{ animationDelay: &#039;2s&#039; }}<br \/>\n          \/&gt;<br \/>\n          &lt;div className&#061;&#039;absolute top-1\/2 left-1\/2 -translate-x-1\/2 -translate-y-1\/2 w-[800px] h-[800px] bg-gradient-to-r from-primary\/3 to-secondary\/3 rounded-full blur-3xl animate-spin-slow&#039; \/&gt;<br \/>\n        &lt;\/div&gt;<\/p>\n<p>        {\/* \u5185\u5bb9\u533a\u57df *\/}<br \/>\n        &lt;div className&#061;&#039;relative max-w-7xl mx-auto px-4 py-8&#039;&gt;<br \/>\n          {\/* \u8fd4\u56de\u6309\u94ae *\/}<br \/>\n          &lt;button<br \/>\n            onClick&#061;{() &#061;&gt; router.push(&#039;\/light&#039;)}<br \/>\n            className&#061;&#039;group mb-8 flex items-center gap-2 px-4 py-3 rounded-2xl bg-card\/80 backdrop-blur-xl border-2 border-border hover:border-primary shadow-lg hover:shadow-xl transition-all duration-300 hover:scale-105 animate-fade-in&#039;<br \/>\n          &gt;<br \/>\n            &lt;div className&#061;&#039;relative&#039;&gt;<br \/>\n              &lt;div className&#061;&#039;absolute inset-0 bg-primary\/20 rounded-full blur-md scale-0 group-hover:scale-150 transition-transform duration-500&#039; \/&gt;<br \/>\n              &lt;ArrowLeft className&#061;&#039;relative w-5 h-5 text-primary group-hover:text-primary transition-all duration-300 group-hover:-translate-x-1&#039; \/&gt;<br \/>\n            &lt;\/div&gt;<br \/>\n            &lt;span className&#061;&#039;text-sm font-medium text-foreground group-hover:text-primary transition-colors duration-300&#039;&gt;<br \/>\n              \u8fd4\u56de<br \/>\n            &lt;\/span&gt;<br \/>\n          &lt;\/button&gt;<\/p>\n<p>          {\/* \u4e3b\u6807\u9898\u5361\u7247 *\/}<br \/>\n          &lt;div className&#061;&#039;mb-8 p-8 rounded-3xl bg-gradient-to-br from-card\/95 to-card\/80 backdrop-blur-2xl border-2 border-border\/50 shadow-2xl animate-fade-in&#039;&gt;<br \/>\n            &lt;div className&#061;&#039;flex items-center gap-4 mb-3&#039;&gt;<br \/>\n              &lt;div className&#061;&#039;relative&#039;&gt;<br \/>\n                &lt;div className&#061;&#039;absolute inset-0 bg-primary\/20 rounded-2xl blur-xl animate-pulse-slow&#039; \/&gt;<br \/>\n                &lt;div className&#061;&#039;relative w-16 h-16 rounded-2xl bg-gradient-to-br from-primary to-primary\/70 flex items-center justify-center shadow-lg&#039;&gt;<br \/>\n                  &lt;FileText className&#061;&#039;w-8 h-8 text-primary-foreground&#039; \/&gt;<br \/>\n                &lt;\/div&gt;<br \/>\n              &lt;\/div&gt;<br \/>\n              &lt;div className&#061;&#039;flex-1&#039;&gt;<br \/>\n                &lt;h1 className&#061;&#039;text-3xl md:text-4xl font-bold bg-gradient-to-r from-primary via-secondary to-accent bg-clip-text text-transparent&#039;&gt;<br \/>\n                  OnlyOffice \u6587\u6863\u9884\u89c8<br \/>\n                &lt;\/h1&gt;<br \/>\n                &lt;p className&#061;&#039;text-sm text-muted-foreground mt-1&#039;&gt;<br \/>\n                  \u652f\u6301 Word\u3001Excel\u3001PowerPoint \u7b49\u591a\u79cd\u683c\u5f0f\u7684\u6587\u6863\u5728\u7ebf\u9884\u89c8<br \/>\n                &lt;\/p&gt;<br \/>\n              &lt;\/div&gt;<br \/>\n            &lt;\/div&gt;<\/p>\n<p>            {\/* \u652f\u6301\u683c\u5f0f\u8bf4\u660e *\/}<br \/>\n            &lt;div className&#061;&#039;mt-4 p-4 rounded-xl bg-muted\/30 border border-border\/50&#039;&gt;<br \/>\n              &lt;div className&#061;&#039;flex items-center gap-2 mb-2&#039;&gt;<br \/>\n                &lt;Sparkles className&#061;&#039;w-4 h-4 text-primary&#039; \/&gt;<br \/>\n                &lt;span className&#061;&#039;text-sm font-semibold text-foreground&#039;&gt;<br \/>\n                  \u652f\u6301\u7684\u6587\u4ef6\u683c\u5f0f<br \/>\n                &lt;\/span&gt;<br \/>\n              &lt;\/div&gt;<br \/>\n              &lt;div className&#061;&#039;grid grid-cols-1 md:grid-cols-3 gap-2 text-xs text-muted-foreground&#039;&gt;<br \/>\n                &lt;div&gt;<br \/>\n                  &lt;span className&#061;&#039;font-medium text-foreground&#039;&gt;\u6587\u6863&#xff1a;&lt;\/span&gt;<br \/>\n                  DOC, DOCX, ODT, RTF, TXT, PDF \u7b49<br \/>\n                &lt;\/div&gt;<br \/>\n                &lt;div&gt;<br \/>\n                  &lt;span className&#061;&#039;font-medium text-foreground&#039;&gt;\u8868\u683c&#xff1a;&lt;\/span&gt;<br \/>\n                  XLS, XLSX, ODS, CSV \u7b49<br \/>\n                &lt;\/div&gt;<br \/>\n                &lt;div&gt;<br \/>\n                  &lt;span className&#061;&#039;font-medium text-foreground&#039;&gt;\u6f14\u793a&#xff1a;&lt;\/span&gt;<br \/>\n                  PPT, PPTX, ODP \u7b49<br \/>\n                &lt;\/div&gt;<br \/>\n              &lt;\/div&gt;<br \/>\n            &lt;\/div&gt;<br \/>\n          &lt;\/div&gt;<\/p>\n<p>          {\/* \u6d4b\u8bd5\u6309\u94ae\u7ec4 *\/}<br \/>\n          &lt;div className&#061;&#039;mb-8 p-6 rounded-3xl bg-gradient-to-br from-card\/95 to-card\/80 backdrop-blur-2xl border-2 border-border\/50 shadow-2xl animate-fade-in&#039;&gt;<br \/>\n            &lt;div className&#061;&#039;flex items-center gap-2 mb-4&#039;&gt;<br \/>\n              &lt;Sparkles className&#061;&#039;w-5 h-5 text-primary&#039; \/&gt;<br \/>\n              &lt;h2 className&#061;&#039;text-lg font-semibold text-foreground&#039;&gt;<br \/>\n                \u5feb\u901f\u6d4b\u8bd5<br \/>\n              &lt;\/h2&gt;<br \/>\n            &lt;\/div&gt;<br \/>\n            &lt;div className&#061;&#039;grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4&#039;&gt;<br \/>\n              {\/* Word \u6d4b\u8bd5\u6309\u94ae *\/}<br \/>\n              &lt;button<br \/>\n                onClick&#061;{() &#061;&gt; handleTest(&#039;1&#039;)}<br \/>\n                className&#061;&#039;group relative overflow-hidden px-6 py-4 rounded-2xl bg-gradient-to-br from-blue-500\/10 to-blue-600\/5 backdrop-blur-xl border-2 border-blue-500\/30 hover:border-blue-500 shadow-lg hover:shadow-2xl hover:shadow-blue-500\/20 transition-all duration-300 hover:scale-105&#039;<br \/>\n              &gt;<br \/>\n                &lt;div className&#061;&#039;absolute inset-0 bg-gradient-to-br from-blue-500\/0 to-blue-600\/0 group-hover:from-blue-500\/10 group-hover:to-blue-600\/5 transition-all duration-300&#039; \/&gt;<br \/>\n                &lt;div className&#061;&#039;relative flex flex-col items-center gap-3&#039;&gt;<br \/>\n                  &lt;div className&#061;&#039;w-12 h-12 rounded-xl bg-gradient-to-br from-blue-500 to-blue-600 flex items-center justify-center shadow-lg group-hover:scale-110 transition-transform duration-300&#039;&gt;<br \/>\n                    &lt;FileText className&#061;&#039;w-6 h-6 text-white&#039; \/&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                  &lt;div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-sm font-semibold text-foreground group-hover:text-blue-600 transition-colors duration-300&#039;&gt;<br \/>\n                      \u6d4b\u8bd5 Word<br \/>\n                    &lt;\/div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-xs text-muted-foreground mt-1&#039;&gt;<br \/>\n                      \u6587\u6863\u7f16\u8f91\u5668<br \/>\n                    &lt;\/div&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                &lt;\/div&gt;<br \/>\n              &lt;\/button&gt;<\/p>\n<p>              {\/* Excel \u6d4b\u8bd5\u6309\u94ae *\/}<br \/>\n              &lt;button<br \/>\n                onClick&#061;{() &#061;&gt; handleTest(&#039;2&#039;)}<br \/>\n                className&#061;&#039;group relative overflow-hidden px-6 py-4 rounded-2xl bg-gradient-to-br from-green-500\/10 to-green-600\/5 backdrop-blur-xl border-2 border-green-500\/30 hover:border-green-500 shadow-lg hover:shadow-2xl hover:shadow-green-500\/20 transition-all duration-300 hover:scale-105&#039;<br \/>\n              &gt;<br \/>\n                &lt;div className&#061;&#039;absolute inset-0 bg-gradient-to-br from-green-500\/0 to-green-600\/0 group-hover:from-green-500\/10 group-hover:to-green-600\/5 transition-all duration-300&#039; \/&gt;<br \/>\n                &lt;div className&#061;&#039;relative flex flex-col items-center gap-3&#039;&gt;<br \/>\n                  &lt;div className&#061;&#039;w-12 h-12 rounded-xl bg-gradient-to-br from-green-500 to-green-600 flex items-center justify-center shadow-lg group-hover:scale-110 transition-transform duration-300&#039;&gt;<br \/>\n                    &lt;File className&#061;&#039;w-6 h-6 text-white&#039; \/&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                  &lt;div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-sm font-semibold text-foreground group-hover:text-green-600 transition-colors duration-300&#039;&gt;<br \/>\n                      \u6d4b\u8bd5 Excel<br \/>\n                    &lt;\/div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-xs text-muted-foreground mt-1&#039;&gt;<br \/>\n                      \u8868\u683c\u7f16\u8f91\u5668<br \/>\n                    &lt;\/div&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                &lt;\/div&gt;<br \/>\n              &lt;\/button&gt;<\/p>\n<p>              {\/* PowerPoint \u6d4b\u8bd5\u6309\u94ae *\/}<br \/>\n              &lt;button<br \/>\n                onClick&#061;{() &#061;&gt; handleTest(&#039;3&#039;)}<br \/>\n                className&#061;&#039;group relative overflow-hidden px-6 py-4 rounded-2xl bg-gradient-to-br from-orange-500\/10 to-orange-600\/5 backdrop-blur-xl border-2 border-orange-500\/30 hover:border-orange-500 shadow-lg hover:shadow-2xl hover:shadow-orange-500\/20 transition-all duration-300 hover:scale-105&#039;<br \/>\n              &gt;<br \/>\n                &lt;div className&#061;&#039;absolute inset-0 bg-gradient-to-br from-orange-500\/0 to-orange-600\/0 group-hover:from-orange-500\/10 group-hover:to-orange-600\/5 transition-all duration-300&#039; \/&gt;<br \/>\n                &lt;div className&#061;&#039;relative flex flex-col items-center gap-3&#039;&gt;<br \/>\n                  &lt;div className&#061;&#039;w-12 h-12 rounded-xl bg-gradient-to-br from-orange-500 to-orange-600 flex items-center justify-center shadow-lg group-hover:scale-110 transition-transform duration-300&#039;&gt;<br \/>\n                    &lt;FileText className&#061;&#039;w-6 h-6 text-white&#039; \/&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                  &lt;div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-sm font-semibold text-foreground group-hover:text-orange-600 transition-colors duration-300&#039;&gt;<br \/>\n                      \u6d4b\u8bd5 PowerPoint<br \/>\n                    &lt;\/div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-xs text-muted-foreground mt-1&#039;&gt;<br \/>\n                      \u6f14\u793a\u6587\u7a3f\u7f16\u8f91\u5668<br \/>\n                    &lt;\/div&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                &lt;\/div&gt;<br \/>\n              &lt;\/button&gt;<\/p>\n<p>              {\/* PDF \u6d4b\u8bd5\u6309\u94ae *\/}<br \/>\n              &lt;button<br \/>\n                onClick&#061;{() &#061;&gt; handleTest(&#039;4&#039;)}<br \/>\n                className&#061;&#039;group relative overflow-hidden px-6 py-4 rounded-2xl bg-gradient-to-br from-red-500\/10 to-red-600\/5 backdrop-blur-xl border-2 border-red-500\/30 hover:border-red-500 shadow-lg hover:shadow-2xl hover:shadow-red-500\/20 transition-all duration-300 hover:scale-105&#039;<br \/>\n              &gt;<br \/>\n                &lt;div className&#061;&#039;absolute inset-0 bg-gradient-to-br from-red-500\/0 to-red-600\/0 group-hover:from-red-500\/10 group-hover:to-red-600\/5 transition-all duration-300&#039; \/&gt;<br \/>\n                &lt;div className&#061;&#039;relative flex flex-col items-center gap-3&#039;&gt;<br \/>\n                  &lt;div className&#061;&#039;w-12 h-12 rounded-xl bg-gradient-to-br from-red-500 to-red-600 flex items-center justify-center shadow-lg group-hover:scale-110 transition-transform duration-300&#039;&gt;<br \/>\n                    &lt;FileText className&#061;&#039;w-6 h-6 text-white&#039; \/&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                  &lt;div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-sm font-semibold text-foreground group-hover:text-red-600 transition-colors duration-300&#039;&gt;<br \/>\n                      \u6d4b\u8bd5 PDF<br \/>\n                    &lt;\/div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-xs text-muted-foreground mt-1&#039;&gt;<br \/>\n                      PDF \u9605\u8bfb\u5668<br \/>\n                    &lt;\/div&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                &lt;\/div&gt;<br \/>\n              &lt;\/button&gt;<br \/>\n            &lt;\/div&gt;<br \/>\n          &lt;\/div&gt;<\/p>\n<p>          {\/* \u4e0a\u4f20\u533a\u57df\u6216\u6587\u4ef6\u9884\u89c8 *\/}<br \/>\n          {!uploadedFile ? (<br \/>\n            &lt;div className&#061;&#039;p-8 rounded-3xl bg-gradient-to-br from-card\/95 to-card\/80 backdrop-blur-2xl border-2 border-border\/50 shadow-2xl animate-fade-in-up&#039;&gt;<br \/>\n              &lt;div<br \/>\n                className&#061;{&#096;<br \/>\n                  border-2 border-dashed rounded-2xl p-16 text-center cursor-pointer<br \/>\n                  transition-all duration-300 relative overflow-hidden<br \/>\n                  ${<br \/>\n                    isDragOver<br \/>\n                      ? &#039;border-primary bg-primary\/10 scale-[1.02]&#039;<br \/>\n                      : &#039;border-border hover:border-primary\/50 hover:bg-muted\/30&#039;<br \/>\n                  }<br \/>\n                &#096;}<br \/>\n                onClick&#061;{() &#061;&gt; fileInputRef.current?.click()}<br \/>\n                onDragOver&#061;{handleDragOver}<br \/>\n                onDragLeave&#061;{handleDragLeave}<br \/>\n                onDrop&#061;{handleDrop}<br \/>\n              &gt;<br \/>\n                {\/* \u88c5\u9970\u6027\u80cc\u666f *\/}<br \/>\n                &lt;div className&#061;&#039;absolute inset-0 overflow-hidden pointer-events-none&#039;&gt;<br \/>\n                  &lt;div className&#061;&#039;absolute top-0 left-1\/4 w-32 h-32 bg-primary\/5 rounded-full blur-2xl animate-float&#039; \/&gt;<br \/>\n                  &lt;div<br \/>\n                    className&#061;&#039;absolute bottom-0 right-1\/4 w-32 h-32 bg-secondary\/5 rounded-full blur-2xl animate-float&#039;<br \/>\n                    style&#061;{{ animationDelay: &#039;1s&#039; }}<br \/>\n                  \/&gt;<br \/>\n                &lt;\/div&gt;<\/p>\n<p>                &lt;div className&#061;&#039;relative flex flex-col items-center gap-6&#039;&gt;<br \/>\n                  &lt;div<br \/>\n                    className&#061;{&#096;<br \/>\n                      w-24 h-24 rounded-full flex items-center justify-center<br \/>\n                      transition-all duration-500<br \/>\n                      ${<br \/>\n                        isDragOver<br \/>\n                          ? &#039;bg-primary scale-110 shadow-2xl shadow-primary\/50&#039;<br \/>\n                          : &#039;bg-gradient-to-br from-primary\/20 to-secondary\/20 shadow-lg&#039;<br \/>\n                      }<br \/>\n                    &#096;}<br \/>\n                  &gt;<br \/>\n                    {isUploading ? (<br \/>\n                      &lt;Loader2 className&#061;&#039;w-12 h-12 text-primary animate-spin&#039; \/&gt;<br \/>\n                    ) : (<br \/>\n                      &lt;Upload<br \/>\n                        className&#061;{&#096;w-12 h-12 transition-all duration-300 ${<br \/>\n                          isDragOver ? &#039;text-white scale-110&#039; : &#039;text-primary&#039;<br \/>\n                        }&#096;}<br \/>\n                      \/&gt;<br \/>\n                    )}<br \/>\n                  &lt;\/div&gt;<\/p>\n<p>                  &lt;div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-2xl font-bold text-foreground mb-2&#039;&gt;<br \/>\n                      {isUploading<br \/>\n                        ? &#039;\u4e0a\u4f20\u4e2d&#8230;&#039;<br \/>\n                        : isDragOver<br \/>\n                          ? &#039;\u677e\u5f00\u4ee5\u4e0a\u4f20\u6587\u4ef6&#039;<br \/>\n                          : &#039;\u70b9\u51fb\u6216\u62d6\u62fd\u6587\u4ef6\u5230\u6b64\u5904&#039;}<br \/>\n                    &lt;\/div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-sm text-muted-foreground mb-4&#039;&gt;<br \/>\n                      \u652f\u6301 Word\u3001Excel\u3001PowerPoint\u3001PDF \u7b49\u591a\u79cd\u683c\u5f0f<br \/>\n                    &lt;\/div&gt;<\/p>\n<p>                    {\/* \u4e0a\u4f20\u8fdb\u5ea6\u6761 *\/}<br \/>\n                    {isUploading &amp;&amp; uploadProgress &gt; 0 &amp;&amp; (<br \/>\n                      &lt;div className&#061;&#039;w-64 mx-auto mb-4&#039;&gt;<br \/>\n                        &lt;div className&#061;&#039;flex items-center justify-between text-xs text-muted-foreground mb-1&#039;&gt;<br \/>\n                          &lt;span&gt;\u4e0a\u4f20\u8fdb\u5ea6&lt;\/span&gt;<br \/>\n                          &lt;span&gt;{uploadProgress}%&lt;\/span&gt;<br \/>\n                        &lt;\/div&gt;<br \/>\n                        &lt;div className&#061;&#039;w-full h-2 bg-muted rounded-full overflow-hidden&#039;&gt;<br \/>\n                          &lt;div<br \/>\n                            className&#061;&#039;h-full bg-gradient-to-r from-primary to-secondary transition-all duration-300&#039;<br \/>\n                            style&#061;{{ width: &#096;${uploadProgress}%&#096; }}<br \/>\n                          \/&gt;<br \/>\n                        &lt;\/div&gt;<br \/>\n                      &lt;\/div&gt;<br \/>\n                    )}<\/p>\n<p>                    &lt;div className&#061;&#039;inline-flex items-center gap-2 px-4 py-2 rounded-full bg-primary\/10 border border-primary\/20&#039;&gt;<br \/>\n                      &lt;FolderOpen className&#061;&#039;w-4 h-4 text-primary&#039; \/&gt;<br \/>\n                      &lt;span className&#061;&#039;text-xs font-medium text-primary&#039;&gt;<br \/>\n                        \u5355\u4e2a\u6587\u4ef6&#xff0c;\u6700\u5927\u652f\u6301 100MB<br \/>\n                      &lt;\/span&gt;<br \/>\n                    &lt;\/div&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                &lt;\/div&gt;<br \/>\n              &lt;\/div&gt;<\/p>\n<p>              &lt;input<br \/>\n                ref&#061;{fileInputRef}<br \/>\n                type&#061;&#039;file&#039;<br \/>\n                accept&#061;{ALL_FORMATS.join(&#039;,&#039;)}<br \/>\n                className&#061;&#039;hidden&#039;<br \/>\n                onChange&#061;{(e) &#061;&gt; {<br \/>\n                  const file &#061; e.target.files?.[0]<br \/>\n                  if (file) handleFileSelect(file)<br \/>\n                }}<br \/>\n              \/&gt;<\/p>\n<p>              {\/* \u9519\u8bef\u63d0\u793a *\/}<br \/>\n              {error &amp;&amp; (<br \/>\n                &lt;div className&#061;&#039;mt-6 p-4 rounded-xl bg-destructive\/10 border-2 border-destructive\/30 flex items-start gap-3 animate-shake&#039;&gt;<br \/>\n                  &lt;AlertCircle className&#061;&#039;w-5 h-5 text-destructive mt-0.5 flex-shrink-0&#039; \/&gt;<br \/>\n                  &lt;div className&#061;&#039;flex-1&#039;&gt;<br \/>\n                    &lt;div className&#061;&#039;font-semibold text-destructive mb-1&#039;&gt;<br \/>\n                      \u4e0a\u4f20\u5931\u8d25<br \/>\n                    &lt;\/div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-sm text-destructive\/80&#039;&gt;{error}&lt;\/div&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                &lt;\/div&gt;<br \/>\n              )}<br \/>\n            &lt;\/div&gt;<br \/>\n          ) : (<br \/>\n            &lt;&gt;<br \/>\n              {\/* \u6587\u4ef6\u4fe1\u606f\u5361\u7247 *\/}<br \/>\n              &lt;div className&#061;&#039;mb-6 p-6 rounded-3xl bg-gradient-to-br from-card\/95 to-card\/80 backdrop-blur-2xl border-2 border-primary\/30 shadow-2xl animate-fade-in&#039;&gt;<br \/>\n                &lt;div className&#061;&#039;flex items-center justify-between&#039;&gt;<br \/>\n                  &lt;div className&#061;&#039;flex items-center gap-4 flex-1&#039;&gt;<br \/>\n                    &lt;div className&#061;&#039;relative&#039;&gt;<br \/>\n                      &lt;div className&#061;&#039;absolute inset-0 bg-green-500\/20 rounded-xl blur-lg animate-pulse-slow&#039; \/&gt;<br \/>\n                      &lt;div className&#061;&#039;relative w-12 h-12 rounded-xl bg-gradient-to-br from-green-500 to-green-600 flex items-center justify-center shadow-lg&#039;&gt;<br \/>\n                        &lt;File className&#061;&#039;w-6 h-6 text-white&#039; \/&gt;<br \/>\n                      &lt;\/div&gt;<br \/>\n                    &lt;\/div&gt;<br \/>\n                    &lt;div className&#061;&#039;flex-1 min-w-0&#039;&gt;<br \/>\n                      &lt;div className&#061;&#039;flex items-center gap-2 mb-1&#039;&gt;<br \/>\n                        &lt;h3 className&#061;&#039;text-lg font-semibold text-foreground truncate&#039;&gt;<br \/>\n                          {uploadedFile.name}<br \/>\n                        &lt;\/h3&gt;<br \/>\n                        {isPreviewReady &amp;&amp; (<br \/>\n                          &lt;div className&#061;&#039;flex items-center gap-1 px-2 py-1 rounded-full bg-green-500\/10 border border-green-500\/30&#039;&gt;<br \/>\n                            &lt;CheckCircle2 className&#061;&#039;w-3 h-3 text-green-500&#039; \/&gt;<br \/>\n                            &lt;span className&#061;&#039;text-xs font-medium text-green-500&#039;&gt;<br \/>\n                              \u9884\u89c8\u5c31\u7eea<br \/>\n                            &lt;\/span&gt;<br \/>\n                          &lt;\/div&gt;<br \/>\n                        )}<br \/>\n                      &lt;\/div&gt;<br \/>\n                      &lt;div className&#061;&#039;flex items-center gap-3 text-xs text-muted-foreground&#039;&gt;<br \/>\n                        &lt;span&gt;{formatBytes(uploadedFile.size)}&lt;\/span&gt;<br \/>\n                        &lt;span&gt;\u2022&lt;\/span&gt;<br \/>\n                        &lt;span className&#061;&#039;capitalize&#039;&gt;<br \/>\n                          {uploadedFile.type} \u6587\u6863<br \/>\n                        &lt;\/span&gt;<br \/>\n                        &lt;span&gt;\u2022&lt;\/span&gt;<br \/>\n                        &lt;span&gt;<br \/>\n                          {new Date(<br \/>\n                            uploadedFile.uploadTime,<br \/>\n                          ).toLocaleTimeString()}<br \/>\n                        &lt;\/span&gt;<br \/>\n                      &lt;\/div&gt;<br \/>\n                      {\/* \u663e\u793a\u6587\u4ef6 URL *\/}<br \/>\n                      {uploadedFile.previewUrl &amp;&amp; (<br \/>\n                        &lt;div className&#061;&#039;mt-2 flex items-center gap-2&#039;&gt;<br \/>\n                          &lt;span className&#061;&#039;text-xs text-muted-foreground&#039;&gt;\u6587\u4ef6\u5730\u5740:&lt;\/span&gt;<br \/>\n                          &lt;a<br \/>\n                            href&#061;{uploadedFile.previewUrl}<br \/>\n                            target&#061;&#039;_blank&#039;<br \/>\n                            rel&#061;&#039;noopener noreferrer&#039;<br \/>\n                            className&#061;&#039;text-xs text-primary hover:underline truncate max-w-md&#039;<br \/>\n                          &gt;<br \/>\n                            {uploadedFile.previewUrl}<br \/>\n                          &lt;\/a&gt;<br \/>\n                        &lt;\/div&gt;<br \/>\n                      )}<br \/>\n                    &lt;\/div&gt;<br \/>\n                  &lt;\/div&gt;<\/p>\n<p>                  &lt;Button<br \/>\n                    onClick&#061;{handleClearFile}<br \/>\n                    variant&#061;&#039;outline&#039;<br \/>\n                    size&#061;&#039;sm&#039;<br \/>\n                    className&#061;&#039;rounded-xl border-2 hover:border-destructive hover:bg-destructive\/5 hover:text-destructive transition-all duration-300&#039;<br \/>\n                  &gt;<br \/>\n                    &lt;X className&#061;&#039;w-4 h-4 mr-1&#039; \/&gt;<br \/>\n                    \u5173\u95ed<br \/>\n                  &lt;\/Button&gt;<br \/>\n                &lt;\/div&gt;<br \/>\n              &lt;\/div&gt;<\/p>\n<p>              {\/* \u9884\u89c8\u533a\u57df *\/}<br \/>\n              &lt;div className&#061;&#039;rounded-3xl bg-gradient-to-br from-card\/95 to-card\/80 backdrop-blur-2xl border-2 border-border\/50 shadow-2xl animate-fade-in-up overflow-hidden&#039;&gt;<br \/>\n                {!isPreviewReady ? (<br \/>\n                  &lt;div className&#061;&#039;w-full h-[calc(100vh-300px)] min-h-[700px] flex flex-col items-center justify-center gap-4 bg-muted\/20&#039;&gt;<br \/>\n                    &lt;Loader2 className&#061;&#039;w-12 h-12 text-primary animate-spin&#039; \/&gt;<br \/>\n                    &lt;div className&#061;&#039;text-lg font-semibold text-foreground&#039;&gt;<br \/>\n                      \u6b63\u5728\u52a0\u8f7d\u9884\u89c8&#8230;<br \/>\n                    &lt;\/div&gt;<br \/>\n                    &lt;div className&#061;&#039;text-sm text-muted-foreground&#039;&gt;<br \/>\n                      \u8bf7\u7a0d\u5019\u7247\u523b<br \/>\n                    &lt;\/div&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                ) : (<br \/>\n                  &lt;div className&#061;&#039;relative&#039;&gt;<br \/>\n                    &lt;div<br \/>\n                      ref&#061;{editorContainerRef}<br \/>\n                      id&#061;&#039;onlyoffice-editor&#039;<br \/>\n                      className&#061;&#039;w-full h-[calc(100vh-300px)] min-h-[700px] bg-white&#039;<br \/>\n                    &gt;<br \/>\n                      {\/* OnlyOffice \u7f16\u8f91\u5668\u5c06\u5728\u8fd9\u91cc\u52a0\u8f7d *\/}<br \/>\n                    &lt;\/div&gt;<br \/>\n                  &lt;\/div&gt;<br \/>\n                )}<br \/>\n              &lt;\/div&gt;<br \/>\n            &lt;\/&gt;<br \/>\n          )}<br \/>\n        &lt;\/div&gt;<br \/>\n      &lt;\/main&gt;<\/p>\n<p>      {\/* \u4e0a\u4e0b\u6587\u83dc\u5355 *\/}<br \/>\n      {contextMenu.visible &amp;&amp; (<br \/>\n        &lt;div<br \/>\n          id&#061;&#039;context-menu&#039;<br \/>\n          className&#061;&#039;fixed z-50&#039;<br \/>\n          style&#061;{{<br \/>\n            left: &#039;50%&#039;,<br \/>\n            top: &#039;50%&#039;,<br \/>\n            transform: &#039;translate(-50%, -50%)&#039;,<br \/>\n          }}<br \/>\n        &gt;<br \/>\n          &lt;div className&#061;&#039;px-4 py-3 rounded-xl bg-gradient-to-br from-card\/95 to-card\/90 backdrop-blur-2xl border-2 border-border\/50 shadow-2xl&#039;&gt;<br \/>\n            &lt;div className&#061;&#039;flex items-center gap-2&#039;&gt;<br \/>\n              {\/* \u6dfb\u52a0\u5230\u5bf9\u8bdd\u6309\u94ae *\/}<br \/>\n              &lt;button<br \/>\n                onClick&#061;{handleAddToChat}<br \/>\n                className&#061;&#039;group relative px-4 py-2.5 rounded-lg hover:bg-primary\/10 transition-all duration-200 flex items-center gap-2&#039;<br \/>\n                title&#061;&#039;\u6dfb\u52a0\u5230\u5bf9\u8bdd&#039;<br \/>\n              &gt;<br \/>\n                &lt;div className&#061;&#039;absolute inset-0 bg-primary\/20 rounded-lg blur-md scale-0 group-hover:scale-100 transition-transform duration-300&#039; \/&gt;<br \/>\n                &lt;MessageSquare className&#061;&#039;relative w-4 h-4 text-foreground group-hover:text-primary transition-colors duration-200&#039; \/&gt;<br \/>\n                &lt;span className&#061;&#039;relative text-sm text-foreground group-hover:text-primary transition-colors duration-200&#039;&gt;<br \/>\n                  \u6dfb\u52a0\u5230\u5bf9\u8bdd<br \/>\n                &lt;\/span&gt;<br \/>\n              &lt;\/button&gt;<\/p>\n<p>              {\/* \u7ffb\u8bd1\u6309\u94ae *\/}<br \/>\n              &lt;button<br \/>\n                onClick&#061;{handleTranslateText}<br \/>\n                className&#061;&#039;group relative px-4 py-2.5 rounded-lg hover:bg-primary\/10 transition-all duration-200 flex items-center gap-2&#039;<br \/>\n                title&#061;&#039;\u7ffb\u8bd1&#039;<br \/>\n              &gt;<br \/>\n                &lt;div className&#061;&#039;absolute inset-0 bg-primary\/20 rounded-lg blur-md scale-0 group-hover:scale-100 transition-transform duration-300&#039; \/&gt;<br \/>\n                &lt;BookOpen className&#061;&#039;relative w-4 h-4 text-foreground group-hover:text-primary transition-colors duration-200&#039; \/&gt;<br \/>\n                &lt;span className&#061;&#039;relative text-sm text-foreground group-hover:text-primary transition-colors duration-200&#039;&gt;<br \/>\n                  \u7ffb\u8bd1<br \/>\n                &lt;\/span&gt;<br \/>\n              &lt;\/button&gt;<br \/>\n            &lt;\/div&gt;<br \/>\n          &lt;\/div&gt;<br \/>\n        &lt;\/div&gt;<br \/>\n      )}<\/p>\n<p>      {\/* \u81ea\u5b9a\u4e49\u52a8\u753b\u6837\u5f0f *\/}<br \/>\n      &lt;style jsx global&gt;{&#096;<br \/>\n        &#064;keyframes pulse-slow {<br \/>\n          0%,<br \/>\n          100% {<br \/>\n            opacity: 0.3;<br \/>\n            transform: scale(1);<br \/>\n          }<br \/>\n          50% {<br \/>\n            opacity: 0.6;<br \/>\n            transform: scale(1.05);<br \/>\n          }<br \/>\n        }<\/p>\n<p>        &#064;keyframes spin-slow {<br \/>\n          from {<br \/>\n            transform: translate(-50%, -50%) rotate(0deg);<br \/>\n          }<br \/>\n          to {<br \/>\n            transform: translate(-50%, -50%) rotate(360deg);<br \/>\n          }<br \/>\n        }<\/p>\n<p>        &#064;keyframes fade-in {<br \/>\n          from {<br \/>\n            opacity: 0;<br \/>\n            transform: translateY(10px);<br \/>\n          }<br \/>\n          to {<br \/>\n            opacity: 1;<br \/>\n            transform: translateY(0);<br \/>\n          }<br \/>\n        }<\/p>\n<p>        &#064;keyframes fade-in-up {<br \/>\n          from {<br \/>\n            opacity: 0;<br \/>\n            transform: translateY(20px);<br \/>\n          }<br \/>\n          to {<br \/>\n            opacity: 1;<br \/>\n            transform: translateY(0);<br \/>\n          }<br \/>\n        }<\/p>\n<p>        &#064;keyframes float {<br \/>\n          0%,<br \/>\n          100% {<br \/>\n            transform: translateY(0px);<br \/>\n          }<br \/>\n          50% {<br \/>\n            transform: translateY(-20px);<br \/>\n          }<br \/>\n        }<\/p>\n<p>        &#064;keyframes shake {<br \/>\n          0%,<br \/>\n          100% {<br \/>\n            transform: translateX(0);<br \/>\n          }<br \/>\n          10%,<br \/>\n          30%,<br \/>\n          50%,<br \/>\n          70%,<br \/>\n          90% {<br \/>\n            transform: translateX(-2px);<br \/>\n          }<br \/>\n          20%,<br \/>\n          40%,<br \/>\n          60%,<br \/>\n          80% {<br \/>\n            transform: translateX(2px);<br \/>\n          }<br \/>\n        }<\/p>\n<p>        .animate-pulse-slow {<br \/>\n          animation: pulse-slow 4s ease-in-out infinite;<br \/>\n        }<\/p>\n<p>        .animate-spin-slow {<br \/>\n          animation: spin-slow 20s linear infinite;<br \/>\n        }<\/p>\n<p>        .animate-fade-in {<br \/>\n          animation: fade-in 0.5s ease-out forwards;<br \/>\n        }<\/p>\n<p>        .animate-fade-in-up {<br \/>\n          animation: fade-in-up 0.6s ease-out forwards;<br \/>\n        }<\/p>\n<p>        .animate-float {<br \/>\n          animation: float 3s ease-in-out infinite;<br \/>\n        }<\/p>\n<p>        .animate-shake {<br \/>\n          animation: shake 0.5s ease-in-out;<br \/>\n        }<\/p>\n<p>        \/* OnlyOffice \u7f16\u8f91\u5668 iframe \u6837\u5f0f *\/<br \/>\n        .m-only-office iframe {<br \/>\n          width: 100% !important;<br \/>\n          height: 100% !important;<br \/>\n          min-height: 700px !important;<br \/>\n          border: none !important;<br \/>\n        }<br \/>\n      &#096;}&lt;\/style&gt;<br \/>\n    &lt;\/&gt;<br \/>\n  )<br \/>\n}<\/p>\n<p>nginx\u914d\u7f6e<\/p>\n<p>        # OnlyOffice cache \u8def\u5f84\u4ee3\u7406<br \/>\n        location \/cache\/ {<br \/>\n            # \u8bbe\u7f6e\u5141\u8bb8\u8de8\u57df<br \/>\n            add_header &#039;Access-Control-Allow-Origin&#039; &#039;*&#039; always;<br \/>\n            add_header &#039;Access-Control-Allow-Methods&#039; &#039;GET, POST, OPTIONS&#039; always;<br \/>\n            add_header &#039;Access-Control-Allow-Headers&#039; &#039;User-Agent,Keep-Alive,Content-Type,Authorization&#039; always;<br \/>\n            add_header &#039;Access-Control-Max-Age&#039; 1728000 always;<\/p>\n<p>            proxy_set_header X-Real-IP $remote_addr;<br \/>\n            proxy_set_header REMOTE-HOST $remote_addr;<br \/>\n            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br \/>\n            proxy_set_header X-NginX-Proxy true;<br \/>\n            proxy_set_header Host $host;<\/p>\n<p>            # \u5173\u952e&#xff1a;\u544a\u8bc9\u540e\u7aef\u670d\u52a1\u8fd9\u662f HTTPS \u8bf7\u6c42<br \/>\n            proxy_set_header X-Forwarded-Proto https;<br \/>\n            proxy_set_header X-Forwarded-Ssl on;<\/p>\n<p>            # \u7981\u7528 gzip \u538b\u7f29<br \/>\n            proxy_set_header Accept-Encoding &#034;&#034;;<\/p>\n<p>            proxy_http_version 1.1;<br \/>\n            proxy_set_header Connection &#034;&#034;;<\/p>\n<p>            # \u5bf9\u4e8e\u4e8c\u8fdb\u5236\u6587\u4ef6&#xff0c;\u5173\u95ed\u7f13\u51b2\u53ef\u80fd\u66f4\u597d<br \/>\n            proxy_buffering off;<br \/>\n            proxy_cache off;<br \/>\n            proxy_request_buffering off;<\/p>\n<p>            # \u4ee3\u7406\u5230 OnlyOffice \u670d\u52a1\u5668<br \/>\n            proxy_pass http:\/\/20.51.117.204\/cache\/;<\/p>\n<p>            # \u589e\u52a0\u8d85\u65f6\u65f6\u95f4<br \/>\n            proxy_connect_timeout 300s;<br \/>\n            proxy_send_timeout 300s;<br \/>\n            proxy_read_timeout 300s;<\/p>\n<p>            # \u7f13\u51b2\u533a\u8bbe\u7f6e&#xff08;\u5373\u4f7f\u5173\u95ed buffering&#xff0c;\u4e5f\u4fdd\u7559\u8fd9\u4e9b\u8bbe\u7f6e&#xff09;<br \/>\n            proxy_buffer_size 128k;<br \/>\n            proxy_buffers 8 128k;<br \/>\n            proxy_busy_buffers_size 256k;<br \/>\n        }<\/p>\n<p>        # OnlyOffice \u4ee3\u7406\u914d\u7f6e<br \/>\n        location \/onlyoffice\/ {<br \/>\n            # \u8bbe\u7f6e\u5141\u8bb8\u8de8\u57df<br \/>\n            add_header &#039;Access-Control-Allow-Origin&#039; &#039;*&#039; always;<br \/>\n            add_header &#039;Access-Control-Allow-Methods&#039; &#039;GET, POST, OPTIONS&#039; always;<br \/>\n            add_header &#039;Access-Control-Allow-Headers&#039; &#039;User-Agent,Keep-Alive,Content-Type,Authorization&#039; always;<br \/>\n            add_header &#039;Access-Control-Max-Age&#039; 1728000 always;<\/p>\n<p>            proxy_set_header X-Real-IP $remote_addr;<br \/>\n            proxy_set_header REMOTE-HOST $remote_addr;<br \/>\n            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br \/>\n            proxy_set_header X-NginX-Proxy true;<br \/>\n            proxy_set_header Host $host;<br \/>\n            # \u4f7f\u7528\u4ee3\u7406\u76ee\u6807\u7684 Host&#xff0c;\u800c\u4e0d\u662f\u5ba2\u6237\u7aef\u8bf7\u6c42\u7684 Host<br \/>\n            # proxy_set_header Host 20.51.117.204;<\/p>\n<p>            # \u5173\u952e&#xff1a;\u544a\u8bc9\u540e\u7aef\u670d\u52a1\u8fd9\u662f HTTPS \u8bf7\u6c42<br \/>\n            proxy_set_header X-Forwarded-Proto https;<br \/>\n            proxy_set_header X-Forwarded-Ssl on;<\/p>\n<p>            proxy_http_version 1.1;<br \/>\n            proxy_set_header Upgrade $http_upgrade;<br \/>\n            proxy_set_header Connection &#034;upgrade&#034;;<\/p>\n<p>            # \u5c06\u54cd\u5e94\u4e2d\u7684 HTTP \u94fe\u63a5\u66ff\u6362\u4e3a HTTPS<br \/>\n            sub_filter &#039;http:\/\/chat.xutongbao.top&#039; &#039;https:\/\/chat.xutongbao.top&#039;;<br \/>\n            sub_filter &#039;http:\/\/${host}&#039; &#039;https:\/\/${host}&#039;;<br \/>\n            sub_filter_once off;<br \/>\n            sub_filter_types *;<\/p>\n<p>            chunked_transfer_encoding off;<br \/>\n            # \u6ce8\u610f&#xff1a;\u4f7f\u7528 sub_filter \u9700\u8981\u5f00\u542f buffering<br \/>\n            proxy_buffering on;<br \/>\n            proxy_cache off;<\/p>\n<p>            # \u4ee3\u7406\u5230 OnlyOffice \u670d\u52a1\u5668<br \/>\n            proxy_pass http:\/\/20.51.117.204\/;<\/p>\n<p>            # \u589e\u52a0\u8d85\u65f6\u65f6\u95f4<br \/>\n            proxy_connect_timeout 300s;<br \/>\n            proxy_send_timeout 300s;<br \/>\n            proxy_read_timeout 300s;<\/p>\n<p>            # \u7f13\u51b2\u533a\u8bbe\u7f6e<br \/>\n            proxy_buffer_size 16k;<br \/>\n            proxy_buffers 4 64k;<br \/>\n            proxy_busy_buffers_size 128k;<br \/>\n        }<\/p>\n<p>        # \u539f\u6709\u9879\u76ee\u6839\u76ee\u5f55 (hash \u6a21\u5f0f)<br \/>\n        location \/ {<br \/>\n            root    \/temp\/yuying;<br \/>\n            index  index.html index.htm;<br \/>\n            add_header Content-Security-Policy upgrade-insecure-requests;<br \/>\n        } <\/p>\n<\/p>\n<h2>\u53c2\u8003\u94fe\u63a5<\/h2>\n<p>https:\/\/blog.csdn.net\/xutongbao\/article\/details\/157180010?spm&#061;1001.2014.3001.5501<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5728\u7ebf\u5730\u5740<br \/>\nhttps:\/\/chat.xutongbao.top\/nextjs\/light\/onlyOffice<br \/>\npage.tsx<br \/>\nuse clientimport { useState, useRef, useEffect } from react<br \/>\nimport Header from \/components\/header<br \/>\nimport {ArrowLeft,Upload,FileText,File,CheckCircle2,AlertCircle,Loader2,X,<\/p>\n","protected":false},"author":2,"featured_media":63847,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[1374,731,1375],"topic":[],"class_list":["post-63855","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-server","tag-excel","tag-powerpoint","tag-word"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u4f7f\u7528claude code\u5f00\u53d1\u5728\u7ebf\u9884\u89c8word\u3001excel\u3001ppt\u3001pdf\u7b49\u591a\u79cd\u6587\u4ef6\uff0c\u57fa\u4e8eonlyoffice\u5b9e\u73b0\u9884\u89c8\uff0conlyoffice\u5305\u542bAI\u63d2\u4ef6\uff0c\u53ef\u4ee5\u5bf9\u6587\u4ef6\u5185\u5bb9\u8fdb\u884c\u5904\u7406 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/63855.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u4f7f\u7528claude code\u5f00\u53d1\u5728\u7ebf\u9884\u89c8word\u3001excel\u3001ppt\u3001pdf\u7b49\u591a\u79cd\u6587\u4ef6\uff0c\u57fa\u4e8eonlyoffice\u5b9e\u73b0\u9884\u89c8\uff0conlyoffice\u5305\u542bAI\u63d2\u4ef6\uff0c\u53ef\u4ee5\u5bf9\u6587\u4ef6\u5185\u5bb9\u8fdb\u884c\u5904\u7406 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"\u5728\u7ebf\u5730\u5740 https:\/\/chat.xutongbao.top\/nextjs\/light\/onlyOffice page.tsx use clientimport { useState, useRef, useEffect } from react import Header from \/components\/header import {ArrowLeft,Upload,FileText,File,CheckCircle2,AlertCircle,Loader2,X,\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/63855.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-01-22T05:40:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122054049-6971b861a333c.png\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"18 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/63855.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/63855.html\",\"name\":\"\u4f7f\u7528claude code\u5f00\u53d1\u5728\u7ebf\u9884\u89c8word\u3001excel\u3001ppt\u3001pdf\u7b49\u591a\u79cd\u6587\u4ef6\uff0c\u57fa\u4e8eonlyoffice\u5b9e\u73b0\u9884\u89c8\uff0conlyoffice\u5305\u542bAI\u63d2\u4ef6\uff0c\u53ef\u4ee5\u5bf9\u6587\u4ef6\u5185\u5bb9\u8fdb\u884c\u5904\u7406 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-01-22T05:40:57+00:00\",\"dateModified\":\"2026-01-22T05:40:57+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/63855.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/63855.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/63855.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u4f7f\u7528claude code\u5f00\u53d1\u5728\u7ebf\u9884\u89c8word\u3001excel\u3001ppt\u3001pdf\u7b49\u591a\u79cd\u6587\u4ef6\uff0c\u57fa\u4e8eonlyoffice\u5b9e\u73b0\u9884\u89c8\uff0conlyoffice\u5305\u542bAI\u63d2\u4ef6\uff0c\u53ef\u4ee5\u5bf9\u6587\u4ef6\u5185\u5bb9\u8fdb\u884c\u5904\u7406\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"\u4f7f\u7528claude code\u5f00\u53d1\u5728\u7ebf\u9884\u89c8word\u3001excel\u3001ppt\u3001pdf\u7b49\u591a\u79cd\u6587\u4ef6\uff0c\u57fa\u4e8eonlyoffice\u5b9e\u73b0\u9884\u89c8\uff0conlyoffice\u5305\u542bAI\u63d2\u4ef6\uff0c\u53ef\u4ee5\u5bf9\u6587\u4ef6\u5185\u5bb9\u8fdb\u884c\u5904\u7406 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/63855.html","og_locale":"zh_CN","og_type":"article","og_title":"\u4f7f\u7528claude code\u5f00\u53d1\u5728\u7ebf\u9884\u89c8word\u3001excel\u3001ppt\u3001pdf\u7b49\u591a\u79cd\u6587\u4ef6\uff0c\u57fa\u4e8eonlyoffice\u5b9e\u73b0\u9884\u89c8\uff0conlyoffice\u5305\u542bAI\u63d2\u4ef6\uff0c\u53ef\u4ee5\u5bf9\u6587\u4ef6\u5185\u5bb9\u8fdb\u884c\u5904\u7406 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"\u5728\u7ebf\u5730\u5740 https:\/\/chat.xutongbao.top\/nextjs\/light\/onlyOffice page.tsx use clientimport { useState, useRef, useEffect } from react import Header from \/components\/header import {ArrowLeft,Upload,FileText,File,CheckCircle2,AlertCircle,Loader2,X,","og_url":"https:\/\/www.wsisp.com\/helps\/63855.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-01-22T05:40:57+00:00","og_image":[{"url":"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260122054049-6971b861a333c.png"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"18 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/63855.html","url":"https:\/\/www.wsisp.com\/helps\/63855.html","name":"\u4f7f\u7528claude code\u5f00\u53d1\u5728\u7ebf\u9884\u89c8word\u3001excel\u3001ppt\u3001pdf\u7b49\u591a\u79cd\u6587\u4ef6\uff0c\u57fa\u4e8eonlyoffice\u5b9e\u73b0\u9884\u89c8\uff0conlyoffice\u5305\u542bAI\u63d2\u4ef6\uff0c\u53ef\u4ee5\u5bf9\u6587\u4ef6\u5185\u5bb9\u8fdb\u884c\u5904\u7406 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-01-22T05:40:57+00:00","dateModified":"2026-01-22T05:40:57+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/63855.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/63855.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/63855.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"\u4f7f\u7528claude code\u5f00\u53d1\u5728\u7ebf\u9884\u89c8word\u3001excel\u3001ppt\u3001pdf\u7b49\u591a\u79cd\u6587\u4ef6\uff0c\u57fa\u4e8eonlyoffice\u5b9e\u73b0\u9884\u89c8\uff0conlyoffice\u5305\u542bAI\u63d2\u4ef6\uff0c\u53ef\u4ee5\u5bf9\u6587\u4ef6\u5185\u5bb9\u8fdb\u884c\u5904\u7406"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/63855","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=63855"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/63855\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media\/63847"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=63855"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=63855"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=63855"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=63855"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}