mirror of
https://github.com/Hommy-master/capcut-mate.git
synced 2026-09-01 15:32:57 +08:00
解决应用程序在macos上访问权限的问题。
This commit is contained in:
@@ -192,6 +192,16 @@ curl -X POST "http://localhost:30000/openapi/capcut-mate/v1/add_videos" \
|
||||
|
||||
剪映小助手客户端提供了桌面端的便捷操作界面,以下是启动方法:
|
||||
|
||||
### macOS 沙箱权限说明
|
||||
|
||||
在 macOS 上运行时,应用可能会请求访问特定文件夹的权限。请按照以下步骤操作:
|
||||
|
||||
1. 如果首次运行时出现权限提示,请允许应用访问所需文件夹
|
||||
2. 如需手动配置,请前往 `系统偏好设置 > 安全性与隐私 > 隐私 > 文件夹访问`
|
||||
3. 确保 CapCut Mate 应用已被添加到允许列表中
|
||||
|
||||
更多详细信息,请参阅 [macOS 沙箱权限配置指南](./docs/macos_sandbox_setup.md)。
|
||||
|
||||
1. 安装依赖
|
||||
|
||||
```bash
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- Enable app sandbox -->
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
|
||||
<!-- File access permissions -->
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
|
||||
<!-- Access to user's Downloads folder -->
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
|
||||
<!-- Access to user's Documents folder -->
|
||||
<key>com.apple.security.files.documents.read-write</key>
|
||||
<true/>
|
||||
|
||||
<!-- Access to user's Pictures folder -->
|
||||
<key>com.apple.security.files.pictures.read-write</key>
|
||||
<true/>
|
||||
|
||||
<!-- Access to user's Music folder -->
|
||||
<key>com.apple.security.files.music.read-write</key>
|
||||
<true/>
|
||||
|
||||
<!-- Access to user's Movies folder -->
|
||||
<key>com.apple.security.files.movies.read-write</key>
|
||||
<true/>
|
||||
|
||||
<!-- Network access -->
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
|
||||
<!-- Hardware access for media files -->
|
||||
<key>com.apple.security.device.audio-input</key>
|
||||
<false/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
+18
-1
@@ -1,4 +1,4 @@
|
||||
const { app, BrowserWindow } = require('electron');
|
||||
const { app, BrowserWindow, dialog } = require('electron');
|
||||
const path = require('path');
|
||||
const logger = require('./nodeapi/logger');
|
||||
|
||||
@@ -67,6 +67,23 @@ function createWindow() {
|
||||
return mainWindow;
|
||||
}
|
||||
|
||||
// 处理未捕获的异常,特别是与文件权限相关的错误
|
||||
process.on('uncaughtException', (error) => {
|
||||
logger.error('未捕获的异常:', error);
|
||||
|
||||
// 在 macOS 沙箱环境下,某些权限错误可能在这里捕获
|
||||
if (process.platform === 'darwin' && error.message &&
|
||||
(error.message.includes('Operation not permitted') || error.message.includes('EPERM'))) {
|
||||
dialog.showMessageBoxSync({
|
||||
type: 'error',
|
||||
title: '权限错误',
|
||||
message: '应用缺少必要的文件访问权限,请检查系统偏好设置中的隐私与安全性设置。',
|
||||
detail: '请在 系统偏好设置 > 安全性与隐私 > 隐私 > 文件夹访问 中允许本应用访问相关文件夹。',
|
||||
buttons: ['确定']
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 当Electron完成初始化并准备创建浏览器窗口时调用此方法
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
|
||||
@@ -187,6 +187,24 @@ async function updateDraftPath(parentWindow) {
|
||||
return { success: false, error: "用户取消了目录选择" };
|
||||
}
|
||||
try {
|
||||
// 验证目录权限
|
||||
try {
|
||||
await fs.access(targetDir, fs.constants.R_OK | fs.constants.W_OK);
|
||||
} catch (accessError) {
|
||||
logger.error('所选目录无读写权限:', accessError);
|
||||
// 尝试使用 dialog 显示错误消息
|
||||
if (parentWindow) {
|
||||
const { dialog } = require('electron');
|
||||
await dialog.showMessageBox(parentWindow, {
|
||||
type: 'error',
|
||||
title: '权限不足',
|
||||
message: '所选目录没有足够的读写权限,请选择其他目录。',
|
||||
buttons: ['确定']
|
||||
});
|
||||
}
|
||||
return { success: false, error: '所选目录没有足够的读写权限' };
|
||||
}
|
||||
|
||||
const configPath = getConfigPath();
|
||||
let config = {};
|
||||
|
||||
@@ -215,15 +233,15 @@ async function getTargetDirectory(parentWindow = null, isUpdate = false) {
|
||||
let config = await readConfig();
|
||||
if (!isUpdate && config.targetDirectory) {
|
||||
try {
|
||||
await fs.access(config.targetDirectory);
|
||||
await fs.access(config.targetDirectory, fs.constants.R_OK | fs.constants.W_OK);
|
||||
return config.targetDirectory;
|
||||
} catch (accessErr) {
|
||||
logger.warn("配置的目录已不存在,将重新选择。");
|
||||
logger.warn("配置的目录已不存在或无访问权限,将重新选择。", accessErr.message);
|
||||
}
|
||||
}
|
||||
|
||||
const dialogOptions = {
|
||||
properties: ["openDirectory"],
|
||||
properties: ["openDirectory", "createDirectory"], // 允许创建新目录
|
||||
title: "请选择目标目录",
|
||||
buttonLabel: "选择此目录",
|
||||
defaultPath: isUpdate ? config.targetDirectory : undefined
|
||||
@@ -238,6 +256,24 @@ async function getTargetDirectory(parentWindow = null, isUpdate = false) {
|
||||
|
||||
if (!result.canceled && result.filePaths.length > 0) {
|
||||
const selectedDir = result.filePaths[0];
|
||||
|
||||
// 再次验证目录权限
|
||||
try {
|
||||
await fs.access(selectedDir, fs.constants.R_OK | fs.constants.W_OK);
|
||||
} catch (accessErr) {
|
||||
logger.error('所选目录无读写权限:', accessErr);
|
||||
if (parentWindow) {
|
||||
const { dialog } = require('electron');
|
||||
await dialog.showMessageBox(parentWindow, {
|
||||
type: 'error',
|
||||
title: '权限不足',
|
||||
message: '所选目录没有足够的读写权限,请重新选择。',
|
||||
buttons: ['确定']
|
||||
});
|
||||
}
|
||||
return ''; // 返回空字符串表示失败
|
||||
}
|
||||
|
||||
config.targetDirectory = selectedDir;
|
||||
await writeConfig(config);
|
||||
return selectedDir;
|
||||
@@ -477,7 +513,16 @@ async function downloadFiles(
|
||||
logger.info("[log] targetDir: " + targetDir);
|
||||
|
||||
// 3. 确保目标目录存在
|
||||
await fs.mkdir(targetDir, { recursive: true }); // recursive: true 可以创建多级目录
|
||||
try {
|
||||
await fs.mkdir(targetDir, { recursive: true }); // recursive: true 可以创建多级目录
|
||||
} catch (mkdirError) {
|
||||
logger.error(`创建目录失败: ${targetDir}`, mkdirError);
|
||||
await appendDownloadLog(
|
||||
{ level: "error", message: `创建目录失败: ${targetDir} - ${mkdirError.message}` },
|
||||
parentWindow
|
||||
);
|
||||
throw mkdirError;
|
||||
}
|
||||
// return { success: true, message: targetDir };
|
||||
|
||||
// 4. 下载文件
|
||||
|
||||
@@ -11,6 +11,10 @@ module.exports = {
|
||||
mac: {
|
||||
icon: "assets/icons/logo.icns",
|
||||
artifactName: "capcut-mate-macos-\${arch}-green.zip",
|
||||
hardenedRuntime: true,
|
||||
gatekeeperAssess: false,
|
||||
entitlements: "assets/entitlements.mac.plist",
|
||||
entitlementsInherit: "assets/entitlements.mac.plist"
|
||||
},
|
||||
files: [
|
||||
"!node_modules/**/*",
|
||||
|
||||
@@ -43,7 +43,11 @@ module.exports = {
|
||||
}
|
||||
],
|
||||
artifactName: "capcut-mate-macos-${arch}-installer.dmg",
|
||||
category: "public.app-category.productivity"
|
||||
category: "public.app-category.productivity",
|
||||
hardenedRuntime: true,
|
||||
gatekeeperAssess: false,
|
||||
entitlements: "assets/entitlements.mac.plist",
|
||||
entitlementsInherit: "assets/entitlements.mac.plist"
|
||||
},
|
||||
dmg: {
|
||||
background: null,
|
||||
|
||||
Reference in New Issue
Block a user