This commit is contained in:
owenchen committed 2026-10-14 21:23:40 +08:00
1 parent e740ec77ec
commit ceb3e7beec
20 files changed
+2280 -138

No files matched your search

@@ -1,30 +1,46 @@
<script setup lang="ts">
/**
* 新建文件夹命名对话框:居中卡片(标题 + 输入 + 取消/创建),
* 只负责收集名称——非法字符校验、CreateDmsFolder 接口与结果提示由页面分流。
* 命名对话框(新建文件夹 / 重命名共用):居中卡片(标题 + 输入 + 取消/确认)。
* 只负责收集名称——非法字符校验、接口与结果提示由页面分流。
* 新建态不传 title/confirmLabel 走默认「新建文件夹/创建」;重命名态由页面传入并预填 initialValue。
* 提交成功后由父级收起 visible;submitting 期间禁用按钮防连点。
*/
import { useLocale } from "uview-pro";
import { computed, ref, watch } from "vue";
const props = defineProps({
/** 对话框是否展开 */
visible: {
type: Boolean,
default: false,
},
/** 创建请求在途:置灰两个按钮 */
submitting: {
type: Boolean,
default: false,
},
/** 对话框是否展开 */
visible: {
type: Boolean,
default: false,
},
/** 创建/重命名请求在途:置灰两个按钮 */
submitting: {
type: Boolean,
default: false,
},
/** 标题文案,默认「新建文件夹」 */
title: {
type: String,
default: "",
},
/** 确认按钮文案,默认「创建」 */
confirmLabel: {
type: String,
default: "",
},
/** 展开时预填的名称(重命名带当前名),空则清空输入 */
initialValue: {
type: String,
default: "",
},
});
const emit = defineEmits<{
/** 取消/遮罩关闭 */
(e: "close"): void;
/** 点了创建且名称非空 */
(e: "confirm", name: string): void;
/** 取消/遮罩关闭 */
(e: "close"): void;
/** 点了创建且名称非空 */
(e: "confirm", name: string): void;
}>();
const { t } = useLocale();
@@ -34,109 +50,109 @@ const name = ref("");
/** 空白名不算可提交 */
const canSubmit = computed(() => name.value.trim().length > 0);
// 每次展开清掉上次的残留输入(对话框实例常驻 tab 页)
// 每次展开按 initialValue 预填(重命名带当前名、新建为空),聚焦即全选方便改(对话框实例常驻 tab 页)
watch(
() => props.visible,
(on) => {
if (on) {
name.value = "";
}
},
() => props.visible,
(on) => {
if (on) {
name.value = props.initialValue || "";
}
},
);
function onConfirm(): void {
if (!props.submitting && canSubmit.value) {
emit("confirm", name.value.trim());
}
if (!props.submitting && canSubmit.value) {
emit("confirm", name.value.trim());
}
}
</script>
<template>
<!-- u-popup 只认 modelValue(v-model);提交中禁点遮罩防误关 -->
<u-popup :model-value="props.visible" mode="center" round="24" :close-on-click-overlay="!props.submitting"
@close="emit('close')">
<view class="folder-name-dialog">
<text class="folder-name-dialog__title">
{{ t("FilePage.addFolder") }}
</text>
<input v-model="name" class="folder-name-dialog__input" :placeholder="t('FilePage.folderPlaceholder')"
:maxlength="50" :disabled="props.submitting" confirm-type="done" @confirm="onConfirm">
<view class="folder-name-dialog__actions">
<view class="folder-name-dialog__btn" @click="emit('close')">
<text class="folder-name-dialog__btn-text">
{{ t("FilePage.folderCancel") }}
</text>
</view>
<view class="folder-name-dialog__btn folder-name-dialog__btn--primary"
:class="{ 'folder-name-dialog__btn--muted': !canSubmit || props.submitting }" @click="onConfirm">
<text class="folder-name-dialog__btn-text folder-name-dialog__btn-text--primary">
{{ t("FilePage.folderConfirm") }}
</text>
</view>
</view>
<!-- u-popup 只认 modelValue(v-model);提交中禁点遮罩防误关 -->
<u-popup :model-value="props.visible" mode="center" round="24" :close-on-click-overlay="!props.submitting"
@close="emit('close')">
<view class="folder-name-dialog">
<text class="folder-name-dialog__title">
{{ props.title || t("FilePage.addFolder") }}
</text>
<input v-model="name" class="folder-name-dialog__input" :placeholder="t('FilePage.folderPlaceholder')"
:maxlength="50" :disabled="props.submitting" confirm-type="done" @confirm="onConfirm">
<view class="folder-name-dialog__actions">
<view class="folder-name-dialog__btn" @click="emit('close')">
<text class="folder-name-dialog__btn-text">
{{ t("FilePage.folderCancel") }}
</text>
</view>
</u-popup>
<view class="folder-name-dialog__btn folder-name-dialog__btn--primary"
:class="{ 'folder-name-dialog__btn--muted': !canSubmit || props.submitting }" @click="onConfirm">
<text class="folder-name-dialog__btn-text folder-name-dialog__btn-text--primary">
{{ props.confirmLabel || t("FilePage.folderConfirm") }}
</text>
</view>
</view>
</view>
</u-popup>
</template>
<style lang="scss" scoped>
.folder-name-dialog {
width: 560rpx;
padding: 40rpx 32rpx 32rpx;
background-color: #ffffff;
width: 560rpx;
padding: 40rpx 32rpx 32rpx;
background-color: #ffffff;
&__title {
display: block;
padding-bottom: 28rpx;
font-size: 32rpx;
font-weight: 600;
color: #1f2329;
text-align: center;
&__title {
display: block;
padding-bottom: 28rpx;
font-size: 32rpx;
font-weight: 600;
color: #1f2329;
text-align: center;
}
&__input {
box-sizing: border-box;
width: 100%;
height: 80rpx;
padding: 0 24rpx;
border: 2rpx solid #e6e7ea;
border-radius: 16rpx;
font-size: 28rpx;
color: #1f2329;
background-color: #f7f8fa;
}
&__actions {
display: flex;
gap: 20rpx;
margin-top: 32rpx;
}
&__btn {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
height: 76rpx;
border-radius: 999rpx;
background-color: #f5f6f8;
&--primary {
background-color: #2b8fff;
}
&__input {
box-sizing: border-box;
width: 100%;
height: 80rpx;
padding: 0 24rpx;
border: 2rpx solid #e6e7ea;
border-radius: 16rpx;
font-size: 28rpx;
color: #1f2329;
background-color: #f7f8fa;
/* 名称为空或提交中:主按钮置灰(仍可点,由 onConfirm 拦截) */
&--muted {
background-color: #b9d6ff;
}
}
&__actions {
display: flex;
gap: 20rpx;
margin-top: 32rpx;
}
&__btn {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
height: 76rpx;
border-radius: 999rpx;
background-color: #f5f6f8;
&--primary {
background-color: #2b8fff;
}
/* 名称为空或提交中:主按钮置灰(仍可点,由 onConfirm 拦截) */
&--muted {
background-color: #b9d6ff;
}
}
&__btn-text {
font-size: 28rpx;
color: #5c626b;
&--primary {
color: #ffffff;
}
&__btn-text {
font-size: 28rpx;
color: #5c626b;
&--primary {
color: #ffffff;
}
}
}
</style>