Files
SmartisanNote.Remake/src/components/Header.vue

258 lines
6.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="component">
<div class="inner code-fun-flex-row code-fun-items-center">
<!-- 左侧图标 -->
<img class="left-icon" :src="leftIconSource" @click="handleLeftAction" />
<!-- 标题区域 -->
<div class="title-container">
<span class="text" @click="handleTitlePress">{{ title }}</span>
<!-- 文件夹展开图标 -->
<img v-if="showFolderIcon" class="folder-icon" :src="folderExpanded ? '/assets/icons/drawable-xxhdpi/folder_title_arrow_pressed.png' : '/assets/icons/drawable-xxhdpi/folder_title_arrow_normal.png'" @click.stop="handleFolderToggle" />
</div>
<!-- 右侧操作按钮 -->
<!-- 新建便签 -->
<img v-if="actionIcon === 'create'" class="image_4" src="/assets/icons/drawable-xxhdpi/btn_create.png" @click="handleAction('create')" />
<!-- 编辑模式 -->
<div v-else-if="actionIcon === 'edit'" class="code-fun-flex-row code-fun-items-center right-group">
<!-- 插入图片 -->
<img class="image_4" src="/assets/icons/drawable-xxhdpi/btn_pic.png" @click="handleAction('insertImage')" />
<!-- 保存便签 -->
<img class="image_4" src="/assets/icons/drawable-xxhdpi/btn_save_notes.png" @click="handleAction('save')" />
</div>
<!-- 预览模式 -->
<div v-else-if="actionIcon === 'preview'" class="code-fun-flex-row code-fun-items-center right-group">
<!-- 删除便签 -->
<img
ref="deleteButtonRef"
class="image_4"
:src="deleteButtonFrame"
@click="handleAction('delete')"
/>
<!-- 分享便签 -->
<img class="image_4" src="/assets/icons/drawable-xxhdpi/btn_share_notes.png" @click="handleAction('share')" />
</div>
<!-- 占位符 -->
<div v-else class="image_4-placeholder"></div>
</div>
</div>
</template>
<script setup>
import { ref, computed, defineExpose } from 'vue'
const props = defineProps({
title: {
type: String,
default: '',
},
onBack: {
type: Function,
default: null,
},
onAction: {
type: Function,
default: null,
},
actionText: {
type: String,
default: '',
},
actionIcon: {
type: String,
default: '',
},
leftIcon: {
type: String,
default: '',
},
leftType: {
type: String,
default: 'back',
},
onLeftAction: {
type: Function,
default: null,
},
onFolderToggle: {
type: Function,
default: null,
},
isFolderExpanded: {
type: Boolean,
default: undefined,
},
onTitlePress: {
type: Function,
default: null,
},
background: {
type: String,
default: 'url(/assets/icons/drawable-xxhdpi/action_bar_default.png)',
},
color: {
type: String,
default: 'white',
},
})
const localFolderExpanded = ref(false)
const deleteButtonRef = ref(null)
const deleteButtonFrame = ref('/assets/icons/drawable-xxhdpi/btn_delete_notes.png')
const isDeleteAnimating = ref(false)
const folderExpanded = computed(() => {
// 优先使用父组件传递的isFolderExpanded状态否则使用本地状态
return props.isFolderExpanded !== undefined ? props.isFolderExpanded : localFolderExpanded.value
})
const showFolderIcon = computed(() => {
// 只有当leftType为settings且有onFolderToggle回调时才显示文件夹图标
return props.leftType === 'settings' && props.onFolderToggle
})
const leftIconSource = computed(() => {
// 根据leftType属性返回对应的图标路径
if (props.leftType === 'settings') {
return '/assets/icons/drawable-xxhdpi/btn_settings.png'
} else {
if (props.color !== 'white') {
return '/assets/icons/drawable-xxhdpi/btn_back_black.png'
} else {
return '/assets/icons/drawable-xxhdpi/btn_back.png'
}
}
})
const handleFolderToggle = () => {
// 切换文件夹展开状态
if (props.isFolderExpanded === undefined) {
// 如果父组件没有传递isFolderExpanded则使用本地状态
localFolderExpanded.value = !localFolderExpanded.value
}
// 调用父组件传递的回调函数
if (props.onFolderToggle) {
props.onFolderToggle()
}
}
// 播放删除按钮动画(只使用存在的帧)
const playDeleteAnimation = () => {
if (isDeleteAnimating.value) return
isDeleteAnimating.value = true
// 只使用存在的帧编号
const frames = [1, 6, 9, 10, 13, 16, 19, 21, 23, 25, 26, 27, 28, 29, 30]
let currentFrameIndex = 0
const playFrame = () => {
if (currentFrameIndex < frames.length) {
// 格式化帧编号(补零)
const frameNumber = frames[currentFrameIndex].toString().padStart(4, '0')
deleteButtonFrame.value = `/assets/icons/drawable-xxhdpi/title_bar_del_btn_mov_${frameNumber}.png`
currentFrameIndex++
// 使用setTimeout控制动画播放速度
setTimeout(playFrame, 50) // 约20fps调整速度以适应帧数
} else {
// 动画播放完成,重置为默认图标
setTimeout(() => {
deleteButtonFrame.value = '/assets/icons/drawable-xxhdpi/btn_delete_notes.png'
isDeleteAnimating.value = false
}, 100)
}
}
// 开始播放动画
playFrame()
}
// 暴露播放删除动画的方法给父组件
defineExpose({
playDeleteAnimation
})
const handleLeftAction = () => {
// 处理左侧图标点击事件
if (props.onLeftAction) {
props.onLeftAction()
} else if (props.leftType !== 'settings' && props.onBack) {
// 兼容旧版本的onBack属性
props.onBack()
}
}
const handleAction = actionType => {
// 处理右侧操作按钮点击事件
if (props.onAction) {
props.onAction(actionType)
}
}
const handleTitlePress = () => {
// 处理标题点击事件
if (props.onTitlePress) {
props.onTitlePress()
}
}
</script>
<style scoped lang="less">
.component {
padding: 2.5rem 0.72rem 0.35rem;
background: v-bind(background);
background-size: 100% 100%;
display: flex;
flex-direction: column;
align-items: flex-end;
position: relative;
box-shadow: 0 0 30px 5px rgba(0, 0, 0, 0.2);
.inner {
display: flex;
justify-content: space-between;
width: 100%;
}
.left-icon,
.image_4 {
width: 1.9rem;
height: 1.9rem;
cursor: pointer;
}
.right-group {
gap: 0.6rem;
}
.image_4-placeholder {
width: 1.9rem;
height: 1.9rem;
}
.title-container {
display: flex;
align-items: center;
cursor: pointer;
flex: 1;
justify-content: center;
.folder-icon {
width: 0.8rem;
height: 0.8rem;
margin-left: 0.2rem;
cursor: pointer;
}
.text {
color: v-bind(color);
font-size: 1.01rem;
line-height: 1.01rem;
letter-spacing: 0.05em;
text-indent: 0.05em;
}
}
}
</style>