新增 Modal组件输入框功能,支持文本输入和Promise返回值

This commit is contained in:
yuantao
2025-10-24 09:43:19 +08:00
parent 2eb7eb8618
commit 65a15341c9
7 changed files with 310 additions and 550 deletions

View File

@@ -88,6 +88,9 @@
--white-60: #ffffff99; /* 60% white */ --white-60: #ffffff99; /* 60% white */
--white-80: #ffffffcc; /* 80% white */ --white-80: #ffffffcc; /* 80% white */
--white-90: #ffffffe6; /* 90% white */ --white-90: #ffffffe6; /* 90% white */
--confirmFontSize: 0.8rem;
--confirmBg: rgba(0, 0, 0, 0.15);
} }
body { body {

View File

@@ -27,7 +27,6 @@
"moment": "^2.30.1", "moment": "^2.30.1",
"pinia": "^3.0.3", "pinia": "^3.0.3",
"vue": "^3.5.22", "vue": "^3.5.22",
"vue-draggable-plus": "^0.6.0",
"vue-router": "^4.5.1" "vue-router": "^4.5.1"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -13,19 +13,19 @@
</template> </template>
<!-- 设置页面 --> <!-- 设置页面 -->
<transition <transition name="settings-slide" v-show="isSettingsRoute" appear>
name="settings-slide"
v-show="isSettingsRoute"
appear>
<SettingsPage class="setting-page" /> <SettingsPage class="setting-page" />
</transition> </transition>
<Modal ref="modalRef" showInput />
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, watch, computed } from 'vue' import { ref, watch, computed, onMounted } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import '@/common/base.css' import '@/common/base.css'
import Modal from '@/components/Modal.vue'
// 导入页面组件 // 导入页面组件
import NoteListPage from './pages/NoteListPage.vue' import NoteListPage from './pages/NoteListPage.vue'
@@ -33,6 +33,7 @@ import SettingsPage from './pages/SettingsPage.vue'
const route = useRoute() const route = useRoute()
const transitionName = ref('slide-left') const transitionName = ref('slide-left')
const modalRef = ref()
// 计算是否为设置页面路由 // 计算是否为设置页面路由
const isSettingsRoute = computed(() => { const isSettingsRoute = computed(() => {
@@ -72,8 +73,6 @@ watch(
} }
} }
) )
// 无额外处理函数
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@@ -1,249 +0,0 @@
<template>
<div v-if="visible" class="pd-mask" @click="handleMaskClick">
<div class="pd-confirm" @click.stop>
<div class="pd-blur"></div>
<div class="pd-plan"></div>
<h2 class="pd-title" v-if="title">{{ title }}</h2>
<p class="pd-message">{{ message }}</p>
<div class="pd-buttons">
<button v-if="showConfirm" class="pd-button pd-confirm-btn" @click="handleConfirm">
{{ confirmText }}
</button>
<button v-if="showCancel" class="pd-button pd-cancel" @click="handleCancel">
{{ cancelText }}
</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, watch, onMounted, onUnmounted } from 'vue'
const props = defineProps({
title: {
type: String,
default: '',
},
message: {
type: String,
default: '',
},
confirmText: {
type: String,
default: '确认',
},
cancelText: {
type: String,
default: '取消',
},
showConfirm: {
type: Boolean,
default: true,
},
showCancel: {
type: Boolean,
default: true,
},
maskClosable: {
type: Boolean,
default: true,
},
})
const emit = defineEmits(['confirm', 'cancel', 'update:visible'])
const visible = defineModel('visible', { type: Boolean, default: false })
// Promise 控制变量
let resolvePromise, rejectPromise
// 返回 Promise 的方法,模拟原生 confirm 行为
const show = (options = {}) => {
// 更新 props 值
Object.assign(props, options)
// 显示对话框
visible.value = true
emit('update:visible', true)
// 返回 Promise
return new Promise((resolve, reject) => {
resolvePromise = resolve
rejectPromise = reject
})
}
const handleConfirm = () => {
emit('confirm')
visible.value = false
emit('update:visible', false)
// 解决 Promise
if (resolvePromise) {
resolvePromise()
resolvePromise = null
rejectPromise = null
}
}
const handleCancel = () => {
emit('cancel')
visible.value = false
emit('update:visible', false)
// 拒绝 Promise
if (rejectPromise) {
rejectPromise()
resolvePromise = null
rejectPromise = null
}
}
const handleMaskClick = () => {
if (props.maskClosable) {
handleCancel() // 点击遮罩相当于取消
}
}
// 添加/移除 body 滚动锁定
const lockBodyScroll = () => {
document.body.style.overflow = 'hidden'
}
const unlockBodyScroll = () => {
document.body.style.overflow = ''
}
onMounted(() => {
if (visible.value) {
lockBodyScroll()
}
})
onUnmounted(() => {
unlockBodyScroll()
})
// 监听 visible 变化
watch(visible, newVal => {
if (newVal) {
lockBodyScroll()
} else {
unlockBodyScroll()
}
})
// 暴露 show 方法给父组件使用
defineExpose({
show,
})
</script>
<style scoped>
.pd-mask {
position: fixed;
inset: 0;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999999999;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: inherit;
background: var(--confirmBg, inherit);
}
.pd-confirm {
background: inherit;
background: var(--confirmTheme, #fff);
text-align: center;
color: var(--confirmColor, #636363);
font-size: var(--confirmFontSize, 1rem);
max-width: 75vw;
min-width: 20em;
box-shadow: 0px 35px 35px -10px rgba(0, 0, 0, 0.33);
border-radius: 10px;
position: relative;
white-space: break-spaces;
word-break: break-all;
overflow: hidden;
}
.pd-blur,
.pd-plan {
position: absolute;
inset: 0;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.pd-plan {
background: inherit;
background: rgba(255, 255, 255, 0.66);
filter: blur(10px) saturate(2);
}
.pd-title {
position: relative;
font-size: 1.3em;
min-height: 1em;
background: var(--confirmBtnBg, #fafafa);
color: var(--confirmBtnColor, #636363);
margin: 0;
padding: 0.5em 0;
}
.pd-message {
position: relative;
border-top: 1px solid var(--confirmBtnBorder, #f1f1f1);
width: 100%;
max-height: 70vh;
border-bottom: 1px solid var(--confirmBtnBorder, #f1f1f1);
margin: 0 auto;
box-sizing: border-box;
padding: 2em 10%;
line-height: 1.4;
overflow: auto;
}
.pd-buttons {
display: flex;
}
.pd-button {
position: relative;
width: 100%;
font-size: 1em;
appearance: none;
background: var(--confirmBtnBg, #fafafa);
color: var(--confirmBtnColor, #636363);
border: none;
border-right: 1px solid var(--confirmBtnBorder, #f1f1f1);
padding: 1em 0;
cursor: pointer;
outline: none;
}
/* 当同时显示确认和取消按钮时每个按钮占50%宽度 */
.pd-button:first-child:nth-last-child(2),
.pd-button:first-child:nth-last-child(2) ~ .pd-button {
width: 50%;
}
/* 当只显示一个按钮时该按钮占100%宽度 */
.pd-button:first-child:nth-last-child(1) {
width: 100%;
border-right: none;
}
/* 只有最后一个按钮没有右边框 */
.pd-button:last-child {
border-right: none;
}
</style>

View File

@@ -103,119 +103,79 @@
<script setup> <script setup>
import { ref, computed, nextTick } from 'vue' import { ref, computed, nextTick } from 'vue'
import { useAppStore } from '../stores/useAppStore' import { useAppStore } from '../stores/useAppStore'
import FolderItem from './FolderItem.vue' import FolderItem from './FolderItem.vue'
const store = useAppStore() const store = useAppStore()
const props = defineProps({ const props = defineProps({
allCount: { allCount: {
type: Number, type: Number,
default: 0, default: 0,
}, },
starredCount: { starredCount: {
type: Number, type: Number,
default: 0, default: 0,
}, },
trashCount: { trashCount: {
type: Number, type: Number,
default: 0, default: 0,
}, },
archiveCount: { archiveCount: {
type: Number, type: Number,
default: 0, default: 0,
}, },
selectedFolder: { selectedFolder: {
type: String, type: String,
default: '', default: '',
}, },
lastSyncTime: { lastSyncTime: {
type: String, type: String,
default: '10/10上午9:28', default: '10/10上午9:28',
}, },
onAllClick: { onAllClick: {
type: Function, type: Function,
default: null, default: null,
}, },
onStarredClick: { onStarredClick: {
type: Function, type: Function,
default: null, default: null,
}, },
onTrashClick: { onTrashClick: {
type: Function, type: Function,
default: null, default: null,
}, },
onArchiveClick: { onArchiveClick: {
type: Function, type: Function,
default: null, default: null,
}, },
onAddFolder: { onAddFolder: {
type: Function, type: Function,
default: null, default: null,
}, },
onFolderClick: { onFolderClick: {
type: Function, type: Function,
default: null, default: null,
}, },
}) })
// 添加文件夹相关状态 // 添加文件夹相关状态
const showAddFolderModal = ref(false) const showAddFolderModal = ref(false)
const newFolderName = ref('') const newFolderName = ref('')
const folderInput = ref(null) const folderInput = ref(null)
// 重命名文件夹相关状态 // 重命名文件夹相关状态
const showRenameFolderModal = ref(false) const showRenameFolderModal = ref(false)
const renameFolderId = ref(null) const renameFolderId = ref(null)
const renameFolderName = ref('') const renameFolderName = ref('')
// 选择模式相关状态 // 选择模式相关状态
const isSelectionMode = ref(false) const isSelectionMode = ref(false)
const selectedFolders = ref([]) const selectedFolders = ref([])
const showDeleteConfirmModal = ref(false) const showDeleteConfirmModal = ref(false)
// 计算自定义文件夹(排除系统文件夹) // 计算自定义文件夹(排除系统文件夹)
const customFolders = computed(() => { const customFolders = computed(() => {
return store.folders.filter(folder => !['all', 'starred', 'trash', 'archive'].includes(folder.id)) return store.folders.filter(folder => !['all', 'starred', 'trash', 'archive'].includes(folder.id))
}) })
// 获取文件夹中的便签数量 // 获取文件夹中的便签数量
const getFolderNoteCount = folderId => { const getFolderNoteCount = folderId => {
return store.notes.filter(note => note.folderId === folderId && !note.isDeleted).length return store.notes.filter(note => note.folderId === folderId && !note.isDeleted).length
} }
@@ -224,28 +184,21 @@ const getFolderNoteCount = folderId => {
const toggleSelectionMode = () => { const toggleSelectionMode = () => {
isSelectionMode.value = !isSelectionMode.value isSelectionMode.value = !isSelectionMode.value
// 退出选择模式时清空选中项 // 退出选择模式时清空选中项
if (!isSelectionMode.value) { if (!isSelectionMode.value) {
selectedFolders.value = [] selectedFolders.value = []
} }
} }
// 切换文件夹选中状态 // 切换文件夹选中状态
const toggleFolderSelection = folderId => { const toggleFolderSelection = folderId => {
if (!isSelectionMode.value) return if (!isSelectionMode.value) return
const index = selectedFolders.value.indexOf(folderId) const index = selectedFolders.value.indexOf(folderId)
if (index > -1) { if (index > -1) {
// 已选中,取消选中 // 已选中,取消选中
selectedFolders.value.splice(index, 1) selectedFolders.value.splice(index, 1)
} else { } else {
// 未选中,添加选中 // 未选中,添加选中
selectedFolders.value.push(folderId) selectedFolders.value.push(folderId)
} }
} }
@@ -266,7 +219,6 @@ const handleFolderClick = folderId => {
const handleDeleteSelectedFolders = () => { const handleDeleteSelectedFolders = () => {
if (selectedFolders.value.length === 0) return if (selectedFolders.value.length === 0) return
showDeleteConfirmModal.value = true showDeleteConfirmModal.value = true
} }
@@ -275,21 +227,15 @@ const handleDeleteSelectedFolders = () => {
const confirmDeleteSelectedFolders = async () => { const confirmDeleteSelectedFolders = async () => {
try { try {
// 删除选中的文件夹 // 删除选中的文件夹
for (const folderId of selectedFolders.value) { for (const folderId of selectedFolders.value) {
// 跳过系统文件夹 // 跳过系统文件夹
if (['all', 'starred', 'trash', 'archive'].includes(folderId)) continue if (['all', 'starred', 'trash', 'archive'].includes(folderId)) continue
await store.deleteFolder(folderId) await store.deleteFolder(folderId)
} }
// 清空选中项并退出选择模式 // 清空选中项并退出选择模式
selectedFolders.value = [] selectedFolders.value = []
isSelectionMode.value = false isSelectionMode.value = false
showDeleteConfirmModal.value = false showDeleteConfirmModal.value = false
} catch (error) { } catch (error) {
console.error('删除文件夹失败:', error) console.error('删除文件夹失败:', error)
@@ -300,11 +246,9 @@ const confirmDeleteSelectedFolders = async () => {
const handleDeleteFolder = folderId => { const handleDeleteFolder = folderId => {
// 阻止事件冒泡到父元素 // 阻止事件冒泡到父元素
event.stopPropagation() event.stopPropagation()
// 确认删除 // 确认删除
if (confirm(`确定要删除文件夹 "${getFolderName(folderId)}" 吗?文件夹中的便签将移至"全部便签"。`)) { if (confirm(`确定要删除文件夹 "${getFolderName(folderId)}" 吗?文件夹中的便签将移至"全部便签"。`)) {
try { try {
store.deleteFolder(folderId) store.deleteFolder(folderId)
@@ -320,18 +264,13 @@ const handleEditFolder = folderId => {
// 阻止事件冒泡到父元素 // 阻止事件冒泡到父元素
event.stopPropagation() event.stopPropagation()
const folder = store.folders.find(f => f.id === folderId) const folder = store.folders.find(f => f.id === folderId)
if (folder) { if (folder) {
renameFolderId.value = folderId renameFolderId.value = folderId
renameFolderName.value = folder.name renameFolderName.value = folder.name
showRenameFolderModal.value = true showRenameFolderModal.value = true
// 在下次DOM更新后聚焦输入框 // 在下次DOM更新后聚焦输入框
nextTick(() => { nextTick(() => {
if (folderInput.value) { if (folderInput.value) {
folderInput.value.focus() folderInput.value.focus()
@@ -346,11 +285,8 @@ const confirmRenameFolder = async () => {
if (renameFolderName.value.trim() && renameFolderId.value) { if (renameFolderName.value.trim() && renameFolderId.value) {
try { try {
await store.updateFolder(renameFolderId.value, { name: renameFolderName.value.trim() }) await store.updateFolder(renameFolderId.value, { name: renameFolderName.value.trim() })
showRenameFolderModal.value = false showRenameFolderModal.value = false
renameFolderId.value = null renameFolderId.value = null
renameFolderName.value = '' renameFolderName.value = ''
} catch (error) { } catch (error) {
console.error('重命名文件夹失败:', error) console.error('重命名文件夹失败:', error)
@@ -362,7 +298,6 @@ const confirmRenameFolder = async () => {
const getFolderName = folderId => { const getFolderName = folderId => {
const folder = store.folders.find(f => f.id === folderId) const folder = store.folders.find(f => f.id === folderId)
return folder ? folder.name : '' return folder ? folder.name : ''
} }
@@ -396,27 +331,13 @@ const handleTrashClick = () => {
} }
} }
const handleArchiveClick = () => {
if (isSelectionMode.value) {
toggleFolderSelection('archive')
} else {
if (props.onArchiveClick) {
props.onArchiveClick()
}
}
}
const handleAddFolder = event => { const handleAddFolder = event => {
// 阻止事件冒泡到父元素 // 阻止事件冒泡到父元素
event.stopPropagation() event.stopPropagation()
showAddFolderModal.value = true showAddFolderModal.value = true
newFolderName.value = '' newFolderName.value = ''
// 在下次DOM更新后聚焦输入框 // 在下次DOM更新后聚焦输入框
nextTick(() => { nextTick(() => {
if (folderInput.value) { if (folderInput.value) {
folderInput.value.focus() folderInput.value.focus()
@@ -429,16 +350,12 @@ const confirmAddFolder = async () => {
try { try {
const newFolder = { const newFolder = {
name: newFolderName.value.trim(), name: newFolderName.value.trim(),
id: `folder_${Date.now()}`, // 生成唯一ID id: `folder_${Date.now()}`, // 生成唯一ID
createdAt: new Date().toISOString(), createdAt: new Date().toISOString(),
} }
await store.addFolder(newFolder) await store.addFolder(newFolder)
showAddFolderModal.value = false showAddFolderModal.value = false
newFolderName.value = '' newFolderName.value = ''
} catch (error) { } catch (error) {
console.error('添加文件夹失败:', error) console.error('添加文件夹失败:', error)

View File

@@ -1,206 +1,297 @@
<template> <template>
<div class="code-fun-flex-col code-fun-justify-start"> <div v-if="visible" class="pd-mask" @click="handleMaskClick">
<div class="code-fun-flex-col code-fun-justify-start group_1"> <div class="pd-confirm" @click.stop>
<div class="code-fun-flex-col code-fun-justify-start code-fun-items-end group"> <h2 class="pd-title">{{ title }}</h2>
<div class="code-fun-flex-col code-fun-justify-start code-fun-items-start code-fun-relative group_2"> <div class="pd-input-container" v-if="showInput">
<div class="code-fun-flex-col section_7"> <input v-model="inputModel" class="pd-input" :placeholder="inputPlaceholder" @keyup.enter="handleConfirm" />
<div class="code-fun-flex-col code-fun-justify-start section_1">
<div class="code-fun-flex-row section_11">
<div class="code-fun-flex-col code-fun-justify-start section_12" @click="handleCancel">
<div class="code-fun-flex-col code-fun-justify-start code-fun-items-center text-wrapper_2">
<span class="text_4">{{ cancelText }}</span>
</div>
</div>
<div class="code-fun-flex-col code-fun-justify-start section_13 code-fun-ml-8" @click="handleConfirm">
<div class="code-fun-flex-col code-fun-justify-start code-fun-items-center text-wrapper_3">
<span class="text_5">{{ confirmText }}</span>
</div>
</div>
</div>
</div>
<div class="code-fun-flex-col code-fun-justify-start code-fun-relative section_9">
<div class="code-fun-flex-col code-fun-justify-start section_10">
<div class="code-fun-flex-col code-fun-justify-start code-fun-items-start text-wrapper">
<input
v-model="inputValue"
class="text_3"
:placeholder="placeholder"
@keyup.enter="handleConfirm"
/>
</div>
</div>
</div>
</div>
<div class="code-fun-flex-col section_8 pos">
<div class="code-fun-flex-col code-fun-justify-start code-fun-items-start code-fun-self-stretch group_3">
<span class="text_2">{{ title }}</span>
</div>
<div class="code-fun-self-start divider"></div>
</div>
</div> </div>
<p class="pd-message" v-else>{{ message }}</p>
<div class="pd-plan"></div>
<div class="pd-buttons">
<button v-if="showConfirm" class="pd-button pd-confirm-btn" @click="handleConfirm">
{{ confirmText }}
</button>
<button v-if="showCancel" class="pd-button pd-cancel" @click="handleCancel">
{{ cancelText }}
</button>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'; import { watch, onMounted, onUnmounted } from 'vue'
const props = defineProps({ const props = defineProps({
title: { title: {
type: String, type: String,
default: '新建文件夹' default: '',
}, },
placeholder: { message: {
type: String, type: String,
default: '新建文件夹' default: '',
}, },
confirmText: { confirmText: {
type: String, type: String,
default: '确' default: '确',
}, },
cancelText: { cancelText: {
type: String, type: String,
default: '取消' default: '取消',
},
showConfirm: {
type: Boolean,
default: true,
},
showCancel: {
type: Boolean,
default: true,
},
maskClosable: {
type: Boolean,
default: false,
},
showInput: {
type: Boolean,
default: false,
},
inputPlaceholder: {
type: String,
default: '请输入文字',
},
inputValue: {
type: String,
default: '',
},
})
const emit = defineEmits(['confirm', 'cancel', 'update:visible'])
const visible = defineModel('visible', { type: Boolean, default: false })
const inputModel = defineModel('inputValue', { type: String, default: '' })
// Promise 控制变量
let resolvePromise, rejectPromise
// 返回 Promise 的方法,模拟原生 confirm 行为
const show = (options = {}) => {
// 更新 props 值
Object.assign(props, options)
// 如果提供了 inputValue则更新输入框的值
if (options.inputValue !== undefined) {
inputModel.value = options.inputValue
} }
});
const emit = defineEmits(['confirm', 'cancel']); // 显示对话框
visible.value = true
emit('update:visible', true)
const inputValue = ref(''); // 返回 Promise
return new Promise((resolve, reject) => {
resolvePromise = resolve
rejectPromise = reject
})
}
const handleConfirm = () => { const handleConfirm = () => {
emit('confirm', inputValue.value); emit('confirm')
}; visible.value = false
emit('update:visible', false)
// 解决 Promise传递输入框的值
if (resolvePromise) {
resolvePromise(inputModel.value)
resolvePromise = null
rejectPromise = null
}
}
const handleCancel = () => { const handleCancel = () => {
emit('cancel'); emit('cancel')
}; visible.value = false
emit('update:visible', false)
// 拒绝 Promise
if (rejectPromise) {
rejectPromise()
resolvePromise = null
rejectPromise = null
}
}
const handleMaskClick = () => {
if (props.maskClosable) {
handleCancel() // 点击遮罩相当于取消
}
}
// 添加/移除 body 滚动锁定
const lockBodyScroll = () => {
document.body.style.overflow = 'hidden'
}
const unlockBodyScroll = () => {
document.body.style.overflow = ''
}
onMounted(() => {
if (visible.value) {
lockBodyScroll()
}
})
onUnmounted(() => {
unlockBodyScroll()
})
// 监听 visible 变化
watch(visible, newVal => {
if (newVal) {
lockBodyScroll()
} else {
unlockBodyScroll()
}
})
// 暴露 show 方法给父组件使用
defineExpose({ show })
</script> </script>
<style scoped lang="less"> <style scoped>
.group_1 { .pd-mask {
padding-bottom: 1rem; position: fixed;
.group { inset: 0;
padding: 0.5rem 0 0.25rem; top: 0;
.group_2 {
margin-right: 0.75rem;
width: 32.31rem;
.section_7 {
padding-top: 5.75rem;
background-color: #00000000;
width: 29.06rem;
height: 18.16rem;
background-image: url(https://codefun-proj-user-res-1256085488.cos.ap-guangzhou.myqcloud.com/686f20ecd54496f19f54e801/68e862ab9520a30011f388ff/17600601480475170758.png);
background-repeat: no-repeat;
background-size: 100% auto;
background-position: 0% 0%;
.section_1 {
margin-top: 7.88rem;
background-color: #00000000;
.section_11 {
padding: 0.5rem 0.5rem 0.75rem;
background-color: #f4f4f7;
border-radius: 0rem 0rem 0.75rem 0.75rem;
border: solid 0.032rem #edeee8;
.section_12 {
padding: 0.25rem 0;
background-color: #00000000;
width: 13.63rem;
height: 3.13rem;
.text-wrapper_2 {
margin: 0 0.25rem;
padding: 0.75rem 0;
background-color: #f2f2f2;
border-radius: 0.25rem;
width: 13.34rem;
border: solid 0.032rem #d7d7d7;
.text_4 {
color: #757575;
font-size: 1.23rem;
font-weight: 700;
line-height: 1.23rem;
}
}
}
.section_13 {
margin-right: 0.25rem;
padding-top: 0.25rem;
background-color: #00000000;
width: 13.59rem;
height: 3.06rem;
.text-wrapper_3 {
margin-left: 0.25rem;
padding: 0.75rem 0;
border-radius: 0.25rem;
background-image: url('assets/53062683132af1946e1a4953530af228.png');
background-size: 100% 100%;
background-repeat: no-repeat;
width: 13.34rem;
.text_5 {
color: #cddff2;
font-size: 1.19rem;
line-height: 1.19rem;
}
}
}
}
}
.section_9 {
margin-top: -12.5rem;
padding: 1.75rem 0 0.25rem;
background-color: #00000000;
.section_10 {
margin: 0 1.5rem;
padding-top: 0.25rem;
background-color: #00000000;
width: 25.88rem;
.text-wrapper {
margin: 0 0.25rem;
padding: 0.75rem 0;
background-color: #fefefe;
border-radius: 0.25rem;
width: 25.53rem;
border: solid 0.063rem #e1e1e1;
.text_3 {
margin-left: 1rem;
color: #d0d0d0;
font-size: 1.38rem;
font-weight: 700;
line-height: 1.38rem;
}
}
}
}
}
.section_8 {
padding: 0 0.13rem;
background-color: #00000000;
width: 32.31rem;
.group_3 {
padding: 1.5rem 0;
width: 32.06rem;
.text_2 {
margin-left: 10.5rem;
color: #7a7a7a;
font-size: 1.54rem;
font-weight: 700;
line-height: 1.54rem;
}
}
.divider {
background-color: #f0f0f0;
width: 29rem;
height: 0.094rem;
}
}
.pos {
position: absolute;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0;
z-index: 999999999;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: inherit;
background: var(--confirmBg, inherit);
}
.pd-confirm {
background: inherit;
background: var(--confirmTheme, #fff);
text-align: center;
color: var(--confirmColor, #636363);
font-size: var(--confirmFontSize, 1rem);
max-width: 75vw;
min-width: 20em;
box-shadow: 0px 35px 35px -10px rgba(0, 0, 0, 0.33);
border-radius: 10px;
position: relative;
white-space: break-spaces;
word-break: break-all;
overflow: hidden;
}
.pd-plan {
background: inherit;
background: rgba(255, 255, 255, 0.66);
filter: blur(10px) saturate(2);
position: absolute;
inset: 0;
top: 0; top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
} }
.pd-title {
position: relative;
font-size: 1.3em;
min-height: 1em;
background: var(--confirmBtnBg, #fafafa);
color: var(--confirmBtnColor, #636363);
margin: 0;
padding: 0.5em 0;
} }
.pd-message {
position: relative;
border-top: 1px solid var(--confirmBtnBorder, #f1f1f1);
width: 100%;
max-height: 70vh;
border-bottom: 1px solid var(--confirmBtnBorder, #f1f1f1);
margin: 0 auto;
box-sizing: border-box;
padding: 2em 10%;
line-height: 1.4;
overflow: auto;
} }
.pd-input-container {
margin-block: 1.5em;
padding: 0 10% 1em;
position: relative;
z-index: 2;
}
.pd-input {
width: 100%;
padding: 0.8em;
font-size: 1em;
border: 1px solid var(--confirmBtnBorder, #f1f1f1);
border-radius: 4px;
box-sizing: border-box;
outline: none;
background: var(--confirmTheme, #fff);
color: var(--confirmColor, #636363);
box-shadow: 0px 0px 4px inset rgba(0, 0, 0, 0.12);
}
.pd-input::placeholder {
color: var(--black-20);
}
.pd-input:focus {
border-color: #4d90fe;
}
.pd-input::selection {
background-color: #4d90fe; /* 选中时的背景颜色 */
color: #ffffff; /* 选中时的文字颜色 */
}
.pd-buttons {
display: flex;
}
.pd-button {
position: relative;
width: 100%;
font-size: 1em;
appearance: none;
background: var(--confirmBtnBg, #fafafa);
color: var(--confirmBtnColor, #636363);
border: none;
border-right: 1px solid var(--confirmBtnBorder, #f1f1f1);
padding: 1em 0;
cursor: pointer;
outline: none;
}
/* 当同时显示确认和取消按钮时每个按钮占50%宽度 */
.pd-button:first-child:nth-last-child(2),
.pd-button:first-child:nth-last-child(2) ~ .pd-button {
width: 50%;
}
/* 当只显示一个按钮时该按钮占100%宽度 */
.pd-button:first-child:nth-last-child(1) {
width: 100%;
border-right: none;
}
/* 只有最后一个按钮没有右边框 */
.pd-button:last-child {
border-right: none;
} }
</style> </style>

View File

@@ -283,7 +283,7 @@ const handleTrashNotesClick = () => {
setIsFolderExpanded(false) setIsFolderExpanded(false)
} }
const handleFolderClick = (folderId) => { const handleFolderClick = folderId => {
setCurrentFolder(folderId) setCurrentFolder(folderId)
setIsFolderExpanded(false) setIsFolderExpanded(false)
} }