|
|
|
@ -3,6 +3,8 @@ const path = require("path"); |
|
|
|
const { v5: uuidv5 } = require("uuid"); |
|
|
|
const { Document } = require("../../models/documents"); |
|
|
|
const { DocumentSyncQueue } = require("../../models/documentSyncQueue"); |
|
|
|
const { userFromSession } = require("../http"); |
|
|
|
const { DeptDocument } = require("../../models/deptDocument"); |
|
|
|
const documentsPath = |
|
|
|
process.env.NODE_ENV === "development" |
|
|
|
? path.resolve(__dirname, `../../storage/documents`) |
|
|
|
@ -24,71 +26,221 @@ async function fileData(filePath = null) { |
|
|
|
return JSON.parse(data); |
|
|
|
} |
|
|
|
|
|
|
|
async function viewLocalFiles() { |
|
|
|
if (!fs.existsSync(documentsPath)) fs.mkdirSync(documentsPath); |
|
|
|
const liveSyncAvailable = await DocumentSyncQueue.enabled(); |
|
|
|
// async function viewLocalFiles() {
|
|
|
|
// if (!fs.existsSync(documentsPath)) fs.mkdirSync(documentsPath);
|
|
|
|
// const liveSyncAvailable = await DocumentSyncQueue.enabled();
|
|
|
|
// const directory = {
|
|
|
|
// name: "documents",
|
|
|
|
// type: "folder",
|
|
|
|
// items: [],
|
|
|
|
// };
|
|
|
|
// for (const file of fs.readdirSync(documentsPath)) {
|
|
|
|
// // console.log("file:", file);
|
|
|
|
// if (path.extname(file) === ".md") continue;
|
|
|
|
// const folderPath = path.resolve(documentsPath, file);
|
|
|
|
// const isFolder = fs.lstatSync(folderPath).isDirectory();
|
|
|
|
// if (isFolder) {
|
|
|
|
// const subdocs = {
|
|
|
|
// name: file,
|
|
|
|
// type: "folder",
|
|
|
|
// items: [],
|
|
|
|
// };
|
|
|
|
// const subfiles = fs.readdirSync(folderPath);
|
|
|
|
// const filenames = {};
|
|
|
|
// for (const subfile of subfiles) {
|
|
|
|
// if (path.extname(subfile) !== ".json") continue;
|
|
|
|
// const filePath = path.join(folderPath, subfile);
|
|
|
|
// const rawData = fs.readFileSync(filePath, "utf8");
|
|
|
|
// // console.log("rawData:", rawData);
|
|
|
|
// const cachefilename = `${file}/${subfile}`;
|
|
|
|
// const { pageContent, ...metadata } = JSON.parse(rawData);
|
|
|
|
// subdocs.items.push({
|
|
|
|
// name: subfile,
|
|
|
|
// type: "file",
|
|
|
|
// ...metadata,
|
|
|
|
// cached: await cachedVectorInformation(cachefilename, true),
|
|
|
|
// canWatch: liveSyncAvailable
|
|
|
|
// ? DocumentSyncQueue.canWatch(metadata)
|
|
|
|
// : false,
|
|
|
|
// // pinnedWorkspaces: [], // This is the list of workspaceIds that have pinned this document
|
|
|
|
// // watched: false, // boolean to indicate if this document is watched in ANY workspace
|
|
|
|
// });
|
|
|
|
// filenames[cachefilename] = subfile;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // Grab the pinned workspaces and watched documents for this folder's documents
|
|
|
|
// // at the time of the query so we don't have to re-query the database for each file
|
|
|
|
// const pinnedWorkspacesByDocument =
|
|
|
|
// await getPinnedWorkspacesByDocument(filenames);
|
|
|
|
// const watchedDocumentsFilenames =
|
|
|
|
// await getWatchedDocumentFilenames(filenames);
|
|
|
|
// for (const item of subdocs.items) {
|
|
|
|
// item.pinnedWorkspaces = pinnedWorkspacesByDocument[item.name] || [];
|
|
|
|
// item.watched =
|
|
|
|
// watchedDocumentsFilenames.hasOwnProperty(item.name) || false;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// directory.items.push(subdocs);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // Make sure custom-documents is always the first folder in picker
|
|
|
|
// directory.items = [
|
|
|
|
// directory.items.find((folder) => folder.name === "custom-documents"),
|
|
|
|
// ...directory.items.filter((folder) => folder.name !== "custom-documents"),
|
|
|
|
// ].filter((i) => !!i);
|
|
|
|
//
|
|
|
|
// return directory;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// async function viewLocalFiles(deptId) {
|
|
|
|
// const directory = {
|
|
|
|
// name: "documents",
|
|
|
|
// type: "folder",
|
|
|
|
// items: [],
|
|
|
|
// };
|
|
|
|
// if (!fs.existsSync(documentsPath)) fs.mkdirSync(documentsPath);
|
|
|
|
// const liveSyncAvailable = await DocumentSyncQueue.enabled();
|
|
|
|
//
|
|
|
|
// // 查询 deptDocuments
|
|
|
|
// const deptDocuments = await DeptDocument.where({ deptId: deptId, delTag: false });
|
|
|
|
// if (!deptDocuments || deptDocuments.length === 0) {
|
|
|
|
// return directory;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // 初始化分类对象
|
|
|
|
// const publicd = {
|
|
|
|
// name: "公开",
|
|
|
|
// type: "folder",
|
|
|
|
// items: [],
|
|
|
|
// };
|
|
|
|
// const privated = {
|
|
|
|
// name: "私有",
|
|
|
|
// type: "folder",
|
|
|
|
// items: [],
|
|
|
|
// };
|
|
|
|
// const temp = {
|
|
|
|
// name: "临时",
|
|
|
|
// type: "folder",
|
|
|
|
// items: [],
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// // 遍历 deptDocuments
|
|
|
|
// for (const doc of deptDocuments) {
|
|
|
|
// try {
|
|
|
|
// const filePath = doc.parsedFilePath; // 获取文件路径
|
|
|
|
// if (!fs.existsSync(filePath)) continue; // 如果文件不存在,跳过
|
|
|
|
//
|
|
|
|
// // 读取文件内容
|
|
|
|
// const rawData = fs.readFileSync(filePath, 'utf8');
|
|
|
|
// const { pageContent, ...metadata } = JSON.parse(rawData);
|
|
|
|
//
|
|
|
|
// // 构造文件信息对象(保持与原方法一致的字段)
|
|
|
|
// const fileInfo = {
|
|
|
|
// name: path.basename(filePath), // 文件名
|
|
|
|
// type: "file",
|
|
|
|
// ...metadata,
|
|
|
|
// cached: await cachedVectorInformation(filePath, true),
|
|
|
|
// canWatch: liveSyncAvailable
|
|
|
|
// ? DocumentSyncQueue.canWatch(metadata)
|
|
|
|
// : false,
|
|
|
|
// pinnedWorkspaces: [], // 初始化为空数组
|
|
|
|
// watched: false, // 初始化为 false
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// // 根据 isPublic 属性分类
|
|
|
|
// if (doc.isPublic === 0) {
|
|
|
|
// publicd.items.push(fileInfo);
|
|
|
|
// } else if (doc.isPublic === 1) {
|
|
|
|
// privated.items.push(fileInfo);
|
|
|
|
// } else {
|
|
|
|
// temp.items.push(fileInfo);
|
|
|
|
// }
|
|
|
|
// } catch (error) {
|
|
|
|
// console.error(`Error processing file ${doc.parsedFilePath}:`, error);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// directory.items = [publicd, privated, temp];
|
|
|
|
// // 返回嵌套结构
|
|
|
|
// return directory;
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
async function viewLocalFiles(deptId) { |
|
|
|
const directory = { |
|
|
|
name: "documents", |
|
|
|
type: "folder", |
|
|
|
items: [], |
|
|
|
}; |
|
|
|
// console.log("111111111111111111111111111111111111111111111111111111111111111111111111111111111");
|
|
|
|
for (const file of fs.readdirSync(documentsPath)) { |
|
|
|
// console.log("file:", file);
|
|
|
|
if (path.extname(file) === ".md") continue; |
|
|
|
const folderPath = path.resolve(documentsPath, file); |
|
|
|
const isFolder = fs.lstatSync(folderPath).isDirectory(); |
|
|
|
if (isFolder) { |
|
|
|
const subdocs = { |
|
|
|
name: file, |
|
|
|
if (!fs.existsSync(documentsPath)) fs.mkdirSync(documentsPath); |
|
|
|
const liveSyncAvailable = await DocumentSyncQueue.enabled(); |
|
|
|
|
|
|
|
// 查询 deptDocuments
|
|
|
|
const deptDocuments = await DeptDocument.where({ deptId: deptId, delTag: false }); |
|
|
|
if (!deptDocuments || deptDocuments.length === 0) { |
|
|
|
return directory; |
|
|
|
} |
|
|
|
|
|
|
|
// 初始化分类对象
|
|
|
|
const publicd = { |
|
|
|
name: "公开", |
|
|
|
type: "folder", |
|
|
|
items: [], |
|
|
|
}; |
|
|
|
const privated = { |
|
|
|
name: "私有", |
|
|
|
type: "folder", |
|
|
|
items: [], |
|
|
|
}; |
|
|
|
const temp = { |
|
|
|
name: "临时", |
|
|
|
type: "folder", |
|
|
|
items: [], |
|
|
|
}; |
|
|
|
const subfiles = fs.readdirSync(folderPath); |
|
|
|
const filenames = {}; |
|
|
|
for (const subfile of subfiles) { |
|
|
|
if (path.extname(subfile) !== ".json") continue; |
|
|
|
const filePath = path.join(folderPath, subfile); |
|
|
|
const rawData = fs.readFileSync(filePath, "utf8"); |
|
|
|
// console.log("rawData:", rawData);
|
|
|
|
const cachefilename = `${file}/${subfile}`; |
|
|
|
|
|
|
|
// 遍历 deptDocuments
|
|
|
|
for (const doc of deptDocuments) { |
|
|
|
try { |
|
|
|
const filePath = doc.parsedFilePath; // 获取文件路径
|
|
|
|
if (!fs.existsSync(filePath)) continue; // 如果文件不存在,跳过
|
|
|
|
|
|
|
|
// 读取文件内容
|
|
|
|
const rawData = fs.readFileSync(filePath, 'utf8'); |
|
|
|
const { pageContent, ...metadata } = JSON.parse(rawData); |
|
|
|
subdocs.items.push({ |
|
|
|
name: subfile, |
|
|
|
|
|
|
|
// 计算相对路径,并将路径分隔符统一为 `/`
|
|
|
|
const relativePath = path.relative(documentsPath, filePath).replace(/\\/g, '/'); |
|
|
|
|
|
|
|
// 构造文件信息对象(保持与原方法一致的字段)
|
|
|
|
const fileInfo = { |
|
|
|
name: path.basename(filePath), // 文件名
|
|
|
|
type: "file", |
|
|
|
...metadata, |
|
|
|
cached: await cachedVectorInformation(cachefilename, true), |
|
|
|
cached: await cachedVectorInformation(filePath, true), |
|
|
|
canWatch: liveSyncAvailable |
|
|
|
? DocumentSyncQueue.canWatch(metadata) |
|
|
|
: false, |
|
|
|
// pinnedWorkspaces: [], // This is the list of workspaceIds that have pinned this document
|
|
|
|
// watched: false, // boolean to indicate if this document is watched in ANY workspace
|
|
|
|
}); |
|
|
|
filenames[cachefilename] = subfile; |
|
|
|
} |
|
|
|
pinnedWorkspaces: [], // 初始化为空数组
|
|
|
|
watched: false, // 初始化为 false
|
|
|
|
relativePath: relativePath, // 新增字段:相对路径(使用 `/` 分隔符)
|
|
|
|
}; |
|
|
|
|
|
|
|
// Grab the pinned workspaces and watched documents for this folder's documents
|
|
|
|
// at the time of the query so we don't have to re-query the database for each file
|
|
|
|
const pinnedWorkspacesByDocument = |
|
|
|
await getPinnedWorkspacesByDocument(filenames); |
|
|
|
const watchedDocumentsFilenames = |
|
|
|
await getWatchedDocumentFilenames(filenames); |
|
|
|
for (const item of subdocs.items) { |
|
|
|
item.pinnedWorkspaces = pinnedWorkspacesByDocument[item.name] || []; |
|
|
|
item.watched = |
|
|
|
watchedDocumentsFilenames.hasOwnProperty(item.name) || false; |
|
|
|
// 根据 isPublic 属性分类
|
|
|
|
if (doc.isPublic === 0) { |
|
|
|
publicd.items.push(fileInfo); |
|
|
|
} else if (doc.isPublic === 1) { |
|
|
|
privated.items.push(fileInfo); |
|
|
|
} else { |
|
|
|
temp.items.push(fileInfo); |
|
|
|
} |
|
|
|
|
|
|
|
directory.items.push(subdocs); |
|
|
|
} catch (error) { |
|
|
|
console.error(`Error processing file ${doc.parsedFilePath}:`, error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Make sure custom-documents is always the first folder in picker
|
|
|
|
directory.items = [ |
|
|
|
directory.items.find((folder) => folder.name === "custom-documents"), |
|
|
|
...directory.items.filter((folder) => folder.name !== "custom-documents"), |
|
|
|
].filter((i) => !!i); |
|
|
|
|
|
|
|
directory.items = [publicd, privated, temp]; |
|
|
|
// 返回嵌套结构
|
|
|
|
return directory; |
|
|
|
} |
|
|
|
|
|
|
|
|