feat: 回车检测&restore添加标签
This commit is contained in:
BIN
src/assets/images/restore.png
Normal file
BIN
src/assets/images/restore.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 284 B |
BIN
src/assets/images/tag-close.png
Normal file
BIN
src/assets/images/tag-close.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 154 B |
@@ -10,6 +10,7 @@
|
||||
<div class="agent-body flex-1 flex flex-col">
|
||||
<List ref="listRef" :message-list="messageList" @regenerate="handleRegenerate" />
|
||||
<Input
|
||||
ref="inputRef"
|
||||
is-agent-mode
|
||||
:generating="isGenerating"
|
||||
@send="handleSendMessage"
|
||||
@@ -20,7 +21,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onUnmounted, onMounted, nextTick,watch } from 'vue'
|
||||
import { ref, reactive, computed, onUnmounted, onMounted, nextTick, watch } from 'vue'
|
||||
import List from './List.vue'
|
||||
import Input from '../../components/Input.vue'
|
||||
import { fetchAgentReply } from '@/api/agent'
|
||||
@@ -45,6 +46,7 @@
|
||||
const messageList = ref([])
|
||||
|
||||
const listRef = ref()
|
||||
const inputRef = ref()
|
||||
const isGenerating = ref(false)
|
||||
const isPaused = ref(false) // 标记是否为主动暂停
|
||||
const params = reactive<AgentParamsType>({
|
||||
@@ -62,11 +64,15 @@
|
||||
})
|
||||
|
||||
const sketchList = ref([])
|
||||
watch(sketchList, (newVal) => {
|
||||
console.log('添加图片链接--------');
|
||||
|
||||
emits('update:sketchList', newVal)
|
||||
}, { deep: true })
|
||||
watch(
|
||||
sketchList,
|
||||
(newVal) => {
|
||||
console.log('添加图片链接--------')
|
||||
|
||||
emits('update:sketchList', newVal)
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 每次请求时创建新的 AbortController
|
||||
let abort: AbortController
|
||||
@@ -255,8 +261,8 @@ watch(sketchList, (newVal) => {
|
||||
|
||||
try {
|
||||
const jsonData = JSON.parse(jsonText)
|
||||
console.log('jsonData', jsonData);
|
||||
|
||||
console.log('jsonData', jsonData)
|
||||
|
||||
// 赋值 project_id 和 version_id
|
||||
// if (jsonData.project_id) params.projectID = jsonData.project_id
|
||||
// if (jsonData.version_id) params.versionID = jsonData.version_id
|
||||
@@ -354,6 +360,10 @@ watch(sketchList, (newVal) => {
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
inputRef
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
@@ -76,8 +76,8 @@
|
||||
// }
|
||||
// return self.renderToken(tokens, idx, options, env, self)
|
||||
// }
|
||||
const str = md.render(props.content.text)
|
||||
// console.log('str',str)
|
||||
const str = md.render(props.content.text)
|
||||
// console.log('str',str)
|
||||
return str
|
||||
})
|
||||
|
||||
@@ -167,10 +167,10 @@
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.message-context{
|
||||
line-height: 2rem;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
.message-context {
|
||||
line-height: 2rem;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
}
|
||||
.operate {
|
||||
margin-top: 1.3rem;
|
||||
@@ -215,3 +215,11 @@
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.message-txt {
|
||||
ul {
|
||||
list-style-position: inside;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -19,8 +19,9 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
//const emit = defineEmits([
|
||||
//])
|
||||
const emit = defineEmits([
|
||||
'restore'
|
||||
])
|
||||
|
||||
const versionsList = ref([])
|
||||
|
||||
@@ -70,7 +71,8 @@ const openTree = (state)=>{
|
||||
treeState.value = state
|
||||
}
|
||||
|
||||
const versionRestore = ()=>{
|
||||
const versionRestore = () => {
|
||||
|
||||
let id = ''
|
||||
if(selectItem.value?.children?.length > 0){
|
||||
function findMaxForYourFormat(items) {
|
||||
@@ -99,6 +101,7 @@ const versionRestore = ()=>{
|
||||
findAndAddChild(versionsList.value, selectItem.value?.versionId, addObj)
|
||||
selectItem.value = {...addObj}
|
||||
treeKey.value++
|
||||
emit('restore')
|
||||
}
|
||||
const versionDelete = (versionDetail)=>{
|
||||
if(!selectItem.value?.versionId)return
|
||||
|
||||
@@ -4,12 +4,16 @@
|
||||
<div class="btn" @click="versionTreeData.drawer = true">Version Tree</div>
|
||||
</div>
|
||||
<div class="content-wrapper">
|
||||
<Agent :title="agentTitle" @update:sketchList="updateSketchList" />
|
||||
<Agent ref="agentRef" :title="agentTitle" @update:sketchList="updateSketchList" />
|
||||
<div class="preview-wrapper">
|
||||
<Preview :type="previewType" :sketchList="sketchList" />
|
||||
</div>
|
||||
</div>
|
||||
<VersionTreeIndex ref="VersionTreeIndexRef" v-model:versionTreeData="versionTreeData" />
|
||||
<VersionTreeIndex
|
||||
ref="VersionTreeIndexRef"
|
||||
v-model:versionTreeData="versionTreeData"
|
||||
@restore="handleRestore"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -21,12 +25,11 @@
|
||||
import { useProjectStore } from '@/stores'
|
||||
import { getProjectInfo } from '@/api/agent'
|
||||
|
||||
|
||||
const agentTitle = ref('Retro Sofa Sketch')
|
||||
const previewType = ref<'sketch' | 'report'>('sketch')
|
||||
|
||||
const VersionTreeIndexRef = ref()
|
||||
|
||||
const agentRef = ref()
|
||||
const sketchList = ref([])
|
||||
const updateSketchList = (newVal) => {
|
||||
console.log('newVal', newVal)
|
||||
@@ -35,21 +38,30 @@
|
||||
}
|
||||
|
||||
const versionTreeData = ref({
|
||||
drawer: false,
|
||||
drawer: false
|
||||
})
|
||||
|
||||
const handleRestore = () => {
|
||||
console.log('-----------', agentRef.value.inputRef.addReportTag)
|
||||
|
||||
agentRef.value?.inputRef?.addReportTag('Restore')
|
||||
}
|
||||
|
||||
const projectStore = useProjectStore()
|
||||
watch(()=>projectStore.state.id, (newVal, oldVal) => {
|
||||
if(newVal){
|
||||
getProjectInfo({ id: newVal }).then(res => {
|
||||
projectStore.setProject(res.project)
|
||||
})
|
||||
watch(
|
||||
() => projectStore.state.id,
|
||||
(newVal, oldVal) => {
|
||||
if (newVal) {
|
||||
getProjectInfo({ id: newVal }).then((res) => {
|
||||
projectStore.setProject(res.project)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
onMounted(()=>{
|
||||
if(projectStore.state.id){
|
||||
getProjectInfo({ id: projectStore.state.id }).then(res => {
|
||||
onMounted(() => {
|
||||
if (projectStore.state.id) {
|
||||
getProjectInfo({ id: projectStore.state.id }).then((res) => {
|
||||
projectStore.setProject(res.project)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
:placeholder="$t('Input.placeholder')"
|
||||
@input="handleEditorInput"
|
||||
@paste="handleEditorPaste"
|
||||
@keypress="handleKeyPress"
|
||||
@keydown="handleKeyDown"
|
||||
></div>
|
||||
</div>
|
||||
<div class="operate flex align-center space-between">
|
||||
@@ -184,6 +184,8 @@
|
||||
import { useAgentStore, useProjectStore } from '@/stores'
|
||||
import lightIcon from '@/assets/images/light-icon.png'
|
||||
import closeIcon from '@/assets/images/close-icon.png'
|
||||
import restoreIcon from '@/assets/images/restore.png'
|
||||
import restoreCloseIcon from '@/assets/images/tag-close.png'
|
||||
import { createProject } from '@/api/agent'
|
||||
import { getStyleImage } from './style'
|
||||
// import Tag from './Tag.vue'
|
||||
@@ -265,22 +267,35 @@
|
||||
const inputValue = ref<string>('')
|
||||
|
||||
const reportTags = ref([])
|
||||
const addReportTag = () => {
|
||||
// 导出给父组件调用的方法
|
||||
const addReportTag = (text?: string) => {
|
||||
// 使用传入的文本,如果没有传入则使用默认的翻译文本
|
||||
const tagText = text || t('Input.trendingReport')
|
||||
|
||||
// create container matching static structure: <div class="editor-tag report-btn flex-center" contenteditable="false">...
|
||||
const tag = document.createElement('div')
|
||||
tag.className = 'editor-tag report-btn flex-center'
|
||||
tag.contentEditable = 'false'
|
||||
|
||||
const imgLeft = document.createElement('img')
|
||||
imgLeft.className = 'light-icon'
|
||||
imgLeft.src = lightIcon as unknown as string
|
||||
|
||||
const textSpan = document.createElement('span')
|
||||
textSpan.innerText = t('Input.trendingReport')
|
||||
|
||||
const imgClose = document.createElement('img')
|
||||
const textSpan = document.createElement('span')
|
||||
imgClose.className = 'close-icon'
|
||||
imgClose.src = closeIcon as unknown as string
|
||||
if (text) {
|
||||
tag.className = 'editor-tag restore flex-center'
|
||||
imgLeft.className = 'restore-icon'
|
||||
imgLeft.src = restoreIcon as unknown as string
|
||||
imgClose.src = restoreCloseIcon as unknown as string
|
||||
imgClose.className = 'close-icon restore'
|
||||
textSpan.className = 'restore-text'
|
||||
} else {
|
||||
tag.className = 'editor-tag report-btn flex-center'
|
||||
imgLeft.className = 'light-icon'
|
||||
imgLeft.src = lightIcon as unknown as string
|
||||
imgClose.src = closeIcon as unknown as string
|
||||
}
|
||||
|
||||
|
||||
textSpan.innerText = tagText
|
||||
|
||||
imgClose.addEventListener('click', (ev) => {
|
||||
ev.stopPropagation()
|
||||
// remove tag when close clicked
|
||||
@@ -398,11 +413,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
const handleKeyPress = (e) => {
|
||||
const handleKeyDown = (e) => {
|
||||
// 检测回车
|
||||
if (e.key === 'Enter') {
|
||||
console.log('11111111111')
|
||||
|
||||
e.preventDefault()
|
||||
handleSendAgent()
|
||||
if (props.isAgentMode) {
|
||||
handleSendAgent()
|
||||
} else {
|
||||
handleCreateProject()
|
||||
}
|
||||
return
|
||||
}
|
||||
if (e.key === 'Backspace') {
|
||||
@@ -446,12 +467,20 @@
|
||||
}
|
||||
|
||||
const handleSendAgent = async () => {
|
||||
console.log('发送信息--------')
|
||||
|
||||
if (props.generating) {
|
||||
emits('pause')
|
||||
return
|
||||
}
|
||||
if (!inputValue.value.trim()) return
|
||||
emits('send', { text: inputValue.value.trim(), images: uploadedImages.value })
|
||||
console.log('222222')
|
||||
|
||||
const payload = { text: inputValue.value.trim(), images: uploadedImages.value }
|
||||
console.log('准备发送 send 事件', payload)
|
||||
emits('send', payload)
|
||||
console.log('send 事件已发送')
|
||||
|
||||
// 发送后清空输入框
|
||||
if (editorRef.value) {
|
||||
editorRef.value.innerHTML = ''
|
||||
@@ -534,7 +563,7 @@
|
||||
temperature: 0.7
|
||||
}
|
||||
const projectres = await createProject(params)
|
||||
console.log('projectres', projectres)
|
||||
// console.log('projectres', projectres)
|
||||
projectStore.setId(projectres)
|
||||
// 保存初始数据到 store
|
||||
agentStore.setInitialProjectData({
|
||||
@@ -543,9 +572,14 @@
|
||||
...params
|
||||
})
|
||||
|
||||
console.log('Create project with:', params)
|
||||
// console.log('Create project with:', params)
|
||||
router.push('/home/agent', { query: params })
|
||||
}
|
||||
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
addReportTag
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@@ -983,9 +1017,32 @@
|
||||
margin: 0 0.5rem;
|
||||
vertical-align: middle;
|
||||
border-radius: 2.2rem;
|
||||
&.restore {
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
display: inline-flex;
|
||||
border: none;
|
||||
border-radius: 0.4rem;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 0.9rem 0 0.7rem;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
span {
|
||||
margin: 0 0.7rem 0 1.2rem;
|
||||
&.restore-text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
max-width: 52rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.light-icon {
|
||||
@@ -999,6 +1056,15 @@
|
||||
height: 1rem;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
&.restore{
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
}
|
||||
}
|
||||
.restore-icon{
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -25,35 +25,15 @@ function slugify(str) {
|
||||
* @returns { string | null } 返回可直接用于 <img :src=""> 的 URL
|
||||
*/
|
||||
export function getStyleImage(types, style) {
|
||||
|
||||
if (!types) types = 'Sofa'
|
||||
if (!types) types = 'Sofa'
|
||||
const type = types.toLowerCase()
|
||||
const map = imagesMaps[type]
|
||||
|
||||
|
||||
const fileName = `${slugify(style)}.png`
|
||||
const key = `/src/assets/images/${type}/${fileName}`
|
||||
console.log('types',types, 'style',style, 'fileName',fileName, 'key',key);
|
||||
|
||||
if (map[key]) {
|
||||
return map[key].default
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
const styleList = [
|
||||
'Venetian Modern',
|
||||
'Coastal',
|
||||
'Maximalism',
|
||||
'Memphis',
|
||||
'Verdant',
|
||||
'Century Chrome',
|
||||
'Modern Revival',
|
||||
'Transitional',
|
||||
"Tuscan 2000's",
|
||||
'Kitsch-core',
|
||||
'Bauhaus',
|
||||
'Constructivism',
|
||||
'Nordic Noir',
|
||||
'Dopamine',
|
||||
'Squiggle'
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user