Merge pull request 'lyc-dev' (#81) from lyc-dev into main
This commit is contained in:
commit
42e8149443
|
@ -142,13 +142,19 @@ const handleNodeClick = (data) => {
|
||||||
|
|
||||||
//增加一个label 之前取的label
|
//增加一个label 之前取的label
|
||||||
nodeData.label = nodeData.itemtitle
|
nodeData.label = nodeData.itemtitle
|
||||||
// 父级节点 如果当前是一级节点 父级则为null
|
let parentNode
|
||||||
let parent = {
|
// 存在children 则为一级节点
|
||||||
id: nodeData.parentid,
|
if(nodeData.children){
|
||||||
label: nodeData.parenttitle,
|
// 为一级节点
|
||||||
itemtitle: nodeData.parenttitle
|
parentNode = null
|
||||||
}
|
}
|
||||||
const parentNode = nodeData.parentid ? parent : null
|
else{
|
||||||
|
parentNode = {
|
||||||
|
id: nodeData.parentid,
|
||||||
|
label: nodeData.parenttitle,
|
||||||
|
itemtitle: nodeData.parenttitle
|
||||||
|
}
|
||||||
|
}
|
||||||
nodeData.parentNode = parentNode
|
nodeData.parentNode = parentNode
|
||||||
let curData = {
|
let curData = {
|
||||||
textBook: {
|
textBook: {
|
||||||
|
|
|
@ -26,52 +26,52 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--List-->
|
<!--List-->
|
||||||
<div class="container-right-list">
|
<div class="container-right-list" ref="listRef">
|
||||||
<template v-for="(item, index) in childTempList">
|
<template v-for="(item, index) in childTempList">
|
||||||
<div class="template-item" v-loading="item.loading">
|
<div class="template-item" v-loading="item.loading">
|
||||||
<div class="item-header">
|
<div class="item-header">
|
||||||
<div>
|
<div>
|
||||||
<span class="blue">#</span>{{ item.name }}
|
<span class="blue">#</span>{{ item.name }}
|
||||||
</div>
|
</div>
|
||||||
<el-popover placement="bottom-end" trigger="hover" popper-class="template-custom-popover">
|
<el-popover placement="bottom-end" trigger="hover" popper-class="template-custom-popover">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button link type="primary">
|
<el-button link type="primary">
|
||||||
<i class="iconfont icon-shenglvehao"></i></el-button>
|
<i class="iconfont icon-shenglvehao"></i></el-button>
|
||||||
</template>
|
</template>
|
||||||
<template #default>
|
<template #default>
|
||||||
<el-button type="primary" link @click="editKeyWord(item)">编辑</el-button>
|
<el-button type="primary" link @click="editKeyWord(item)">编辑</el-button>
|
||||||
<el-button type="primary" link @click="removeItem(item, true)">移除</el-button>
|
<el-button type="primary" link @click="removeItem(item, true)">移除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-text">
|
<div class="item-text">
|
||||||
{{ item.prompt }}
|
{{ item.prompt }}
|
||||||
</div>
|
</div>
|
||||||
<div class="item-text text-answer" v-if="item.answer">
|
<div class="item-text text-answer" v-if="item.answer">
|
||||||
<div class="item-icon">
|
<div class="item-icon">
|
||||||
<i class="iconfont icon-ai"></i>
|
<i class="iconfont icon-ai"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-answer">
|
<div class="item-answer">
|
||||||
<TypingEffect :text="item.oldAnswer" :delay="10" :aiShow="item.aiShow" @complete="onSaveTemp(item)" />
|
<TypingEffect v-if="isStarted[index]" :text="item.answer" :delay="10" :aiShow="item.aiShow" @complete="handleCompleteText($event,index)" @updateScroll="scrollToBottom($event,index)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ai-btn" v-if="item.answer">
|
<div class="ai-btn" v-if="item.answer">
|
||||||
<el-button type="primary" link @click="againResult(index, item)">
|
<el-button type="primary" link @click="againResult(index, item)">
|
||||||
<i class="iconfont icon-ai1"></i>
|
<i class="iconfont icon-ai1"></i>
|
||||||
重新研读
|
重新研读
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" link @click="onAdjust(index, item)">
|
<el-button type="primary" link @click="onAdjust(index, item)">
|
||||||
<i class="iconfont icon-duihua"></i>
|
<i class="iconfont icon-duihua"></i>
|
||||||
AI对话调整
|
AI对话调整
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" link @click="onEdit(index, item)">
|
<el-button type="primary" link @click="onEdit(index, item)">
|
||||||
<i class="iconfont icon-bianji1"></i>
|
<i class="iconfont icon-bianji1"></i>
|
||||||
手动编辑结果
|
手动编辑结果
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-empty v-if="!childTempList.length" description="暂无模板数据" />
|
<el-empty v-if="!childTempList.length" description="暂无模板数据" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--编辑结果-->
|
<!--编辑结果-->
|
||||||
|
@ -83,7 +83,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted, watch, onUnmounted } from 'vue'
|
import { ref, reactive, onMounted, watch, onUnmounted, nextTick } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { tempSave, completion, modelList, removeChildTemp, tempResult, editTempResult } from '@/api/mode/index'
|
import { tempSave, completion, modelList, removeChildTemp, tempResult, editTempResult } from '@/api/mode/index'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
|
@ -146,14 +146,16 @@ const getChildTemplate = () => {
|
||||||
tempLoading.value = true
|
tempLoading.value = true
|
||||||
modelList({ model: props.type, type: 2, parentId: curTemplate.id }).then(res => {
|
modelList({ model: props.type, type: 2, parentId: curTemplate.id }).then(res => {
|
||||||
childTempList.value = res.rows
|
childTempList.value = res.rows
|
||||||
|
if(childTempList.value.length){
|
||||||
|
childTempList.value.forEach(item => item.answer = '')
|
||||||
|
}
|
||||||
getTempResult()
|
getTempResult()
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
tempLoading.value = false
|
tempLoading.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const isStarted = ref([]);
|
||||||
|
const listRef = ref()
|
||||||
// 查询模板结果
|
// 查询模板结果
|
||||||
const getTempResult = () => {
|
const getTempResult = () => {
|
||||||
tempResult({ mainModelId: curTemplate.id, pageNum: 1, pageSize: 10000 }).then(res => {
|
tempResult({ mainModelId: curTemplate.id, pageNum: 1, pageSize: 10000 }).then(res => {
|
||||||
|
@ -161,14 +163,40 @@ const getTempResult = () => {
|
||||||
childTempList.value.forEach(item => {
|
childTempList.value.forEach(item => {
|
||||||
rows.forEach(el => {
|
rows.forEach(el => {
|
||||||
if (item.id == el.modelId) {
|
if (item.id == el.modelId) {
|
||||||
item.answer = el.content
|
item.answer = getResult(el.content)
|
||||||
item.resultId = el.id
|
item.resultId = el.id
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
if(rows.length > 0){
|
||||||
|
isStarted.value = new Array(rows.length).fill(true)
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const scrollToBottom = (height,index) =>{
|
||||||
|
|
||||||
|
if (listRef.value) {
|
||||||
|
let sum = 0
|
||||||
|
let listDom = listRef.value.children
|
||||||
|
|
||||||
|
if(index == 0){
|
||||||
|
// 220 去掉头部
|
||||||
|
let screenHeight = window.innerHeight - 220
|
||||||
|
if(height > screenHeight){
|
||||||
|
listRef.value.scrollTop = (height - screenHeight + 50)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
for(let i = 0; i < index; i++){
|
||||||
|
sum += listDom[i].clientHeight
|
||||||
|
}
|
||||||
|
listRef.value.scrollTop = sum + height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 模板切换
|
// 模板切换
|
||||||
const changeTemplate = (val) => {
|
const changeTemplate = (val) => {
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
|
@ -203,11 +231,11 @@ const removeItem = async (item, isChild) => {
|
||||||
).then(() => {
|
).then(() => {
|
||||||
removeChildTemp(item.id).then(res => {
|
removeChildTemp(item.id).then(res => {
|
||||||
ElMessage.success('操作成功')
|
ElMessage.success('操作成功')
|
||||||
if(isChild){
|
if (isChild) {
|
||||||
// 获取子模板
|
// 获取子模板
|
||||||
getChildTemplate()
|
getChildTemplate()
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
// 获取主模板
|
// 获取主模板
|
||||||
getTemplateList()
|
getTemplateList()
|
||||||
}
|
}
|
||||||
|
@ -215,7 +243,7 @@ const removeItem = async (item, isChild) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
editKeyWord(item,!isChild)
|
editKeyWord(item, !isChild)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,19 +268,18 @@ const onEdit = (index, item) => {
|
||||||
|
|
||||||
const modeType = ref('课标')
|
const modeType = ref('课标')
|
||||||
watch(() => props.type, (newVal) => {
|
watch(() => props.type, (newVal) => {
|
||||||
if (newVal == 1){
|
if (newVal == 1) {
|
||||||
modeType.value = '课标'
|
modeType.value = '课标'
|
||||||
}
|
}
|
||||||
if (newVal == 2){
|
if (newVal == 2) {
|
||||||
modeType.value = '教材'
|
modeType.value = '教材'
|
||||||
}
|
}
|
||||||
if (newVal == 2){
|
if (newVal == 3) {
|
||||||
modeType.value = '考试'
|
modeType.value = '考试'
|
||||||
}
|
}
|
||||||
|
|
||||||
}, { immediate: false })
|
}, { immediate: false })
|
||||||
|
|
||||||
|
|
||||||
// 重新研读
|
// 重新研读
|
||||||
const params = reactive(
|
const params = reactive(
|
||||||
{
|
{
|
||||||
|
@ -260,76 +287,102 @@ const params = reactive(
|
||||||
dataset_id: ''
|
dataset_id: ''
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// 重新研读
|
// 重新研读
|
||||||
|
const isAgain = ref(false)
|
||||||
const againResult = async (index, item) => {
|
const againResult = async (index, item) => {
|
||||||
|
isAgain.value = true
|
||||||
|
isStarted.value[index] = false
|
||||||
|
childTempList.value[index].answer = ''
|
||||||
|
|
||||||
|
if(index == 0){
|
||||||
|
listRef.value.scrollTop = 0
|
||||||
|
|
||||||
|
}else{
|
||||||
|
scrollToBottom(50, index)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await nextTick()
|
||||||
childTempList.value[index].loading = true
|
childTempList.value[index].loading = true
|
||||||
item.aiShow = true
|
item.aiShow = true
|
||||||
childTempList.value[index].oldAnswer = ''
|
|
||||||
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}${modeType.value} 对${curNode.itemtitle}进行教学分析`
|
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}${modeType.value} 对${curNode.itemtitle}进行教学分析`
|
||||||
const { data } = await completion(params)
|
const { data } = await completion(params)
|
||||||
let answer = data.answer
|
childTempList.value[index].answer = getResult(data.answer);
|
||||||
childTempList.value[index].oldAnswer = answer
|
isStarted.value[index] = true
|
||||||
childTempList.value[index].answer = getResult(answer);
|
|
||||||
// onEditSave(item)
|
|
||||||
} finally {
|
} finally {
|
||||||
childTempList.value[index].loading = false
|
childTempList.value[index].loading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 一键研读
|
// 一键研读
|
||||||
const getCompletion = async () => {
|
const getCompletion = async () => {
|
||||||
|
isStarted.value = new Array(childTempList.length).fill(false)
|
||||||
|
isStarted.value[0] = true
|
||||||
|
|
||||||
|
childTempList.value.forEach(item =>{
|
||||||
|
if(item.answer){
|
||||||
|
item.answer = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
for (let item of childTempList.value) {
|
for (let item of childTempList.value) {
|
||||||
try {
|
try {
|
||||||
item.loading = true
|
item.loading = true
|
||||||
item.aiShow = true
|
item.aiShow = true
|
||||||
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}${modeType.value} 对${curNode.itemtitle}进行教学分析`
|
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}${modeType.value} 对${curNode.itemtitle}进行教学分析`
|
||||||
const { data } = await completion(params)
|
const { data } = await completion(params)
|
||||||
let answer = data.answer
|
item.answer = getResult(data.answer)
|
||||||
item.oldAnswer = answer
|
onSaveTemp(item)
|
||||||
item.answer = getResult(answer);
|
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
item.loading = false
|
item.loading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleCompleteText = async (answer, index) =>{
|
||||||
|
if (index < childTempList.value.length - 1) {
|
||||||
|
isStarted.value[index + 1] = true; // 开始显示下一个文本
|
||||||
|
}
|
||||||
|
if(isAgain.value){
|
||||||
|
try{
|
||||||
|
await editTempResult({ id: childTempList.value[index].resultId, content: answer })
|
||||||
|
}finally{
|
||||||
|
isAgain.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 替换分析结果
|
// 替换分析结果
|
||||||
emitter.on('onSaveAdjust', (item) => {
|
emitter.on('onSaveAdjust', (item) => {
|
||||||
childTempList.value[curIndex.value].oldAnswer = item
|
childTempList.value[curIndex.value].answer = item
|
||||||
let answer = getResult(item);
|
|
||||||
childTempList.value[curIndex.value].oldAnswer = item
|
|
||||||
childTempList.value[curIndex.value].answer = answer
|
|
||||||
onEditSave(childTempList.value[curIndex.value])
|
onEditSave(childTempList.value[curIndex.value])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// 保存 重新研读后的结果
|
// 保存 重新研读后的结果
|
||||||
const onEditSave = async (item) =>{
|
const onEditSave = async (item) => {
|
||||||
const { res } = await editTempResult({id: item.resultId, content: item.oldAnswer})
|
const { res } = await editTempResult({ id: item.resultId, content: item.answer })
|
||||||
ElMessage.success(res)
|
ElMessage.success(res)
|
||||||
getChildTemplate()
|
getChildTemplate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存模板
|
// 保存模板
|
||||||
const onSaveTemp = (item) => {
|
const onSaveTemp = (item) => {
|
||||||
if(item.oldAnswer == '') return
|
if (item.answer == '') return
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
mainModelId: curTemplate.id,
|
mainModelId: curTemplate.id,
|
||||||
modelId: item.id,
|
modelId: item.id,
|
||||||
examDocld: '',
|
examDocld: '',
|
||||||
content: item.oldAnswer
|
content: item.answer
|
||||||
}
|
}
|
||||||
tempSave(data).then(res => {})
|
tempSave(data).then(res => { })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分析获取课标对话结果
|
// 去掉字符串中的 ### **
|
||||||
let getResult = (text) => {
|
let getResult = (str) => {
|
||||||
text = text.replace(/^\n\n(.*?)\n\n$/s, '<div>$1</div>');
|
let newStr = str.replace(/#+|(\*\*)/g, '');
|
||||||
text = text.replace(/^\n(.*?)\n$/s, '<p>$1</p>');
|
return newStr
|
||||||
text = text.replace(/\*\*(.*?)\*\*/g, "<div class='text-tit'>$1</div>");
|
|
||||||
text = text.replace(/(\d+\..*?)\n/g, "<div class='text-num'>$1</div>\n");
|
|
||||||
return text
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 操作之后获取字模板
|
// 操作之后获取字模板
|
||||||
|
@ -381,87 +434,85 @@ onUnmounted(() => {
|
||||||
padding: 5px 15px;
|
padding: 5px 15px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.template-item {
|
||||||
|
background: #fff;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
.template-item {
|
.item-header {
|
||||||
background: #fff;
|
display: flex;
|
||||||
padding: 10px;
|
align-items: center;
|
||||||
margin-top: 10px;
|
font-size: 16px;
|
||||||
border-radius: 5px;
|
font-weight: bold;
|
||||||
|
color: #000;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
.item-header {
|
.blue {
|
||||||
display: flex;
|
font-size: 22px;
|
||||||
align-items: center;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #000;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.blue {
|
|
||||||
font-size: 22px;
|
|
||||||
color: #409eff;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-text {
|
|
||||||
display: flex;
|
|
||||||
margin-top: 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
text-align: left;
|
|
||||||
color: #606266;
|
|
||||||
|
|
||||||
.item-icon {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
line-height: 30px;
|
|
||||||
text-align: center;
|
|
||||||
background: #F6F6F6;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-right: 10px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-answer {
|
|
||||||
flex-direction: column;
|
|
||||||
padding-top: 5px;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
:deep(.text-tit) {
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.text-num) {
|
|
||||||
padding-left: 2em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-answer {
|
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
}
|
margin-right: 5px;
|
||||||
|
|
||||||
.ai-btn {
|
|
||||||
margin-top: 10px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
.iconfont {
|
|
||||||
margin-right: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-button) {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-ai1 {
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item-text {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: left;
|
||||||
|
color: #606266;
|
||||||
|
|
||||||
|
.item-icon {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
text-align: center;
|
||||||
|
background: #F6F6F6;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 10px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-answer {
|
||||||
|
flex-direction: column;
|
||||||
|
padding-top: 5px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
:deep(.text-tit) {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.text-num) {
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-answer {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ai-btn {
|
||||||
|
margin-top: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-button) {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-ai1 {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="typing-effect">
|
<div class="typing-effect" ref="typingEffectRef">
|
||||||
<!-- <span v-html="displayedText"></span> -->
|
<!-- <span v-html="displayedText"></span> -->
|
||||||
<el-input
|
<el-input
|
||||||
v-model="displayedText"
|
v-model="displayedText"
|
||||||
|
@ -14,11 +14,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, watch } from 'vue';
|
import { ref, onMounted, watch, nextTick } from 'vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
text: {
|
text: {
|
||||||
type: String,
|
type: [String, Object],
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
delay: {
|
delay: {
|
||||||
|
@ -26,35 +26,48 @@ const props = defineProps({
|
||||||
default: 100 // 默认每个字符出现的延迟时间,单位是毫秒
|
default: 100 // 默认每个字符出现的延迟时间,单位是毫秒
|
||||||
},
|
},
|
||||||
aiShow: {
|
aiShow: {
|
||||||
type: [Boolean]
|
type: [Boolean] // 为true 只展示
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const emit = defineEmits(['complete']);
|
const typingEffectRef = ref(null);
|
||||||
|
const emit = defineEmits(['complete', 'updateScroll']);
|
||||||
const displayedText = ref('');
|
const displayedText = ref('');
|
||||||
const index = ref(0);
|
const index = ref(0);
|
||||||
|
|
||||||
const type = () => {
|
const type = async () => {
|
||||||
if(!props.aiShow) return
|
await nextTick()
|
||||||
|
if(!props.aiShow) {
|
||||||
|
displayedText.value = props.text
|
||||||
|
return
|
||||||
|
}
|
||||||
if (index.value <= props.text.length) {
|
if (index.value <= props.text.length) {
|
||||||
displayedText.value += props.text.charAt(index.value);
|
displayedText.value += props.text.charAt(index.value);
|
||||||
index.value++;
|
index.value++;
|
||||||
setTimeout(() => type(), props.delay);
|
setTimeout(() => {
|
||||||
|
type();
|
||||||
|
emit('updateScroll', typingEffectRef.value.clientHeight); // 每次添加新字符后滚动到底部
|
||||||
|
}, props.delay);
|
||||||
} else {
|
} else {
|
||||||
// 当所有字符都显示完毕时,触发 complete 事件
|
// 当所有字符都显示完毕时,触发 complete 事件
|
||||||
emit('complete');
|
emit('complete',displayedText.value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
type();
|
resetAndType();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监听 props 的变化,以便当传入的 text 或 delay 发生改变时重新开始打字机效果
|
const resetAndType = () =>{
|
||||||
watch([() => props.text, () => props.delay], () => {
|
|
||||||
displayedText.value = '';
|
displayedText.value = '';
|
||||||
index.value = 0;
|
index.value = 0;
|
||||||
type();
|
type();
|
||||||
});
|
}
|
||||||
|
|
||||||
|
// 监听 props 的变化,以便当传入的 text 或 delay 发生改变时重新开始打字机效果
|
||||||
|
watch([() => props.text, () => props.delay], resetAndType);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -194,7 +194,7 @@ onMounted(() =>{
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|
||||||
.img {
|
.img {
|
||||||
width: 100px;
|
width: 100%;
|
||||||
height: 130px;
|
height: 130px;
|
||||||
border: solid #ccc 1px;
|
border: solid #ccc 1px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="info-name">{{ state.user.nickName }}</div>
|
<div class="info-name">{{ state.user.nickName }}</div>
|
||||||
<div class="infomation">
|
<div class="infomation">
|
||||||
<selectClass/>
|
<selectClass v-if="!isSubject"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -46,8 +46,10 @@ const state = reactive({
|
||||||
postGroup: {}
|
postGroup: {}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const isSubject = ref(false)
|
||||||
async function getUser() {
|
async function getUser() {
|
||||||
getUserProfile().then((response) => {
|
getUserProfile().then((response) => {
|
||||||
|
isSubject.value = response.roleGroup.indexOf('场馆管理员') != -1
|
||||||
// response.data.avatar = import.meta.env.VITE_APP_BASE_API + response.data.avatar
|
// response.data.avatar = import.meta.env.VITE_APP_BASE_API + response.data.avatar
|
||||||
Object.assign(state.user,response.data)
|
Object.assign(state.user,response.data)
|
||||||
state.roleGroup = response.roleGroup
|
state.roleGroup = response.roleGroup
|
||||||
|
|
Loading…
Reference in New Issue