edit 框架设计

This commit is contained in:
lyc 2025-01-07 16:25:07 +08:00
parent 586ce134f8
commit 49facdffa9
2 changed files with 142 additions and 59 deletions

View File

@ -13,30 +13,38 @@
<i class="iconfont icon-shanchu"></i>
删除大纲
</el-button>
<el-button type="primary" @click="isEdit = true">
<i class="iconfont icon-bianji"></i>编辑大纲
</el-button>
</div>
</div>
<div class="center-con" v-loading="loading">
<!-- <TypingEffect v-if="answer" :text="answer" :delay="10" :aiShow="aiShow"/> -->
<div style="font-size: 18px;color: #409eff;">封面页</div>
<div class="con-item mb-5">
<div class="item-name">标题{{ answer.title }}</div>
<div class="item-name">副标题{{answer.subTitle }}</div>
</div>
<div style="font-size: 18px;color: #409eff;">目录页</div>
<div class="con-item" v-for="(item,index) in answer.chapters">
<div class="item-name">{{index + 1}}{{ item.chapterTitle }}</div>
<div class="item-text">
<p v-for="(el,i) in item.chapterContents">{{ index + 1 }} - {{ i + 1}} : {{ el.chapterTitle }}</p>
<template v-if="answer.title">
<div class="flex justify-between">
<span style="font-size: 18px;color: #409eff;">封面页</span>
<el-button type="primary" link @click="onEdit(item, -1)">编辑</el-button>
</div>
</div>
<el-empty v-if="!answer.title" description="请选择符合您需要的教学模式,生成教学大纲" />
<div class="con-item mb-5">
<div class="item-name">标题{{ answer.title }}</div>
<div class="item-name">副标题{{ answer.subTitle }}</div>
</div>
<div style="font-size: 18px;color: #409eff;">目录页</div>
<div class="con-item" v-for="(item, index) in answer.chapters">
<div class="item-name">
<span>{{ index + 1 }}{{ item.chapterTitle }}</span>
<el-button type="primary" link @click="onEdit(item, index)">编辑</el-button>
</div>
<div class="item-text">
<p v-for="(el, i) in item.chapterContents">{{ index + 1 }} - {{ i + 1 }} : {{ el.chapterTitle }}</p>
</div>
</div>
</template>
<el-empty v-else description="请选择符合您需要的教学模式,生成教学大纲" />
</div>
</div>
<EditDialog v-model="isEdit" :item="curItem" />
<EditDialog v-model="isEdit" :item="editItem" :index="editIndex" />
</template>
<script setup>
@ -47,9 +55,10 @@ import EditDialog from './edit-dialog.vue'
import emitter from '@/utils/mitt'
import * as commUtils from '@/utils/comm.js'
import { createChart, sendChart } from '@/api/ai/index'
import { completion, addSyllabus, syllabuss, removeSyllabus } from '@/api/mode/index.js'
import { completion, addSyllabus, syllabuss, removeSyllabus, editSyllabus } from '@/api/mode/index.js'
import { createOutlineV2 } from '@/utils/ppt-request.js'
import useUserStore from '@/store/modules/user'
import { cloneDeep } from 'lodash'
const curMode = ref(2)
const isEdit = ref(false)
@ -70,26 +79,22 @@ const modeOptions = ref([
//
const selectedData = ref([])
emitter.on('selected', (data)=>{
emitter.on('selected', (data) => {
selectedData.value = data
})
//
const curItem = reactive({})
emitter.on('onShow', (data)=>{
emitter.on('onShow', (data) => {
console.log(data)
aiShow.value = false
Object.assign(answer, JSON.parse(data.outline))
Object.assign(curItem, data)
curItem.answer = curItem.outline
getDetails(data.id)
emitter.emit('onResult',data)
})
const getDetails = (id) =>{
syllabuss(id).then( res =>{
Object.assign(curItem, res.data)
emitter.emit('onResult', res.data)
})
}
const params = reactive(
{
@ -103,13 +108,13 @@ const params = reactive(
const loading = ref(false)
const answer = reactive({})
const createAi = async ()=>{
if(selectedData.value.length == 0){
const createAi = async () => {
if (selectedData.value.length == 0) {
ElMessage.warning('请先选择教学环节后再生成教学大纲')
return
}
let str = selectedData.value.map( item => item.name).join('、')
let str = selectedData.value.map(item => item.name).join('、')
let bookV = curNode.roottitle.split('-')[1] + '版'
loading.value = true
aiShow.value = true
@ -131,10 +136,10 @@ const createAi = async ()=>{
//
else {
const res = await completion(params)
data = res.data
}
const res = await createOutlineV2({query: data.answer})
const res = await createOutlineV2({ query: data.answer })
console.log(res)
emitter.emit('onResult', res)
Object.assign(answer, res.outline)
@ -144,15 +149,53 @@ const createAi = async ()=>{
}
}
//
const editItem = reactive({})
const editIndex = ref(0)
const onEdit = (item, index)=>{
let obj = null
if(index == -1){
obj = {
title: answer.title,
subTitle: answer.subTitle
}
}
else{
obj = cloneDeep(item)
}
editIndex.value = index
isEdit.value = true
Object.assign(editItem, obj)
}
emitter.on('editItem', (item) =>{
if(editIndex.value == -1){
answer.title = item.title
answer.subTitle = item.subTitle
}else{
answer.chapters[editIndex.value] = item
}
let data = cloneDeep(curItem)
data.outline = JSON.stringify(cloneDeep(answer))
loading.value = true
editSyllabus(data).then( res =>{
ElMessage.success('操作成功')
}).finally( ()=>{
loading.value = false
})
})
//
const onSaveTemp = async (answer) => {
if (answer == '') return
let modelIds = selectedData.value.map( item => item.id).join(',')
let modelIds = selectedData.value.map(item => item.id).join(',')
const data = {
eduId: curNode.id,
outline: answer,
outlineType: curMode.value == 1 ? 0 : 1,
outlineType: curMode.value == 1 ? 0 : 1,
modelIds,
sourceType: 1,
createUserId: user.userId,
@ -162,7 +205,7 @@ const onSaveTemp = async (answer) => {
}
//
const delAnswer = () =>{
const delAnswer = () => {
ElMessageBox.confirm(
'确定要删除大纲吗?',
'温馨提示',
@ -178,8 +221,8 @@ const delAnswer = () =>{
answer.value = ''
emitter.emit('resetSelect')
})
.catch(() => {})
.catch(() => { })
}
@ -192,10 +235,12 @@ const getChartId = () => {
})
}
onUnmounted(()=>{
onUnmounted(() => {
emitter.off('selected')
emitter.off('onShow')
emitter.off('editItem')
})
const curNode = reactive({})
@ -216,18 +261,21 @@ onMounted(() => {
</script>
<style lang="scss" scoped>
.container-center{
.container-center {
height: 100%;
font-size: 15px;
flex-direction: column;
.center-header{
.center-header {
justify-content: space-between;
align-items: center;
.icon-jiahao{
.icon-jiahao {
font-size: 12px;
}
}
.center-con{
.center-con {
flex: 1;
margin-top: 5px;
background-color: #fff;
@ -235,11 +283,16 @@ onMounted(() => {
text-align: left;
overflow-y: auto;
padding: 15px;
.con-item{
.con-item {
display: flex;
flex-direction: column;
margin-top: 15px;
.item-text{
.item-name{
display: flex;
justify-content: space-between;
}
.item-text {
background: #F2F2F2;
padding: 15px;
border-radius: 5px;
@ -248,5 +301,4 @@ onMounted(() => {
}
}
}
</style>

View File

@ -7,11 +7,28 @@
</div>
</template>
<div class="dialog-content" v-loading="loading">
<el-row>
<el-col :span="24">
<el-input v-model="textarea" :autosize="{ minRows: 5, maxRows: 15 }" type="textarea" />
</el-col>
</el-row>
<template v-if="props.index == -1">
<div class="flex mb-5">
<span class="name">标题</span>
<el-input v-model="editItem.title" />
</div>
<div class="flex mb-5">
<span class="name">副标题</span>
<el-input v-model="editItem.subTitle" />
</div>
</template>
<template v-else>
<div class="flex mb-5">
<span class="name">标题</span>
<el-input v-model="editItem.chapterTitle" />
</div>
<div class="flex">
<span class="name">内容</span>
<div class="flex edit-con">
<el-input class="mb-3" v-model="item.chapterTitle" v-for="item in editItem.chapterContents" />
</div>
</div>
</template>
</div>
<template #footer>
@ -26,13 +43,13 @@
</template>
<script setup>
import { ref, watch} from 'vue'
import { reactive, ref, watch} from 'vue'
import { ElMessage } from 'element-plus'
import { editSyllabus } from '@/api/mode/index.js'
import { cloneDeep } from 'lodash';
import emitter from '@/utils/mitt';
const textarea = ref('')
const isDialog = defineModel()
const loading = ref(false)
@ -40,20 +57,28 @@ const loading = ref(false)
const props = defineProps({
item: {
type: Object,
default: () => {
return { name: '11' }
}
},
index: {
type: [Number, String]
}
})
watch(() => props.item.answer, (newVal) => {
if (newVal) {
textarea.value = newVal
const editItem = reactive({})
watch(() => isDialog.value, (newVal) => {
if(newVal){
let data = cloneDeep(props.item)
Object.assign(editItem, data)
}
},{ deep: true })
const emit = defineEmits(['saveEdit'])
const onSave = () =>{
emitter.emit('editItem', editItem)
isDialog.value = false
return
loading.value = true
let data = cloneDeep(props.item)
data.outline = textarea.value
@ -83,6 +108,12 @@ const onSave = () =>{
.dialog-content {
padding-top: 10px;
.name{
flex-shrink: 0;
}
.edit-con{
width: 100%;
flex-direction: column;
}
}
</style>