|
|
<!--
|
|
|
* @Author: qinzhenpen qzp1807@126.com
|
|
|
* @Date: 2025-03-03 14:13:35
|
|
|
* @LastEditors: qinzhenpen qzp1807@126.com
|
|
|
* @LastEditTime: 2025-05-07 10:05:57
|
|
|
* @FilePath: \financial-big-data\src\components\Ai\index.vue
|
|
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
|
-->
|
|
|
<template>
|
|
|
<div class="index">
|
|
|
<div class="min-h-screen" ref="header">
|
|
|
<div class="title">
|
|
|
<h1>在这里,用 AI 智能学习,直通就业</h1>
|
|
|
</div>
|
|
|
<div class="tz-tobs mb10">
|
|
|
<template v-for="(tbas, idx) in tabList" :key="tbas.name">
|
|
|
<div :style="{ background: `url(${getAssetsFile(`${idx + 1}.webp`)}) no-repeat`, backgroundSize: '100% 100%' }" :class="[tbas == tabactive ? 'el-tobs-item active' : ' el-tobs-item', { 'el-tobs-item-active': claActive == tbas.name }]" @click="changeTab(tbas)">
|
|
|
<span>{{ tbas.name }}</span>
|
|
|
</div>
|
|
|
</template>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="tz-centent" ref="container">
|
|
|
<div class="tz-step" ref="step">
|
|
|
<div class="tz-stop-info">
|
|
|
<template v-for="item in tabactive.children" :key="item.title">
|
|
|
<div :class="['info-title', { 'info-title-active': stopActive == item.title }]" @click="changeStop(item.title)">{{ item.title }}</div>
|
|
|
</template>
|
|
|
</div>
|
|
|
<div class="tz-stop-centent">
|
|
|
<div class="stop">
|
|
|
<template v-for="(item, index) in tabactive.children" :key="index">
|
|
|
<template v-if="item.title == stopActive">
|
|
|
<div :class="['stop-item', { 'info-title-completedSteps': childs.isTemplateBased }, { 'info-title-completedSteps-disdabled': !isTaskEnabled(item.child, idx) }]" v-for="(childs, idx) in item.child" :key="childs" @click="onClick(childs, idx)">{{ childs.name }}</div>
|
|
|
</template>
|
|
|
</template>
|
|
|
</div>
|
|
|
<div class="fbtn fr" style="display: flex; gap: 20px">
|
|
|
<el-upload :auto-upload="false" class="avatar-uploader" :show-file-list="false" :data="domfile" :on-change="submitDocument" accept=".xls,.xlsx,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">
|
|
|
<template #trigger>
|
|
|
<el-button type="primary" :disabled="!allTrue()">提交</el-button>
|
|
|
</template>
|
|
|
</el-upload>
|
|
|
<el-button type="success" @click="exportSession">导出会话</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<el-scrollbar :height="scrollbarHeight" ref="scrollArea">
|
|
|
<ul class="QAlist">
|
|
|
<li :class="[item.role == 'user' ? 'questionItem' : 'answerItem']" v-for="item in messages" :key="item" :data-name="item.name">
|
|
|
<div :class="[item.role == 'user' ? 'qustionCon' : 'answerCon']">
|
|
|
<div v-if="item.role !== 'user'" class="answerCon-img">
|
|
|
<img src="@/assets/images/ai.webp" alt="" />
|
|
|
</div>
|
|
|
<MdPreview :editorId="id" :modelValue="item.content" :codeFoldable="false" theme="dark" codeTheme="a11y" />
|
|
|
<div class="copy">
|
|
|
<el-tooltip class="box-item" effect="dark" content="复制" placement="top">
|
|
|
<svg-icon icon-class="copy" v-copyText="item.content" v-copyText:callback="copyTextSuccess" />
|
|
|
</el-tooltip>
|
|
|
</div>
|
|
|
</div>
|
|
|
</li>
|
|
|
<li v-if="isRequestPending">
|
|
|
<div style="display: flex; align-items: center">
|
|
|
<img src="@/assets/images/ai.webp" alt="" />
|
|
|
<div style="height: 68px" v-loading="isRequestPending" :element-loading-svg="svg"></div>
|
|
|
</div>
|
|
|
</li>
|
|
|
<li>
|
|
|
<div class="task-introduction" v-if="messages.length <= 0">
|
|
|
<div class="title mb10">
|
|
|
<span>{{ tabactive.introduce }}</span>
|
|
|
</div>
|
|
|
<p style="font-size: 1rem !important">提示词小技巧:</p>
|
|
|
<ul>
|
|
|
<li>提问时给出具体知识点、技能点等数量要求:</li>
|
|
|
<li>每个点或者整体加上字数限制:</li>
|
|
|
<li>要求AI输出表格,进行图表等可视化展示:</li>
|
|
|
<li>针对AI给出内容某一点继续详细追问,进行深入学习了解:</li>
|
|
|
</ul>
|
|
|
</div>
|
|
|
</li>
|
|
|
</ul>
|
|
|
</el-scrollbar>
|
|
|
</div>
|
|
|
<div class="tz-footer-ipt" ref="footer">
|
|
|
<el-input type="textarea" placeholder="可以问我任何问题" v-model.trim="inputMessage" @keyup.enter="sendMessage" :autosize="{ minRows: 4.5, maxRows: 3 }" />
|
|
|
<svg-icon icon-class="发送" class="fr" v-if="isTypingComplete" @click="sendMessage" :class="{ disdabled: !inputMessage }" />
|
|
|
<svg-icon icon-class="中断" class="fr" @click="gInterrupt" v-else />
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
<script setup>
|
|
|
import { MdPreview, MdCatalog } from "md-editor-v3";
|
|
|
import { getAssetsFile } from "@/utils/index.js";
|
|
|
import * as AI from "@/api/AI.js";
|
|
|
import * as indexApi from "@/api/index";
|
|
|
import "md-editor-v3/lib/style.css";
|
|
|
import useUserStore from "@/store/modules/user";
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
const userStore = useUserStore();
|
|
|
const scrollbarHeight = ref("auto"); // 动态高度
|
|
|
const container = ref(null); // 父容器
|
|
|
const header = ref(null); // 头部
|
|
|
const step = ref(null); // 头部
|
|
|
const footer = ref(null); // 底部
|
|
|
let resizeObserver = null; // ResizeObserver 实例
|
|
|
const inputMessage = ref("");
|
|
|
const isRequestPending = ref(false);
|
|
|
const isTypingComplete = ref(true);
|
|
|
const scrollArea = ref(null);
|
|
|
const tabList = ref([
|
|
|
{
|
|
|
name: "知识画布",
|
|
|
cor: "#55c5c3",
|
|
|
introduce: "本模块分为理论知识、实务知识、未来展望三个模块,每个模块分为五个步骤,学生根据相应步骤提示词,了解实训系统相关理论知识重点难点及学习建议,学习实训系统相关业务实务知识提作流程,相关单据协议及业务风险等,最后了解业务现状及理论研究,新技术应用等情况,了解未来发展趋势",
|
|
|
children: [
|
|
|
{
|
|
|
title: "理论知识",
|
|
|
child: [
|
|
|
{ name: "课程知识点", com: "请梳理xxx课程相关知识点,每个知识点解释字数50字以内" },
|
|
|
{ name: "核心知识点", com: "请梳理xxx课程最核心的5个模块,每个知识点解释字数50字以内" },
|
|
|
{ name: "最难的部分", com: "请指出xxx课程最难的1个模块,并解释原因,字数300字以内" },
|
|
|
{ name: "难点详解", com: "请详细解释xxx,字数800字以内" },
|
|
|
{ name: "学习建议", com: "请给我一些xxx课程的学习建议,字数300字以内" },
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "实务知识",
|
|
|
child: [
|
|
|
{
|
|
|
name: "实务知识概述",
|
|
|
com: "xxx相关实务知识有哪些?",
|
|
|
},
|
|
|
{
|
|
|
name: "业务操作流程",
|
|
|
com: "xxx业务在实务中是怎么操作的?",
|
|
|
},
|
|
|
{
|
|
|
name: "相关单据协议",
|
|
|
com: "xxx业务在实操中会用到哪些合同协议文件?",
|
|
|
},
|
|
|
{
|
|
|
name: "业务风险管理",
|
|
|
com: "xxx业务有哪些风险?如何防范?",
|
|
|
},
|
|
|
{
|
|
|
name: "流程优化建议",
|
|
|
com: "xxx业务流程可以进行优化以提高效率吗?请给出优化建议?",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "未来展望",
|
|
|
child: [
|
|
|
{
|
|
|
name: "业务现状",
|
|
|
com: "xxx国际和国内发展现状",
|
|
|
},
|
|
|
{
|
|
|
name: "理论研究",
|
|
|
com: "xxx相关理论有哪些,研究现状如何,是否有理论研究突破",
|
|
|
},
|
|
|
{
|
|
|
name: "新技术应用",
|
|
|
com: "xxx业务应用了哪些新技术?比如人工智能、大数据、物联网等新技术",
|
|
|
},
|
|
|
{
|
|
|
name: "技术应用详解",
|
|
|
com: "xxx技术在xxx业务中是如何应用的?有哪些应用案例?",
|
|
|
},
|
|
|
{
|
|
|
name: "发展趋势",
|
|
|
com: "xxx发展趋势如何?",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
name: "行业企业",
|
|
|
cor: "#538af7",
|
|
|
introduce: "本模块分为就业行业分析、企业对比、企业调研三个模块,每个模块分为五个步骤。学生根据相应步骤提示词,了解目标行业的发展现状、就业趋势及核心技能要求,掌握不同企业的业务模式、文化特点及竞争优势,并通过调研工具和方法,深入分析企业的组织架构、岗位需求及职业发展路径。最后,学生将结合行业动态和企业实践,形成对就业市场的全面认知,为职业规划提供科学依据。",
|
|
|
children: [
|
|
|
{
|
|
|
title: "就业行业",
|
|
|
child: [
|
|
|
{
|
|
|
name: "行业类型",
|
|
|
com: "xxx相关的就业行业类型主要有哪些?列出xx个行业",
|
|
|
},
|
|
|
{
|
|
|
name: "行业发展状况",
|
|
|
com: "xxx行业发展状况如何?",
|
|
|
},
|
|
|
{
|
|
|
name: "行业对比分析",
|
|
|
com: "请比较xx行业和xx行业,分析行业相关优劣及发展前景,输出表格",
|
|
|
},
|
|
|
{
|
|
|
name: "最佳客户化",
|
|
|
com: "请从行业特点及前景出发,客观推荐一个xx相关行业",
|
|
|
},
|
|
|
{
|
|
|
name: "行业详细分析",
|
|
|
com: "请详细分析xx行业,可以从多个方面进行分析",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "企业对比",
|
|
|
child: [
|
|
|
{
|
|
|
name: "企业规模",
|
|
|
com: "请对比前述相关xx家企业规模,并按企业规模大小排序",
|
|
|
},
|
|
|
{
|
|
|
name: "企业所在地",
|
|
|
com: "请根据前述xx家企业所在地,分析相关企业地域集聚现象",
|
|
|
},
|
|
|
{
|
|
|
name: "企业盈利",
|
|
|
com: "请根据企业规模,对比分析xx家企业盈利能力,并根据盈利能力进行排序",
|
|
|
},
|
|
|
{
|
|
|
name: "企业福利",
|
|
|
com: "请对比分析前述xx家企业福利状况,并根据福利状况进行排序",
|
|
|
},
|
|
|
{
|
|
|
name: "招聘情况",
|
|
|
com: "请对比分析前述xx家企业招聘情况,哪些企业招聘量较大?",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "企业调研",
|
|
|
child: [
|
|
|
{
|
|
|
name: "行业相关企业",
|
|
|
com: "xxx行业相关企业有哪些?请列出xx家",
|
|
|
},
|
|
|
{
|
|
|
name: "企业发展状况",
|
|
|
com: "xx企业发展历程及现状",
|
|
|
},
|
|
|
{
|
|
|
name: "企业财务状况",
|
|
|
com: "xx企业财务状况如何?盈利能力如何?财务风险如何?",
|
|
|
},
|
|
|
{
|
|
|
name: "企业面临风险",
|
|
|
com: "xx企业面临哪些风险?从政策、区域、行业、企业等多层面多角度分析",
|
|
|
},
|
|
|
{
|
|
|
name: "就业企业建议",
|
|
|
com: "上述相关企业推荐哪些企业作为就业企业?最佳荐哪家企业?",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
name: "岗位类型",
|
|
|
cor: "#eabd42",
|
|
|
introduce: "本模块分为岗位类型、岗位发展、推荐岗位三个模块,每个模块分为五个步骤。学生根据相应步骤提示词,了解不同岗位的职责要求、技能需求及工作特点,掌握岗位的职业发展路径及晋升机会,并通过分析行业趋势和个人兴趣,获得适合自己的岗位推荐及发展建议。最后,学生将结合岗位需求和自身优势,制定清晰的职业规划,为未来的就业选择提供科学指导。",
|
|
|
children: [
|
|
|
{
|
|
|
title: "岗位类型",
|
|
|
child: [
|
|
|
{
|
|
|
name: "岗位类型",
|
|
|
com: "xx相关的岗位类型有哪些?请列举出xx个",
|
|
|
},
|
|
|
{
|
|
|
name: "类型详解",
|
|
|
com: "请详细解释xx类岗位",
|
|
|
},
|
|
|
{
|
|
|
name: "工作内容",
|
|
|
com: "xx类岗位工作内容有哪些?",
|
|
|
},
|
|
|
{
|
|
|
name: "人员画像",
|
|
|
com: "xx类岗位工作人员画像,哪些人适合从事xx类岗位",
|
|
|
},
|
|
|
{
|
|
|
name: "推荐适合类型",
|
|
|
com: "我是一个xxx样的人,请为我推荐合适的岗位类型",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "岗位发展",
|
|
|
child: [
|
|
|
{
|
|
|
name: "基层岗位",
|
|
|
com: "xxx相关基层岗位",
|
|
|
},
|
|
|
{
|
|
|
name: "中层岗位",
|
|
|
com: "xx相关中层岗位",
|
|
|
},
|
|
|
{
|
|
|
name: "高层岗位",
|
|
|
com: "xx相关高层岗位",
|
|
|
},
|
|
|
{
|
|
|
name: "岗位现状",
|
|
|
com: "xx岗位现状",
|
|
|
},
|
|
|
{
|
|
|
name: "岗位前景",
|
|
|
com: "xx岗位发展前景",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "推荐岗位",
|
|
|
child: [
|
|
|
{
|
|
|
name: "具体岗位",
|
|
|
com: "xxx相关岗位有哪些?请列出xx个岗位",
|
|
|
},
|
|
|
{
|
|
|
name: "岗位对比",
|
|
|
com: "请列出以上几个岗位,分析岗位优缺点,输出表格",
|
|
|
},
|
|
|
{
|
|
|
name: "岗位晋升路径",
|
|
|
com: "xx岗位晋升路径是怎样的?",
|
|
|
},
|
|
|
{
|
|
|
name: "岗位可替代性",
|
|
|
com: "随着社会发展,xx岗位是否容易被替代?",
|
|
|
},
|
|
|
{
|
|
|
name: "推荐合适岗位",
|
|
|
com: "简单描述个人信息及性格特点,让AI推荐合适岗位",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
name: "技能要求",
|
|
|
cor: "#f1858b",
|
|
|
children: [
|
|
|
{
|
|
|
title: "岗位技能",
|
|
|
child: [
|
|
|
{
|
|
|
name: "岗位技能",
|
|
|
com: "XX类岗位技能有哪些?请列出xx种技能",
|
|
|
},
|
|
|
{
|
|
|
name: "理论支撑",
|
|
|
com: "XX技能需要哪些理论知识支撑,需要学习哪些理论课程?",
|
|
|
},
|
|
|
{
|
|
|
name: "实训实习",
|
|
|
com: "可以通过哪些实训或者实习来学习相关技能?",
|
|
|
},
|
|
|
{
|
|
|
name: "感兴趣技能",
|
|
|
com: "我对XX技能感兴趣,请详细解释如何学习该技能",
|
|
|
},
|
|
|
{
|
|
|
name: "实习推荐",
|
|
|
com: "如果想加强学习XX技能,可以推荐相关企业实习吗,请列出XX家企业",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "技能发展",
|
|
|
child: [
|
|
|
{
|
|
|
name: "技能发展路径",
|
|
|
com: "XXX技能发展路径",
|
|
|
},
|
|
|
{
|
|
|
name: "初级技能",
|
|
|
com: "XX相关初级技能",
|
|
|
},
|
|
|
{
|
|
|
name: "中级技能",
|
|
|
com: "XXX相关中级技能",
|
|
|
},
|
|
|
{
|
|
|
name: "高级技能",
|
|
|
com: "XXX相关高级技能",
|
|
|
},
|
|
|
{
|
|
|
name: "发展前景",
|
|
|
com: "XXX相关技能发展前景",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "技能学习",
|
|
|
child: [
|
|
|
{
|
|
|
name: "岗位核心技能",
|
|
|
com: "XXX岗位核心技能有哪些?列出x种",
|
|
|
},
|
|
|
{
|
|
|
name: "核心技能详解",
|
|
|
com: "请详细解释上述xx技能",
|
|
|
},
|
|
|
{
|
|
|
name: "学习渠道推荐",
|
|
|
com: "请推荐学习XX技能的渠道,免费的和收费的各列",
|
|
|
},
|
|
|
{
|
|
|
name: "学习方法",
|
|
|
com: "请推荐XX技能的学习方法,帮助制定学习计划",
|
|
|
},
|
|
|
{
|
|
|
name: "学习建议",
|
|
|
com: "请给我一些XX技能学习建议",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
name: "薪资水平",
|
|
|
cor: "#4da3f0",
|
|
|
introduce: "本模块分为地域薪资、企业薪资、岗位薪资三个模块,每个模块分为五个步骤。学生根据相应步骤提示词,了解不同地区的薪资水平及生活成本,掌握不同类型企业的薪资结构及福利待遇,并通过分析岗位的薪资差异及增长潜力,获得科学的薪资预期及职业选择建议。最后,学生将结合地域、企业及岗位的薪资数据,制定合理的职业发展目标。",
|
|
|
children: [
|
|
|
{
|
|
|
title: "地域新资",
|
|
|
child: [
|
|
|
{
|
|
|
name: "各地新资概况",
|
|
|
com: "我国各大主要城市xx行业新资水平",
|
|
|
},
|
|
|
{
|
|
|
name: "各地新资对比",
|
|
|
com: "请对比上述城市新资水平并进行排序,输出表格",
|
|
|
},
|
|
|
{
|
|
|
name: "意向地新资",
|
|
|
com: "我想在xx城市工作,请根据该城市xx相关行业新资水平",
|
|
|
},
|
|
|
{
|
|
|
name: "意向地新资",
|
|
|
com: "xx城市针对大学生就业有何帮扶政策及福利?",
|
|
|
},
|
|
|
{
|
|
|
name: "地点推荐",
|
|
|
com: "请根据当地新资水平和福利政策,客观推荐工作地点",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "企业新资",
|
|
|
child: [
|
|
|
{
|
|
|
name: "各企业新资",
|
|
|
com: "xx相关行业企业新资水平如何?请列出xx家企业新资水平",
|
|
|
},
|
|
|
{
|
|
|
name: "新资对比分析",
|
|
|
com: "请对比分析上述企业新资福利情况,并进行排序,输出表格",
|
|
|
},
|
|
|
{
|
|
|
name: "意向企业新资",
|
|
|
com: "xx企业新资水平如何,该企业各岗位新资水平如何?输出表格",
|
|
|
},
|
|
|
{
|
|
|
name: "意向企业福利",
|
|
|
com: "xx企业整体福利状况如何?各类岗位福利状况如何?输出表格",
|
|
|
},
|
|
|
{
|
|
|
name: "企业推荐",
|
|
|
com: "请根据企业新资福利状况,客观推荐xx家适合就业的企业",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "岗位新资",
|
|
|
child: [
|
|
|
{
|
|
|
name: "岗位新资对比",
|
|
|
com: "xxx相关岗位新资对比情况,输出表格",
|
|
|
},
|
|
|
{
|
|
|
name: "初级岗位新资",
|
|
|
com: "xxx相关初级岗位新资水平,列出x个岗位,输出表格",
|
|
|
},
|
|
|
{
|
|
|
name: "中级岗位新资",
|
|
|
com: "xxx相关中级岗位新资水平,列出x个岗位,输出表格",
|
|
|
},
|
|
|
{
|
|
|
name: "高级岗位新资",
|
|
|
com: "xxx相关高级岗位新资水平,列出x个岗位,输出表格",
|
|
|
},
|
|
|
{
|
|
|
name: "适合岗位",
|
|
|
com: "针对刚毕业的xx学校大学生,期望新资是xxx到xxx,喜欢xx,不喜欢xx,请推荐合适的岗位",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
name: "简历优化",
|
|
|
cor: "#56c8c5",
|
|
|
introduce: "本模块分为个人信息、简历撰写、个人技能三个模块,每个模块分为五个步骤。学生根据相应步骤提示词,了解如何系统化整理个人信息,掌握简历撰写的核心技巧与注意事项,并通过针对性的技能提升建议,增强个人竞争力。最后,学生将结合个人信息、简历优化及技能提升,打造一份高质量的求职材料,为成功就业奠定坚实基础。",
|
|
|
children: [
|
|
|
{
|
|
|
title: "个人信息",
|
|
|
child: [
|
|
|
{
|
|
|
name: "基础信息",
|
|
|
com: "年龄、性别、籍贯、所在地等信息",
|
|
|
},
|
|
|
{
|
|
|
name: "教育信息",
|
|
|
com: "毕业院校、专业、所学课程等信息",
|
|
|
},
|
|
|
{
|
|
|
name: "性格特点",
|
|
|
com: "个人性格特点概述,例如外向、开朗、擅长交际、稳重、谨慎等外界评价",
|
|
|
},
|
|
|
{
|
|
|
name: "自我评价",
|
|
|
com: "个人自我评价,个人兴趣爱好等自我认知",
|
|
|
},
|
|
|
{
|
|
|
name: "自我期待",
|
|
|
com: "未来希望在哪个方向发展,期待自己成为一个什么样的人",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "简历撰写",
|
|
|
child: [
|
|
|
{
|
|
|
name: "简历模板",
|
|
|
com: "上传自己撰写的简历初稿",
|
|
|
},
|
|
|
{
|
|
|
name: "针对企业",
|
|
|
com: "想要给xx企业投简历,请给出修改建议",
|
|
|
},
|
|
|
{
|
|
|
name: "针对岗位类型",
|
|
|
com: "意向岗位类型是xx,想要针对xx岗位,请给出修改建议",
|
|
|
},
|
|
|
{
|
|
|
name: "AI版本简历",
|
|
|
com: "继续补充相关信息,个性化进行简历修改",
|
|
|
},
|
|
|
{
|
|
|
name: "终稿导出",
|
|
|
com: "导出修改后的简历终稿",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
{
|
|
|
title: "个人技能",
|
|
|
child: [
|
|
|
{
|
|
|
name: "知识技能",
|
|
|
com: "掌握的实务性较强的知识技能,学会的一些工具,如Python等",
|
|
|
},
|
|
|
{
|
|
|
name: "技能证书",
|
|
|
com: "考取的相关职业资格证,各类技能证书等",
|
|
|
},
|
|
|
{
|
|
|
name: "实验实训",
|
|
|
com: "开展的哪些技能实训",
|
|
|
},
|
|
|
{
|
|
|
name: "企业实习",
|
|
|
com: "是否有企业实习经历",
|
|
|
},
|
|
|
{
|
|
|
name: "技能发展",
|
|
|
com: "未来想在哪方面继续学习,精进技能",
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
],
|
|
|
},
|
|
|
]);
|
|
|
const claActive = ref(tabList.value[0].name);
|
|
|
const tabactive = ref(tabList.value[0]);
|
|
|
const stopActive = ref("理论知识");
|
|
|
const currentNode = ref(null);
|
|
|
const taskinfo = ref({});
|
|
|
let abortController = null;
|
|
|
const messages = ref([]);
|
|
|
const domfile = ref(null);
|
|
|
// **计算每个任务是否可点击**
|
|
|
const isTaskEnabled = (list, index) => {
|
|
|
if (index === 0) return true; // 第一个任务默认可点击
|
|
|
console.log(list[index - 1].isTemplateBased, "list[index - 1].isTemplateBased");
|
|
|
return list[index - 1].isTemplateBased ?? false;
|
|
|
};
|
|
|
// 发送消息
|
|
|
const sendMessage = async () => {
|
|
|
if (!inputMessage.value.trim() || isRequestPending.value) return proxy.$message.warning("请输入内容");
|
|
|
isRequestPending.value = true;
|
|
|
isTypingComplete.value = true; // 重置为初始状态
|
|
|
let isTemplateBased = false;
|
|
|
if (currentNode.value) {
|
|
|
isTemplateBased = isBasedOnCom(inputMessage.value, currentNode.value.com);
|
|
|
if (!isTemplateBased) {
|
|
|
isRequestPending.value = false;
|
|
|
isTypingComplete.value = false; // 重置为初始状态
|
|
|
} else {
|
|
|
isRequestPending.value = true;
|
|
|
isTypingComplete.value = true; // 重置为初始状态
|
|
|
}
|
|
|
}
|
|
|
// 重置状态
|
|
|
// 添加用户消息
|
|
|
messages.value.push({
|
|
|
id: Date.now(),
|
|
|
role: "user",
|
|
|
content: inputMessage.value,
|
|
|
module: claActive.value,
|
|
|
stop: stopActive.value,
|
|
|
isTemplateBased: isTemplateBased,
|
|
|
name: currentNode.value?.name ?? "",
|
|
|
});
|
|
|
// 用户提问后立即滚动到底部
|
|
|
nextTick(() => {
|
|
|
scrollToBottom();
|
|
|
inputMessage.value = "";
|
|
|
});
|
|
|
abortController = new AbortController();
|
|
|
const signal = abortController.signal;
|
|
|
// 调用后端API
|
|
|
let params = {
|
|
|
systemOwner: "电商互联网产品",
|
|
|
userId: userStore.userInfo.userId,
|
|
|
type: "2",
|
|
|
};
|
|
|
isTypingComplete.value = false;
|
|
|
// 将参数对象转换为查询字符串
|
|
|
const queryString = new URLSearchParams(params);
|
|
|
const aiBase = (import.meta.env.VITE_APP_AI_API || "/ai/").replace(/\/?$/, "/");
|
|
|
const resp = await fetch(`${aiBase}api/kimi4?${queryString}`, {
|
|
|
method: "POST",
|
|
|
headers: {
|
|
|
"Content-Type": "application/json",
|
|
|
},
|
|
|
body: inputMessage.value.trim(),
|
|
|
signal,
|
|
|
});
|
|
|
// 添加AI消息占位
|
|
|
let newMessage = reactive({ id: Date.now(), role: "assistant", content: "", module: claActive.value, stop: stopActive.value, name: currentNode.value?.name ?? "" });
|
|
|
messages.value.push(newMessage); // 滚动到底部
|
|
|
// 处理流式响应
|
|
|
const reader = resp.body.getReader();
|
|
|
const decoder = new TextDecoder("utf-8");
|
|
|
while (true) {
|
|
|
const { done, value } = await reader.read();
|
|
|
isRequestPending.value = false;
|
|
|
if (done) break;
|
|
|
const text = decoder.decode(value, { stream: true });
|
|
|
await typeText(newMessage, text);
|
|
|
//滚动到最新消息
|
|
|
nextTick(() => {
|
|
|
const scrollEl = scrollArea.value.wrapRef;
|
|
|
scrollEl.scrollTop = scrollEl.scrollHeight;
|
|
|
});
|
|
|
}
|
|
|
};
|
|
|
const isBasedOnCom = (input, com) => {
|
|
|
// 1. 将 'xxx' 替换为匹配任意字符(包括换行)
|
|
|
const comPattern = com.replace(/xxx/g, "([\\s\\S]+)");
|
|
|
// 2. 构造正则,确保其严格匹配其他部分
|
|
|
const regex = new RegExp(`^${comPattern}$`);
|
|
|
// 3. 测试用户输入是否符合模式
|
|
|
return regex.test(input);
|
|
|
};
|
|
|
const typeText = (message, text) => {
|
|
|
return new Promise((resolve) => {
|
|
|
isTypingComplete.value = false; // 重置状态
|
|
|
let index = 0;
|
|
|
message.content = ""; // 清空原内容
|
|
|
const textLength = text.length;
|
|
|
const chunkSize = textLength > 100 ? 3 : 1; // 根据文本长度动态调整批量字数
|
|
|
const typingSpeed = textLength > 100 ? 30 : 60; // 适配长短文本
|
|
|
const interval = setInterval(() => {
|
|
|
if (index < text.length) {
|
|
|
message.content += text.slice(index, index + chunkSize);
|
|
|
index += chunkSize;
|
|
|
if (index % 10 === 0) nextTick(() => scrollToBottom()); // 限制滚动更新频率
|
|
|
} else {
|
|
|
clearInterval(interval);
|
|
|
isTypingComplete.value = true;
|
|
|
AI.submitTaskStep({
|
|
|
...taskinfo.value,
|
|
|
contentOne: JSON.stringify(messages.value),
|
|
|
}).then((res) => {
|
|
|
createPracticalTraining();
|
|
|
});
|
|
|
nextTick(() => scrollToBottom());
|
|
|
resolve();
|
|
|
}
|
|
|
}, typingSpeed);
|
|
|
});
|
|
|
};
|
|
|
// 滚动到底部的函数
|
|
|
const scrollToBottom = () => {
|
|
|
const scrollEl = scrollArea.value.wrapRef;
|
|
|
if (scrollEl) {
|
|
|
scrollEl.scrollTop = scrollEl.scrollHeight;
|
|
|
}
|
|
|
};
|
|
|
const scrollToElement = async (dataName) => {
|
|
|
await nextTick(); // 确保 DOM 更新完成
|
|
|
const scrollContainer = scrollArea.value?.wrapRef; // 获取 el-scrollbar 内部滚动容器
|
|
|
const targetElement = scrollContainer?.querySelector(`[data-name="${dataName}"]`);
|
|
|
if (targetElement) {
|
|
|
const top = targetElement.offsetTop; // 计算元素距离父容器顶部的偏移量
|
|
|
scrollContainer.scrollTo({ top, behavior: "smooth" }); // 平滑滚动
|
|
|
} else {
|
|
|
console.error(`未找到 data-name="${dataName}" 的元素`);
|
|
|
}
|
|
|
};
|
|
|
// 中断对话
|
|
|
const gInterrupt = () => {
|
|
|
if (abortController) {
|
|
|
abortController.abort();
|
|
|
abortController = null;
|
|
|
isRequestPending.value = false;
|
|
|
isTypingComplete.value = true;
|
|
|
}
|
|
|
};
|
|
|
const onClick = (type, idx) => {
|
|
|
const element = document.querySelectorAll(".stop-item"); // 选择你的元素
|
|
|
if (element && element[idx].classList.contains("info-title-completedSteps-disdabled")) return (inputMessage.value = "");
|
|
|
if (!type?.isTemplateBased) {
|
|
|
let arr = ["课程知识点", "核心知识点", "最难的部分", "实务知识概述", "学习建议", "业务现状", "理论研究", "发展趋势"];
|
|
|
if (arr.includes(type.name)) {
|
|
|
inputMessage.value = type.com.replace("xxx", "电商互联网产品开发实训系统");
|
|
|
} else {
|
|
|
inputMessage.value = type.com;
|
|
|
}
|
|
|
}
|
|
|
currentNode.value = type; //记录当前步骤节点
|
|
|
scrollToElement(type.name);
|
|
|
};
|
|
|
const changeTab = (type) => {
|
|
|
tabactive.value = type;
|
|
|
claActive.value = type.name;
|
|
|
stopActive.value = type.children[0].title;
|
|
|
createPracticalTraining();
|
|
|
};
|
|
|
const copyTextSuccess = () => {
|
|
|
proxy.$modal.msgSuccess("复制成功");
|
|
|
};
|
|
|
const getCurrentTeachingClassId = async () => {
|
|
|
const cachedClassId = proxy.$cache.session.get("currentTeachingClassId");
|
|
|
if (cachedClassId) return cachedClassId;
|
|
|
const res = await indexApi.getCurrentTeachingClass({ userId: userStore.userInfo.userId });
|
|
|
const classId = res?.data?.schoolClassId || "";
|
|
|
if (classId) {
|
|
|
proxy.$cache.session.set("currentTeachingClassId", classId);
|
|
|
}
|
|
|
return classId;
|
|
|
};
|
|
|
// 选择步骤
|
|
|
const changeStop = (stop) => {
|
|
|
stopActive.value = stop;
|
|
|
setTimeout(() => {
|
|
|
createPracticalTraining();
|
|
|
}, 0);
|
|
|
};
|
|
|
// 创建任务
|
|
|
const createPracticalTraining = async () => {
|
|
|
await nextTick(); // 等待 Vue 状态更新完成
|
|
|
const currentClassId = await getCurrentTeachingClassId();
|
|
|
if (!currentClassId) return;
|
|
|
const requestData = {
|
|
|
systemOwner: "区块链金融",
|
|
|
userId: userStore.userInfo.userId,
|
|
|
classId: currentClassId,
|
|
|
schoolId: userStore.userInfo.schoolId,
|
|
|
module: claActive.value,
|
|
|
step: stopActive.value, // 确保这里传递的是最新的值
|
|
|
};
|
|
|
AI.createTask(requestData).then((res) => {
|
|
|
if (res) {
|
|
|
taskinfo.value = res.data;
|
|
|
messages.value = res.data.contentOne ? JSON.parse(res.data.contentOne) : [];
|
|
|
setTimeout(() => {
|
|
|
syncBackendStatus(messages.value);
|
|
|
}, 0);
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
// 同步后端状态到前端 tabList
|
|
|
const syncBackendStatus = (backendMessages) => {
|
|
|
// 分离 user 和 assistant 消息
|
|
|
const userMessages = backendMessages.filter((message) => message.role === "user" && message.isTemplateBased === true);
|
|
|
const assistantMessages = backendMessages.filter((message) => message.role === "assistant");
|
|
|
// 遍历 user 消息
|
|
|
userMessages.forEach((userMessage) => {
|
|
|
const { module, stop, name } = userMessage;
|
|
|
// 查找对应的 assistant 消息,要求 name、module、stop 一致且 content 不为空
|
|
|
const matchingAssistant = assistantMessages.find((assistant) => assistant.module === module && assistant.stop === stop && assistant.name === name && assistant.content && assistant.content.trim() !== "");
|
|
|
// 如果没有匹配的 assistant 消息或 content 为空,直接返回
|
|
|
if (!matchingAssistant) return;
|
|
|
// 查找对应的选项卡
|
|
|
const tab = tabList.value.find((tab) => tab.name === module);
|
|
|
if (!tab) return;
|
|
|
|
|
|
// 查找对应的任务
|
|
|
const task = tab.children.find((child) => child.title === stop);
|
|
|
if (!task) return;
|
|
|
// 查找对应的步骤
|
|
|
const step = task.child.find((child) => child.name === name);
|
|
|
if (step) {
|
|
|
// 只有当 assistant 消息匹配且 content 不为空时,设置为 true
|
|
|
step.isTemplateBased = true;
|
|
|
// console.log('同步后的步骤:', step);
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
// 会话记录导出
|
|
|
const exportSession = (id) => {
|
|
|
AI.exportSession({
|
|
|
missionModuleId: taskinfo.value.missionModuleId,
|
|
|
}).then((res) => {
|
|
|
// 创建 Blob 对象
|
|
|
const blob = new Blob([res], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
|
|
|
// 创建下载链接
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
const link = document.createElement("a");
|
|
|
link.href = url;
|
|
|
link.download = `${stopActive.value}会话数据.xlsx`; // 这里可以自定义文件名
|
|
|
document.body.appendChild(link);
|
|
|
// 触发下载
|
|
|
link.click();
|
|
|
// 清理
|
|
|
document.body.removeChild(link);
|
|
|
URL.revokeObjectURL(url);
|
|
|
});
|
|
|
};
|
|
|
const submitDocument = (val) => {
|
|
|
domfile.value = val.raw;
|
|
|
const formData = new FormData();
|
|
|
formData.append("file", domfile.value);
|
|
|
formData.append("missionModuleId", taskinfo.value.missionModuleId);
|
|
|
AI.uploadResourceFile(formData).then((res) => {
|
|
|
AI.submitTask({
|
|
|
...taskinfo.value,
|
|
|
uploadUrl: res.data,
|
|
|
}).then((res) => {
|
|
|
createPracticalTraining();
|
|
|
proxy.$modal.msgSuccess("提交成功");
|
|
|
});
|
|
|
});
|
|
|
};
|
|
|
// 判断数组中所有元素是否都是 true,且数组不为空
|
|
|
const allTrue = () => {
|
|
|
// 根据stopActive和claActive的值筛选tabList中的数据
|
|
|
const filteredTabList = tabList.value.filter((tab) => tab.name === claActive.value);
|
|
|
const filteredTasks = filteredTabList[0].children.filter((task) => task.title === stopActive.value);
|
|
|
const steps = filteredTasks[0].child;
|
|
|
return steps.every((step) => step.isTemplateBased);
|
|
|
};
|
|
|
// 计算高度的函数
|
|
|
const updateHeight = () => {
|
|
|
const windowHeight = window.innerHeight; // 视口高度
|
|
|
const headerHeight = header.value?.offsetHeight || 0; // 头部高度
|
|
|
const footerHeight = footer.value?.offsetHeight || 0; // 底部高度
|
|
|
const stepHeight = step.value?.offsetHeight || 0; // 底部高度
|
|
|
const totalOffset = headerHeight + footerHeight + stepHeight; // 总偏移量
|
|
|
scrollbarHeight.value = `${windowHeight - totalOffset - 150}px`;
|
|
|
};
|
|
|
onMounted(() => {
|
|
|
createPracticalTraining();
|
|
|
updateHeight();
|
|
|
// 监听窗口大小变化
|
|
|
window.addEventListener("resize", updateHeight);
|
|
|
// 使用 ResizeObserver 监听头部和底部的尺寸变化
|
|
|
resizeObserver = new ResizeObserver(() => {
|
|
|
updateHeight(); // 元素尺寸变化时重新计算
|
|
|
});
|
|
|
if (header.value) resizeObserver.observe(header.value);
|
|
|
if (footer.value) resizeObserver.observe(footer.value);
|
|
|
});
|
|
|
// 清理监听
|
|
|
onUnmounted(() => {
|
|
|
window.removeEventListener("resize", updateHeight);
|
|
|
if (resizeObserver) {
|
|
|
resizeObserver.disconnect();
|
|
|
}
|
|
|
});
|
|
|
</script>
|
|
|
<style lang="scss">
|
|
|
.index {
|
|
|
padding: 20px 40px;
|
|
|
height: calc(100vh - 2.5rem);
|
|
|
position: relative;
|
|
|
background: url("@/assets/images/背景.webp") no-repeat;
|
|
|
background-size: 100% 100%;
|
|
|
.min-h-screen {
|
|
|
text-align: center;
|
|
|
.title {
|
|
|
h1 {
|
|
|
font-size: 2.25rem;
|
|
|
line-height: 2.5rem;
|
|
|
margin-top: 0px;
|
|
|
color: #ffffff;
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.tz-tobs {
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(6, 1fr);
|
|
|
grid-gap: 1rem;
|
|
|
margin-top: 1rem;
|
|
|
width: calc(100vw - 50rem);
|
|
|
margin: 0 auto;
|
|
|
margin-bottom: 10px;
|
|
|
.el-tobs-item {
|
|
|
position: relative;
|
|
|
height: 3rem;
|
|
|
border-radius: 8px;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
flex-direction: column;
|
|
|
text-align: center;
|
|
|
cursor: pointer;
|
|
|
color: #ffffff;
|
|
|
font-weight: normal;
|
|
|
// 超出
|
|
|
overflow: hidden;
|
|
|
.svg-icon {
|
|
|
width: 2rem;
|
|
|
height: 2rem;
|
|
|
}
|
|
|
.el-tobs-item-active {
|
|
|
.svg-icon {
|
|
|
// 翻转180度
|
|
|
transform: rotate(0deg);
|
|
|
fill: #19578b;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.active {
|
|
|
//放大
|
|
|
transform: scale(1.12);
|
|
|
font-size: var(--student-fs-h1);
|
|
|
font-weight: 600;
|
|
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
|
|
color: #ffffff;
|
|
|
}
|
|
|
.el-tobs-item-active {
|
|
|
.svg-icon {
|
|
|
// 翻转180度
|
|
|
transform: rotate(0deg);
|
|
|
}
|
|
|
.svg-icon {
|
|
|
transform: rotate(180deg);
|
|
|
}
|
|
|
&:hover {
|
|
|
transition: all 0.2s;
|
|
|
background-color: #eff6ff;
|
|
|
}
|
|
|
}
|
|
|
.el-tobs-item-active {
|
|
|
.svg-icon {
|
|
|
// 翻转180度
|
|
|
transform: rotate(0deg);
|
|
|
fill: #19578b;
|
|
|
}
|
|
|
}
|
|
|
.active {
|
|
|
background: #eff6ff;
|
|
|
border-color: rgb(191 219 254);
|
|
|
}
|
|
|
}
|
|
|
.tz-centent {
|
|
|
width: calc(100vw - 50rem);
|
|
|
height: calc(100vh - 25rem);
|
|
|
margin: 0 auto;
|
|
|
.QAlist {
|
|
|
padding-left: 0px;
|
|
|
li {
|
|
|
display: flex !important;
|
|
|
overflow: hidden;
|
|
|
margin-bottom: 12px;
|
|
|
:deep(.el-loading-mask) {
|
|
|
background: transparent !important;
|
|
|
}
|
|
|
}
|
|
|
.task-introduction {
|
|
|
color: #ffffff;
|
|
|
.title {
|
|
|
font-size: 1.2rem;
|
|
|
}
|
|
|
// p除了第一个
|
|
|
p:not(:first-child) {
|
|
|
margin-top: 1rem;
|
|
|
font-size: 0.8rem !important;
|
|
|
}
|
|
|
ul {
|
|
|
margin: 0;
|
|
|
padding: 0;
|
|
|
width: 30rem;
|
|
|
li {
|
|
|
margin-top: 10px;
|
|
|
background: #011031;
|
|
|
border: 1px solid #003e7c;
|
|
|
border-radius: 12px 12px 12px 0;
|
|
|
padding: 10px 12px 10px 12px;
|
|
|
font-size: var(--student-fs-body);
|
|
|
color: #ffffff;
|
|
|
// 鼠标小手
|
|
|
cursor: pointer;
|
|
|
line-height: 22px;
|
|
|
&:hover {
|
|
|
background: #002c5b;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
:deep(.md-editor-preview-wrapper) {
|
|
|
padding: 0px 0px !important;
|
|
|
.md-editor-preview {
|
|
|
font-size: var(--student-fs-body) !important;
|
|
|
}
|
|
|
}
|
|
|
.questionItem {
|
|
|
// display: flex;
|
|
|
justify-content: flex-end;
|
|
|
.qustionCon {
|
|
|
background: #ffffff;
|
|
|
border-radius: 12px 12px 0 12px;
|
|
|
// padding: 0px 12px 0px 16px;
|
|
|
font-weight: 400;
|
|
|
font-size: var(--student-fs-body);
|
|
|
line-height: 20px;
|
|
|
max-width: calc(100% - 51px);
|
|
|
word-break: break-all;
|
|
|
}
|
|
|
}
|
|
|
.answerItem {
|
|
|
display: flex;
|
|
|
margin-bottom: 12px;
|
|
|
overflow: hidden;
|
|
|
:deep(.answerCon) {
|
|
|
display: flex;
|
|
|
font-weight: 400;
|
|
|
font-size: var(--student-fs-body);
|
|
|
// color: rgb(68, 68, 68);
|
|
|
line-height: 22px;
|
|
|
// width: calc(100% - 51px);
|
|
|
word-break: break-all;
|
|
|
flex: 1 1 0%;
|
|
|
padding: 0px 16px 0px 16px;
|
|
|
}
|
|
|
}
|
|
|
margin-top: 10px;
|
|
|
}
|
|
|
.tz-step {
|
|
|
margin-top: 2rem;
|
|
|
width: 100%;
|
|
|
height: 8rem;
|
|
|
display: flex;
|
|
|
gap: 2rem;
|
|
|
.tz-stop-info {
|
|
|
width: calc(100% - 90%);
|
|
|
overflow: hidden;
|
|
|
.info-title {
|
|
|
font-size: 1rem;
|
|
|
font-weight: 600;
|
|
|
color: #ffffff;
|
|
|
background: #19578b;
|
|
|
text-emphasis: none;
|
|
|
text-align: center;
|
|
|
padding: 0.5rem 0px;
|
|
|
border-radius: 0.5rem;
|
|
|
margin-bottom: 0.5rem;
|
|
|
width: 100%;
|
|
|
// 鼠标小手
|
|
|
cursor: pointer;
|
|
|
&:hover {
|
|
|
background: #2d89e3;
|
|
|
transition: all 0.3s;
|
|
|
}
|
|
|
}
|
|
|
.info-title-active {
|
|
|
background: #2d89e3;
|
|
|
transition: all 0.3s;
|
|
|
}
|
|
|
}
|
|
|
.tz-stop-centent {
|
|
|
flex: 1;
|
|
|
background: #002c5b;
|
|
|
border-radius: 0.5rem;
|
|
|
min-width: calc(100% - 20%); /* 确保宽度自适应 */
|
|
|
overflow: hidden; /* 防止内容溢出 */
|
|
|
// padding-left: 5rem;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: space-between;
|
|
|
padding: 0px 4rem 0 4rem;
|
|
|
.stop {
|
|
|
flex: 1; /* 让 .stop 容器占据剩余空间 */
|
|
|
height: 100%;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 2rem;
|
|
|
.stop-item {
|
|
|
width: 6rem;
|
|
|
height: 3rem;
|
|
|
line-height: 3rem;
|
|
|
text-align: center;
|
|
|
border-radius: 0.4rem;
|
|
|
background: #06233f;
|
|
|
font-size: 0.9rem;
|
|
|
color: #ffffff;
|
|
|
position: relative;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
.stop-item:not(:last-child) {
|
|
|
&::after {
|
|
|
content: "→";
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
right: -1.8rem;
|
|
|
display: block;
|
|
|
color: red;
|
|
|
font-size: 23px;
|
|
|
}
|
|
|
}
|
|
|
.info-title-completedSteps {
|
|
|
background: #2378cb;
|
|
|
}
|
|
|
.info-title-completedSteps:not(:last-child) {
|
|
|
&::after {
|
|
|
content: "→";
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
right: -1.8rem;
|
|
|
display: block;
|
|
|
color: #2378cb !important;
|
|
|
font-size: 23px;
|
|
|
}
|
|
|
}
|
|
|
.info-title-completedSteps-disdabled {
|
|
|
background: #d6dee8;
|
|
|
cursor: not-allowed;
|
|
|
}
|
|
|
}
|
|
|
.fbtn {
|
|
|
.el-button {
|
|
|
height: 3rem;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.tz-footer-ipt {
|
|
|
position: absolute;
|
|
|
left: 50%;
|
|
|
bottom: 20px;
|
|
|
transform: translateX(-50%);
|
|
|
width: calc(100vw - 50rem);
|
|
|
height: 11rem;
|
|
|
background: #001d40;
|
|
|
margin: 0 auto;
|
|
|
border-radius: 35px;
|
|
|
padding: 10px;
|
|
|
border: 1px solid #003e7c;
|
|
|
.svg-icon {
|
|
|
width: 3rem;
|
|
|
height: 2.7rem;
|
|
|
// 鼠标小手
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
.disdabled {
|
|
|
// 禁用
|
|
|
cursor: not-allowed;
|
|
|
.svg-icon {
|
|
|
fill: #d6dee8;
|
|
|
}
|
|
|
}
|
|
|
.el-textarea {
|
|
|
.el-textarea__inner {
|
|
|
background: transparent !important;
|
|
|
box-shadow: none !important;
|
|
|
// 光标颜色
|
|
|
border-radius: 0px;
|
|
|
color: #ffffff;
|
|
|
&::placeholder {
|
|
|
color: #ffffff;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.qustionCon {
|
|
|
.md-editor {
|
|
|
--md-color: #333333 !important;
|
|
|
--md-bk-color: transparent !important;
|
|
|
}
|
|
|
}
|
|
|
.answerCon {
|
|
|
display: flex;
|
|
|
gap: 1rem;
|
|
|
position: relative;
|
|
|
padding-right: 10px;
|
|
|
.copy {
|
|
|
position: absolute;
|
|
|
top: 5px;
|
|
|
right: 12px;
|
|
|
display: none;
|
|
|
.svg-icon {
|
|
|
fill: #ffffff;
|
|
|
width: 1.5rem;
|
|
|
height: 1.5rem;
|
|
|
}
|
|
|
}
|
|
|
&:hover {
|
|
|
.copy {
|
|
|
display: block;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
}
|
|
|
.md-editor {
|
|
|
background: #011031;
|
|
|
border-radius: 10px;
|
|
|
border: 1px solid #003e7c;
|
|
|
--md-color: #ffffff !important;
|
|
|
--md-bk-color: #02132f !important;
|
|
|
}
|
|
|
}
|
|
|
.el-loading-mask {
|
|
|
background: transparent !important;
|
|
|
.el-loading-spinner {
|
|
|
text-align: left;
|
|
|
padding-left: 2.5rem;
|
|
|
}
|
|
|
}
|
|
|
.qustionCon {
|
|
|
position: relative;
|
|
|
padding-left: 10px;
|
|
|
.copy {
|
|
|
position: absolute;
|
|
|
top: 5px;
|
|
|
left: 8px;
|
|
|
display: none;
|
|
|
.svg-icon {
|
|
|
fill: #333333;
|
|
|
width: 1.5rem;
|
|
|
height: 1.5rem;
|
|
|
}
|
|
|
}
|
|
|
&:hover {
|
|
|
.copy {
|
|
|
display: block;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.el-scrollbar {
|
|
|
--el-scrollbar-bg-color: transparent !important;
|
|
|
}
|
|
|
// 媒体查询监听视口小于1920
|
|
|
@media screen and (max-width: 1700px) {
|
|
|
.el-textarea {
|
|
|
height: 2rem !important;
|
|
|
.el-textarea__inner {
|
|
|
font-size: 0.8rem;
|
|
|
}
|
|
|
}
|
|
|
.tz-step {
|
|
|
.tz-stop-info {
|
|
|
display: none;
|
|
|
}
|
|
|
.tz-stop-centent {
|
|
|
padding: 0px 1rem 0 1rem !important;
|
|
|
.stop-item {
|
|
|
width: 4rem !important;
|
|
|
font-size: 0.7rem !important;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.tz-footer-ipt {
|
|
|
height: 6rem !important;
|
|
|
}
|
|
|
}
|
|
|
</style>
|
|
|
|