choiceQuestionDetailDialog.vue 34 KB

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