ow
This commit is contained in:
1 parent
3194f98ac0
commit
e740ec77ec
24 files changed
+1561
-65
No files matched your search
@@ -6,9 +6,9 @@
|
||||
* file-breadcrumb 目录面包屑(仅子目录态:左起排列,放不下折成 根+…+尾部段)
|
||||
* search-input 搜索框(v-model 即时过滤,确认键触发服务端搜索)
|
||||
* quick-entry 快捷功能入口(横向滚动图标组)
|
||||
* file-tab-filter 分类标签 + 排序 + 视图切换 + 多选开关
|
||||
* file-tab-filter 分类标签 + 新建文件夹 + 排序 + 视图切换 + 多选开关
|
||||
* file-grid-list 文件网格/列表卡片
|
||||
* float-add-btn 右下角悬浮加号
|
||||
* float-add-btn 右下角悬浮加号(直接选文件上传)
|
||||
* 数据来自后端 DMS 接口(composables/useDmsFiles,调用链对齐旧 WebVue DmsFileEnquiry.vue);
|
||||
* 组件契约(data/custom/fileBrowser.ts)不关心数据源,演示数据到真实接口只动页面层。
|
||||
* 目录导航:点文件夹下钻;子目录态隐藏底部 tabbar,返回箭头/面包屑退层级。
|
||||
@@ -18,24 +18,38 @@ import type { FileCategory, FileItem, FileKind, FileTabItem, QuickEntryItem } fr
|
||||
import { useLocale } from "uview-pro";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { useAuthGuard, useDmsFiles, useThemeGradient } from "@/composables";
|
||||
import { DmsFileEntity } from "@/data/auto/dmsFileEntity";
|
||||
import { pageUrl } from "@/router/routes";
|
||||
import dmsFileService from "@/service/master/dmsFileService";
|
||||
import { useUploadQueueStore } from "@/stores/uploadQueue";
|
||||
import { chooseFiles } from "@/utils/chooseFiles";
|
||||
import { transferGlyph } from "@/utils/transferGlyph";
|
||||
|
||||
const { t } = useLocale();
|
||||
|
||||
// 页面底渐变跟随主题(派生逻辑在 composables/useThemeGradient,多页共用)
|
||||
const { themeBackground } = useThemeGradient();
|
||||
|
||||
const { files, loading, errorText, pathStack, atRoot, init, retry, openFolder, back, goTo, search } = useDmsFiles();
|
||||
const { files, loading, errorText, pathStack, atRoot, init, openTrail, retry, openFolder, back, goTo, search } = useDmsFiles();
|
||||
|
||||
// 首次显示拉根目录,之后每次回到页面只刷新当前目录(重进 tab 不该丢位置重新拉全链)
|
||||
// 上传队列(全局 store):入队在本页、胶囊读它的进行中计数、守卫回调消费它的面包屑导航请求
|
||||
const uploadQueue = useUploadQueueStore();
|
||||
|
||||
// 首次显示拉根目录,之后每次回到页面只刷新当前目录(重进 tab 不该丢位置重新拉全链);
|
||||
// 回页末尾消费传输页的面包屑导航请求(reLaunch 重建后恢复到目标目录)
|
||||
let started = false;
|
||||
useAuthGuard(() => {
|
||||
useAuthGuard(async () => {
|
||||
if (started) {
|
||||
retry();
|
||||
return;
|
||||
await retry();
|
||||
}
|
||||
else {
|
||||
started = true;
|
||||
await init();
|
||||
}
|
||||
const trail = uploadQueue.takeNav();
|
||||
if (trail) {
|
||||
await openTrail(trail);
|
||||
}
|
||||
started = true;
|
||||
init();
|
||||
});
|
||||
|
||||
// ===== 页面状态(全部单向下发,组件只上报意图) =====
|
||||
@@ -102,11 +116,6 @@ function toast(title: string): void {
|
||||
uni.showToast({ title, icon: "none" });
|
||||
}
|
||||
|
||||
/** 待接入真实功能时的统一占位提示 */
|
||||
function todoTip(): void {
|
||||
toast(t("FilePage.todoTip"));
|
||||
}
|
||||
|
||||
// ===== 导航栏 / 面包屑 =====
|
||||
function onToggleSearch(): void {
|
||||
showSearch.value = !showSearch.value;
|
||||
@@ -334,20 +343,83 @@ function onSheetAction(key: string, file: FileItem): void {
|
||||
toast(`${file.name} · ${key} · ${t("FilePage.todoTip")}`);
|
||||
}
|
||||
|
||||
// 新建文件夹命名对话框(CreateDmsFolder 在途标记防连点)
|
||||
const folderDialogVisible = ref(false);
|
||||
const folderSubmitting = ref(false);
|
||||
|
||||
// 上传队列状态见文件头部的 uploadQueue store
|
||||
|
||||
/** 悬浮「+」:新建文件夹已拆到工具栏图标,这里直接选文件上传 */
|
||||
function onAdd(): void {
|
||||
todoTip();
|
||||
pickAndUpload();
|
||||
}
|
||||
|
||||
/** 工具栏「文件夹+」图标:弹新建文件夹命名对话框 */
|
||||
function onNewFolder(): void {
|
||||
folderDialogVisible.value = true;
|
||||
}
|
||||
|
||||
/** 名称限制对齐后端目录模型:不能含路径分隔符(FolderLocalName 直接参与路径拼接) */
|
||||
async function onCreateFolder(name: string): Promise<void> {
|
||||
if (/[\\/]/.test(name)) {
|
||||
toast(t("FilePage.folderInvalid"));
|
||||
return;
|
||||
}
|
||||
folderSubmitting.value = true;
|
||||
try {
|
||||
const entity = new DmsFileEntity();
|
||||
entity.FileName = name;
|
||||
entity.FilePath = pathStack.value[pathStack.value.length - 1]?.value ?? "";
|
||||
await dmsFileService.CreateDmsFolder(entity);
|
||||
folderDialogVisible.value = false;
|
||||
toast(t("FilePage.folderCreated"));
|
||||
// 新建完直接刷当前目录,不等切回页面才重查
|
||||
retry();
|
||||
}
|
||||
catch (error: any) {
|
||||
// 业务异常主拦截器已弹模态,这里只兜网络层失败
|
||||
if (error?.errMsg) {
|
||||
toast(error.errMsg);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
folderSubmitting.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 选文件→入队(快照面包屑链供传输页展示/跳回)→跳传输列表;之后用户跳走不影响上传 */
|
||||
async function pickAndUpload(): Promise<void> {
|
||||
try {
|
||||
const picked = await chooseFiles();
|
||||
if (!picked.length) {
|
||||
return;
|
||||
}
|
||||
uploadQueue.addFiles(picked, [...pathStack.value]);
|
||||
uni.navigateTo({ url: pageUrl("transport") });
|
||||
}
|
||||
catch (error: any) {
|
||||
toast(error?.errMsg || error?.message || t("FilePage.todoTip"));
|
||||
}
|
||||
}
|
||||
|
||||
function goTransport(): void {
|
||||
uni.navigateTo({ url: pageUrl("transport") });
|
||||
}
|
||||
|
||||
/** 胶囊内的自绘传输字形(白字蓝底,颜色固定,模块级生成一次) */
|
||||
const transferIconWhite = transferGlyph("#ffffff");
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 操作面板/多选操作栏展开时收起 tabbar:tabbar 在页面 fixed 层叠上下文之外,
|
||||
弹层 z-index 再高也压不住它,直接隐藏最干净(主流云盘同款交互) -->
|
||||
<app-page :hide-nav="true" :show-tabbar="atRoot && !actionFile && !selectMode">
|
||||
<app-page :hide-nav="true" :show-tabbar="atRoot && !actionFile && !selectMode && !folderDialogVisible">
|
||||
<view class="file-page" :style="{ background: themeBackground }">
|
||||
<!-- 上半屏整体固定,只有文件列表所在的 scroll-view 内部滚动(整页不滚) -->
|
||||
<view class="file-page__head">
|
||||
<page-navbar :title="navTitle" :show-back="!atRoot" :search-on="showSearch" :quick-on="showQuick" @back="onBack"
|
||||
@toggle-search="onToggleSearch" @toggle-quick="onToggleQuick" />
|
||||
<page-navbar :title="navTitle" :show-back="!atRoot" :search-on="showSearch" :quick-on="showQuick"
|
||||
:transferring="uploadQueue.uploadingCount" @back="onBack" @toggle-search="onToggleSearch"
|
||||
@toggle-quick="onToggleQuick" @transfer="goTransport" />
|
||||
<!-- 子目录态才有的路径条:白色衬底包住面包屑(外面不再是灰页面底),左起全量显示,溢出折叠 -->
|
||||
<view v-if="!atRoot" class="file-page__crumb">
|
||||
<file-breadcrumb :items="pathStack" @nav="onCrumbNav" />
|
||||
@@ -360,7 +432,8 @@ function onAdd(): void {
|
||||
<quick-entry :items="quickEntries" @click="onQuickClick" />
|
||||
</view>
|
||||
<file-tab-filter :tabs="tabs" :active="category" :view-mode="viewMode" :select-mode="selectMode"
|
||||
@change="onCategoryChange" @sort="onSort" @toggle-view="onToggleView" @toggle-select="onToggleSelect" />
|
||||
@change="onCategoryChange" @sort="onSort" @toggle-view="onToggleView" @toggle-select="onToggleSelect"
|
||||
@new-folder="onNewFolder" />
|
||||
<view v-if="selectMode" class="file-page__selection">
|
||||
<text class="file-page__selection-text">
|
||||
{{ t("FilePage.selectedCount", { count: selectedIds.length }) }}
|
||||
@@ -410,8 +483,17 @@ function onAdd(): void {
|
||||
</view>
|
||||
<!-- 多选态加号让位底部操作栏,避免两个悬浮物打架 -->
|
||||
<float-add-btn v-if="!selectMode" @click="onAdd" />
|
||||
<!-- 上传中悬浮胶囊:任意目录下一键回传输列表(任务在 store 里,跳走不中断) -->
|
||||
<view v-if="uploadQueue.uploadingCount && !selectMode" class="file-page__transfer" @click="goTransport">
|
||||
<image class="file-page__transfer-img" :src="transferIconWhite" mode="aspectFit" />
|
||||
<text class="file-page__transfer-text">
|
||||
{{ uploadQueue.uploadingCount }} {{ t("TransportPage.transferring") }}
|
||||
</text>
|
||||
</view>
|
||||
<file-action-sheet :visible="!!actionFile" :file="actionFile" @close="actionFile = null"
|
||||
@action="onSheetAction" />
|
||||
<folder-name-dialog :visible="folderDialogVisible" :submitting="folderSubmitting"
|
||||
@close="folderDialogVisible = false" @confirm="onCreateFolder" />
|
||||
<!-- 多选底部操作栏:常驻非模态(无遮罩),勾选与动作可交替进行;
|
||||
动作集是旧系统多选子集——共享/发布按同媒体类型条件,重命名/移动仅单选 -->
|
||||
<view v-if="selectMode" class="file-page__actions">
|
||||
@@ -493,6 +575,32 @@ function onAdd(): void {
|
||||
}
|
||||
}
|
||||
|
||||
/* 上传中悬浮胶囊:左下角常驻(避开右侧可拖动加号),点击回传输列表 */
|
||||
.file-page__transfer {
|
||||
position: fixed;
|
||||
bottom: 220rpx;
|
||||
left: 24rpx;
|
||||
z-index: 8;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
padding: 16rpx 28rpx;
|
||||
border-radius: 999rpx;
|
||||
background-color: rgba(41, 121, 255, 0.9);
|
||||
box-shadow: 0 6rpx 16rpx rgba(41, 121, 255, 0.35);
|
||||
}
|
||||
|
||||
.file-page__transfer-text {
|
||||
font-size: 24rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* 胶囊内自绘传输字形:与原文案图标同尺寸(26rpx) */
|
||||
.file-page__transfer-img {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
}
|
||||
|
||||
.file-page__selection {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in new issue
Block a user