@datawhale/prosemirror-render 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/dist/AttachmentBlock-ChMNTUOo.mjs +351 -0
  2. package/dist/AttachmentBlock-DsmJP3Kw.js +1 -0
  3. package/dist/AttachmentInline-Dc3dp0g-.js +1 -0
  4. package/dist/AttachmentInline-tbC8BJBy.mjs +52 -0
  5. package/dist/AttachmentMenu-B5x8P9_n.mjs +541 -0
  6. package/dist/AttachmentMenu-ExoCOe4B.js +1 -0
  7. package/dist/Blockquote-BamWUQND.mjs +15 -0
  8. package/dist/Blockquote-CQSBFnsu.js +1 -0
  9. package/dist/BulletList-BQTUD69X.mjs +15 -0
  10. package/dist/BulletList-CFjF3U-l.js +1 -0
  11. package/dist/Callout-Cu6HI-xq.mjs +28 -0
  12. package/dist/Callout-DPdOqTb4.js +1 -0
  13. package/dist/CellOutput-C33VK0df.mjs +981 -0
  14. package/dist/CellOutput-DiKZlIFa.js +6 -0
  15. package/dist/CodeBlock-Cjuxuq7B.mjs +8359 -0
  16. package/dist/CodeBlock-DWniNUQB.js +148 -0
  17. package/dist/Doc-6s4VMDsx.mjs +15 -0
  18. package/dist/Doc-D2yvlSII.js +1 -0
  19. package/dist/FoldBlock-DRdlU-DX.mjs +75 -0
  20. package/dist/FoldBlock-ZPMf0QsR.js +1 -0
  21. package/dist/Grid-GfmJxM93.mjs +31 -0
  22. package/dist/Grid-QToZdaRT.js +1 -0
  23. package/dist/HardBreak-B2tFO31P.mjs +13 -0
  24. package/dist/HardBreak-Dbf5Zg5o.js +1 -0
  25. package/dist/Heading-BElRvhGn.mjs +21 -0
  26. package/dist/Heading-BUnffIAz.js +1 -0
  27. package/dist/HorizontalRule-BRG45oT0.mjs +13 -0
  28. package/dist/HorizontalRule-CE09LZGf.js +1 -0
  29. package/dist/IFrame-CaAOVLGN.mjs +17 -0
  30. package/dist/IFrame-DcCpSoDC.js +1 -0
  31. package/dist/Image-C8v5dCij.mjs +105 -0
  32. package/dist/Image-cHL85CXs.js +1 -0
  33. package/dist/ListItem-BrjxeGxz.js +1 -0
  34. package/dist/ListItem-X0T7a_z8.mjs +15 -0
  35. package/dist/MathDisplay-CESKZV46.js +1 -0
  36. package/dist/MathDisplay-CoGsFzXW.mjs +30 -0
  37. package/dist/MathInline-0xTZoIIq.mjs +30 -0
  38. package/dist/MathInline-C_1SJUVz.js +1 -0
  39. package/dist/McChoices-Aj394G5E.mjs +52 -0
  40. package/dist/McChoices-B4euzY7M.js +1 -0
  41. package/dist/McQuestion-Dq0aM5tC.js +1 -0
  42. package/dist/McQuestion-DvD-J47M.mjs +38 -0
  43. package/dist/McSolution-C5sTXz3y.mjs +24 -0
  44. package/dist/McSolution-N79CllH9.js +1 -0
  45. package/dist/MultipleChoice-DTCF3Q8m.js +1 -0
  46. package/dist/MultipleChoice-Dv-k1zUU.mjs +47 -0
  47. package/dist/OrderedList-B8v1gchv.mjs +17 -0
  48. package/dist/OrderedList-DMl3tvwP.js +1 -0
  49. package/dist/Paragraph-CzRSCJNr.js +1 -0
  50. package/dist/Paragraph-DGcZy8t_.mjs +16 -0
  51. package/dist/SlotNode-6OpoUcOa.mjs +10 -0
  52. package/dist/SlotNode-DMG0R6Vf.js +1 -0
  53. package/dist/TableCell-BY9gdldc.js +1 -0
  54. package/dist/TableCell-Bp52L368.mjs +20 -0
  55. package/dist/TableContainer-C5KXY6f7.js +1 -0
  56. package/dist/TableContainer-C9PhNGlz.mjs +29 -0
  57. package/dist/TableHeader-BTuqvorM.js +1 -0
  58. package/dist/TableHeader-C7KKz3e1.mjs +17 -0
  59. package/dist/TableRow-D4F6AKFt.js +1 -0
  60. package/dist/TableRow-OzpVq1qW.mjs +15 -0
  61. package/dist/Text-Br_pcGz4.mjs +78 -0
  62. package/dist/Text-DlUfrsNI.js +1 -0
  63. package/dist/emoji-Bk6FG72F.js +1 -0
  64. package/dist/emoji-CmOToDEU.mjs +3711 -0
  65. package/dist/index-D2CtpNvR.js +1 -0
  66. package/dist/index-DVmWCrQE.mjs +159 -0
  67. package/dist/index.cjs.js +1 -0
  68. package/dist/index.es.js +4 -0
  69. package/dist/katex-CS0ZfoxP.js +261 -0
  70. package/dist/katex-r9TeExgs.mjs +11690 -0
  71. package/dist/prosemirror-render.css +1 -0
  72. package/dist/types/apis/monitor.d.ts +9 -0
  73. package/dist/types/apis/tingwu.d.ts +14 -0
  74. package/dist/types/apis/types.d.ts +23 -0
  75. package/dist/types/components/TreeRecursive.vue.d.ts +7 -0
  76. package/dist/types/components/TreeRender.vue.d.ts +9 -0
  77. package/dist/types/components/collections/async/AsyncError.vue.d.ts +3 -0
  78. package/dist/types/components/collections/async/AsyncLoading.vue.d.ts +3 -0
  79. package/dist/types/components/collections/attachment/AttachmentBlock.vue.d.ts +7 -0
  80. package/dist/types/components/collections/attachment/AttachmentInline.vue.d.ts +7 -0
  81. package/dist/types/components/collections/attachment/AttachmentMenu.vue.d.ts +16 -0
  82. package/dist/types/components/collections/attachment/VideoDetail.vue.d.ts +7 -0
  83. package/dist/types/components/collections/attachment/index.d.ts +1 -0
  84. package/dist/types/components/collections/basic/Blockquote.vue.d.ts +17 -0
  85. package/dist/types/components/collections/basic/BulletList.vue.d.ts +17 -0
  86. package/dist/types/components/collections/basic/HardBreak.vue.d.ts +7 -0
  87. package/dist/types/components/collections/basic/Heading.vue.d.ts +17 -0
  88. package/dist/types/components/collections/basic/HorizontalRule.vue.d.ts +7 -0
  89. package/dist/types/components/collections/basic/ListItem.vue.d.ts +17 -0
  90. package/dist/types/components/collections/basic/OrderedList.vue.d.ts +17 -0
  91. package/dist/types/components/collections/basic/Paragraph.vue.d.ts +17 -0
  92. package/dist/types/components/collections/basic/Text.vue.d.ts +7 -0
  93. package/dist/types/components/collections/basic/index.d.ts +1 -0
  94. package/dist/types/components/collections/callout/Callout.vue.d.ts +7 -0
  95. package/dist/types/components/collections/callout/index.d.ts +1 -0
  96. package/dist/types/components/collections/code/CellOutput.vue.d.ts +7 -0
  97. package/dist/types/components/collections/code/CodeBlock.vue.d.ts +7 -0
  98. package/dist/types/components/collections/code/index.d.ts +1 -0
  99. package/dist/types/components/collections/fold/FoldBlock.vue.d.ts +7 -0
  100. package/dist/types/components/collections/fold/index.d.ts +1 -0
  101. package/dist/types/components/collections/grid/Grid.vue.d.ts +7 -0
  102. package/dist/types/components/collections/grid/index.d.ts +1 -0
  103. package/dist/types/components/collections/iframe/IFrame.vue.d.ts +7 -0
  104. package/dist/types/components/collections/iframe/index.d.ts +1 -0
  105. package/dist/types/components/collections/img/Image.vue.d.ts +7 -0
  106. package/dist/types/components/collections/img/index.d.ts +1 -0
  107. package/dist/types/components/collections/index.d.ts +1 -0
  108. package/dist/types/components/collections/math/MathDisplay.vue.d.ts +7 -0
  109. package/dist/types/components/collections/math/MathInline.vue.d.ts +7 -0
  110. package/dist/types/components/collections/math/index.d.ts +1 -0
  111. package/dist/types/components/collections/multipleChoice/McChoices.vue.d.ts +16 -0
  112. package/dist/types/components/collections/multipleChoice/McQuestion.vue.d.ts +7 -0
  113. package/dist/types/components/collections/multipleChoice/McSolution.vue.d.ts +8 -0
  114. package/dist/types/components/collections/multipleChoice/MultipleChoice.vue.d.ts +7 -0
  115. package/dist/types/components/collections/multipleChoice/index.d.ts +1 -0
  116. package/dist/types/components/collections/table/TableCell.vue.d.ts +17 -0
  117. package/dist/types/components/collections/table/TableContainer.vue.d.ts +17 -0
  118. package/dist/types/components/collections/table/TableHeader.vue.d.ts +17 -0
  119. package/dist/types/components/collections/table/TableRow.vue.d.ts +17 -0
  120. package/dist/types/components/collections/table/index.d.ts +1 -0
  121. package/dist/types/components/collections/utils.d.ts +2 -0
  122. package/dist/types/components/collections/wrapper/Doc.vue.d.ts +17 -0
  123. package/dist/types/components/collections/wrapper/SlotNode.vue.d.ts +13 -0
  124. package/dist/types/components/collections/wrapper/index.d.ts +1 -0
  125. package/dist/types/components/index.d.ts +1 -0
  126. package/dist/types/icons/Attachment/CardView.vue.d.ts +9 -0
  127. package/dist/types/icons/Attachment/Code/Bat.vue.d.ts +3 -0
  128. package/dist/types/icons/Attachment/Code/C.vue.d.ts +3 -0
  129. package/dist/types/icons/Attachment/Code/Cpp.vue.d.ts +3 -0
  130. package/dist/types/icons/Attachment/Code/Css.vue.d.ts +3 -0
  131. package/dist/types/icons/Attachment/Code/Go.vue.d.ts +3 -0
  132. package/dist/types/icons/Attachment/Code/Html.vue.d.ts +3 -0
  133. package/dist/types/icons/Attachment/Code/Java.vue.d.ts +3 -0
  134. package/dist/types/icons/Attachment/Code/Js.vue.d.ts +3 -0
  135. package/dist/types/icons/Attachment/Code/Json.vue.d.ts +3 -0
  136. package/dist/types/icons/Attachment/Code/Jsx.vue.d.ts +3 -0
  137. package/dist/types/icons/Attachment/Code/Md.vue.d.ts +3 -0
  138. package/dist/types/icons/Attachment/Code/Php.vue.d.ts +3 -0
  139. package/dist/types/icons/Attachment/Code/Python.vue.d.ts +3 -0
  140. package/dist/types/icons/Attachment/Code/Rb.vue.d.ts +3 -0
  141. package/dist/types/icons/Attachment/Code/Sh.vue.d.ts +3 -0
  142. package/dist/types/icons/Attachment/Code/Sql.vue.d.ts +3 -0
  143. package/dist/types/icons/Attachment/Code/Swift.vue.d.ts +3 -0
  144. package/dist/types/icons/Attachment/Code/Ts.vue.d.ts +3 -0
  145. package/dist/types/icons/Attachment/Code/Tsx.vue.d.ts +3 -0
  146. package/dist/types/icons/Attachment/Code/Vue.vue.d.ts +3 -0
  147. package/dist/types/icons/Attachment/Excel.vue.d.ts +3 -0
  148. package/dist/types/icons/Attachment/Eye.vue.d.ts +3 -0
  149. package/dist/types/icons/Attachment/FullScreen.vue.d.ts +3 -0
  150. package/dist/types/icons/Attachment/InlineView.vue.d.ts +9 -0
  151. package/dist/types/icons/Attachment/Pdf.vue.d.ts +3 -0
  152. package/dist/types/icons/Attachment/Ppt.vue.d.ts +3 -0
  153. package/dist/types/icons/Attachment/PreviewView.vue.d.ts +9 -0
  154. package/dist/types/icons/Attachment/UnknownFile.vue.d.ts +3 -0
  155. package/dist/types/icons/Attachment/VideoIcon.vue.d.ts +3 -0
  156. package/dist/types/icons/Attachment/VideoPlay.vue.d.ts +3 -0
  157. package/dist/types/icons/Attachment/Word.vue.d.ts +3 -0
  158. package/dist/types/icons/Code/Confirm.vue.d.ts +3 -0
  159. package/dist/types/icons/Code/Paste.vue.d.ts +3 -0
  160. package/dist/types/icons/Common/Choice.vue.d.ts +3 -0
  161. package/dist/types/icons/Common/Close.vue.d.ts +3 -0
  162. package/dist/types/icons/Common/Comment.vue.d.ts +3 -0
  163. package/dist/types/icons/Common/CopyAnchorLink.vue.d.ts +3 -0
  164. package/dist/types/icons/Common/Delete.vue.d.ts +3 -0
  165. package/dist/types/icons/Common/Download.vue.d.ts +3 -0
  166. package/dist/types/icons/Common/FoldClose.vue.d.ts +3 -0
  167. package/dist/types/icons/Common/FoldOpen.vue.d.ts +3 -0
  168. package/dist/types/icons/Common/Plate.vue.d.ts +3 -0
  169. package/dist/types/icons/Common/Question.vue.d.ts +3 -0
  170. package/dist/types/icons/Common/ShareTextLink.vue.d.ts +3 -0
  171. package/dist/types/index.d.ts +2 -0
  172. package/dist/types/types.d.ts +269 -0
  173. package/dist/types/utils/common.d.ts +1 -0
  174. package/dist/types/utils/emoji.d.ts +10 -0
  175. package/dist/types/utils/globalStatus.d.ts +16 -0
  176. package/dist/types/utils/shiki.d.ts +3 -0
  177. package/dist/types/utils/useAttachment.d.ts +8 -0
  178. package/package.json +29 -0
  179. package/src/apis/monitor.ts +8 -0
  180. package/src/apis/tingwu.ts +22 -0
  181. package/src/apis/types.ts +45 -0
  182. package/src/components/TreeRecursive.vue +47 -0
  183. package/src/components/TreeRender.vue +404 -0
  184. package/src/components/collections/async/AsyncError.vue +17 -0
  185. package/src/components/collections/async/AsyncLoading.vue +1 -0
  186. package/src/components/collections/attachment/AttachmentBlock.vue +561 -0
  187. package/src/components/collections/attachment/AttachmentInline.vue +90 -0
  188. package/src/components/collections/attachment/AttachmentMenu.vue +359 -0
  189. package/src/components/collections/attachment/VideoDetail.vue +375 -0
  190. package/src/components/collections/attachment/index.ts +6 -0
  191. package/src/components/collections/basic/Blockquote.vue +15 -0
  192. package/src/components/collections/basic/BulletList.vue +15 -0
  193. package/src/components/collections/basic/HardBreak.vue +11 -0
  194. package/src/components/collections/basic/Heading.vue +15 -0
  195. package/src/components/collections/basic/HorizontalRule.vue +11 -0
  196. package/src/components/collections/basic/ListItem.vue +15 -0
  197. package/src/components/collections/basic/OrderedList.vue +15 -0
  198. package/src/components/collections/basic/Paragraph.vue +19 -0
  199. package/src/components/collections/basic/Text.vue +73 -0
  200. package/src/components/collections/basic/index.ts +13 -0
  201. package/src/components/collections/callout/Callout.vue +77 -0
  202. package/src/components/collections/callout/index.ts +5 -0
  203. package/src/components/collections/code/CellOutput.vue +72 -0
  204. package/src/components/collections/code/CodeBlock.vue +83 -0
  205. package/src/components/collections/code/index.ts +6 -0
  206. package/src/components/collections/fold/FoldBlock.vue +130 -0
  207. package/src/components/collections/fold/index.ts +5 -0
  208. package/src/components/collections/grid/Grid.vue +70 -0
  209. package/src/components/collections/grid/index.ts +5 -0
  210. package/src/components/collections/iframe/IFrame.vue +19 -0
  211. package/src/components/collections/iframe/index.ts +5 -0
  212. package/src/components/collections/img/Image.vue +318 -0
  213. package/src/components/collections/img/index.ts +5 -0
  214. package/src/components/collections/index.ts +29 -0
  215. package/src/components/collections/math/MathDisplay.vue +42 -0
  216. package/src/components/collections/math/MathInline.vue +42 -0
  217. package/src/components/collections/math/index.ts +6 -0
  218. package/src/components/collections/multipleChoice/McChoices.vue +72 -0
  219. package/src/components/collections/multipleChoice/McQuestion.vue +61 -0
  220. package/src/components/collections/multipleChoice/McSolution.vue +47 -0
  221. package/src/components/collections/multipleChoice/MultipleChoice.vue +62 -0
  222. package/src/components/collections/multipleChoice/index.ts +8 -0
  223. package/src/components/collections/table/TableCell.vue +20 -0
  224. package/src/components/collections/table/TableContainer.vue +32 -0
  225. package/src/components/collections/table/TableHeader.vue +15 -0
  226. package/src/components/collections/table/TableRow.vue +15 -0
  227. package/src/components/collections/table/index.ts +8 -0
  228. package/src/components/collections/utils.ts +17 -0
  229. package/src/components/collections/wrapper/Doc.vue +15 -0
  230. package/src/components/collections/wrapper/SlotNode.vue +5 -0
  231. package/src/components/collections/wrapper/index.ts +6 -0
  232. package/src/components/index.ts +1 -0
  233. package/src/icons/Attachment/CardView.vue +21 -0
  234. package/src/icons/Attachment/Code/Bat.vue +26 -0
  235. package/src/icons/Attachment/Code/C.vue +26 -0
  236. package/src/icons/Attachment/Code/Cpp.vue +26 -0
  237. package/src/icons/Attachment/Code/Css.vue +34 -0
  238. package/src/icons/Attachment/Code/Go.vue +26 -0
  239. package/src/icons/Attachment/Code/Html.vue +34 -0
  240. package/src/icons/Attachment/Code/Java.vue +42 -0
  241. package/src/icons/Attachment/Code/Js.vue +26 -0
  242. package/src/icons/Attachment/Code/Json.vue +26 -0
  243. package/src/icons/Attachment/Code/Jsx.vue +30 -0
  244. package/src/icons/Attachment/Code/Md.vue +26 -0
  245. package/src/icons/Attachment/Code/Php.vue +26 -0
  246. package/src/icons/Attachment/Code/Python.vue +30 -0
  247. package/src/icons/Attachment/Code/Rb.vue +26 -0
  248. package/src/icons/Attachment/Code/Sh.vue +30 -0
  249. package/src/icons/Attachment/Code/Sql.vue +30 -0
  250. package/src/icons/Attachment/Code/Swift.vue +26 -0
  251. package/src/icons/Attachment/Code/Ts.vue +26 -0
  252. package/src/icons/Attachment/Code/Tsx.vue +30 -0
  253. package/src/icons/Attachment/Code/Vue.vue +24 -0
  254. package/src/icons/Attachment/Excel.vue +26 -0
  255. package/src/icons/Attachment/Eye.vue +15 -0
  256. package/src/icons/Attachment/FullScreen.vue +15 -0
  257. package/src/icons/Attachment/InlineView.vue +21 -0
  258. package/src/icons/Attachment/Pdf.vue +25 -0
  259. package/src/icons/Attachment/Ppt.vue +26 -0
  260. package/src/icons/Attachment/PreviewView.vue +21 -0
  261. package/src/icons/Attachment/UnknownFile.vue +26 -0
  262. package/src/icons/Attachment/VideoIcon.vue +25 -0
  263. package/src/icons/Attachment/VideoPlay.vue +15 -0
  264. package/src/icons/Attachment/Word.vue +26 -0
  265. package/src/icons/Code/Confirm.vue +38 -0
  266. package/src/icons/Code/Paste.vue +8 -0
  267. package/src/icons/Common/Choice.vue +28 -0
  268. package/src/icons/Common/Close.vue +15 -0
  269. package/src/icons/Common/Comment.vue +16 -0
  270. package/src/icons/Common/CopyAnchorLink.vue +15 -0
  271. package/src/icons/Common/Delete.vue +15 -0
  272. package/src/icons/Common/Download.vue +15 -0
  273. package/src/icons/Common/FoldClose.vue +9 -0
  274. package/src/icons/Common/FoldOpen.vue +9 -0
  275. package/src/icons/Common/Plate.vue +23 -0
  276. package/src/icons/Common/Question.vue +8 -0
  277. package/src/icons/Common/ShareTextLink.vue +15 -0
  278. package/src/index.ts +3 -0
  279. package/src/types.ts +236 -0
  280. package/src/utils/common.ts +6 -0
  281. package/src/utils/emoji.ts +3715 -0
  282. package/src/utils/globalStatus.ts +19 -0
  283. package/src/utils/shiki.ts +25 -0
  284. package/src/utils/useAttachment.ts +215 -0
  285. package/tsconfig.build.json +10 -0
  286. package/tsconfig.json +23 -0
  287. package/vite.config.ts +24 -0
