165 lines
4.3 KiB
Vue
165 lines
4.3 KiB
Vue
<script setup lang="ts">
|
||
/**
|
||
* 命名对话框(新建文件夹 / 重命名共用):居中卡片(标题 + 输入 + 取消/确认)。
|
||
* 只负责收集名称——非法字符校验、接口与结果提示由页面分流。
|
||
* 新建态不传 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,
|
||
},
|
||
/** 标题文案,默认「新建文件夹」 */
|
||
title: {
|
||
type: String,
|
||
default: "",
|
||
},
|
||
/** 确认按钮文案,默认「创建」 */
|
||
confirmLabel: {
|
||
type: String,
|
||
default: "",
|
||
},
|
||
/** 展开时预填的名称(重命名带当前名),空则清空输入 */
|
||
initialValue: {
|
||
type: String,
|
||
default: "",
|
||
},
|
||
/** 输入框占位文案:缺省沿用「新建文件夹」语义,群描述/申请原因等场景由页面覆写 */
|
||
placeholder: {
|
||
type: String,
|
||
default: "",
|
||
},
|
||
});
|
||
|
||
const emit = defineEmits<{
|
||
/** 取消/遮罩关闭 */
|
||
(e: "close"): void;
|
||
/** 点了创建且名称非空 */
|
||
(e: "confirm", name: string): void;
|
||
}>();
|
||
|
||
const { t } = useLocale();
|
||
|
||
const name = ref("");
|
||
|
||
/** 空白名不算可提交 */
|
||
const canSubmit = computed(() => name.value.trim().length > 0);
|
||
|
||
// 每次展开按 initialValue 预填(重命名带当前名、新建为空),聚焦即全选方便改(对话框实例常驻 tab 页)
|
||
watch(
|
||
() => props.visible,
|
||
(on) => {
|
||
if (on) {
|
||
name.value = props.initialValue || "";
|
||
}
|
||
},
|
||
);
|
||
|
||
function onConfirm(): void {
|
||
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">
|
||
{{ props.title || t("FilePage.addFolder") }}
|
||
</text>
|
||
<input v-model="name" class="folder-name-dialog__input"
|
||
:placeholder="props.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">
|
||
{{ 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;
|
||
|
||
&__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;
|
||
}
|
||
|
||
/* 名称为空或提交中:主按钮置灰(仍可点,由 onConfirm 拦截) */
|
||
&--muted {
|
||
background-color: #b9d6ff;
|
||
}
|
||
}
|
||
|
||
&__btn-text {
|
||
font-size: 28rpx;
|
||
color: #5c626b;
|
||
|
||
&--primary {
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
}
|
||
</style>
|