Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 179 additions & 0 deletions src/components/FavoriteComponentsModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
<template>
<div class="modal-overlay" @click.self="closeModal" v-if="visible">
<div class="modal-content">
<div class="modal-header">
<h2>选择收藏夹组件</h2>
<button class="close-button" @click="closeModal">×</button>
</div>
<div class="modal-body">
<ul v-if="favorites.length > 0">
<li
v-for="(favorite, index) in favorites"
:key="index"
@click="selectFavorite(favorite)"
>
<!-- Display the favorite name -->
<div class="favorite-name">{{ favorite.name }}</div>
<!-- TODO: Add a more sophisticated preview -->
<button class="delete-button" @click.stop="handleDeleteFavorite(favorite.name)">删除</button>
</li>
</ul>
</div>
<div class="modal-footer">
<button @click="closeModal">取消</button>
<!-- TODO: Add a confirmation button if multiple selection is allowed -->
</div>
</div>
</div>
</template>

<script lang="ts" setup>
import { ref, watch } from 'vue'
import type { PPTElement } from '@/types/slides'

// Assuming FavoriteItem is defined in useFavoriteComponents and includes 'name'
import useFavoriteComponents, { type FavoriteItem } from '@/hooks/useFavoriteComponents'

const props = defineProps<{
visible: boolean;
favorites: FavoriteItem[]; // Use FavoriteItem type
}>()

const emit = defineEmits<{
(e: 'update:visible', value: boolean): void;
(e: 'select-favorite', elements: PPTElement[]): void;
}>()

const { getFavorites, removeFavorite } = useFavoriteComponents()

// We need a local ref to manage the displayed favorites in the modal
const displayedFavorites = ref<FavoriteItem[]>([])

// Watch the visible prop to load favorites when the modal opens
watch(() => props.visible, (isVisible) => {
if (isVisible) {
displayedFavorites.value = getFavorites()
}
})

const closeModal = () => {
console.log('closeModal called')
emit('update:visible', false)
console.log('update:visible emitted')
}

// Function to handle favorite selection
const selectFavorite = (favorite: FavoriteItem) => {
// Emit the elements array part of the FavoriteItem
emit('select-favorite', favorite.elements)
closeModal()
}

const handleDeleteFavorite = (name: string) => {
removeFavorite(name)
displayedFavorites.value = getFavorites() // This line refreshes the displayed list
}

// TODO: Implement selection logic
</script>

<style scoped>
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}

.modal-content {
background-color: white;
padding: 20px;
border-radius: 8px;
width: 90%;
max-width: 500px;
max-height: 80%;
overflow-y: auto;
display: flex;
flex-direction: column;
}

.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
margin-bottom: 10px;
}

.modal-header h2 {
margin: 0;
}

.close-button {
background: none;
border: none;
font-size: 1.5em;
cursor: pointer;
}

.modal-body ul {
list-style: none;
padding: 0;
}

.modal-body li {
padding: 10px 0;
border-bottom: 1px solid #eee;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
}

.modal-body li:last-child {
border-bottom: none;
}

.favorite-name {
flex-grow: 1;
}

.delete-button {
background: none;
border: none;
color: red;
cursor: pointer;
margin-left: 10px;
}

.delete-button:hover {
text-decoration: underline;
}

.modal-footer {
display: flex;
justify-content: flex-end;
padding-top: 10px;
border-top: 1px solid #eee;
}

.modal-footer button {
margin-left: 10px;
padding: 8px 15px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #fff;
cursor: pointer;
}

.modal-footer button:hover {
background-color: #f0f0f0;
}
</style>
54 changes: 54 additions & 0 deletions src/hooks/useFavoriteComponents.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { PPTElement } from '@/types/slides'

const STORAGE_KEY = 'pptist-favorite-components'

// TODO: Implement this function
const generateSvgPreview = async (elements: PPTElement[]): Promise<string> => {
console.log('Generating SVG preview for:', elements)
// Placeholder implementation
await Promise.resolve()
return ''
}

export interface FavoriteItem {
elements: PPTElement[];
name: string;
previewSvg?: string;
}

export default () => {

const getFavorites = (): FavoriteItem[] => {
const favoritesJson = localStorage.getItem(STORAGE_KEY)
return favoritesJson ? JSON.parse(favoritesJson) : []
}

const addFavorite = (elements: PPTElement[], name: string) => {
if (!elements || elements.length === 0 || !name) return

const favorites = getFavorites()

const newFavorite: FavoriteItem = {
elements: elements,
name: name,
previewSvg: '',
}

favorites.push(newFavorite)
localStorage.setItem(STORAGE_KEY, JSON.stringify(favorites))
}

const removeFavorite = (name: string) => {
const favorites = getFavorites()
const updatedFavorites = favorites.filter(favorite => favorite.name !== name)
localStorage.setItem(STORAGE_KEY, JSON.stringify(updatedFavorites))
}

// TODO: Implement other necessary functions later

return {
addFavorite,
getFavorites,
removeFavorite,
}
}
22 changes: 21 additions & 1 deletion src/views/Editor/Canvas/EditableElement.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</template>

<script lang="ts" setup>
import { computed } from 'vue'
import { computed, ref } from 'vue'
import { ElementTypes, type PPTElement } from '@/types/slides'
import type { ContextmenuItem } from '@/components/Contextmenu/types'

Expand All @@ -28,6 +28,7 @@ import useOrderElement from '@/hooks/useOrderElement'
import useAlignElementToCanvas from '@/hooks/useAlignElementToCanvas'
import useCopyAndPasteElement from '@/hooks/useCopyAndPasteElement'
import useSelectElement from '@/hooks/useSelectElement'
import useFavoriteComponents from '@/hooks/useFavoriteComponents'

import { ElementOrderCommands, ElementAlignCommands } from '@/types/edit'

Expand All @@ -41,6 +42,9 @@ import LatexElement from '@/views/components/element/LatexElement/index.vue'
import VideoElement from '@/views/components/element/VideoElement/index.vue'
import AudioElement from '@/views/components/element/AudioElement/index.vue'

import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'

const props = defineProps<{
elementInfo: PPTElement
elementIndex: number
Expand Down Expand Up @@ -72,6 +76,18 @@ const { lockElement, unlockElement } = useLockElement()
const { copyElement, pasteElement, cutElement } = useCopyAndPasteElement()
const { selectAllElements } = useSelectElement()

const mainStore = useMainStore()
const { activeElementList } = storeToRefs(mainStore)
const { addFavorite } = useFavoriteComponents()

const addToFavoritesHandler = () => {
const favoriteName = prompt('请输入收藏组件的名称:')
if (favoriteName !== null && favoriteName.trim() !== '') {
addFavorite(activeElementList.value, favoriteName.trim())
// console.log('Selected elements added to favorites.')
}
}

const contextmenus = (): ContextmenuItem[] => {
if (props.elementInfo.lock) {
return [{
Expand All @@ -96,6 +112,10 @@ const contextmenus = (): ContextmenuItem[] => {
subText: 'Ctrl + V',
handler: pasteElement,
},
{
text: '添加到收藏夹',
handler: addToFavoritesHandler,
},
{ divider: true },
{
text: '水平居中',
Expand Down
Loading