@@ -0,0 +1,561 @@
1
+ <template>
2
+ <div @mouseenter="isHovered = true" @mouseleave="handleMouseLeave" class="attachment-block-container">
3
+ <div v-if="node.attrs.dispType === 'card'" class="attachment-block-card-container">
4
+ <div class="attachment-block-card-icon">
5
+ <component :is="icon" class="attachment-block-card-icon-svg" />
6
+ </div>
7
+ <div class="attachment-block-card-info">
8
+ <div class="attachment-block-card-info-name">{{ node.attrs.fileName }}.{{ node.attrs.fileType }}</div>
9
+ <div class="attachment-block-card-info-size" v-if="!uploading && !node.attrs.uploadError">
10
+ {{ calculatedFileSize }}
11
+ </div>
12
+ <div class="attachment-block-card-info-size" v-else-if="uploading && !node.attrs.uploadError">
13
+ 附件正在上传中,请等待...
14
+ </div>
15
+ <div class="attachment-block-card-info-size" v-else style="color: rgb(247, 78, 0)">
16
+ 附件出错,请等待管理员处理
17
+ </div>
18
+ </div>
19
+ <div class="attachment-block-card-preview">
20
+ <!-- TODO:不使用Element-Plus的v-loading,为图标添加上传时的loading状态 -->
21
+ <div class="attachment-block-card-preview-wrapper" @click="handleFullScreen">
22
+ <component :is="isVideo(node.attrs.fileType) ? VideoPlay : Eye" class="attachment-block-card-preview-btn" />
23
+ </div>
24
+ </div>
25
+ <div class="attachment-block-card-menu" v-show="isHovered && !uploading && !node.attrs.uploadError"
26
+ @mouseenter="handleEnterMenu">
27
+ <AttachmentMenu :node="node" v-model:show-full-screen-dialog="showFullScreenPreview" />
28
+ </div>
29
+ </div>
30
+ <div v-else-if="node.attrs.dispType === 'preview'" class="attachment-block-preview-container">
31
+ <!-- 判断是否是视频文件类型 -->
32
+ <div v-if="isVideo(node.attrs.fileType)" class="video-block-preview-container">
33
+ <div class="video-block-container" :class="{ 'has-sidebar': showAiPanel }">
34
+ <div class="video-main-section">
35
+ <div class="video-player-wrapper" v-if="!uploading && !node.attrs.uploadError">
36
+ <video ref="videoPreviewRef" :src="resolvedFileUrl(node.attrs.src)" controls
37
+ class="video-element"></video>
38
+ </div>
39
+
40
+ <div class="video-uploading-wrapper" v-else>
41
+ <div class="uploading-content" v-if="!node.attrs.uploadError">
42
+ <div class="spinner"></div>
43
+ <span>视频正在上传中,请等待...</span>
44
+ </div>
45
+ <div class="error-content" v-else>
46
+ <span>⚠️ 视频出错,请等待管理员处理</span>
47
+ </div>
48
+ </div>
49
+
50
+ <div class="video-toolbar" v-if="!uploading && node.attrs.tingwuTaskId">
51
+ <div class="toolbar-info">
52
+ <span class="toolbar-title">分析</span>
53
+ <span class="toolbar-desc">摘要与章节</span>
54
+ </div>
55
+ <button class="ai-toggle-btn" :class="{ active: showAiPanel }" @click="toggleAiPanel">
56
+ <i class="icon-ai">✨</i> {{ showAiPanel ? '收起助手' : 'AI 助手' }}
57
+ </button>
58
+ </div>
59
+ </div>
60
+
61
+ <div class="video-sidebar-section" v-if="showAiPanel">
62
+ <VideoDetail :taskId="node.attrs.tingwuTaskId!" :videoRef="videoPreviewRef" @close="showAiPanel = false" />
63
+ </div>
64
+ </div>
65
+ </div>
66
+ <!-- 非视频类型的文件预览 -->
67
+ <div v-else class="notVideo-block-preview-container">
68
+ <div class="attachment-block-preview-content" :class="{ 'attachment-block-preview-dark-bg': !canPreview }">
69
+ <component v-if="canPreview" class="attachment-block-preview-iframe"
70
+ :src="resolvedFileUrl(genPreviewSrc(node.attrs.src))"
71
+ :is="node.attrs.fileType === 'pdf' ? 'embed' : 'iframe'"></component>
72
+ <div class="attachment-block-preview-unable" v-else>
73
+ <img class="attachment-block-preview-unable-img" :src="cannotPreviewImgDataUrl" alt="该文件类型无法预览" />
74
+ <div class="attachment-block-preview-unable-text">
75
+ <strong style="font-weight: bold">.{{ node.attrs.fileType }}</strong>文件类型无法预览
76
+ </div>
77
+ <div class="attachment-block-preview-unable-text">
78
+ {{ node.attrs.fileName }}.{{ node.attrs.fileType }}&nbsp;·&nbsp;{{ calculatedFileSize }}
79
+ </div>
80
+ </div>
81
+ </div>
82
+ <div class="attachment-block-preview-footer" :class="{ 'attachment-block-preview-dark-bg': !canPreview }">
83
+ <component :is="icon" class="attachment-block-preview-icon-svg" />
84
+ <span class="attachment-block-preview-info">{{ node.attrs.fileName }}.{{ node.attrs.fileType }}</span>
85
+ </div>
86
+ </div>
87
+ <div class="attachment-block-preview-menu" v-show="isHovered && !uploading && !node.attrs.uploadError"
88
+ @mouseenter="handleEnterMenu">
89
+ <AttachmentMenu :node="node" />
90
+ </div>
91
+ </div>
92
+ </div>
93
+ </template>
94
+
95
+ <script setup lang="ts">
96
+ import { computed, inject, ref, useTemplateRef } from 'vue';
97
+ import { monitorApi } from '@datawhale/dipwap-render/apis/monitor';
98
+ import { axiosKey } from '@datawhale/dipwap-render/apis/types';
99
+ import Eye from '@datawhale/dipwap-render/icons/Attachment/Eye.vue';
100
+ import VideoPlay from '@datawhale/dipwap-render/icons/Attachment/VideoPlay.vue';
101
+ import { resolvedFileUrl } from '@datawhale/dipwap-render/utils/common';
102
+ import { useAttachment } from '@datawhale/dipwap-render/utils/useAttachment';
103
+ import type { PMAttachmentBlock } from '@datawhale/dipwap-types/index';
104
+ import AttachmentMenu from './AttachmentMenu.vue';
105
+ import VideoDetail from './VideoDetail.vue';
106
+
107
+ const { node } = defineProps<{
108
+ node: PMAttachmentBlock;
109
+ }>();
110
+
111
+ const service = inject(axiosKey);
112
+
113
+ const videoPreviewRef = useTemplateRef('videoPreviewRef');
114
+
115
+ const uploading = computed(() => node.attrs.uploadProgress === undefined || node.attrs.uploadProgress < 1);
116
+
117
+ const { icon, calculatedFileSize, cannotPreviewImgDataUrl, canPreview, genPreviewSrc } = useAttachment(
118
+ node.attrs.fileType,
119
+ node.attrs.fileSize,
120
+ );
121
+
122
+ // 检查文件类型是否是视频
123
+ const isVideo = (fileType: string) => {
124
+ const videoTypes = ['mp4', 'avi', 'mkv', 'mov'];
125
+ return videoTypes.includes(fileType);
126
+ };
127
+
128
+ const showAiPanel = ref(false);
129
+
130
+ const toggleAiPanel = async () => {
131
+ showAiPanel.value = !showAiPanel.value;
132
+ if (service && showAiPanel.value && node.attrs.tingwuTaskId) {
133
+ // @ts-ignore
134
+ await monitorApi(service, {
135
+ log: JSON.stringify({
136
+ name: 'toggleVideoAiPanel',
137
+ tingwuTaskId: node.attrs.tingwuTaskId,
138
+ videoPageUrl: window.location.href,
139
+ }),
140
+ });
141
+ }
142
+ };
143
+
144
+ const showFullScreenPreview = ref(false);
145
+ const handleFullScreen = () => {
146
+ showFullScreenPreview.value = true;
147
+ alert('全屏预览功能将在后续版本中开放');
148
+ };
149
+
150
+ // 菜单相关
151
+ // 菜单与节点之间有缝隙,所以需要延迟关闭菜单的时间,使得鼠标在移动到菜单上时经过缝隙而不会关闭菜单
152
+ const isHovered = ref(false); // 鼠标是否在节点上
153
+ const timer = ref<number | null>(null);
154
+
155
+ const handleMouseLeave = () => {
156
+ timer.value = setTimeout(() => {
157
+ isHovered.value = false;
158
+ }, 200) as unknown as number;
159
+ };
160
+
161
+ const handleEnterMenu = () => {
162
+ if (timer.value) {
163
+ clearTimeout(timer.value);
164
+ timer.value = null;
165
+ }
166
+ };
167
+ </script>
168
+
169
+ <style scoped lang="scss">
170
+ // 变量定义
171
+ $primary-color: #2563eb;
172
+ $border-color: #e5e7eb;
173
+ $bg-gray: #f9fafb;
174
+ $text-main: #111827;
175
+ $text-sub: #6b7280;
176
+
177
+ .attachment-block-container {
178
+ margin: 16px 0;
179
+ }
180
+
181
+ .attachment-block-card-container {
182
+ display: flex;
183
+ position: relative;
184
+ align-items: center;
185
+ justify-content: center;
186
+ width: 100%;
187
+ max-width: 400px;
188
+ height: 65.14px;
189
+ box-sizing: border-box;
190
+ background-color: #fff;
191
+ border-radius: 8px;
192
+ border: 1px solid rgb(222, 224, 227);
193
+ cursor: pointer;
194
+
195
+ &:hover {
196
+ border-color: rgb(194, 212, 255);
197
+ box-shadow: rgb(194, 212, 255) 0px 0px 0px 1px;
198
+ }
199
+
200
+ .attachment-block-card-icon {
201
+ width: 48px;
202
+ height: 48px;
203
+ margin: 8px 12px 8px 8px;
204
+ box-sizing: border-box;
205
+
206
+ .attachment-block-card-icon-svg {
207
+ width: 48px;
208
+ height: 48px;
209
+ }
210
+ }
211
+
212
+ .attachment-block-card-info {
213
+ flex: 1;
214
+ display: flex;
215
+ flex-direction: column;
216
+ justify-content: center;
217
+
218
+ .attachment-block-card-info-name {
219
+ user-select: none;
220
+ display: -webkit-box;
221
+ -webkit-line-clamp: 2;
222
+ -webkit-box-orient: vertical;
223
+ text-overflow: ellipsis;
224
+ text-align: left;
225
+ overflow: hidden;
226
+ color: #1f2329;
227
+ max-height: 44px;
228
+ max-width: 260px;
229
+ line-height: 22px;
230
+ }
231
+
232
+ .attachment-block-card-info-size {
233
+ height: 17px;
234
+ white-space: nowrap;
235
+ font-size: 12px;
236
+ color: #646a73;
237
+ user-select: none;
238
+ line-height: 1.8;
239
+ }
240
+ }
241
+
242
+ .attachment-block-card-preview {
243
+ padding-right: 4px;
244
+ margin: auto;
245
+ height: 48px;
246
+ display: flex;
247
+ align-items: center;
248
+ box-sizing: border-box;
249
+
250
+ .attachment-block-card-preview-wrapper {
251
+ text-decoration: none;
252
+ text-overflow: ellipsis;
253
+ white-space: nowrap;
254
+ height: 34px;
255
+ width: 34px;
256
+ text-align: center;
257
+ position: relative;
258
+ overflow: unset;
259
+ margin: 0 16px;
260
+ cursor: pointer;
261
+ padding: 4px;
262
+ line-height: 24px;
263
+ display: flex;
264
+ justify-content: center;
265
+ align-items: center;
266
+ box-sizing: border-box;
267
+
268
+ &:hover {
269
+ background-color: rgba(31, 35, 41, 0.08);
270
+ border-radius: 6px;
271
+ }
272
+
273
+ .attachment-block-card-preview-btn {
274
+ height: 20px;
275
+ width: 20px;
276
+ }
277
+ }
278
+ }
279
+
280
+ .attachment-block-card-menu {
281
+ position: absolute;
282
+ top: -46px;
283
+ left: 200px;
284
+ z-index: 86;
285
+ transform: translateX(-50%);
286
+ }
287
+ }
288
+
289
+ .attachment-block-preview-container {
290
+ position: relative;
291
+
292
+ .attachment-block-preview-menu {
293
+ position: absolute;
294
+ top: -46px;
295
+ left: 410px;
296
+ z-index: 86;
297
+ transform: translateX(-50%);
298
+ }
299
+
300
+ .video-block-preview-container {
301
+ display: flex;
302
+ flex-direction: column;
303
+ justify-content: center;
304
+ align-items: center;
305
+ margin-bottom: 16px;
306
+
307
+ // --- 灰色大卡片容器 ---
308
+ .video-block-container {
309
+ // 【关键 1】作为定位锚点
310
+ position: relative;
311
+
312
+ display: flex;
313
+ flex-direction: column;
314
+ gap: 16px;
315
+ background-color: $bg-gray; // 确保有这个变量,或者用 #f9fafb
316
+ border: 1px solid $border-color;
317
+ border-radius: 12px;
318
+ padding: 16px;
319
+ margin: 16px 0;
320
+ transition: all 0.3s ease;
321
+
322
+ // 【关键 2】允许子元素(侧边栏)显示在盒子外部
323
+ overflow: visible;
324
+ }
325
+
326
+ .video-main-section {
327
+ flex: 1;
328
+ width: 100%;
329
+ min-width: 0;
330
+ display: flex;
331
+ flex-direction: column;
332
+ gap: 12px;
333
+ }
334
+
335
+ // --- 视频播放器 ---
336
+ .video-player-wrapper {
337
+ width: 100%;
338
+ aspect-ratio: 16 / 9;
339
+ background-color: #000;
340
+ border-radius: 8px;
341
+ overflow: hidden;
342
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
343
+
344
+ .video-element {
345
+ width: 100%;
346
+ height: 100%;
347
+ object-fit: contain;
348
+ }
349
+ }
350
+
351
+ // --- 上传状态 ---
352
+ .video-uploading-wrapper {
353
+ width: 100%;
354
+ aspect-ratio: 16 / 9;
355
+ background-color: #fff;
356
+ border-radius: 8px;
357
+ display: flex;
358
+ align-items: center;
359
+ justify-content: center;
360
+ border: 1px dashed $border-color;
361
+
362
+ .uploading-content,
363
+ .error-content {
364
+ display: flex;
365
+ flex-direction: column;
366
+ align-items: center;
367
+ gap: 8px;
368
+ font-size: 14px;
369
+ color: $text-sub;
370
+ }
371
+
372
+ .error-content {
373
+ color: #ef4444;
374
+ }
375
+
376
+ .spinner {
377
+ width: 24px;
378
+ height: 24px;
379
+ border: 2px solid #e5e7eb;
380
+ border-top-color: $primary-color;
381
+ border-radius: 50%;
382
+ animation: spin 1s linear infinite;
383
+ }
384
+ }
385
+
386
+ // --- 工具栏 ---
387
+ .video-toolbar {
388
+ display: flex;
389
+ justify-content: space-between;
390
+ align-items: center;
391
+ background: #fff;
392
+ padding: 12px;
393
+ border-radius: 8px;
394
+ border: 1px solid $border-color;
395
+
396
+ .toolbar-info {
397
+ display: flex;
398
+ flex-direction: column;
399
+
400
+ .toolbar-title {
401
+ font-weight: 500;
402
+ color: $text-main;
403
+ font-size: 14px;
404
+ }
405
+
406
+ .toolbar-desc {
407
+ font-size: 12px;
408
+ color: $text-sub;
409
+
410
+ @media (max-width: 380px) {
411
+ display: none;
412
+ }
413
+ }
414
+ }
415
+
416
+ .ai-toggle-btn {
417
+ display: flex;
418
+ align-items: center;
419
+ gap: 6px;
420
+ padding: 8px 16px;
421
+ border-radius: 6px;
422
+ font-size: 14px;
423
+ font-weight: 500;
424
+ cursor: pointer;
425
+ border: none;
426
+ background-color: $primary-color;
427
+ color: white;
428
+ -webkit-tap-highlight-color: transparent;
429
+
430
+ &:active {
431
+ opacity: 0.9;
432
+ }
433
+
434
+ &.active {
435
+ background-color: #eff6ff;
436
+ color: $primary-color;
437
+ border: 1px solid #bfdbfe;
438
+ }
439
+ }
440
+ }
441
+
442
+ // --- 【关键 3】完全位于右侧外部的 AI 面板 ---
443
+ .video-sidebar-section {
444
+ width: 100%; // 移动端默认样式
445
+
446
+ // 桌面端逻辑 (大于 768px 或根据你的布局宽度调整)
447
+ @media (min-width: 768px) {
448
+ // 1. 绝对定位
449
+ position: absolute;
450
+
451
+ // 2. 顶部与卡片对齐
452
+ top: 0;
453
+
454
+ // 3. 位于卡片右侧外部 (left: 100% 表示从容器最右边开始)
455
+ left: 100%;
456
+
457
+ // 4. 间距调整
458
+ margin-left: 16px;
459
+
460
+ // 5. 尺寸与高度 (由内容自动撑开,不强制拉伸)
461
+ width: 320px;
462
+ height: auto;
463
+ // max-height: 100%; // 如果你想限制高度不超过视频卡片,取消这行注释
464
+
465
+ // 6. 视觉样式 (因为它在外面,需要单独的卡片样式)
466
+ background-color: #fff;
467
+ border: 1px solid $border-color;
468
+ border-radius: 12px;
469
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
470
+ padding: 0; // 如果 VideoDetail 自带 padding,这里设为 0
471
+ z-index: 1;
472
+
473
+ // 7. 动画
474
+ animation: fadeInRight 0.3s ease-out;
475
+ }
476
+ }
477
+
478
+ @keyframes spin {
479
+ to {
480
+ transform: rotate(360deg);
481
+ }
482
+ }
483
+
484
+ @keyframes fadeInRight {
485
+ from {
486
+ opacity: 0;
487
+ transform: translateX(-10px);
488
+ }
489
+
490
+ to {
491
+ opacity: 1;
492
+ transform: translateX(0);
493
+ }
494
+ }
495
+ }
496
+
497
+ .notVideo-block-preview-container {
498
+ max-width: 820px;
499
+ border-radius: 8px;
500
+ border: 1px solid #dee0e3;
501
+
502
+ .attachment-block-preview-content {
503
+ height: 409px;
504
+ box-sizing: border-box;
505
+ display: flex;
506
+ flex-direction: column;
507
+ align-items: center;
508
+ justify-content: center;
509
+
510
+ .attachment-block-preview-iframe {
511
+ width: 100%;
512
+ height: 100%;
513
+ border-top-left-radius: 8px;
514
+ border-top-right-radius: 8px;
515
+ }
516
+
517
+ .attachment-block-preview-unable {
518
+ width: 100%;
519
+ display: flex;
520
+ flex-direction: column;
521
+ align-items: center;
522
+ justify-content: center;
523
+
524
+ .attachment-block-preview-unable-img {
525
+ width: 120px;
526
+ height: 120px;
527
+ display: block;
528
+ margin-bottom: 16px;
529
+ }
530
+
531
+ .attachment-block-preview-unable-text {
532
+ font-size: 14px;
533
+ color: rgb(100, 106, 115);
534
+ margin-top: 4px;
535
+ line-height: 1.8;
536
+ }
537
+ }
538
+ }
539
+
540
+ .attachment-block-preview-footer {
541
+ height: 42px;
542
+ box-sizing: border-box;
543
+ padding: 0 12px;
544
+ display: flex;
545
+ align-items: center;
546
+ border-top: 1px solid #dee0e3;
547
+ background-color: #fff;
548
+
549
+ .attachment-block-preview-icon-svg {
550
+ width: 18px;
551
+ height: 18px;
552
+ margin-right: 8px;
553
+ }
554
+ }
555
+
556
+ .attachment-block-preview-dark-bg {
557
+ background-color: rgb(242, 243, 245);
558
+ }
559
+ }
560
+ }
561
+ </style>
@@ -0,0 +1,90 @@
1
+ <template>
2
+ <div class="attachment-inline-container" @mouseenter="isHovered = true" @mouseleave="handleMouseLeave">
3
+ <component :is="icon" class="attachment-inline-icon" ref="iconRef" />
4
+ <span class="attachment-inline-text" ref="textRef">{{ node.attrs.fileName }}.{{ node.attrs.fileType }}</span>
5
+ <div class="attachment-inline-menu" v-show="isHovered" @mouseenter="handleEnterMenu">
6
+ <AttachmentMenu :node="node" />
7
+ </div>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ import { nextTick, onMounted, ref } from 'vue';
13
+ import { useAttachment } from '@datawhale/dipwap-render/utils/useAttachment';
14
+ import type { PMAttachmentInline } from '@datawhale/dipwap-types/index';
15
+ import AttachmentMenu from './AttachmentMenu.vue';
16
+
17
+ const { node } = defineProps<{ node: PMAttachmentInline }>();
18
+ const { icon } = useAttachment(node.attrs.fileType, node.attrs.fileSize);
19
+
20
+ const textRef = ref<HTMLSpanElement | null>(null);
21
+
22
+ const totalWidth = ref(`0px`);
23
+
24
+ onMounted(async () => {
25
+ const iconWidth = 1.15 * parseFloat(getComputedStyle(document.documentElement).fontSize);
26
+ await nextTick();
27
+ if (textRef.value) {
28
+ totalWidth.value = `${(iconWidth + textRef.value!.offsetWidth + 2) / 2}px`;
29
+ }
30
+ });
31
+
32
+ // 菜单相关
33
+ // 菜单与节点之间有缝隙,所以需要延迟关闭菜单的时间,使得鼠标在移动到菜单上时经过缝隙而不会关闭菜单
34
+ const isHovered = ref(false); // 鼠标是否在节点上
35
+ const timer = ref<number | null>(null);
36
+
37
+ const handleMouseLeave = () => {
38
+ // esl
39
+ timer.value = setTimeout(() => {
40
+ isHovered.value = false;
41
+ }, 200) as unknown as number;
42
+ };
43
+
44
+ const handleEnterMenu = () => {
45
+ if (timer.value) {
46
+ clearTimeout(timer.value);
47
+ timer.value = null;
48
+ }
49
+ };
50
+ </script>
51
+
52
+ <style scoped lang="scss">
53
+ .attachment-inline-container {
54
+ display: inline-block;
55
+ height: 100%;
56
+ box-sizing: border-box;
57
+ line-height: 1.15em;
58
+ padding: 3px 2px;
59
+ position: relative;
60
+ cursor: pointer;
61
+
62
+ &:hover {
63
+ background-color: rgba(51, 109, 244, 0.1);
64
+ border-radius: 4px;
65
+ }
66
+
67
+ .attachment-inline-icon {
68
+ width: 1.15em;
69
+ height: 1.15em;
70
+ -webkit-transform: translateY(2px);
71
+ transform: translateY(2px);
72
+ }
73
+
74
+ .attachment-inline-text {
75
+ margin-left: 2px;
76
+ color: rgb(20, 86, 240);
77
+ }
78
+
79
+ .attachment-inline-loading {
80
+ color: rgb(119, 164, 226);
81
+ }
82
+
83
+ .attachment-inline-menu {
84
+ position: absolute;
85
+ top: -46px;
86
+ left: v-bind(totalWidth);
87
+ transform: translateX(-50%);
88
+ }
89
+ }
90
+ </style>