Sfoglia il codice sorgente

资源,右键菜单复制到功能调试

tanshanming 8 mesi fa
parent
commit
631a81d5eb

+ 2 - 1
.env.development

@@ -5,7 +5,8 @@ NODE_ENV = development
 VITE_TITLE = Snowy
 
 # 接口地址
-VITE_API_BASEURL = http://192.168.1.204:9003
+VITE_API_BASEURL = http://192.168.31.14:9003
+# VITE_API_BASEURL = http://192.168.31.6:9003
 
 # 本地端口
 VITE_PORT = 9000

+ 7 - 0
.vscode/settings.json

@@ -0,0 +1,7 @@
+{
+    "i18n-ally.localesPaths": [
+        "src/locales",
+        "public/tinymce/langs",
+        "src/locales/lang"
+    ]
+}

+ 0 - 2
src/snowy.js

@@ -33,10 +33,8 @@ export default {
 		app.config.globalProperties.$RESOURCE_CONFIG = reSourceConfig
 		app.config.globalProperties.$TOOL = tool
 		app.config.globalProperties.hasPerm = hasPerm
-		console.log('globalFunction==', globalFunction)
 		app.config.globalProperties.$file = globalFunction.file
 		for (let key in fileOperationPlugins) {
-			console.log('fileOperationPlugins==', key, fileOperationPlugins[key])
 			app.config.globalProperties[`$${key}`] = fileOperationPlugins[key]
 		}
 		// 注册常用组件

+ 36 - 0
src/utils/tool.js

@@ -63,6 +63,42 @@ tool.session = {
 	}
 }
 
