choiceQuestionDetailDialog.vue 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. <template>
  2. <div class="choiceQuestionDetailDialog">
  3. <div
  4. class="content"
  5. :style="{
  6. width: slideWidth + 'px',
  7. height: slideHeight + 'px',
  8. }"
  9. >
  10. <span class="closeIcon" @click="closeSlideIndex()">
  11. <img src="../../../assets/img/close.png" />
  12. </span>
  13. <!-- 选择题 -->
  14. <div
  15. class="c_t45"
  16. v-if="workDetail && workDetail.type === '45' && props.showData"
  17. >
  18. <div class="c_t45_title">
  19. <div v-if=" props.showData.choiceQuestionListData[props.showData.workIndex]">{{
  20. props.showData.choiceQuestionListData[props.showData.workIndex]
  21. .teststitle
  22. }}</div>
  23. <span class="c_t45_t_btn" :class="{'c_t45_t_btn_noActive': props.showData.workIndex <= 0}" @click="changeWorkIndex(0)">上一题</span>
  24. <span class="c_t45_t_btn" :class="{'c_t45_t_btn_noActive': props.showData.workIndex >= props.showData.choiceQuestionListData.length - 1}" @click="changeWorkIndex(1)">下一题</span>
  25. </div>
  26. <img
  27. class="c_t45_img"
  28. :src="
  29. props.showData.choiceQuestionListData[props.showData.workIndex]
  30. .timuList[0].src
  31. "
  32. v-if=" props.showData.choiceQuestionListData[props.showData.workIndex] &&
  33. props.showData.choiceQuestionListData[props.showData.workIndex]
  34. .timuList.length > 0
  35. "
  36. />
  37. <span
  38. class="c_t45_type"
  39. v-if="
  40. props.showData.choiceQuestionListData[props.showData.workIndex]
  41. .type === '1'
  42. "
  43. >单选题</span
  44. >
  45. <span
  46. class="c_t45_type"
  47. v-if="
  48. props.showData.choiceQuestionListData[props.showData.workIndex]
  49. .type === '2'
  50. "
  51. >多选项</span
  52. >
  53. <div
  54. class="c_t45_echarts"
  55. :style="{
  56. width: slideWidth - 40 + 'px',
  57. }"
  58. >
  59. <div id="echartsArea1" ref="echartsArea1"></div>
  60. </div>
  61. </div>
  62. <!-- 问答题 -->
  63. <div
  64. class="c_t15"
  65. v-if="workDetail && workDetail.type === '15' && props.showData"
  66. >
  67. <div class="c_t15_title">{{ workDetail.json.answerQ }}</div>
  68. <span class="c_t15_type">问答题</span>
  69. <div class="c_t15_content" v-show="!lookWorkData">
  70. <div
  71. class="c_t15_c_item"
  72. v-for="item in processedWorkArray"
  73. :key="item.id"
  74. @click="lookWork(item.id)"
  75. >
  76. <div class="c_t15_c_i_top">
  77. <span>S</span>
  78. <div>{{ item.name }}</div>
  79. </div>
  80. <div class="c_t15_c_i_bottom">
  81. <span v-html="item.content.answer"></span>
  82. </div>
  83. </div>
  84. </div>
  85. <div class="c_t15_workDetail" v-if="lookWorkData">
  86. <div class="c_t15_wd_top">
  87. <img
  88. src="../../../assets/img/arrow_left.png"
  89. @click="lookWork('')"
  90. />
  91. <span>S</span>
  92. <div>{{ lookWorkData.name }}</div>
  93. </div>
  94. <div class="c_t15_wd_content">
  95. <span v-html="lookWorkData.content.answer"></span>
  96. <div
  97. class="c_t15_wd_c_imageList"
  98. v-if="lookWorkData.content.fileList.length > 0"
  99. >
  100. <img
  101. v-for="item in lookWorkData.content.fileList"
  102. :src="item.url"
  103. :key="item.uploadTime"
  104. @click="lookImage(item.url)"
  105. />
  106. </div>
  107. </div>
  108. </div>
  109. </div>
  110. <!-- AI应用 -->
  111. <div
  112. class="c_t72"
  113. v-if="props.showData && props.showData.toolType === 72"
  114. >
  115. <div class="c_t72_title">AI应用</div>
  116. <span class="c_t72_type">AI应用</span>
  117. <div class="c_t72_content" v-show="!lookWorkData">
  118. <div
  119. class="c_t72_c_item"
  120. v-for="item in processedWorkArray"
  121. :key="item.id"
  122. @click="lookWork(item.id)"
  123. >
  124. <div class="c_t72_c_i_top">
  125. <span>S</span>
  126. <div>{{ item.name }}</div>
  127. </div>
  128. </div>
  129. </div>
  130. <div class="c_t72_workDetail" v-if="lookWorkData">
  131. <div class="c_t72_wd_top">
  132. <img
  133. src="../../../assets/img/arrow_left.png"
  134. @click="lookWork('')"
  135. />
  136. <span>S</span>
  137. <div>{{ lookWorkData.name }}</div>
  138. </div>
  139. <div class="c_t72_wd_content">
  140. <template
  141. v-for="(item, index) in lookWorkData.content"
  142. :key="item.id"
  143. >
  144. <div class="messageNodeArea" v-if="item.messages || item.imageUrls">
  145. <div class="messageNode">
  146. <div class="mn_title">节点{{ index + 1 }}</div>
  147. <div class="mn_content">
  148. <template
  149. v-for="(item2, index2) in item.messages"
  150. :key="`${index}-${index2}`"
  151. >
  152. <div>
  153. <div
  154. class="na_m_item"
  155. v-if="item2.role == 'user' && item2.content"
  156. >
  157. <div class="na_m_i_name">
  158. {{ item2.sender }}
  159. </div>
  160. <div
  161. class="na_m_i_content"
  162. v-html="item2.content"
  163. ></div>
  164. </div>
  165. <div
  166. class="na_m_item"
  167. v-if="item2.role == 'assistant' && item2.content"
  168. >
  169. <div class="na_m_i_name aiName">
  170. {{ item2.sender }}
  171. </div>
  172. <div
  173. class="na_m_i_content"
  174. v-html="item2.content"
  175. ></div>
  176. </div>
  177. </div>
  178. </template>
  179. <template v-if="item.imageUrls" v-for="(item3,index3) in item.imageUrls" :key="`${index}-${index3}`">
  180. <div class="na_m_item">
  181. <div class="na_m_i_name">
  182. {{ item.type }}
  183. </div>
  184. <div class="na_m_i_content">
  185. <img style="height: 100px;width: auto;" :src="item3" />
  186. </div>
  187. </div>
  188. </template>
  189. </div>
  190. </div>
  191. </div>
  192. </template>
  193. </div>
  194. </div>
  195. </div>
  196. <!-- H5页面 -->
  197. <div
  198. class="c_t73"
  199. v-if="props.showData && props.showData.toolType === 73"
  200. >
  201. <div class="c_t73_title">页面图片</div>
  202. <span class="c_t73_type">H5页面</span>
  203. <div class="c_t73_content" v-show="!lookWorkData">
  204. <div
  205. class="c_t73_c_item"
  206. v-for="item in processedWorkArray"
  207. :key="item.id"
  208. @click="lookWork(item.id)"
  209. >
  210. <div class="c_t73_c_i_top">
  211. <span>S</span>
  212. <div>{{ item.name }}</div>
  213. </div>
  214. <div class="c_t73_c_i_bottom">
  215. <img :src="item.content" />
  216. </div>
  217. </div>
  218. </div>
  219. <div class="c_t73_workDetail" v-if="lookWorkData">
  220. <div class="c_t73_wd_top">
  221. <img
  222. src="../../../assets/img/arrow_left.png"
  223. @click="lookWork('')"
  224. />
  225. <span>S</span>
  226. <div>{{ lookWorkData.name }}</div>
  227. </div>
  228. <div class="c_t73_wd_content">
  229. <img :src="lookWorkData.content" />
  230. </div>
  231. </div>
  232. </div>
  233. </div>
  234. <previewImageTool ref="previewImageToolRef" />
  235. </div>
  236. </template>
  237. <script setup lang="ts">
  238. import { computed, ref, watch, onUnmounted, nextTick } from 'vue'
  239. import * as echarts from 'echarts'
  240. import previewImageTool from '../../components/tool/previewImageTool.vue'
  241. import MarkdownIt from 'markdown-it'
  242. import useImport from '@/hooks/useImport'
  243. const props = defineProps<{
  244. visible: number[];
  245. workIndex: number;
  246. slideWidth: number;
  247. slideHeight: number;
  248. slideIndex: number;
  249. showData: any;
  250. workArray: any[];
  251. }>()
  252. const emit = defineEmits<{
  253. (e: 'update:visible', v: number[]): void;
  254. (e: 'changeWorkIndex', v: number): void;
  255. }>()
  256. const visible = computed({
  257. get: () => props.visible,
  258. set: (v: number[]) => emit('update:visible', v),
  259. })
  260. const workDetail = computed(() => {
  261. if (props.showData) {
  262. return props.showData.workDetail
  263. }
  264. return null
  265. })
  266. // 预览图片组件
  267. const previewImageToolRef = ref<any>(null)
  268. const md = new MarkdownIt()
  269. const { getFile } = useImport()
  270. // 判断是否是 URL 链接
  271. const isUrl = (str: string): boolean => {
  272. try {
  273. const url = new URL(str)
  274. return (url.protocol === 'http:' || url.protocol === 'https:') && str.includes('json')
  275. }
  276. catch {
  277. return false
  278. }
  279. }
  280. // 从链接获取文件内容
  281. const loadContentFromUrl = async (url: string): Promise<string> => {
  282. try {
  283. const fileData = await getFile(url)
  284. if (fileData && fileData.data) {
  285. // 将 ArrayBuffer 转为字符串
  286. const uint8Array = new Uint8Array(fileData.data)
  287. const jsonStr = new TextDecoder('utf-8').decode(uint8Array)
  288. return jsonStr
  289. }
  290. return ''
  291. }
  292. catch (error) {
  293. console.error('获取文件内容失败:', error)
  294. return ''
  295. }
  296. }
  297. // 处理单个作业内容
  298. const processWorkContent = async (content: string, toolType: number): Promise<any> => {
  299. let contentToParse = content
  300. // 如果是链接,先获取文件内容
  301. if (isUrl(content)) {
  302. contentToParse = await loadContentFromUrl(content)
  303. }
  304. if (!contentToParse) {
  305. return null
  306. }
  307. try {
  308. if ([45, 15].includes(toolType)) {
  309. return JSON.parse(decodeURIComponent(contentToParse))
  310. }
  311. else if (toolType === 72) {
  312. const parsed = JSON.parse(contentToParse)
  313. if (Array.isArray(parsed)) {
  314. parsed.forEach((item: any) => {
  315. if (item.messages && item.messages.length) {
  316. item.messages.forEach((item2: any) => {
  317. // 如果已经包含html标签则不再渲染
  318. if (
  319. !/^(\s*<[^>]+>.*<\/[^>]+>\s*|<[^>]+\/>\s*)$/s.test(
  320. item2.content.trim()
  321. )
  322. ) {
  323. item2.content = item2.content.replace(/&lt;/g, '<').replace(/&quot;/g, '"').replace(/&gt;/g, '>')
  324. item2.content = md.render(item2.content)
  325. }
  326. })
  327. }
  328. })
  329. }
  330. return parsed
  331. }
  332. return contentToParse
  333. }
  334. catch (error) {
  335. console.error('解析内容失败:', error)
  336. return null
  337. }
  338. }
  339. const processedWorkArray = ref<any[]>([])
  340. // 监听 workArray 和 showData 变化
  341. watch(
  342. () => [props.workArray, props.showData?.toolType],
  343. async () => {
  344. if (props.workArray && props.showData) {
  345. const _workArray = JSON.parse(JSON.stringify(props.workArray))
  346. // 处理每个作业内容
  347. for (const i of _workArray) {
  348. if (i.content) {
  349. const processedContent = await processWorkContent(i.content, props.showData.toolType)
  350. if (processedContent !== null) {
  351. i.content = processedContent
  352. }
  353. }
  354. }
  355. processedWorkArray.value = _workArray
  356. }
  357. else {
  358. processedWorkArray.value = []
  359. }
  360. },
  361. { immediate: true, deep: true }
  362. )
  363. // 关闭对应的作业详细页面
  364. const closeSlideIndex = () => {
  365. visible.value = visible.value.filter((v) => v !== props.slideIndex)
  366. }
  367. // 切换题目
  368. const changeWorkIndex = (type:number) => {
  369. emit('changeWorkIndex', type)
  370. // console.log(props.workIndex, props.showData.choiceQuestionListData.length)
  371. // if (type === 0 && props.workIndex > 0) {
  372. // emit('changeWorkIndex', 0)
  373. // }
  374. // else if (type === 1 && props.workIndex < props.showData.choiceQuestionListData.length) {
  375. // emit('changeWorkIndex', props.workIndex + 1)
  376. // }
  377. }
  378. // 选择题图表div
  379. const echartsArea1 = ref<any>(null)
  380. // 查看的作业详细id
  381. const lookWorkDetail = ref<string>('')
  382. // 查看作业详细的数据
  383. const lookWorkData = computed(() => {
  384. let _result = null
  385. if (lookWorkDetail.value && processedWorkArray.value.length > 0) {
  386. const _workFind = processedWorkArray.value.find(
  387. (i: any) => i.id === lookWorkDetail.value
  388. )
  389. if (_workFind) {
  390. _result = _workFind
  391. }
  392. }
  393. return _result
  394. })
  395. // 查看图片
  396. const lookImage = (url: string) => {
  397. if (previewImageToolRef.value) {
  398. previewImageToolRef.value.previewImage(url)
  399. }
  400. }
  401. // 查看作业
  402. const lookWork = (id: string) => {
  403. lookWorkDetail.value = id
  404. }
  405. // 选择题图表实例
  406. const myChart = ref<any>(null)
  407. // resize防抖定时器
  408. let resizeTimer: ReturnType<typeof setTimeout> | null = null
  409. // 处理ECharts resize
  410. const handleChartResize = () => {
  411. // 清除之前的定时器
  412. if (resizeTimer) {
  413. clearTimeout(resizeTimer)
  414. }
  415. resizeTimer = setTimeout(() => {
  416. nextTick(() => {
  417. if (
  418. myChart.value &&
  419. typeof myChart.value.resize === 'function' &&
  420. !myChart.value.isDisposed()
  421. ) {
  422. try {
  423. myChart.value.resize()
  424. }
  425. catch (e) {
  426. // console.error('myChart resize error:', e)
  427. // 如果resize失败,重新初始化图表
  428. if (
  429. props.showData &&
  430. props.showData.workDetail &&
  431. props.showData.workDetail.type === '45'
  432. ) {
  433. setEchartsArea1()
  434. }
  435. }
  436. }
  437. })
  438. }, 200) // 防抖延迟200ms
  439. }
  440. // 设置选择题图表
  441. const setEchartsArea1 = () => {
  442. // 如果已有实例且未销毁,先销毁
  443. if (myChart.value && !myChart.value.isDisposed()) {
  444. myChart.value.dispose()
  445. }
  446. if (echartsArea1.value) {
  447. myChart.value = echarts.init(echartsArea1.value)
  448. }
  449. else {
  450. myChart.value = null
  451. }
  452. if (myChart.value) {
  453. const _work =
  454. props.showData.choiceQuestionListData[props.showData.workIndex]
  455. // 修正版,处理xAxis.data内为图片对象的case,formatter始终只拿到src或自定义label,保证无[object Object]问题
  456. const option = {
  457. tooltip: {
  458. show: false, // 禁用鼠标移动到柱体时的内容显示
  459. },
  460. yAxis: {
  461. show: false, // 不显示最左边的y轴
  462. },
  463. xAxis: {
  464. data: [],
  465. axisLabel: {
  466. color: 'rgba(0, 0, 0, 0.9)',
  467. fontWeight: 600,
  468. fontSize: 17,
  469. lineHeight: 20,
  470. interval: 0,
  471. formatter: function(value: any, idx: number) {
  472. // 如果是字符串且格式为JSON(图片),则解析处理
  473. if (typeof value === 'string') {
  474. try {
  475. const obj = JSON.parse(value)
  476. if (obj && typeof obj === 'object' && obj.imgType && obj.src) {
  477. return '{img' + idx + '|}'
  478. }
  479. }
  480. catch (e) {
  481. // 非JSON字符串,直接返回
  482. // 如果文本文字超过8个字,换行
  483. if (typeof value === 'string') {
  484. let displayValue = value
  485. if (value.length > 20) {
  486. displayValue = value.substr(0, 20) + '...'
  487. }
  488. // 8个字换行
  489. let output = ''
  490. for (let i = 0; i < displayValue.length; i += 8) {
  491. output += displayValue.substr(i, 8)
  492. if (i + 8 < displayValue.length) {
  493. output += '\n'
  494. }
  495. }
  496. return output
  497. }
  498. return value
  499. }
  500. return value
  501. }
  502. // 兼容老格式(容错):value本身是对象,并有图片信息
  503. if (
  504. value &&
  505. typeof value === 'object' &&
  506. value.imgType &&
  507. value.src
  508. ) {
  509. return '{img' + idx + '|}'
  510. }
  511. // 其他类型直接空
  512. return ''
  513. },
  514. rich: (() => {
  515. // 动态生成所有图片的 rich 格式
  516. const richObj: any = {}
  517. _work.choiceUser.forEach((op: any, idx: number) => {
  518. if (
  519. op.option &&
  520. typeof op.option === 'object' &&
  521. op.option.imgType &&
  522. op.option.src
  523. ) {
  524. richObj['img' + idx] = {
  525. height: 40,
  526. width: 40,
  527. align: 'center',
  528. backgroundColor: {
  529. image: op.option.src,
  530. },
  531. }
  532. }
  533. })
  534. return richObj
  535. })(),
  536. },
  537. },
  538. series: [
  539. {
  540. name: '',
  541. type: 'bar',
  542. data: [],
  543. barWidth: '50%', // 柱体宽度缩小40%
  544. itemStyle: {
  545. color: 'rgba(252, 207, 0, 1)',
  546. },
  547. label: {
  548. show: true,
  549. position: 'top',
  550. color: 'rgba(116, 139, 115, 1)',
  551. fontSize: 22,
  552. fontWeight: 500,
  553. lineHeight: 24,
  554. },
  555. },
  556. ],
  557. }
  558. _work.choiceUser.forEach((i: any, idx: number) => {
  559. // 如果是图片,存src对象,否则为字符串
  560. if (
  561. i.option &&
  562. typeof i.option === 'object' &&
  563. i.option.imgType &&
  564. i.option.src
  565. ) {
  566. (option.xAxis.data as any[]).push(
  567. JSON.stringify({ imgType: i.option.imgType, src: i.option.src })
  568. ) // 仅保留相关字段
  569. }
  570. else if (typeof i.option === 'string') {
  571. (option.xAxis.data as any[]).push(i.option)
  572. }
  573. else {
  574. (option.xAxis.data as any[]).push('')
  575. }
  576. (option.series[0].data as any[]).push(i.user.length)
  577. })
  578. console.log(option)
  579. // {
  580. // title: {
  581. // text: 'ECharts 入门示例'
  582. // },
  583. // tooltip: {},
  584. // xAxis: {
  585. // data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
  586. // },
  587. // yAxis: {},
  588. // series: [
  589. // {
  590. // name: '销量',
  591. // type: 'bar',
  592. // data: [5, 20, 36, 10, 10, 20]
  593. // }
  594. // ]
  595. // }
  596. myChart.value.setOption(option)
  597. }
  598. }
  599. // 监听选择题数据变化
  600. watch(
  601. () => props.showData,
  602. (newVal, oldVal) => {
  603. console.log('发生变化,showData')
  604. if (
  605. newVal &&
  606. newVal.choiceQuestionListData[newVal.workIndex] &&
  607. props.showData.workDetail.type === '45'
  608. ) {
  609. if (
  610. oldVal &&
  611. newVal.choiceQuestionListData[newVal.workIndex] &&
  612. oldVal.choiceQuestionListData[oldVal.workIndex]
  613. ) {
  614. if (
  615. JSON.stringify(newVal.choiceQuestionListData[newVal.workIndex]) !==
  616. JSON.stringify(oldVal.choiceQuestionListData[oldVal.workIndex])
  617. ) {
  618. setEchartsArea1()
  619. }
  620. }
  621. }
  622. else {
  623. myChart.value = null
  624. }
  625. },
  626. { immediate: true, deep: true }
  627. )
  628. // 监听作业变化
  629. watch(
  630. () => props.showData?.choiceQuestionListData,
  631. (newVal, oldVal) => {
  632. console.log('choiceQuestionListData变化了')
  633. if (
  634. (newVal || newVal === 0) &&
  635. props.showData.workDetail &&
  636. props.showData.workDetail.type === '45'
  637. ) {
  638. if (JSON.stringify(newVal) !== JSON.stringify(oldVal)) {
  639. setEchartsArea1()
  640. }
  641. else {
  642. console.log('choiceQuestionListData没有变化')
  643. }
  644. }
  645. else {
  646. myChart.value = null
  647. }
  648. },
  649. { deep: true }
  650. )
  651. // 监听作业变化
  652. watch(
  653. () => props.showData?.workIndex,
  654. (newVal) => {
  655. if (
  656. (newVal || newVal === 0) &&
  657. props.showData.workDetail &&
  658. props.showData.workDetail.type === '45'
  659. ) {
  660. setEchartsArea1()
  661. }
  662. else {
  663. myChart.value = null
  664. }
  665. }
  666. )
  667. // 监听echartsArea1变化
  668. watch(
  669. () => echartsArea1.value,
  670. (newVal) => {
  671. if (
  672. newVal &&
  673. props.showData &&
  674. props.showData.workDetail &&
  675. props.showData.workDetail.type === '45'
  676. ) {
  677. setEchartsArea1()
  678. }
  679. else {
  680. myChart.value = null
  681. }
  682. }
  683. )
  684. // 监听页面宽度变化
  685. watch(
  686. () => props.slideWidth,
  687. (newVal) => {
  688. if (
  689. newVal &&
  690. props.showData &&
  691. props.showData.workDetail &&
  692. props.showData.workDetail.type === '45'
  693. ) {
  694. handleChartResize()
  695. }
  696. }
  697. )
  698. // 组件卸载时清理ECharts实例
  699. onUnmounted(() => {
  700. // 清除定时器
  701. if (resizeTimer) {
  702. clearTimeout(resizeTimer)
  703. resizeTimer = null
  704. }
  705. // 销毁ECharts实例
  706. if (myChart.value && !myChart.value.isDisposed()) {
  707. myChart.value.dispose()
  708. myChart.value = null
  709. }
  710. })
  711. </script>
  712. <style lang="scss" scoped>
  713. .choiceQuestionDetailDialog {
  714. background: none;
  715. position: relative;
  716. width: 100%;
  717. height: 100%;
  718. z-index: 1;
  719. .content {
  720. width: 100%;
  721. height: 100%;
  722. position: relative;
  723. background: #fff;
  724. box-sizing: border-box;
  725. padding: 40px;
  726. overflow: auto;
  727. .closeIcon {
  728. position: absolute;
  729. right: 20px;
  730. top: 20px;
  731. cursor: pointer;
  732. width: 20px;
  733. height: 20px;
  734. img {
  735. width: 100%;
  736. height: 100%;
  737. }
  738. }
  739. .c_t45 {
  740. width: 100%;
  741. min-height: 100%;
  742. display: flex;
  743. align-items: center;
  744. flex-direction: column;
  745. height: auto;
  746. .c_t45_title {
  747. color: rgba(0, 0, 0, 0.9);
  748. font-weight: 600;
  749. font-size: 24px;
  750. line-height: 24px;
  751. position: relative;
  752. width: 100%;
  753. display: flex;
  754. align-items: center;
  755. justify-content: center;
  756. user-select: none;
  757. &>div{
  758. max-width: calc(100% - 200px);
  759. }
  760. &>span{
  761. position: absolute;
  762. top: 20px;
  763. cursor: pointer;
  764. &:nth-of-type(1){
  765. left: 0;
  766. }
  767. &:nth-of-type(2){
  768. right: 0;
  769. }
  770. }
  771. .c_t45_t_btn_noActive{
  772. color: #CCCCCC;
  773. }
  774. }
  775. .c_t45_img {
  776. max-width: 200px;
  777. object-fit: cover;
  778. margin-top: 20px;
  779. }
  780. .c_t45_type {
  781. font-weight: 400;
  782. font-size: 15px;
  783. line-height: 21px;
  784. letter-spacing: 0.5px;
  785. color: rgba(0, 0, 0, 1);
  786. opacity: 0.5;
  787. margin-top: 20px;
  788. }
  789. .c_t45_echarts {
  790. width: 100%;
  791. flex: 1;
  792. min-height: 400px;
  793. display: flex;
  794. align-items: center;
  795. box-sizing: border-box;
  796. & > div {
  797. width: 100%;
  798. height: 400px;
  799. }
  800. }
  801. }
  802. .c_t15 {
  803. width: 100%;
  804. min-height: 100%;
  805. display: flex;
  806. align-items: center;
  807. flex-direction: column;
  808. height: auto;
  809. padding: 40px;
  810. .c_t15_title {
  811. color: rgba(0, 0, 0, 0.9);
  812. font-weight: 600;
  813. font-size: 24px;
  814. line-height: 24px;
  815. }
  816. .c_t15_type {
  817. font-weight: 400;
  818. font-size: 15px;
  819. line-height: 21px;
  820. letter-spacing: 0.5px;
  821. color: rgba(0, 0, 0, 1);
  822. opacity: 0.5;
  823. margin-top: 20px;
  824. }
  825. .c_t15_content {
  826. width: 100%;
  827. height: auto;
  828. display: grid;
  829. grid-template-columns: repeat(3, 1fr);
  830. gap: 20px;
  831. margin-top: 40px;
  832. .c_t15_c_item {
  833. width: 100%;
  834. height: auto;
  835. box-shadow: 2px 4px 20px 0px rgba(0, 0, 0, 0.2);
  836. box-sizing: border-box;
  837. border-radius: 12px;
  838. padding: 16px;
  839. background: rgba(255, 255, 255, 0.6);
  840. transition: 0.3s;
  841. cursor: pointer;
  842. &:hover {
  843. box-shadow: 4px 4px 14px 0px rgba(252, 207, 0, 0.5);
  844. background: rgba(255, 255, 255, 0.6);
  845. }
  846. .c_t15_c_i_top {
  847. display: flex;
  848. align-items: center;
  849. gap: 10px;
  850. & > span {
  851. display: block;
  852. width: 25px;
  853. height: 25px;
  854. display: flex;
  855. align-items: center;
  856. justify-content: center;
  857. background: rgba(252, 207, 0, 1);
  858. border-radius: 4px;
  859. color: rgba(255, 255, 255, 1);
  860. font-weight: bold;
  861. font-size: 14px;
  862. }
  863. & > div {
  864. color: rgba(0, 0, 0, 0.7);
  865. font-weight: 800;
  866. }
  867. }
  868. .c_t15_c_i_bottom {
  869. margin-top: 15px;
  870. font-weight: 300;
  871. font-size: 14px;
  872. height: 40px;
  873. max-width: 100%;
  874. overflow: hidden;
  875. text-overflow: ellipsis;
  876. display: -webkit-box;
  877. -webkit-line-clamp: 2;
  878. -webkit-box-orient: vertical;
  879. }
  880. }
  881. }
  882. .c_t15_workDetail {
  883. width: 100%;
  884. height: auto;
  885. margin-top: 40px;
  886. box-shadow: 4px 4px 14px 0px rgba(252, 207, 0, 0.5);
  887. box-sizing: border-box;
  888. padding: 16px;
  889. border-radius: 12px;
  890. display: flex;
  891. flex-direction: column;
  892. .c_t15_wd_top {
  893. width: 100%;
  894. display: flex;
  895. align-items: center;
  896. gap: 15px;
  897. & > img {
  898. width: 25px;
  899. height: 25px;
  900. cursor: pointer;
  901. }
  902. & > span {
  903. display: block;
  904. width: 30px;
  905. height: 30px;
  906. display: flex;
  907. align-items: center;
  908. justify-content: center;
  909. background: rgba(252, 207, 0, 1);
  910. border-radius: 4px;
  911. color: rgba(255, 255, 255, 1);
  912. font-weight: bold;
  913. font-size: 16px;
  914. }
  915. & > div {
  916. color: rgba(0, 0, 0, 0.7);
  917. font-weight: 800;
  918. font-size: 18px;
  919. }
  920. }
  921. .c_t15_wd_content {
  922. width: 100%;
  923. margin-top: 20px;
  924. max-height: 100%;
  925. overflow: auto;
  926. flex-wrap: wrap;
  927. .c_t15_wd_c_imageList {
  928. width: 100%;
  929. gap: 20px;
  930. margin-top: 20px;
  931. & > img {
  932. width: 100px;
  933. height: auto;
  934. cursor: pointer;
  935. margin-right: 20px;
  936. object-fit: cover;
  937. }
  938. }
  939. }
  940. }
  941. }
  942. .c_t72 {
  943. width: 100%;
  944. min-height: 100%;
  945. display: flex;
  946. align-items: center;
  947. flex-direction: column;
  948. height: auto;
  949. padding: 40px;
  950. .c_t72_title {
  951. color: rgba(0, 0, 0, 0.9);
  952. font-weight: 600;
  953. font-size: 24px;
  954. line-height: 24px;
  955. }
  956. .c_t72_type {
  957. font-weight: 400;
  958. font-size: 15px;
  959. line-height: 21px;
  960. letter-spacing: 0.5px;
  961. color: rgba(0, 0, 0, 1);
  962. opacity: 0.5;
  963. margin-top: 20px;
  964. }
  965. .c_t72_content {
  966. width: 100%;
  967. height: auto;
  968. display: grid;
  969. grid-template-columns: repeat(4, 1fr);
  970. gap: 20px;
  971. margin-top: 40px;
  972. .c_t72_c_item {
  973. width: 100%;
  974. height: auto;
  975. box-shadow: 2px 4px 20px 0px rgba(0, 0, 0, 0.2);
  976. box-sizing: border-box;
  977. border-radius: 12px;
  978. padding: 16px;
  979. background: rgba(255, 255, 255, 0.6);
  980. transition: 0.3s;
  981. cursor: pointer;
  982. &:hover {
  983. box-shadow: 4px 4px 14px 0px rgba(252, 207, 0, 0.5);
  984. background: rgba(255, 255, 255, 0.6);
  985. }
  986. .c_t72_c_i_top {
  987. display: flex;
  988. align-items: center;
  989. gap: 10px;
  990. & > span {
  991. display: block;
  992. width: 25px;
  993. height: 25px;
  994. display: flex;
  995. align-items: center;
  996. justify-content: center;
  997. background: rgba(252, 207, 0, 1);
  998. border-radius: 4px;
  999. color: rgba(255, 255, 255, 1);
  1000. font-weight: bold;
  1001. font-size: 14px;
  1002. }
  1003. & > div {
  1004. color: rgba(0, 0, 0, 0.7);
  1005. font-weight: 800;
  1006. }
  1007. }
  1008. .c_t72_c_i_bottom {
  1009. margin-top: 15px;
  1010. font-weight: 300;
  1011. font-size: 14px;
  1012. // height: 40px;
  1013. max-width: 100%;
  1014. overflow: hidden;
  1015. text-overflow: ellipsis;
  1016. display: -webkit-box;
  1017. -webkit-line-clamp: 2;
  1018. -webkit-box-orient: vertical;
  1019. img {
  1020. width: 100%;
  1021. max-height: 200px;
  1022. object-fit: cover;
  1023. }
  1024. }
  1025. }
  1026. }
  1027. .c_t72_workDetail {
  1028. width: 100%;
  1029. height: auto;
  1030. margin-top: 40px;
  1031. box-shadow: 4px 4px 14px 0px rgba(252, 207, 0, 0.5);
  1032. box-sizing: border-box;
  1033. padding: 16px;
  1034. border-radius: 12px;
  1035. display: flex;
  1036. flex-direction: column;
  1037. .c_t72_wd_top {
  1038. width: 100%;
  1039. display: flex;
  1040. align-items: center;
  1041. gap: 15px;
  1042. & > img {
  1043. width: 25px;
  1044. height: 25px;
  1045. cursor: pointer;
  1046. }
  1047. & > span {
  1048. display: block;
  1049. width: 30px;
  1050. height: 30px;
  1051. display: flex;
  1052. align-items: center;
  1053. justify-content: center;
  1054. background: rgba(252, 207, 0, 1);
  1055. border-radius: 4px;
  1056. color: rgba(255, 255, 255, 1);
  1057. font-weight: bold;
  1058. font-size: 16px;
  1059. }
  1060. & > div {
  1061. color: rgba(0, 0, 0, 0.7);
  1062. font-weight: 800;
  1063. font-size: 18px;
  1064. }
  1065. }
  1066. .c_t72_wd_content {
  1067. width: 100%;
  1068. margin-top: 20px;
  1069. max-height: 100%;
  1070. overflow: auto;
  1071. flex-wrap: wrap;
  1072. display: flex;
  1073. align-items: center;
  1074. justify-content: center;
  1075. .na_m_item {
  1076. width: 100%;
  1077. height: auto;
  1078. margin: 10px 0;
  1079. }
  1080. .na_m_i_name {
  1081. width: fit-content;
  1082. max-width: 100%;
  1083. height: auto;
  1084. box-sizing: border-box;
  1085. padding: 10px 10px;
  1086. display: flex;
  1087. align-items: center;
  1088. border-radius: 10px 10px 0 0;
  1089. background-color: #9747ff;
  1090. color: #fff;
  1091. text-overflow: ellipsis;
  1092. overflow: hidden;
  1093. white-space: nowrap;
  1094. }
  1095. .aiName {
  1096. background-color: #0560fc;
  1097. }
  1098. .na_m_i_content {
  1099. padding: 10px;
  1100. border: solid 1px #e7e7e7;
  1101. box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.1);
  1102. border-radius: 0 0 12px 12px;
  1103. background-color: #fff;
  1104. :deep(img){
  1105. max-width: 100%;
  1106. }
  1107. }
  1108. .messageNode {
  1109. width: 100%;
  1110. height: auto;
  1111. box-sizing: border-box;
  1112. padding: 10px 10px;
  1113. border: 0.5px solid #e7e7e7;
  1114. border-radius: 12px;
  1115. gap: 10px;
  1116. margin-top: 20px;
  1117. }
  1118. .messageNodeArea{
  1119. width: 100%;
  1120. height: auto;
  1121. }
  1122. }
  1123. }
  1124. }
  1125. .c_t73 {
  1126. width: 100%;
  1127. min-height: 100%;
  1128. display: flex;
  1129. align-items: center;
  1130. flex-direction: column;
  1131. height: auto;
  1132. padding: 40px;
  1133. .c_t73_title {
  1134. color: rgba(0, 0, 0, 0.9);
  1135. font-weight: 600;
  1136. font-size: 24px;
  1137. line-height: 24px;
  1138. }
  1139. .c_t73_type {
  1140. font-weight: 400;
  1141. font-size: 15px;
  1142. line-height: 21px;
  1143. letter-spacing: 0.5px;
  1144. color: rgba(0, 0, 0, 1);
  1145. opacity: 0.5;
  1146. margin-top: 20px;
  1147. }
  1148. .c_t73_content {
  1149. width: 100%;
  1150. height: auto;
  1151. display: grid;
  1152. grid-template-columns: repeat(4, 1fr);
  1153. gap: 20px;
  1154. margin-top: 40px;
  1155. .c_t73_c_item {
  1156. width: 100%;
  1157. height: auto;
  1158. box-shadow: 2px 4px 20px 0px rgba(0, 0, 0, 0.2);
  1159. box-sizing: border-box;
  1160. border-radius: 12px;
  1161. padding: 16px;
  1162. background: rgba(255, 255, 255, 0.6);
  1163. transition: 0.3s;
  1164. cursor: pointer;
  1165. &:hover {
  1166. box-shadow: 4px 4px 14px 0px rgba(252, 207, 0, 0.5);
  1167. background: rgba(255, 255, 255, 0.6);
  1168. }
  1169. .c_t73_c_i_top {
  1170. display: flex;
  1171. width: 100%;
  1172. align-items: center;
  1173. gap: 10px;
  1174. & > span {
  1175. display: block;
  1176. width: 25px;
  1177. height: 25px;
  1178. display: flex;
  1179. align-items: center;
  1180. justify-content: center;
  1181. background: rgba(252, 207, 0, 1);
  1182. border-radius: 4px;
  1183. color: rgba(255, 255, 255, 1);
  1184. font-weight: bold;
  1185. font-size: 14px;
  1186. }
  1187. & > div {
  1188. color: rgba(0, 0, 0, 0.7);
  1189. font-weight: 800;
  1190. }
  1191. }
  1192. .c_t73_c_i_bottom {
  1193. margin-top: 15px;
  1194. font-weight: 300;
  1195. font-size: 14px;
  1196. // height: 40px;
  1197. max-width: 100%;
  1198. overflow: hidden;
  1199. text-overflow: ellipsis;
  1200. display: -webkit-box;
  1201. -webkit-line-clamp: 2;
  1202. -webkit-box-orient: vertical;
  1203. img {
  1204. width: 100%;
  1205. max-height: 200px;
  1206. object-fit: cover;
  1207. }
  1208. }
  1209. }
  1210. }
  1211. .c_t73_workDetail {
  1212. width: 100%;
  1213. height: auto;
  1214. margin-top: 40px;
  1215. box-shadow: 4px 4px 14px 0px rgba(252, 207, 0, 0.5);
  1216. box-sizing: border-box;
  1217. padding: 16px;
  1218. border-radius: 12px;
  1219. display: flex;
  1220. flex-direction: column;
  1221. .c_t73_wd_top {
  1222. width: 100%;
  1223. display: flex;
  1224. align-items: center;
  1225. gap: 15px;
  1226. & > img {
  1227. width: 25px;
  1228. height: 25px;
  1229. cursor: pointer;
  1230. }
  1231. & > span {
  1232. display: block;
  1233. width: 30px;
  1234. height: 30px;
  1235. display: flex;
  1236. align-items: center;
  1237. justify-content: center;
  1238. background: rgba(252, 207, 0, 1);
  1239. border-radius: 4px;
  1240. color: rgba(255, 255, 255, 1);
  1241. font-weight: bold;
  1242. font-size: 16px;
  1243. }
  1244. & > div {
  1245. color: rgba(0, 0, 0, 0.7);
  1246. font-weight: 800;
  1247. font-size: 18px;
  1248. }
  1249. }
  1250. .c_t73_wd_content {
  1251. width: 100%;
  1252. margin-top: 20px;
  1253. max-height: 100%;
  1254. overflow: auto;
  1255. flex-wrap: wrap;
  1256. display: flex;
  1257. align-items: center;
  1258. justify-content: center;
  1259. & > img {
  1260. max-width: 100%;
  1261. object-fit: cover;
  1262. }
  1263. }
  1264. }
  1265. }
  1266. }
  1267. }
  1268. </style>