From 1dc706654e0166e400085d2b2b0fe5ef06daf132 Mon Sep 17 00:00:00 2001 From: icssoa <615206459@qq.com> Date: Fri, 31 Oct 2025 11:28:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20cool-share=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=88=86=E4=BA=AB=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- pages/demo/other/share.uvue | 8 +- uni_modules/cool-share/index.d.ts | 3 +- .../cool-share/utssdk/app-android/index.uts | 60 ++-- .../cool-share/utssdk/app-harmony/index.uts | 3 +- .../cool-share/utssdk/app-harmony/share.ets | 46 +-- .../utssdk/app-ios/PrivacyInfo.xcprivacy | 14 + .../cool-share/utssdk/app-ios/config.json | 3 + .../cool-share/utssdk/app-ios/index.uts | 287 ++++++++++++++++++ uni_modules/cool-share/utssdk/interface.uts | 24 +- 10 files changed, 385 insertions(+), 65 deletions(-) create mode 100644 uni_modules/cool-share/utssdk/app-ios/PrivacyInfo.xcprivacy create mode 100644 uni_modules/cool-share/utssdk/app-ios/config.json create mode 100644 uni_modules/cool-share/utssdk/app-ios/index.uts diff --git a/package.json b/package.json index 61a7905..96f7757 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cool-unix", - "version": "8.0.29", + "version": "8.0.30", "license": "MIT", "scripts": { "build-ui": "node ./uni_modules/cool-ui/scripts/generate-types.js", diff --git a/pages/demo/other/share.uvue b/pages/demo/other/share.uvue index 8313f6f..a89cac4 100644 --- a/pages/demo/other/share.uvue +++ b/pages/demo/other/share.uvue @@ -29,7 +29,7 @@ function shareText() { shareWithSystem({ type: "text", title: "Cool Unix 是一个高效的项目脚手架", - summary: "", + summary: "Cool Unix 是一个高效的项目脚手架", success: () => { console.log("success"); }, @@ -42,7 +42,7 @@ function shareText() { function shareImage() { shareWithSystem({ type: "image", - imageUrl: "https://cool-js.com/logo.png", + url: "https://cool-js.com/logo.png", success: () => { console.log("success"); } @@ -52,7 +52,7 @@ function shareImage() { function shareFile() { shareWithSystem({ type: "file", - href: "https://show.cool-admin.com/用户导入模版.xlsx", + url: "https://show.cool-admin.com/用户导入模版.xlsx", success: () => { console.log("success"); } @@ -62,7 +62,7 @@ function shareFile() { function shareLink() { shareWithSystem({ type: "link", - href: "https://cool-js.com/", + url: "https://cool-js.com/", success: () => { console.log("success"); } diff --git a/uni_modules/cool-share/index.d.ts b/uni_modules/cool-share/index.d.ts index ef63c55..4dee4f9 100644 --- a/uni_modules/cool-share/index.d.ts +++ b/uni_modules/cool-share/index.d.ts @@ -3,8 +3,7 @@ declare module "@/uni_modules/cool-share" { type: "text" | "image" | "file" | "link" | "video" | "audio"; title?: string; summary?: string; - href?: string; - imageUrl?: string; + url?: string; success?: () => void; fail?: (error: string) => void; }): void; diff --git a/uni_modules/cool-share/utssdk/app-android/index.uts b/uni_modules/cool-share/utssdk/app-android/index.uts index bf43228..ce49450 100644 --- a/uni_modules/cool-share/utssdk/app-android/index.uts +++ b/uni_modules/cool-share/utssdk/app-android/index.uts @@ -169,24 +169,24 @@ function createFileUriAsync( /** * 创建图片分享 Intent(异步) - * @param imageUrl 图片路径(支持本地路径和网络 URL) + * @param url 图片路径(支持本地路径和网络 URL) * @param title 分享标题 * @param success 成功回调 * @param fail 失败回调 */ function createImageShareIntent( - imageUrl: string, + url: string, title: string, success: (intent: Intent) => void, fail: (error: string) => void ): void { - if (imageUrl == "") { + if (url == "") { fail("图片路径不能为空"); return; } createFileUriAsync( - imageUrl, + url, (uri: Uri) => { const intent = new Intent(Intent.ACTION_SEND); intent.setType(MimeTypes["IMAGE"] as string); @@ -203,24 +203,24 @@ function createImageShareIntent( /** * 创建视频分享 Intent(异步) - * @param videoUrl 视频路径(支持本地路径和网络 URL) + * @param url 视频路径(支持本地路径和网络 URL) * @param title 分享标题 * @param success 成功回调 * @param fail 失败回调 */ function createVideoShareIntent( - videoUrl: string, + url: string, title: string, success: (intent: Intent) => void, fail: (error: string) => void ): void { - if (videoUrl == "") { + if (url == "") { fail("视频路径不能为空"); return; } createFileUriAsync( - videoUrl, + url, (uri: Uri) => { const intent = new Intent(Intent.ACTION_SEND); intent.setType(MimeTypes["VIDEO"] as string); @@ -237,24 +237,24 @@ function createVideoShareIntent( /** * 创建音频分享 Intent(异步) - * @param audioUrl 音频路径(支持本地路径和网络 URL) + * @param url 音频路径(支持本地路径和网络 URL) * @param title 分享标题 * @param success 成功回调 * @param fail 失败回调 */ function createAudioShareIntent( - audioUrl: string, + url: string, title: string, success: (intent: Intent) => void, fail: (error: string) => void ): void { - if (audioUrl == "") { + if (url == "") { fail("音频路径不能为空"); return; } createFileUriAsync( - audioUrl, + url, (uri: Uri) => { const intent = new Intent(Intent.ACTION_SEND); intent.setType(MimeTypes["AUDIO"] as string); @@ -308,20 +308,20 @@ function createFileShareIntent( /** * 创建链接分享 Intent - * @param href 链接地址 + * @param url 链接地址 * @param title 分享标题 * @param summary 分享描述 * @param success 成功回调 * @param fail 失败回调 */ function createLinkShareIntent( - href: string, + url: string, title: string, summary: string, success: (intent: Intent) => void, fail: (error: string) => void ): void { - if (href == "") { + if (url == "") { fail("链接地址不能为空"); return; } @@ -334,8 +334,8 @@ function createLinkShareIntent( if (summary != "") { content = content == "" ? summary : content + "\n" + summary; } - if (href != "") { - content = content == "" ? href : content + "\n" + href; + if (url != "") { + content = content == "" ? url : content + "\n" + url; } const intent = new Intent(Intent.ACTION_SEND); @@ -349,13 +349,13 @@ function createLinkShareIntent( * 创建文本分享 Intent * @param title 分享标题 * @param summary 分享描述 - * @param href 附加链接(可选) + * @param url 附加链接(可选) * @param success 成功回调 */ function createTextShareIntent( title: string, summary: string, - href: string, + url: string, success: (intent: Intent) => void ): void { // 组合分享内容 @@ -366,8 +366,8 @@ function createTextShareIntent( if (summary != "") { content = content == "" ? summary : content + "\n" + summary; } - if (href != "") { - content = content == "" ? href : content + "\n" + href; + if (url != "") { + content = content == "" ? url : content + "\n" + url; } // 如果内容为空,使用默认文本 @@ -413,8 +413,7 @@ function startShareActivity( * @param options.type 分享类型: text(文本) | image(图片) | video(视频) | audio(音频) | file(文件) | link(链接) * @param options.title 分享标题 * @param options.summary 分享描述/内容 - * @param options.href 链接地址或文件路径 - * @param options.imageUrl 图片/视频/音频路径(支持本地路径和网络 URL) + * @param options.url 资源路径(图片/视频/音频/文件路径或链接地址,支持本地路径和网络 URL) * @param options.success 成功回调 * @param options.fail 失败回调 */ @@ -422,8 +421,7 @@ export function shareWithSystem(options: ShareWithSystemOptions): void { const type = options.type; const title = options.title ?? ""; const summary = options.summary ?? ""; - const href = options.href ?? ""; - const imageUrl = options.imageUrl ?? ""; + const url = options.url ?? ""; // 成功和失败回调 const onSuccess = (intent: Intent) => { @@ -445,17 +443,17 @@ export function shareWithSystem(options: ShareWithSystemOptions): void { // 根据分享类型创建对应的 Intent if (type == ShareType["IMAGE"]) { - createImageShareIntent(imageUrl, title, onSuccess, onFail); + createImageShareIntent(url, title, onSuccess, onFail); } else if (type == ShareType["VIDEO"]) { - createVideoShareIntent(imageUrl, title, onSuccess, onFail); + createVideoShareIntent(url, title, onSuccess, onFail); } else if (type == ShareType["AUDIO"]) { - createAudioShareIntent(imageUrl, title, onSuccess, onFail); + createAudioShareIntent(url, title, onSuccess, onFail); } else if (type == ShareType["FILE"]) { - createFileShareIntent(href, title, onSuccess, onFail); + createFileShareIntent(url, title, onSuccess, onFail); } else if (type == ShareType["LINK"]) { - createLinkShareIntent(href, title, summary, onSuccess, onFail); + createLinkShareIntent(url, title, summary, onSuccess, onFail); } else { // 默认为文本分享 - createTextShareIntent(title, summary, href, onSuccess); + createTextShareIntent(title, summary, url, onSuccess); } } diff --git a/uni_modules/cool-share/utssdk/app-harmony/index.uts b/uni_modules/cool-share/utssdk/app-harmony/index.uts index aa68117..c5dc9fb 100644 --- a/uni_modules/cool-share/utssdk/app-harmony/index.uts +++ b/uni_modules/cool-share/utssdk/app-harmony/index.uts @@ -6,8 +6,7 @@ export function shareWithSystem(options: ShareWithSystemOptions) { options.type, options.title ?? "", options.summary ?? "", - options.href ?? "", - options.imageUrl ?? "", + options.url ?? "", options.success ?? (() => {}), options.fail ?? (() => {}) ); diff --git a/uni_modules/cool-share/utssdk/app-harmony/share.ets b/uni_modules/cool-share/utssdk/app-harmony/share.ets index 1bc2745..78c7bbc 100644 --- a/uni_modules/cool-share/utssdk/app-harmony/share.ets +++ b/uni_modules/cool-share/utssdk/app-harmony/share.ets @@ -33,17 +33,17 @@ function getUtdTypeByPath(filePath: string, defaultType: string): string { /** * 创建图片分享数据 - * @param imageUrl 图片路径(支持本地路径和网络 URL) + * @param url 图片路径(支持本地路径和网络 URL) * @param title 分享标题 * @param summary 分享描述 * @returns 分享数据对象 */ -function createImageShareData(imageUrl: string, title: string, summary: string): systemShare.SharedData | null { - if (imageUrl === '') { +function createImageShareData(url: string, title: string, summary: string): systemShare.SharedData | null { + if (url === '') { return null; } - const filePath = UTSHarmony.getResourcePath(imageUrl); + const filePath = UTSHarmony.getResourcePath(url); const utdTypeId = getUtdTypeByPath(filePath, utd.UniformDataType.IMAGE); return new systemShare.SharedData({ @@ -56,17 +56,17 @@ function createImageShareData(imageUrl: string, title: string, summary: string): /** * 创建视频分享数据 - * @param videoUrl 视频路径(支持本地路径和网络 URL) + * @param url 视频路径(支持本地路径和网络 URL) * @param title 分享标题 * @param summary 分享描述 * @returns 分享数据对象 */ -function createVideoShareData(videoUrl: string, title: string, summary: string): systemShare.SharedData | null { - if (videoUrl === '') { +function createVideoShareData(url: string, title: string, summary: string): systemShare.SharedData | null { + if (url === '') { return null; } - const filePath = UTSHarmony.getResourcePath(videoUrl); + const filePath = UTSHarmony.getResourcePath(url); const utdTypeId = getUtdTypeByPath(filePath, utd.UniformDataType.VIDEO); return new systemShare.SharedData({ @@ -79,17 +79,17 @@ function createVideoShareData(videoUrl: string, title: string, summary: string): /** * 创建音频分享数据 - * @param audioUrl 音频路径(支持本地路径和网络 URL) + * @param url 音频路径(支持本地路径和网络 URL) * @param title 分享标题 * @param summary 分享描述 * @returns 分享数据对象 */ -function createAudioShareData(audioUrl: string, title: string, summary: string): systemShare.SharedData | null { - if (audioUrl === '') { +function createAudioShareData(url: string, title: string, summary: string): systemShare.SharedData | null { + if (url === '') { return null; } - const filePath = UTSHarmony.getResourcePath(audioUrl); + const filePath = UTSHarmony.getResourcePath(url); const utdTypeId = getUtdTypeByPath(filePath, utd.UniformDataType.AUDIO); return new systemShare.SharedData({ @@ -160,16 +160,16 @@ function createFileShareData(filePath: string, title: string, summary: string): /** * 创建链接分享数据 - * @param href 链接地址 + * @param url 链接地址 * @param title 分享标题 * @param summary 分享描述 * @returns 分享数据对象 */ -function createLinkShareData(href: string, title: string, summary: string): systemShare.SharedData { +function createLinkShareData(url: string, title: string, summary: string): systemShare.SharedData { return new systemShare.SharedData({ utd: utd.UniformDataType.HYPERLINK, title: title, - content: href, + content: url, description: summary }); } @@ -194,12 +194,11 @@ function createTextShareData(title: string, summary: string): systemShare.Shared * @param options.type 分享类型: text(文本) | image(图片) | video(视频) | audio(音频) | file(文件) | link(链接) * @param options.title 分享标题 * @param options.summary 分享描述/内容 - * @param options.href 链接地址或文件路径 - * @param options.imageUrl 图片/视频/音频路径(支持本地路径和网络 URL) + * @param options.url 资源路径(图片/视频/音频/文件路径或链接地址,支持本地路径和网络 URL) * @param options.success 成功回调 * @param options.fail 失败回调 */ -export function share(type: string, title: string, summary: string, href: string, imageUrl: string, success: () => void, fail: (error: string) => void): void { +export function share(type: string, title: string, summary: string, url: string, success: () => void, fail: (error: string) => void): void { // 获取UI上下文 const uiContext: UIContext = UTSHarmony.getCurrentWindow()?.getUIContext(); const context: common.UIAbilityContext = uiContext.getHostContext() as common.UIAbilityContext; @@ -210,32 +209,33 @@ export function share(type: string, title: string, summary: string, href: string switch (type) { case ShareType.IMAGE: - shareData = createImageShareData(imageUrl, title, summary); + shareData = createImageShareData(url, title, summary); errorMsg = '图片路径不能为空'; break; case ShareType.VIDEO: - shareData = createVideoShareData(imageUrl, title, summary); + shareData = createVideoShareData(url, title, summary); errorMsg = '视频路径不能为空'; break; case ShareType.AUDIO: - shareData = createAudioShareData(imageUrl, title, summary); + shareData = createAudioShareData(url, title, summary); errorMsg = '音频路径不能为空'; break; case ShareType.FILE: - shareData = createFileShareData(href, title, summary); + shareData = createFileShareData(url, title, summary); errorMsg = '文件路径不能为空'; break; case ShareType.LINK: - shareData = createLinkShareData(href, title, summary); + shareData = createLinkShareData(url, title, summary); break; default: // 默认为文本分享 shareData = createTextShareData(title, summary); + errorMsg = '分享内容不能为空'; break; } diff --git a/uni_modules/cool-share/utssdk/app-ios/PrivacyInfo.xcprivacy b/uni_modules/cool-share/utssdk/app-ios/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..5397adc --- /dev/null +++ b/uni_modules/cool-share/utssdk/app-ios/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + NSPrivacyTrackingDomains + + + diff --git a/uni_modules/cool-share/utssdk/app-ios/config.json b/uni_modules/cool-share/utssdk/app-ios/config.json new file mode 100644 index 0000000..74ed9c6 --- /dev/null +++ b/uni_modules/cool-share/utssdk/app-ios/config.json @@ -0,0 +1,3 @@ +{ + "deploymentTarget": "12" +} \ No newline at end of file diff --git a/uni_modules/cool-share/utssdk/app-ios/index.uts b/uni_modules/cool-share/utssdk/app-ios/index.uts new file mode 100644 index 0000000..8a30f58 --- /dev/null +++ b/uni_modules/cool-share/utssdk/app-ios/index.uts @@ -0,0 +1,287 @@ +import { UIActivityViewController, UIImage } from "UIKit"; +import { URL, Data } from "Foundation"; +import { ShareWithSystemOptions } from "../interface.uts"; + +/** + * 分享类型枚举 + */ +const ShareType = { + TEXT: "text", // 纯文本分享 + IMAGE: "image", // 图片分享 + VIDEO: "video", // 视频分享 + AUDIO: "audio", // 音频分享 + FILE: "file", // 文件分享 + LINK: "link" // 链接分享 +}; + +/** + * 判断是否为网络 URL + * @param url 地址 + * @returns 是否为网络 URL + */ +function isNetworkUrl(url: string): boolean { + return url.startsWith("http://") || url.startsWith("https://"); +} + +/** + * 下载网络文件到本地缓存 + * @param url 网络地址 + * @param success 成功回调,返回本地文件路径 + * @param fail 失败回调 + */ +function downloadNetworkFile( + url: string, + success: (localPath: string) => void, + fail: (error: string) => void +): void { + uni.downloadFile({ + url: url, + success: (res) => { + if (res.statusCode == 200) { + success(res.tempFilePath); + } else { + fail(`下载失败,状态码: ${res.statusCode}`); + } + }, + fail: (err) => { + fail(`下载失败: ${err.errMsg ?? "未知错误"}`); + } + }); +} + +/** + * 处理文件路径并加载数据 + * @param filePath 文件路径 + * @returns Data 对象或 null + */ +function loadFileData(filePath: string): Data | null { + const absolutePath = UTSiOS.convert2AbsFullPath(filePath); + const fileURL = new URL((fileURLWithPath = absolutePath)); + const data = UTSiOS.try(new Data((contentsOf = fileURL)), "?"); + return data; +} + +/** + * 创建文本分享内容 + * @param title 标题 + * @param summary 描述 + * @param url 链接 + * @returns 分享内容数组 + */ +function createTextShareItems(title: string, summary: string, url: string): any[] { + // 组合分享内容 + let content = ""; + if (title != "") { + content = title; + } + if (summary != "") { + content = content == "" ? summary : content + "\n" + summary; + } + if (url != "") { + content = content == "" ? url : content + "\n" + url; + } + + // 如果内容为空,使用默认文本 + if (content == "") { + content = "分享内容"; + } + + return [content]; +} + +/** + * 创建图片分享内容 + * @param url 图片路径 + * @param success 成功回调 + * @param fail 失败回调 + */ +function createImageShareItems( + url: string, + success: (items: any[]) => void, + fail: (error: string) => void +): void { + if (url == "") { + fail("图片路径不能为空"); + return; + } + + const handleImagePath = (localPath: string) => { + const absolutePath = UTSiOS.convert2AbsFullPath(localPath); + const image = new UIImage((contentsOfFile = absolutePath)); + + if (image == null) { + fail("图片加载失败"); + return; + } + + success([image]); + }; + + if (isNetworkUrl(url)) { + // 网络图片先下载 + downloadNetworkFile(url, handleImagePath, fail); + } else { + // 本地图片直接处理 + handleImagePath(url); + } +} + +/** + * 创建文件分享内容(视频、音频、文件) + * @param filePath 文件路径 + * @param success 成功回调 + * @param fail 失败回调 + */ +function createFileShareItems( + filePath: string, + success: (items: any[]) => void, + fail: (error: string) => void +): void { + if (filePath == "") { + fail("文件路径不能为空"); + return; + } + + const handleFilePath = (localPath: string) => { + const data = loadFileData(localPath); + + if (data == null) { + fail("文件加载失败"); + return; + } + + const absolutePath = UTSiOS.convert2AbsFullPath(localPath); + const fileURL = new URL.init((fileURLWithPath = absolutePath)); + + success([data, fileURL]); + }; + + if (isNetworkUrl(filePath)) { + // 网络文件先下载 + downloadNetworkFile(filePath, handleFilePath, fail); + } else { + // 本地文件直接处理 + handleFilePath(filePath); + } +} + +/** + * 启动系统分享界面 + * @param items 分享内容数组 + * @param success 成功回调 + * @param fail 失败回调 + */ +function presentShareController( + items: any[], + success: () => void, + fail: (error: string) => void +): void { + DispatchQueue.main.async( + (execute = (): void => { + const activityViewController = new UIActivityViewController( + (activityItems = items), + (applicationActivities = nil) + ); + + const currentVC = UTSiOS.getCurrentViewController(); + if (currentVC == null) { + fail("无法获取当前视图控制器"); + return; + } + + currentVC.present( + activityViewController, + (animated = true), + (completion = () => { + success(); + }) + ); + }) + ); +} + +/** + * 系统分享功能 + * @param options 分享参数 + * @param options.type 分享类型: text(文本) | image(图片) | video(视频) | audio(音频) | file(文件) | link(链接) + * @param options.title 分享标题 + * @param options.summary 分享描述/内容 + * @param options.url 资源路径(图片/视频/音频/文件路径或链接地址,支持本地路径和网络 URL) + * @param options.success 成功回调 + * @param options.fail 失败回调 + */ +export function shareWithSystem(options: ShareWithSystemOptions): void { + const type = options.type; + const title = options.title ?? ""; + const summary = options.summary ?? ""; + const url = options.url ?? ""; + + // 根据分享类型创建对应的内容 + if (type == (ShareType["TEXT"] as string) || type == (ShareType["LINK"] as string)) { + // 文本或链接分享 + const items = createTextShareItems(title, summary, url); + presentShareController( + items, + () => { + options.success?.(); + }, + (error: string) => { + options.fail?.(error); + } + ); + } else if (type == (ShareType["IMAGE"] as string)) { + // 图片分享 + createImageShareItems( + url, + (items: any[]) => { + presentShareController( + items, + () => { + options.success?.(); + }, + (error: string) => { + options.fail?.(error); + } + ); + }, + (error: string) => { + options.fail?.(error); + } + ); + } else if ( + type == (ShareType["VIDEO"] as string) || + type == (ShareType["AUDIO"] as string) || + type == (ShareType["FILE"] as string) + ) { + // 视频、音频、文件分享 + createFileShareItems( + url, + (items: any[]) => { + presentShareController( + items, + () => { + options.success?.(); + }, + (error: string) => { + options.fail?.(error); + } + ); + }, + (error: string) => { + options.fail?.(error); + } + ); + } else { + // 未知类型,默认使用文本分享 + const items = createTextShareItems(title, summary, url); + presentShareController( + items, + () => { + options.success?.(); + }, + (error: string) => { + options.fail?.(error); + } + ); + } +} diff --git a/uni_modules/cool-share/utssdk/interface.uts b/uni_modules/cool-share/utssdk/interface.uts index 15cfd4a..f46fb21 100644 --- a/uni_modules/cool-share/utssdk/interface.uts +++ b/uni_modules/cool-share/utssdk/interface.uts @@ -1,9 +1,29 @@ export type ShareWithSystemOptions = { + /** + * 分享类型: + * text(文本) | image(图片) | video(视频) | audio(音频) | file(文件) | link(链接) + */ type: string; + /** + * 分享标题 + */ title?: string; + /** + * 分享描述或内容 + */ summary?: string; - href?: string; - imageUrl?: string; + /** + * 分享资源路径: + * 如果是图片/视频/音频/文件,填写资源路径或网络URL + * 如果是link,填写链接地址 + */ + url?: string; + /** + * 分享成功回调 + */ success?: () => void; + /** + * 分享失败回调,返回错误信息 + */ fail?: (error: string) => void; };