+// cookie操作
+tool.cookie = {
+	set(name, value, options = {}) {
+		let expires = options.expires
+		if (typeof expires === 'number') {
+			const days = options.expires
+			const date = new Date()
+			date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000)
+			expires = options.expires = date
+		}
+		if (expires && expires.toUTCString) {
+			options.expires = expires.toUTCString()
+		}
+		value = encodeURIComponent(value)
+		let updatedCookie = name + '=' + value
+		for (const propName in options) {
+			updatedCookie += '; ' + propName
+			const propValue = options[propName]
+			if (propValue !== true) {
+				updatedCookie += '=' + propValue
+			}
+		}
+		document.cookie = updatedCookie
+		return updatedCookie
+	},
+	get(name) {
+		const matches = document.cookie.match(
+			new RegExp('(?:^|; )' + name.replace(/([.$?*|{}()[\]\\/+^])/g, '\\$1') + '=([^;]*)')
+		)
+		return matches ? decodeURIComponent(matches[1]) : undefined
+	},
+	remove(name) {
+		this.set(name, '', { expires: -1 })
+	}
+}
+
 // 千分符
 tool.groupSeparator = (num) => {
 	num = `${num}`

+ 2 - 0
src/views/auth/login/util.js

@@ -9,6 +9,8 @@ import routerUtil from '@/utils/routerUtil'
 
 export const afterLogin = async (loginToken) => {
 	tool.data.set('TOKEN', loginToken)
+	//cookie里添加 token
+	tool.cookie.set('token', loginToken)
 	// 获取登录的用户信息
 	const loginUser = await loginApi.getLoginUser()
 	const globalStore = useGlobalStore()

+ 0 - 1
src/views/myResource/common/FileTable.vue

@@ -318,7 +318,6 @@
 	const customRow = (record, index) => {
 		return {
 			onContextmenu: (event) => {
-				console.log('邮件右键事件', record, index)
 				// 阻止右键事件冒泡
 				event.cancelBubble = true
 				// xs 以上的屏幕

+ 4 - 4
src/views/myResource/file/box/contextMenu/Box.vue

@@ -30,7 +30,7 @@
 			<li class="right-menu-item" @click="handleShareFileBtnClick(selectedFile)" v-if="shareBtnShow">
 				<share-alt-outlined /> 分享
 			</li>
-			<!-- <li class="right-menu-item" @click="visible = false" v-if="downloadBtnShow">
+			<li class="right-menu-item" @click="visible = false" v-if="downloadBtnShow">
 				<a
 					target="_blank"
 					style="display: block; color: inherit"
@@ -39,7 +39,7 @@
 				>
 					<download-outlined /> 下载
 				</a>
-			</li> -->
+			</li>
 			<!-- 0-解压到当前文件夹, 1-自动创建该文件名目录,并解压到目录里, 3-手动选择解压目录 -->
 			<li class="right-menu-item unzip-menu-item" v-if="unzipBtnShow">
 				<folder-outlined /> 解压缩
@@ -73,13 +73,13 @@
 			<li class="right-menu-item" @click="handleClickFileEdit(selectedFile)" v-if="onlineEditBtnShow">
 				<edit-outlined /> 在线编辑
 			</li>
-			<!-- <li
+			<li
 				class="right-menu-item"
 				@click="$file.copyShareLink(selectedFile.shareBatchNum, selectedFile.extractionCode)"
 				v-if="copyLinkBtnShow"
 			>
 				<edit-outlined /> 复制链接
-			</li> -->
+			</li>
 			<li class="right-menu-item" @click="handleShowDetailInfo(selectedFile)" v-if="detailInfoBtnShow">
 				<file-outlined /> 文件详情
 			</li>

+ 227 - 136
src/views/myResource/file/dialog/copyFile/Dialog.vue

@@ -1,49 +1,43 @@
 <template>
+	<!-- 复制文件-选择目标路径 -->
 	<a-modal
 		title="选择目标路径"
-		v-model:visible="visible"
-		:maskClosable="false"
+		:visible="internalVisible"
+		:confirm-loading="sureBtnLoading"
 		@ok="handleDialogSure"
 		@cancel="handleDialogClose"
-		@afterVisibleChange="handleVisibleChange"
+		:afterClose="handleDialogClose"
+		:maskClosable="false"
 	>
-		<div class="dialog-content">
-			<div class="radio-group">
-				<a-radio-group v-model:value="isFerry" @change="toggleAdvanced">
-					<a-radio-button :value="0">系统内操作</a-radio-button>
-					<a-radio-button v-show="showFerry" :value="1">摆渡至内网</a-radio-button>
-				</a-radio-group>
+		<div class="dialog-div-custom">
+			<!-- 选择的目标路径 -->
+			<div class="target-path">
+				<span class="label">目标路径:</span>
+				<a-input class="content" v-model:value="targetPath" readonly size="small"></a-input>
 			</div>
-
-			<template v-if="advanced">
-				<div class="target-path">
-					<span class="label">目标路径:</span>
-					<a-input v-model:value="targetPath" readonly size="small" />
-				</div>
-
-				<a-spin :spinning="loading">
-					<a-directory-tree
-						:treeData="fileTree"
-						:fieldNames="{
-							children: 'children',
-							title: 'label'
-						}"
-						:defaultExpandedKeys="defaultExpandedKeys"
-						@select="handleNodeClick"
-					>
-						<template #title="{ node, data }">
-							<div class="custom-tree-node">
-								<span class="label">{{ node.title }}</span>
-								<a-button type="link" size="small" class="add-folder-btn" @click.stop="handleAddFolderBtnClick(data)">
-									新建文件夹
-								</a-button>
-							</div>
-						</template>
-					</a-directory-tree>
-				</a-spin>
-			</template>
+			<!-- 文件目录树 -->
+			<a-spin :spinning="loading">
+				<a-tree
+					:tree-data="fileTree"
+					:field-names="{ children: 'children', title: 'label', key: 'id' }"
+					highlight-current
+					:expandedKeys="defaultExpandedKeys"
+					@update:expandedKeys="(val) => (defaultExpandedKeys = val)"
+					node-key="id"
+					@select="handleNodeClick"
+					:showLine="true"
+				>
+					<template #title="{ dataRef }">
+						<span class="custom-tree-node">
+							<span class="label">{{ dataRef.label }}</span>
+							<a-button class="add-folder-btn" type="link" size="small" @click.stop="handleAddFolderBtnClick(dataRef)">
+								新建文件夹
+							</a-button>
+						</span>
+					</template>
+				</a-tree>
+			</a-spin>
 		</div>
-
 		<template #footer>
 			<a-button @click="handleDialogClose">取 消</a-button>
 			<a-button type="primary" :loading="sureBtnLoading" @click="handleDialogSure"> 确 定 </a-button>
@@ -52,172 +46,269 @@
 </template>
 
 <script setup>
-	import { ref, onMounted } from 'vue'
+	import { ref, getCurrentInstance, watch } from 'vue'
+	import { getFoldTree, copyFile } from '@/api/myResource/file.js'
 	import { message } from 'ant-design-vue'
-	import { getFoldTree, copyFile, getFerryStatus } from '@/api/myResource/file'
 	const { proxy } = getCurrentInstance()
+
 	const props = defineProps({
-		fileInfo: Object,
-		callback: Function
+		visible: {
+			type: Boolean,
+			default: false
+		},
+		fileInfo: {
+			type: Object,
+			default: () => ({})
+		}
 	})
 
-	const visible = ref(false)
-	const targetPath = ref('/')
-	const fileTree = ref([])
-	const loading = ref(false)
-	const isFerry = ref(0)
-	const advanced = ref(true)
-	const showFerry = ref(false)
+	const emit = defineEmits(['update:visible', 'cancel', 'confirm'])
+	const internalVisible = ref(props.visible) // 使用 internalVisible 作为主要的响应式状态
+	const targetPath = ref('/') //  目标路径
+	const fileTree = ref([]) //  文件夹目录树
+	const loading = ref(false) //  文件夹目录树 loading 状态
 	const defaultExpandedKeys = ref([])
-	const sureBtnLoading = ref(false)
+	const sureBtnLoading = ref(false) //  确定按钮 loading 状态
 
-	const getFerryStatusData = async () => {
-		const res = await getFerryStatus()
-		showFerry.value = res.data
-	}
+	watch(
+		internalVisible, // 监听内部的 internalVisible ref
+		(newVal, oldVal) => {
+			// console.log('Dialog.vue: internalVisible watcher. New:', newVal, 'Old:', oldVal);
+			if (newVal && !oldVal) {
+				// 仅在从 false 变为 true 时调用,即对话框打开时
+				handleDialogOpen()
+			}
+		}
+	)
 
-	const toggleAdvanced = () => {
-		advanced.value = isFerry.value === 0
-	}
+	// 如果父组件通过 prop 更新 visible,也需要同步到 internalVisible
+	watch(
+		() => props.visible,
+		(newVal) => {
+			// console.log('Dialog.vue: props.visible watcher. New:', newVal);
+			internalVisible.value = newVal
+		}
+	)
 
+	/**
+	 * 取消按钮点击事件 & 对话框关闭的回调
+	 */
 	const handleDialogClose = () => {
-		visible.value = false
-		props.callback('cancel')
+		internalVisible.value = false
+		emit('update:visible', false) // 如果父组件需要 .sync 修饰符或者 v-model:visible
+		emit('cancel')
 	}
 
-	const handleVisibleChange = (val) => {
-		if (val) {
-			initFileTree()
-		}
+	/**
+	 * 对话框打开的回调
+	 */
+	const handleDialogOpen = () => {
+		// console.log('Dialog.vue: handleDialogOpen called');
+		initFileTree()
+		targetPath.value = '/' // 重置目标路径
 	}
 
+	/**
+	 * 初始化文件目录树
+	 */
 	const initFileTree = async (id) => {
+		console.log('复制到')
+		loading.value = true
 		try {
-			loading.value = true
 			const res = await getFoldTree()
 			if (res.success) {
 				fileTree.value = [res.data]
-				defaultExpandedKeys.value = id ? [id] : [fileTree.value[0].id]
+				defaultExpandedKeys.value = id ? [id] : fileTree.value.length > 0 ? [fileTree.value[0].id] : []
 			} else {
 				message.error(res.message)
 			}
+		} catch (error) {
+			message.error('获取文件夹树失败')
+			console.error(error)
 		} finally {
 			loading.value = false
 		}
 	}
 
-	const handleNodeClick = (selectedKeys, { node }) => {
-		targetPath.value = node.filePath || '/'
+	/**
+	 * 目录树节点点击回调函数
+	 * @param {Array} selectedKeys 当前选中的节点的 key
+	 * @param {object} e event 对象,包含 {selected: bool, selectedNodes, node, event}
+	 */
+	const handleNodeClick = (selectedKeys, e) => {
+		if (e.node && e.node.dataRef) {
+			targetPath.value = e.node.dataRef.filePath ? e.node.dataRef.filePath : '/'
+		}
 	}
 
+	/**
+	 * 新建文件夹按钮点击事件
+	 * @description 调用新建文件夹服务,并在弹窗确认回调事件中刷新文件夹树
+	 */
 	const handleAddFolderBtnClick = async (data) => {
-		const result = await proxy.$openDialog.addFolder({
-			filePath: data.filePath || '/'
-		})
-		if (result === 'confirm') {
+		try {
+			// $openDialog 假设是全局挂载的,通过 proxy 访问
+			// 您需要确保 proxy.$openDialog.addFolder 返回一个 Promise
+			await proxy.$openDialog.addFolder({
+				filePath: data.filePath || '/'
+			})
 			initFileTree(data.id)
+		} catch (error) {
+			// 如果 addFolder reject 或者用户取消,这里可以捕获
+			// message.info('取消新建文件夹');
+			console.log('Add folder cancelled or failed', error)
 		}
 	}
 
+	/**
+	 * 确定按钮点击事件
+	 * @description 调用复制文件接口
+	 */
 	const handleDialogSure = async () => {
+		sureBtnLoading.value = true
+		let data = {
+			filePath: targetPath.value,
+			userFileIds: props.fileInfo.userFileId // 假设父组件通过 prop 传递 fileInfo
+		}
 		try {
-			sureBtnLoading.value = true
-			const res = await copyFile({
-				filePath: targetPath.value,
-				userFileIds: props.fileInfo.userFileId,
-				isFerry: isFerry.value
-			})
-
+			const res = await copyFile(data)
 			if (res.success) {
 				message.success('复制成功')
-				visible.value = false
-				props.callback('confirm')
+				internalVisible.value = false
+				emit('update:visible', false)
+				emit('confirm')
 			} else {
 				message.error(res.message)
 			}
+		} catch (error) {
+			message.error('复制文件失败')
+			console.error(error)
 		} finally {
 			sureBtnLoading.value = false
 		}
 	}
 
-	onMounted(() => {
-		getFerryStatusData()
-	})
-
+	// 暴露给模板或者父组件(如果需要ref访问)
 	defineExpose({
-		visible
+		visible: internalVisible // 暴露 internalVisible
 	})
 </script>
 
 <style lang="less" scoped>
+	// 假设 varibles.less 和 mixins.less 在 @/style/myResource/ 目录下
+	// 并且包含 $Primary 和 setScrollbar 的 Less 等效定义
 	@import '@/style/myResource/varibles.less';
+	@import '@/style/myResource/mixins.less';
 
-	.dialog-content {
-		height: 300px;
-		overflow: auto;
-
-		.radio-group {
-			margin-bottom: 20px;
+	// 使用 ::v-deep 替代 >>>
+	:deep(.ant-modal) {
+		.ant-modal-header {
+			display: flex; // antd 默认就是 flex,可能不需要
 		}
 
-		.target-path {
-			display: flex;
-			align-items: center;
-			margin-bottom: 16px;
+		.ant-modal-body {
+			padding: 10px 30px;
 
-			.label {
-				width: 80px;
-			}
+			.dialog-div-custom {
+				// 修改类名以避免与 antd 内部类名冲突
+				height: 300px;
+				overflow: auto;
+				// .setScrollbar(6px); // 假设 setScrollbar 是一个 mixin
+				// 示例:自定义滚动条样式 (需要浏览器支持)
+				&::-webkit-scrollbar {
+					width: 6px;
+				}
+				&::-webkit-scrollbar-thumb {
+					background: #ccc; // 滚动条颜色
+					border-radius: 3px;
+				}
+				&::-webkit-scrollbar-track {
+					background: #f1f1f1; // 轨道颜色
+				}
 
-			.ant-input {
-				flex: 1;
-			}
-		}
+				.target-path {
+					display: flex;
+					align-items: center;
+					margin-bottom: 10px; // 增加一些间距
 
-		.custom-tree-node {
-			width: 100%;
-			display: flex;
-			align-items: center;
-			justify-content: space-between;
+					.label {
+						width: 80px;
+						flex-shrink: 0; // 防止被压缩
+					}
 
-			.add-folder-btn {
-				display: none;
-			}
+					.content {
+						flex: 1;
+					}
+				}
+
+				.ant-tree {
+					.ant-tree-treenode {
+						width: 100%;
+						border: 1px solid red;
+						// antd v4+ 使用 .ant-tree-treenode
+						.ant-tree-node-content-wrapper {
+							height: 34px;
+							font-size: 16px;
+							display: flex; // 确保自定义内容能正确布局
+							align-items: center;
+						}
+						&:hover {
+							.add-folder-btn {
+								color: yellow;
+								display: inline-block; // 或者 block,取决于布局需求
+							}
+						}
 
-			&:hover .add-folder-btn {
-				display: inline-block;
+						.ant-tree-switcher .ant-tree-switcher-icon svg {
+							font-size: 18px; // 调整展开/折叠图标大小
+						}
+
+						.custom-tree-node {
+							flex: 1;
+							display: flex;
+							align-items: center;
+							justify-content: space-between;
+							font-size: 14px;
+							padding-right: 8px;
+
+							.add-folder-btn {
+								color: #000000;
+								display: none; // 默认隐藏
+								margin-left: 8px; // 给按钮一些左边距
+							}
+						}
+					}
+
+					// antd 中选中的节点样式由 ant-tree-node-selected 控制
+					.ant-tree-treenode.ant-tree-node-selected > .ant-tree-node-content-wrapper {
+						// color: @Primary; // 假设 @Primary 是从 varibles.less 导入的主题色
+						// antd 默认有选中色,如果需要覆盖,可以在这里设置
+					}
+				}
 			}
 		}
 	}
-
-	.ant-btn-primary {
-		&,
-		&:hover,
-		&:focus {
-			background-color: @primary-color;
-			border-color: @primary-color;
-		}
+	:deep(.ant-tree .ant-tree-treenode .custom-tree-node) {
+		display: flex;
+		justify-content: space-between;
+		width: 100%;
 	}
 
-	.ant-btn {
-		&:hover,
-		&:focus {
-			background-color: @hover-color;
-			border-color: @hover-color;
-			color: white;
-		}
+	:deep(.ant-tree .ant-tree-treenode:hover .custom-tree-node .add-folder-btn) {
+		color: #29175b !important;
+		display: inline-block !important;
 	}
 
-	.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected {
-		color: @primary-color;
+	:deep(.ant-tree .ant-tree-treenode .custom-tree-node .add-folder-btn) {
+		color: green;
+		display: none !important;
+		margin-left: 8px;
 	}
-
-	.ant-radio-button-wrapper-checked {
-		color: @primary-color !important;
-		border-color: @primary-color !important;
-
-		&::before {
-			background-color: @primary-color !important;
+	:deep(.ant-tree) {
+		.ant-tree-treenode,
+		.ant-tree-node-content-wrapper,
+		.ant-tree-title {
+			width: 100%;
 		}
 	}
 </style>

+ 1 - 1
vite.config.js

@@ -53,7 +53,7 @@ export default defineConfig(({ command, mode }) => {
 			port: envConfig.VITE_PORT,
 			proxy: {
 				'/api': {
-					target: envConfig.VITE_API_BASEURL,
+					target: 'http://192.168.31.14:9003',
 					ws: false,
 					changeOrigin: true
 					// rewrite: (path) => path.replace(/^\/api/, '')