first commit

This commit is contained in:
2026-06-02 10:42:33 +08:00
commit dd4975fd2c
1084 changed files with 442416 additions and 0 deletions

11
unpackage/dist/build/.nvue/app.css.js vendored Normal file
View File

@@ -0,0 +1,11 @@
var __getOwnPropNames = Object.getOwnPropertyNames;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var require_app_css = __commonJS({
"app.css.js"(exports) {
const _style_0 = {};
exports.styles = [_style_0];
}
});
export default require_app_css();

2
unpackage/dist/build/.nvue/app.js vendored Normal file
View File

@@ -0,0 +1,2 @@
Promise.resolve("./app.css.js").then(() => {
});

View File

@@ -0,0 +1,206 @@
// @ts-nocheck
import Intent from 'android.content.Intent';
import ClipData from 'android.content.ClipData';
import Uri from 'android.net.Uri';
import InputStream from 'java.io.InputStream';
import OpenableColumns from 'android.provider.OpenableColumns';
import Cursor from 'android.database.Cursor';
import File from 'java.io.File';
import FileInputStream from 'java.io.FileInputStream';
import FileOutputStream from 'java.io.FileOutputStream';
import BufferedOutputStream from 'java.io.BufferedOutputStream';
import ByteArrayInputStream from 'java.io.ByteArrayInputStream';
import { ChooseFileOption, ChooseFile, ChooseFileSuccessCallbackResult } from '../interface'
import { GeneralCallbackResultImpl } from '../unierror'
const REQUEST_CODE_CHOOSE_FILE : Int = 42
let resultFunction : ((requestCode : Int, resultCode : Int, data ?: Intent) => void) | null = null
class ChooseFileImpl implements ChooseFile {
name : string = ''
path : string = ''
// private _path : string = ''
size : number = 0
time : number = 0
type : string = 'file'
// private uri : Uri
private options: ChooseFileOption
constructor(uri : Uri, options : ChooseFileOption) {
// this.uri = uri
this.options = options
this.time = Date.now()
this.type = this.getFileTypeFromUri(uri);
// this._path = uri.getPath() ?? ''
this.getFileInfoFromUri(uri)
if (this.isCache(options)) {
this.copyFileToCache(uri)
}
}
private isCache(options : ChooseFileOption) : boolean {
const extension = this.getFileExtension(this.name)
const extensions = options.extension
const type = options.type ?? 'all'
const hasExtension = extensions != null && extension != '' && extensions.includes(extension)
const isVideoOrImage = ['video', 'image'].includes(type)
const isFileAndNotVideoOrImage = type == 'file' && !['video', 'image'].includes(this.type);
if ((type == 'all' || isVideoOrImage || isFileAndNotVideoOrImage) && !hasExtension) {
return true
} else {
return false
}
}
private getFileExtension(fileName : string) : string {
const lastDotIndex = fileName.lastIndexOf(".");
if (lastDotIndex == -1) {
return "";
}
return fileName.substring(lastDotIndex + 1);
}
private copyFileToCache(uri : Uri) {
const cacheDir = UTSAndroid.getAppCachePath();
const context = UTSAndroid.getAppContext();
if(cacheDir != null) {
const path = new File(cacheDir);
if (!path.exists()) {
path.mkdir();
}
}
let fileName = this.name
if(this.options.filename != null) {
fileName = this.options.filename!;
if(this.options.count != null && this.options.count! > 1) {
fileName = `${fileName}_${Date.now()}`;
}
const extension = this.getFileExtension(this.name)
fileName = `${fileName}.${extension}`
}
const destFile = new File(cacheDir, fileName);
try {
const inputStream = context!.getContentResolver().openInputStream(uri)
const outputStream = new FileOutputStream(destFile)
if (inputStream != null) {
let buffer = ByteArray(1024);
let c = inputStream.read(buffer)
while (c > 0) {
outputStream.write(buffer, 0, c);
c = inputStream.read(buffer)
}
}
this.path = cacheDir + fileName//this.name
} catch (e) {
}
}
private getFileTypeFromUri(uri : Uri) : string {
const context = UTSAndroid.getAppContext();
let fileType = 'file'
let mimeType = context!.getContentResolver().getType(uri);
if (mimeType != null) {
if (mimeType.startsWith("video")) {
fileType = "video";
} else if (mimeType.startsWith("image")) {
fileType = "image";
}
}
return fileType;
}
private getFileInfoFromUri(uri : Uri) {
const context = UTSAndroid.getAppContext();
let cursor = context!.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
this.name = cursor.getString(cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME))
const fileSize = cursor.getLong(cursor.getColumnIndexOrThrow(OpenableColumns.SIZE));
this.size = Number.from(fileSize)
cursor.close();
} else if ("file".equals(uri.getScheme())) {
this.name = uri.getLastPathSegment() ?? '';
const file = new File(uri.getPath() ?? '');
const fileSize = file.length();
this.size = Number.from(fileSize)
}
}
}
export function chooseFile(options : ChooseFileOption) {
if (resultFunction != null) {
UTSAndroid.offAppActivityResult(resultFunction!)
}
const type = options.type ?? 'all'
const intent = new Intent(Intent.ACTION_GET_CONTENT);
if (type.equals("all") || type.equals("file")) {
intent.setType("*/*");
} else if (type.equals("video")) {
intent.setType("video/*");
} else if (type.equals("image")) {
intent.setType("image/*");
}
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, options.count == 1 ? false : true); // 允许多选
resultFunction = (requestCode : Int, resultCode : Int, data ?: Intent) => {
if (requestCode == REQUEST_CODE_CHOOSE_FILE) {
UTSAndroid.offAppActivityResult(resultFunction!);
if (resultCode == -1 && data != null) {
const clipData = data.getClipData();
const tempFiles : ChooseFile[] = []
if (clipData != null) {
// 多选
// const itemCount = clipData.getItemCount();
// if (options.count != null && options.count! > itemCount) {
// const err = new GeneralCallbackResultImpl(9010002, `选中文件数量超过${options.count}`)
// options.fail?.(err)
// options.complete?.(err)
// return
// }
for (let i = 0; i < clipData.getItemCount(); i++) {
const uri = clipData.getItemAt(i.toInt()).getUri();
const chooseFile = new ChooseFileImpl(uri, options);
if(chooseFile.path !=''){
tempFiles.push(chooseFile)
}
}
} else {
// 单选
const uri = data.getData();
if (uri != null) {
const chooseFile = new ChooseFileImpl(uri, options)
if(chooseFile.path !='' ){
tempFiles.push(chooseFile)
}
}
}
const count = options.count ?? Integer.MAX_VALUE // Number.MAX_VALUE
if(tempFiles.length > 0 && count >= tempFiles.length){
options.success?.({
tempFiles,
errMsg: 'chooseFile:ok'
} as ChooseFileSuccessCallbackResult)
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件或文件超过设置数量`)
options.fail?.(err)
options.complete?.(err)
}
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件`)
options.fail?.(err)
options.complete?.(err)
}
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件`)
options.fail?.(err)
options.complete?.(err)
}
}
UTSAndroid.onAppActivityResult(resultFunction!)
UTSAndroid.getUniActivity()!.startActivityForResult(Intent.createChooser(intent, "选择文件"), REQUEST_CODE_CHOOSE_FILE)
// UTSAndroid.getUniActivity()!.overridePendingTransition((10).toInt(), (0).toInt());
}

View File

@@ -0,0 +1,138 @@
// @ts-nocheck
import { ChooseFileOption, ChooseFile, ChooseFileSuccessCallbackResult } from '../interface'
import { UIDocumentPickerDelegate, UIDocumentPickerMode } from "UIKit"
import { URL, FileManager } from 'Foundation';
import { GeneralCallbackResultImpl } from '../unierror'
import { DispatchQueue } from 'Dispatch';
const documentTypes : Map<string, string[]> = new Map([
["all", ["public.item"]],
["file", [
"public.text",
"public.zip-archive",
"public.data",
"com.adobe.pdf",
"com.microsoft.word.doc",
"com.microsoft.word.docx",
"com.microsoft.excel.xls",
"com.microsoft.excel.xlsx"
]
],
["video", ["public.movie"]],
["image", ["public.image"]],
])
class ChooseFileImpl {
name : string = ''
path : string = ''
size : number = 0
time : number = 0
type : string = 'file'
constructor(uri : URL, options : ChooseFileOption) {
try {
const originalFileName = uri.lastPathComponent;
const attributes = UTSiOS.try(FileManager.default.attributesOfItem(atPath = uri.path))
const fileSize = attributes[FileAttributeKey.size] as number
const pathExtension = `${uri.pathExtension}`
const imageFormats = ['jpeg', 'jpg', 'png', 'gif', 'bmp', 'tiff', 'svg']
const videoFormats = ['mov', 'm4v', 'mp4', 'avi']
let fileName = originalFileName
if(options.filename != null) {
fileName = options.filename!
if(options.count != null && options.count! > 1) {
fileName = `${fileName}_${Date.now()}`;
}
fileName = `${fileName}.${pathExtension}`
}
const dataPath = UTSiOS.getDataPath().replace(/data$/, "doc");
const file = new URL(fileURLWithPath = dataPath).appendingPathComponent(fileName)//.absoluteString
const fileData = FileManager.default.contents(atPath = uri.path);
UTSiOS.try(fileData?.write(to = file))
if (imageFormats.includes(pathExtension)) {
this.type = 'image'
} else if (videoFormats.includes(pathExtension)) {
this.type = 'video'
} else {
this.type = 'file'
}
this.name = `${originalFileName}`
this.size = fileSize
this.path = `${file.absoluteString}`
} catch (e) {
}
}
}
class FilePickerManager implements UIDocumentPickerDelegate {
options : ChooseFileOption = {}
constructor() { }
chooseFile(options : ChooseFileOption) {
DispatchQueue.main.async(execute = () : void => {
this.options = options
const type = options.type ?? 'all'
const count = options.count ?? 1
const types = (documentTypes.get(type) ?? documentTypes.get('all')) as string[]
let documentPicker = UIDocumentPickerViewController(
documentTypes = types,
in = UIDocumentPickerMode.import
)
documentPicker.delegate = this
// 多选要大于 ios11
if (UTSiOS.available("iOS 11.0, *")) {
documentPicker.allowsMultipleSelection = count > 1
}
UTSiOS.getCurrentViewController().present(documentPicker, animated = true)
})
}
documentPicker(controller : UIDocumentPickerViewController, @argumentLabel("didPickDocumentsAt") urls : URL[]) {
DispatchQueue.main.async(execute = () : void => {
const tempFiles : ChooseFile[] = []
for (let i = 0; i < urls.length; i++) {
const url = urls[i]
const chooseFile = new ChooseFileImpl(url, this.options);
// IOS -> js 无法传class?
const file : ChooseFile = {
name: chooseFile.name,
path: chooseFile.path,
size: chooseFile.size,
time: chooseFile.time,
type: chooseFile.type,
}
if (chooseFile.path != '') {
tempFiles.push(file)
}
}
const count = this.options.count ?? Number.from(Double.greatestFiniteMagnitude) //Number.from(Double.MAX_VALUE)
if (tempFiles.length > 0 && count >= tempFiles.length) {
const res : ChooseFileSuccessCallbackResult = {
tempFiles,
errMsg: 'chooseFile:ok'
}
this.options.success?.(res)
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件或文件超过设置数量`)
this.options.fail?.(err)
this.options.complete?.(err)
}
})
}
}
const fileManager = new FilePickerManager()
export function chooseFile(options : ChooseFileOption) {
fileManager.chooseFile(options)
}

View File

@@ -0,0 +1,35 @@
// @ts-nocheck
export * from './interface';
import { type ChooseFileOption } from './interface';
export function chooseFile(options: ChooseFileOption){
console.error('chooseFile 不支持该平台')
}

View File

@@ -0,0 +1,108 @@
// @ts-nocheck
/**
* 错误码
* 根据uni错误码规范要求建议错误码以90开头以下是错误码示例
* - 9010001 错误信息1
* - 9010002 错误信息2
*/
export type ChooseFileErrorCode = 9010001 | 9010002 | 1101001 | 1101002 | 1101003 | 1101004 | 1101005 | 1101006 | 1101007 | 1101008 | 1101009 | 1101010;
/**
* myApi 的错误回调参数
*/
export interface GeneralCallbackResult extends IUniError {
errCode : ChooseFileErrorCode
};
/** 返回选择的文件的本地临时文件对象数组 */
export interface ChooseFile {
/** 选择的文件名称 */
name : string
/** 本地临时文件路径 (本地路径) */
path : string
/** 本地临时文件大小,单位 B */
size : number
/** 选择的文件的会话发送时间Unix时间戳工具暂不支持此属性 */
time : number
/** 选择的文件类型
*
* 可选值:
* - 'video': 选择了视频文件;
* - 'image': 选择了图片文件;
* - 'file': 选择了除图片和视频的文件; */
type : 'video' | 'image' | 'file' | 'all'
}
export type ChooseFileSuccessCallbackResult = {
/** 返回选择的文件的本地临时文件对象数组 */
tempFiles : ChooseFile[],
errMsg : string
}
/** 接口调用成功的回调函数 */
export type ChooseFileSuccessCallback = (
result : ChooseFileSuccessCallbackResult
) => void
/** 接口调用失败的回调函数 */
export type ChooseFileFailCallback = (res : GeneralCallbackResult) => void
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
export type ChooseFileCompleteCallback = (
res : GeneralCallbackResult
) => void
export type ChooseFileOption = {
/**
* 指定文件名,如果是多选就在后面增加上时间
*/
filename?: string
/**
* 最多可以选择的文件数量。
* @defaultValue 100
*/
count ?: number | null,
/**
* 所选文件类型
* @defaultValue all
*/
type ?: string | null,
/**
* 根据文件拓展名过滤每一项都不能是空字符串。默认不过滤。仅H5支持
*/
extension ?: (string[]) | null,
/**
* 成功则返回图片的本地文件路径列表 tempFilePaths
*/
success ?: ChooseFileSuccessCallback | null,
/**
* 接口调用失败的回调函数
*/
fail ?: ChooseFileFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete ?: ChooseFileCompleteCallback | null
}

View File

@@ -0,0 +1,40 @@
// @ts-nocheck
/* 此规范为 uni 规范,可以按照自己的需要选择是否实现 */
import { ChooseFileErrorCode, GeneralCallbackResult } from "./interface.uts"
/**
* 错误主题
* 注意:错误主题一般为插件名称,每个组件不同,需要使用时请更改。
* [可选实现]
*/
export const UniErrorSubject = 'chooseFile"';
/**
* 错误信息
* @UniError
* [可选实现]
*/
export const UniErrors : Map<ChooseFileErrorCode, string> = new Map([
/**
* 错误码及对应的错误信息
*/
[9010001, 'chooseFile:ok'],
[9010002, 'ChooseFile:failed'],
]);
/**
* 错误对象实现
*/
export class GeneralCallbackResultImpl extends UniError implements GeneralCallbackResult {
/**
* 错误对象构造函数
*/
constructor(errCode : ChooseFileErrorCode, errMsg: string|null = null) {
super();
this.errSubject = UniErrorSubject;
this.errCode = errCode;
this.errMsg = errMsg ?? UniErrors[errCode] ?? "";
}
}

View File

@@ -0,0 +1,202 @@
// @ts-nocheck
import Intent from 'android.content.Intent';
import ClipData from 'android.content.ClipData';
import Uri from 'android.net.Uri';
import InputStream from 'java.io.InputStream';
import OpenableColumns from 'android.provider.OpenableColumns';
import Cursor from 'android.database.Cursor';
import File from 'java.io.File';
import FileInputStream from 'java.io.FileInputStream';
import FileOutputStream from 'java.io.FileOutputStream';
import BufferedOutputStream from 'java.io.BufferedOutputStream';
import ByteArrayInputStream from 'java.io.ByteArrayInputStream';
import { ChooseFileOption, ChooseFile, ChooseFileSuccessCallbackResult } from '../interface';
import { GeneralCallbackResultImpl } from '../unierror';
const REQUEST_CODE_CHOOSE_FILE: Int = 42;
let resultFunction: ((requestCode: Int, resultCode: Int, data?: Intent) => void) | null = null;
class ChooseFileImpl implements ChooseFile {
override name: string = '';
override path: string = '';
// private _path : string = ''
override size: number = 0;
override time: number = 0;
override type: string = 'file';
// private uri : Uri
private options: ChooseFileOption;
constructor(uri: Uri, options: ChooseFileOption) {
// this.uri = uri
this.options = options;
this.time = Date.now();
this.type = this.getFileTypeFromUri(uri);
// this._path = uri.getPath() ?? ''
this.getFileInfoFromUri(uri);
if (this.isCache(options)) {
this.copyFileToCache(uri);
}
}
private isCache(options: ChooseFileOption): boolean {
const extension = this.getFileExtension(this.name);
const extensions = options.extension;
const type = options.type ?? 'all';
const hasExtension = extensions != null && extension != '' && extensions.includes(extension);
const isVideoOrImage = ['video', 'image'].includes(type);
const isFileAndNotVideoOrImage = type == 'file' && !['video', 'image'].includes(this.type);
if ((type == 'all' || isVideoOrImage || isFileAndNotVideoOrImage) && !hasExtension) {
return true;
}
else {
return false;
}
}
private getFileExtension(fileName: string): string {
const lastDotIndex = fileName.lastIndexOf(".");
if (lastDotIndex == -1) {
return "";
}
return fileName.substring(lastDotIndex + 1);
}
private copyFileToCache(uri: Uri) {
const cacheDir = UTSAndroid.getAppCachePath();
const context = UTSAndroid.getAppContext();
if (cacheDir != null) {
const path = new File(cacheDir);
if (!path.exists()) {
path.mkdir();
}
}
let fileName = this.name;
if (this.options.filename != null) {
fileName = this.options.filename!;
if (this.options.count != null && this.options.count! > 1) {
fileName = `${fileName}_${Date.now()}`;
}
const extension = this.getFileExtension(this.name);
fileName = `${fileName}.${extension}`;
}
const destFile = new File(cacheDir, fileName);
try {
const inputStream = context!.getContentResolver().openInputStream(uri);
const outputStream = new FileOutputStream(destFile);
if (inputStream != null) {
let buffer = ByteArray(1024);
let c = inputStream.read(buffer);
while (c > 0) {
outputStream.write(buffer, 0, c);
c = inputStream.read(buffer);
}
}
this.path = cacheDir + fileName; //this.name
}
catch (e: any) {
}
}
private getFileTypeFromUri(uri: Uri): string {
const context = UTSAndroid.getAppContext();
let fileType = 'file';
let mimeType = context!.getContentResolver().getType(uri);
if (mimeType != null) {
if (mimeType.startsWith("video")) {
fileType = "video";
}
else if (mimeType.startsWith("image")) {
fileType = "image";
}
}
return fileType;
}
private getFileInfoFromUri(uri: Uri) {
const context = UTSAndroid.getAppContext();
let cursor = context!.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
this.name = cursor.getString(cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME));
const fileSize = cursor.getLong(cursor.getColumnIndexOrThrow(OpenableColumns.SIZE));
this.size = Number.from(fileSize);
cursor.close();
}
else if ("file".equals(uri.getScheme())) {
this.name = uri.getLastPathSegment() ?? '';
const file = new File(uri.getPath() ?? '');
const fileSize = file.length();
this.size = Number.from(fileSize);
}
}
}
export function chooseFile(options: ChooseFileOption) {
if (resultFunction != null) {
UTSAndroid.offAppActivityResult(resultFunction!);
}
const type = options.type ?? 'all';
const intent = new Intent(Intent.ACTION_GET_CONTENT);
if (type.equals("all") || type.equals("file")) {
intent.setType("*/*");
}
else if (type.equals("video")) {
intent.setType("video/*");
}
else if (type.equals("image")) {
intent.setType("image/*");
}
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, options.count == 1 ? false : true); // 允许多选
resultFunction = (requestCode: Int, resultCode: Int, data?: Intent) => {
if (requestCode == REQUEST_CODE_CHOOSE_FILE) {
UTSAndroid.offAppActivityResult(resultFunction!);
if (resultCode == -1 && data != null) {
const clipData = data.getClipData();
const tempFiles: ChooseFile[] = [];
if (clipData != null) {
// 多选
// const itemCount = clipData.getItemCount();
// if (options.count != null && options.count! > itemCount) {
// const err = new GeneralCallbackResultImpl(9010002, `选中文件数量超过${options.count}`)
// options.fail?.(err)
// options.complete?.(err)
// return
// }
for (let i = 0; i < clipData.getItemCount(); i++) {
const uri = clipData.getItemAt(i.toInt()).getUri();
const chooseFile = new ChooseFileImpl(uri, options);
if (chooseFile.path != '') {
tempFiles.push(chooseFile);
}
}
}
else {
// 单选
const uri = data.getData();
if (uri != null) {
const chooseFile = new ChooseFileImpl(uri, options);
if (chooseFile.path != '') {
tempFiles.push(chooseFile);
}
}
}
const count = options.count ?? Integer.MAX_VALUE; // Number.MAX_VALUE
if (tempFiles.length > 0 && count >= tempFiles.length) {
options.success?.({
tempFiles,
errMsg: 'chooseFile:ok'
} as ChooseFileSuccessCallbackResult);
}
else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件或文件超过设置数量`);
options.fail?.(err);
options.complete?.(err);
}
}
else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件`);
options.fail?.(err);
options.complete?.(err);
}
}
else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件`);
options.fail?.(err);
options.complete?.(err);
}
};
UTSAndroid.onAppActivityResult(resultFunction!);
UTSAndroid.getUniActivity()!.startActivityForResult(Intent.createChooser(intent, "选择文件"), REQUEST_CODE_CHOOSE_FILE);
// UTSAndroid.getUniActivity()!.overridePendingTransition((10).toInt(), (0).toInt());
}

View File

@@ -0,0 +1,76 @@
// @ts-nocheck
/**
* 错误码
* 根据uni错误码规范要求建议错误码以90开头以下是错误码示例
* - 9010001 错误信息1
* - 9010002 错误信息2
*/
export type ChooseFileErrorCode = 9010001 | 9010002 | 1101001 | 1101002 | 1101003 | 1101004 | 1101005 | 1101006 | 1101007 | 1101008 | 1101009 | 1101010;
/**
* myApi 的错误回调参数
*/
export interface GeneralCallbackResult extends IUniError {
errCode: ChooseFileErrorCode;
}
;
/** 返回选择的文件的本地临时文件对象数组 */
export interface ChooseFile {
/** 选择的文件名称 */
name: string;
/** 本地临时文件路径 (本地路径) */
path: string;
/** 本地临时文件大小,单位 B */
size: number;
/** 选择的文件的会话发送时间Unix时间戳工具暂不支持此属性 */
time: number;
/** 选择的文件类型
*
* 可选值:
* - 'video': 选择了视频文件;
* - 'image': 选择了图片文件;
* - 'file': 选择了除图片和视频的文件; */
type: 'video' | 'image' | 'file' | 'all';
}
export type ChooseFileSuccessCallbackResult = {
/** 返回选择的文件的本地临时文件对象数组 */
tempFiles: ChooseFile[];
errMsg: string;
};
/** 接口调用成功的回调函数 */
export type ChooseFileSuccessCallback = (result: ChooseFileSuccessCallbackResult) => void;
/** 接口调用失败的回调函数 */
export type ChooseFileFailCallback = (res: GeneralCallbackResult) => void;
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
export type ChooseFileCompleteCallback = (res: GeneralCallbackResult) => void;
export type ChooseFileOption = {
/**
* 指定文件名,如果是多选就在后面增加上时间
*/
filename?: string;
/**
* 最多可以选择的文件数量。
* @defaultValue 100
*/
count?: number | null;
/**
* 所选文件类型
* @defaultValue all
*/
type?: string | null;
/**
* 根据文件拓展名过滤每一项都不能是空字符串。默认不过滤。仅H5支持
*/
extension?: (string[]) | null;
/**
* 成功则返回图片的本地文件路径列表 tempFilePaths
*/
success?: ChooseFileSuccessCallback | null;
/**
* 接口调用失败的回调函数
*/
fail?: ChooseFileFailCallback | null;
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: ChooseFileCompleteCallback | null;
};

View File

@@ -0,0 +1,35 @@
// @ts-nocheck
/* 此规范为 uni 规范,可以按照自己的需要选择是否实现 */
import { ChooseFileErrorCode, GeneralCallbackResult } from "./interface.uts";
/**
* 错误主题
* 注意:错误主题一般为插件名称,每个组件不同,需要使用时请更改。
* [可选实现]
*/
export const UniErrorSubject = 'chooseFile"';
/**
* 错误信息
* @UniError
* [可选实现]
*/
export const UniErrors: Map<ChooseFileErrorCode, string> = new Map([
/**
* 错误码及对应的错误信息
*/
[9010001, 'chooseFile:ok'],
[9010002, 'ChooseFile:failed'],
]);
/**
* 错误对象实现
*/
export class GeneralCallbackResultImpl extends UniError implements GeneralCallbackResult {
/**
* 错误对象构造函数
*/
constructor(errCode: ChooseFileErrorCode, errMsg: string | null = null) {
super();
this.errSubject = UniErrorSubject;
this.errCode = errCode;
this.errMsg = errMsg ?? UniErrors[errCode] ?? "";
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>View</title>
<link rel="icon" href="data:,">
<link rel="stylesheet" href="app.css" />
<script>var __uniConfig = {"globalStyle":{},"darkmode":false}</script>
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
</head>
<body>
<div id="app"></div>
<script src="uni-app-view.umd.js"></script>
</body>
</html>

View File

@@ -0,0 +1,11 @@
;(function(){
let u=void 0,isReady=false,onReadyCallbacks=[],isServiceReady=false,onServiceReadyCallbacks=[];
const __uniConfig = {"pages":[],"globalStyle":{"backgroundColor":"#F8F8F8","navigationBar":{"backgroundColor":"#F8F8F8","titleText":"uni-app","type":"default","titleColor":"#000000"},"isNVue":false},"nvue":{"compiler":"uni-app","styleCompiler":"uni-app","flex-direction":"column"},"renderer":"auto","appname":"test1","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":true},"compilerVersion":"5.07","entryPagePath":"pages/Login/Login","entryPageQuery":"","realEntryPagePath":"","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000},"locales":{},"darkmode":false,"themeConfig":{}};
const __uniRoutes = [{"path":"pages/Login/Login","meta":{"isQuit":true,"isEntry":true,"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"登录页面","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/Chat/Chat","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"聊天页面(主页面)","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/WorkSpace/WorkSpace","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"工作区文件管理","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/UserProfileModal/UserProfileModal","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/ContactPages/ContactPages","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/WorkSpace/TemplateSpace/TemplateSpace","meta":{"titleNView":false,"bounce":"none","softinputMode":"adjustResize","navigationBar":{"titleText":"","style":"custom","type":"default"},"isNVue":false}},{"path":"pages/text/text","meta":{"navigationBar":{"titleText":"","type":"default"},"isNVue":false}},{"path":"pages/text/text2","meta":{"navigationBar":{"type":"default"},"isNVue":false}}].map(uniRoute=>(uniRoute.meta.route=uniRoute.path,__uniConfig.pages.push(uniRoute.path),uniRoute.path='/'+uniRoute.path,uniRoute));
__uniConfig.styles=[];//styles
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}});
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:16})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,global:u,window:u,document:u,frames:u,self:u,location:u,navigator:u,localStorage:u,history:u,Caches:u,screen:u,alert:u,confirm:u,prompt:u,fetch:u,XMLHttpRequest:u,WebSocket:u,webkit:u,print:u}}}});
})();

View File

@@ -0,0 +1 @@
(function(){})();

File diff suppressed because one or more lines are too long

3
unpackage/dist/build/app-plus/app.css vendored Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -0,0 +1,112 @@
{
"@platforms": [
"android",
"iPhone",
"iPad"
],
"id": "__UNI__923FD9E",
"name": "test1",
"version": {
"name": "1.0.0",
"code": "1"
},
"description": "",
"developer": {
"name": "",
"email": "",
"url": ""
},
"permissions": {
"UniNView": {
"description": "UniNView原生渲染"
}
},
"plus": {
"useragent": {
"value": "uni-app",
"concatenate": true
},
"splashscreen": {
"target": "id:1",
"autoclose": true,
"waiting": true,
"delay": 0
},
"popGesture": "close",
"launchwebview": {
"render": "always",
"id": "1",
"kernel": "WKWebview"
},
"compatible": {
"ignoreVersion": true
},
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"distribute": {
"google": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
"apple": {
"dSYMs": false
},
"plugins": {
"audio": {
"mp3": {
"description": "Android平台录音支持MP3格式文件"
}
}
}
},
"statusbar": {
"immersed": "supportedDevice",
"style": "dark",
"background": "#F8F8F8"
},
"uniStatistics": {
"enable": false
},
"allowsInlineMediaPlayback": true,
"uni-app": {
"control": "uni-v3",
"vueVersion": "3",
"compilerVersion": "5.07",
"nvueCompiler": "uni-app",
"renderer": "auto",
"nvue": {
"flex-direction": "column"
},
"nvueLaunchMode": "normal",
"webView": {
"minUserAgentVersion": "49.0"
}
}
},
"app-harmony": {
"useragent": {
"value": "uni-app",
"concatenate": true
},
"uniStatistics": {
"enable": false
}
},
"launch_path": "__uniappview.html"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.login-container[data-v-d4b9d5ac]{padding:4.375rem 1.875rem 3.125rem;box-sizing:border-box;display:flex;flex-direction:column}.login-card[data-v-d4b9d5ac]{position:relative;flex:1;width:100%;height:100%;padding:.625rem;box-sizing:border-box;background:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center}.conner[data-v-d4b9d5ac]{position:absolute;width:1.25rem;height:1.25rem}.conner-tl[data-v-d4b9d5ac]{top:0;left:0;border-top:2px solid #aaaaff;border-left:2px solid #aaaaff}.conner-tr[data-v-d4b9d5ac]{top:0;right:0;border-top:2px solid #aaaaff;border-right:2px solid #aaaaff}.conner-bl[data-v-d4b9d5ac]{bottom:0;left:0;border-bottom:2px solid #aaaaff;border-left:2px solid #aaaaff}.conner-br[data-v-d4b9d5ac]{bottom:0;right:0;border-bottom:2px solid #aaaaff;border-right:2px solid #aaaaff}.login-header[data-v-d4b9d5ac]{display:flex;justify-content:center;align-items:center;flex-direction:column}.login-header-logo[data-v-d4b9d5ac]{display:flex;justify-content:center;align-items:center}.login-header-logo uni-text[data-v-d4b9d5ac]{margin-left:.25rem;font-size:1.875rem;font-weight:700;color:#aaf;text-shadow:0 0 .3125rem rgba(170,170,255,.4),0 0 .625rem rgba(170,170,255,.3)}.icon-wrapper[data-v-d4b9d5ac]{width:2.8125rem;height:2.8125rem;border-radius:50%;background-color:#fff;display:flex;align-items:center;justify-content:center;animation:glow-d4b9d5ac 2s ease-in-out infinite}@keyframes glow-d4b9d5ac{0%,to{box-shadow:0 0 .625rem rgba(170,170,255,.3)}50%{box-shadow:0 0 .625rem rgba(170,170,255,.4),0 0 .9375rem rgba(170,170,255,.3),0 0 1.5625rem rgba(170,170,255,.2)}}.icon-wrapper .danao-style[data-v-d4b9d5ac]{font-size:2.1875rem;color:#aaf}.sub-title[data-v-d4b9d5ac]{margin-top:.625rem;font-size:1.125rem;font-weight:500;color:#666;text-shadow:0 0 .3125rem #999}.form-wrapper[data-v-d4b9d5ac]{margin-top:1.5625rem;width:15.625rem;padding:2.5rem .9375rem;background-color:rgba(170,170,255,.05);border-radius:.625rem;box-shadow:0 0 .3125rem rgba(170,170,255,.5);display:flex;flex-direction:column}.form-item[data-v-d4b9d5ac]{margin-top:.625rem}.form-item .form-input[data-v-d4b9d5ac]{width:100%;height:2.5rem;padding:0 10px;box-sizing:border-box;border-radius:.9375rem;border:.03125rem solid #e5e5e5}.form-item .focused[data-v-d4b9d5ac]{border-color:#aaf;box-shadow:0 0 .3125rem rgba(170,170,255,.5)}.form-item .error[data-v-d4b9d5ac]{border-color:red;box-shadow:0 0 .3125rem rgba(255,0,0,.5)}.error-info[data-v-d4b9d5ac]{font-size:.75rem;color:red}.form-option[data-v-d4b9d5ac]{margin-top:.3125rem;display:flex;justify-content:space-between}.form-option .checkbox-wrapper[data-v-d4b9d5ac]{display:flex;justify-content:start;align-items:center}.form-option .checkbox-wrapper .checkbox[data-v-d4b9d5ac]{width:.9375rem;height:.9375rem;border:.03125rem solid #666;display:flex;justify-content:center;align-items:center}.form-option .checkbox-wrapper .checked[data-v-d4b9d5ac]{background-color:#aaf}.form-option .checkbox-wrapper .checkbox uni-text[data-v-d4b9d5ac]{color:#fff}[data-v-d4b9d5ac] .login-btn{margin-top:.9375rem;width:15.625rem;height:3.125rem;border-radius:2.5rem;background:linear-gradient(to right,#aaf,#2969ed)}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.container[data-v-939e1d1d]{padding:.625rem;background-color:#f5f5f5;min-height:100vh}.status-card[data-v-939e1d1d],.config-card[data-v-939e1d1d],.control-card[data-v-939e1d1d],.send-card[data-v-939e1d1d],.log-card[data-v-939e1d1d]{background-color:#fff;border-radius:.5rem;padding:.9375rem;margin-bottom:.625rem;box-shadow:0 .0625rem .25rem rgba(0,0,0,.05)}.status-label[data-v-939e1d1d]{font-size:.875rem;color:#666;margin-bottom:.5rem}.status-value[data-v-939e1d1d]{display:inline-block;padding:.375rem 1rem;border-radius:.25rem;font-size:.875rem;font-weight:500}.status-connected[data-v-939e1d1d]{background-color:#e6f7e6;color:#52c41a}.status-connecting[data-v-939e1d1d]{background-color:#fff7e6;color:#faad14}.status-disconnected[data-v-939e1d1d]{background-color:#f5f5f5;color:#999}.status-error[data-v-939e1d1d]{background-color:#fff1f0;color:#ff4d4f}.status-info[data-v-939e1d1d]{margin-top:.5rem}.reconnect-info[data-v-939e1d1d]{font-size:.75rem;color:#faad14}.section-title[data-v-939e1d1d]{font-size:1rem;font-weight:600;color:#333;margin-bottom:.75rem;display:block}.input-group[data-v-939e1d1d]{margin-bottom:.75rem}.input-label[data-v-939e1d1d]{font-size:.875rem;color:#666;margin-bottom:.375rem;display:block}.input-field[data-v-939e1d1d]{border:.0625rem solid #e8e8e8;border-radius:.25rem;padding:.625rem;font-size:.875rem;background-color:#fafafa}.control-card[data-v-939e1d1d]{display:flex;gap:.625rem}.btn[data-v-939e1d1d]{flex:1;height:2.75rem;line-height:2.75rem;border-radius:.375rem;font-size:1rem;text-align:center;border:none}.btn-primary[data-v-939e1d1d]{background-color:#1890ff;color:#fff}.btn-danger[data-v-939e1d1d]{background-color:#ff4d4f;color:#fff}.btn-secondary[data-v-939e1d1d]{background-color:#f0f0f0;color:#666}.btn-outline[data-v-939e1d1d]{background-color:transparent;color:#1890ff;border:.0625rem solid #1890ff}.btn-small[data-v-939e1d1d]{height:2rem;line-height:2rem;font-size:.8125rem;padding:0 .75rem}.btn[disabled][data-v-939e1d1d]{opacity:.5}.send-input-wrapper[data-v-939e1d1d]{display:flex;flex-direction:column;gap:.625rem}.send-input[data-v-939e1d1d]{border:.0625rem solid #e8e8e8;border-radius:.25rem;padding:.625rem;font-size:.875rem;min-height:5rem;background-color:#fafafa;box-sizing:border-box}.send-buttons[data-v-939e1d1d]{display:flex;gap:.625rem}.quick-messages[data-v-939e1d1d]{margin-top:.75rem;padding-top:.75rem;border-top:.0625rem solid #f0f0f0}.quick-label[data-v-939e1d1d]{font-size:.8125rem;color:#999;margin-bottom:.5rem;display:block}.quick-btns[data-v-939e1d1d]{display:flex;flex-wrap:wrap;gap:.5rem}.quick-btn[data-v-939e1d1d]{padding:.375rem .75rem;background-color:#f0f5ff;color:#1890ff;border-radius:.25rem;font-size:.8125rem;border:none}.quick-btn[disabled][data-v-939e1d1d]{opacity:.5}.log-header[data-v-939e1d1d]{display:flex;justify-content:space-between;align-items:center;margin-bottom:.75rem}.log-title-wrapper[data-v-939e1d1d]{display:flex;align-items:center;gap:.375rem}.log-title-wrapper .section-title[data-v-939e1d1d]{margin-bottom:0}.log-count[data-v-939e1d1d]{font-size:.75rem;color:#999}.log-actions[data-v-939e1d1d]{display:flex;gap:.375rem}.log-list[data-v-939e1d1d]{max-height:15.625rem;background-color:#1e1e1e;border-radius:.25rem;padding:.625rem}.log-item[data-v-939e1d1d]{display:flex;margin-bottom:.375rem;font-family:Courier New,monospace;font-size:.75rem;line-height:1.6}.log-time[data-v-939e1d1d]{color:#888;margin-right:.5rem;flex-shrink:0}.log-content[data-v-939e1d1d]{word-break:break-all;flex:1;color:#fff}.log-info .log-content[data-v-939e1d1d]{color:#fff}.log-success .log-content[data-v-939e1d1d]{color:#52c41a}.log-error .log-content[data-v-939e1d1d]{color:#ff4d4f}.log-warn .log-content[data-v-939e1d1d]{color:#faad14}.log-send .log-content[data-v-939e1d1d]{color:#1890ff}.log-receive .log-content[data-v-939e1d1d]{color:#52c41a}

View File

@@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,161 @@
@font-face {
font-family: "iconfont"; /* Project id */
src: url('iconfont.ttf?t=1776936195904') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-del:before {
content: "\e616";
}
.icon-zhaoxiangji:before {
content: "\e663";
}
.icon-duoxuan:before {
content: "\e630";
}
.icon-jia:before {
content: "\e659";
}
.icon-quxiao:before {
content: "\e625";
}
.icon-tuichu:before {
content: "\e617";
}
.icon-fuzhi:before {
content: "\e6e6";
}
.icon-shangchuan:before {
content: "\e797";
}
.icon-total_selection:before {
content: "\e660";
}
.icon-tingzhi:before {
content: "\e611";
}
.icon-wenjianjia:before {
content: "\e64b";
}
.icon-caidan:before {
content: "\eaf1";
}
.icon-wenjian:before {
content: "\e729";
}
.icon-biezhen:before {
content: "\e647";
}
.icon-bianji:before {
content: "\e605";
}
.icon-fasong:before {
content: "\e705";
}
.icon-download:before {
content: "\e61a";
}
.icon-edit-fill:before {
content: "\e61d";
}
.icon-favorite-fill:before {
content: "\e61f";
}
.icon-favorite:before {
content: "\e620";
}
.icon-upload:before {
content: "\e63e";
}
.icon-yonghuziliao:before {
content: "\e6a1";
}
.icon-pen-fill:before {
content: "\e667";
}
.icon-qunliao:before {
content: "\e606";
}
.icon-shipintonghua:before {
content: "\e609";
}
.icon-tianjia:before {
content: "\e60d";
}
.icon-tongxunlu:before {
content: "\e612";
}
.icon-tianjiahaoyou:before {
content: "\e613";
}
.icon-shanchu:before {
content: "\e6d3";
}
.icon-choose-fill:before {
content: "\e6a2";
}
.icon-a-wenjianjiawenjian:before {
content: "\e69e";
}
.icon-sousuo:before {
content: "\e6eb";
}
.icon-Robot:before {
content: "\e661";
}
.icon-saochu:before {
content: "\e6a3";
}
.icon-fanhui:before {
content: "\e765";
}
.icon-brain-2-fill:before {
content: "\e800";
}
.icon-gengduo:before {
content: "\e6c5";
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,268 @@
{
"id": "",
"name": "",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "109713",
"name": "垃圾桶",
"font_class": "del",
"unicode": "e616",
"unicode_decimal": 58902
},
{
"icon_id": "630128",
"name": "照相机",
"font_class": "zhaoxiangji",
"unicode": "e663",
"unicode_decimal": 58979
},
{
"icon_id": "695132",
"name": "多选",
"font_class": "duoxuan",
"unicode": "e630",
"unicode_decimal": 58928
},
{
"icon_id": "947061",
"name": "加",
"font_class": "jia",
"unicode": "e659",
"unicode_decimal": 58969
},
{
"icon_id": "954218",
"name": "取消",
"font_class": "quxiao",
"unicode": "e625",
"unicode_decimal": 58917
},
{
"icon_id": "1348254",
"name": "退出",
"font_class": "tuichu",
"unicode": "e617",
"unicode_decimal": 58903
},
{
"icon_id": "2733945",
"name": "复制",
"font_class": "fuzhi",
"unicode": "e6e6",
"unicode_decimal": 59110
},
{
"icon_id": "4294108",
"name": "上传",
"font_class": "shangchuan",
"unicode": "e797",
"unicode_decimal": 59287
},
{
"icon_id": "4922119",
"name": "全选",
"font_class": "total_selection",
"unicode": "e660",
"unicode_decimal": 58976
},
{
"icon_id": "4955291",
"name": "停止",
"font_class": "tingzhi",
"unicode": "e611",
"unicode_decimal": 58897
},
{
"icon_id": "5121520",
"name": "文件夹",
"font_class": "wenjianjia",
"unicode": "e64b",
"unicode_decimal": 58955
},
{
"icon_id": "5387521",
"name": "菜单",
"font_class": "caidan",
"unicode": "eaf1",
"unicode_decimal": 60145
},
{
"icon_id": "5672455",
"name": "文件",
"font_class": "wenjian",
"unicode": "e729",
"unicode_decimal": 59177
},
{
"icon_id": "6246289",
"name": "别针",
"font_class": "biezhen",
"unicode": "e647",
"unicode_decimal": 58951
},
{
"icon_id": "7515699",
"name": "编辑",
"font_class": "bianji",
"unicode": "e605",
"unicode_decimal": 58885
},
{
"icon_id": "8440993",
"name": "发送",
"font_class": "fasong",
"unicode": "e705",
"unicode_decimal": 59141
},
{
"icon_id": "9512543",
"name": "下载",
"font_class": "download",
"unicode": "e61a",
"unicode_decimal": 58906
},
{
"icon_id": "9512544",
"name": "编辑",
"font_class": "edit-fill",
"unicode": "e61d",
"unicode_decimal": 58909
},
{
"icon_id": "9512556",
"name": "收藏",
"font_class": "favorite-fill",
"unicode": "e61f",
"unicode_decimal": 58911
},
{
"icon_id": "9512559",
"name": "收藏",
"font_class": "favorite",
"unicode": "e620",
"unicode_decimal": 58912
},
{
"icon_id": "9512675",
"name": "上传",
"font_class": "upload",
"unicode": "e63e",
"unicode_decimal": 58942
},
{
"icon_id": "11633996",
"name": "用户资料",
"font_class": "yonghuziliao",
"unicode": "e6a1",
"unicode_decimal": 59041
},
{
"icon_id": "17775968",
"name": "笔",
"font_class": "pen-fill",
"unicode": "e667",
"unicode_decimal": 58983
},
{
"icon_id": "18537099",
"name": "群聊",
"font_class": "qunliao",
"unicode": "e606",
"unicode_decimal": 58886
},
{
"icon_id": "18537375",
"name": "视频通话",
"font_class": "shipintonghua",
"unicode": "e609",
"unicode_decimal": 58889
},
{
"icon_id": "18654056",
"name": "添加",
"font_class": "tianjia",
"unicode": "e60d",
"unicode_decimal": 58893
},
{
"icon_id": "18655694",
"name": "通讯录",
"font_class": "tongxunlu",
"unicode": "e612",
"unicode_decimal": 58898
},
{
"icon_id": "18656610",
"name": "添加好友",
"font_class": "tianjiahaoyou",
"unicode": "e613",
"unicode_decimal": 58899
},
{
"icon_id": "24660909",
"name": "删除",
"font_class": "shanchu",
"unicode": "e6d3",
"unicode_decimal": 59091
},
{
"icon_id": "25015243",
"name": "选择箭头-fill",
"font_class": "choose-fill",
"unicode": "e6a2",
"unicode_decimal": 59042
},
{
"icon_id": "27229314",
"name": "文件夹,文件",
"font_class": "a-wenjianjiawenjian",
"unicode": "e69e",
"unicode_decimal": 59038
},
{
"icon_id": "27995029",
"name": "搜索",
"font_class": "sousuo",
"unicode": "e6eb",
"unicode_decimal": 59115
},
{
"icon_id": "28661052",
"name": "Robot",
"font_class": "Robot",
"unicode": "e661",
"unicode_decimal": 58977
},
{
"icon_id": "32429618",
"name": "扫除",
"font_class": "saochu",
"unicode": "e6a3",
"unicode_decimal": 59043
},
{
"icon_id": "38950621",
"name": "返回",
"font_class": "fanhui",
"unicode": "e765",
"unicode_decimal": 59237
},
{
"icon_id": "42230703",
"name": "brain-2-fill",
"font_class": "brain-2-fill",
"unicode": "e800",
"unicode_decimal": 59392
},
{
"icon_id": "43005043",
"name": "更多",
"font_class": "gengduo",
"unicode": "e6c5",
"unicode_decimal": 59077
}
]
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,26 @@
## 0.1.32025-09-16
- chore: 更新文档
## 0.1.22025-06-07
- chore: 更新文档
## 0.1.12025-06-02
- feat: 兼容鸿蒙next
## 0.1.02025-04-04
- chore: 更新文档
## 0.0.92025-03-11
- fix: 修复安卓报错的问题
## 0.0.82025-03-11
- fix: 修复报错的问题
## 0.0.72025-03-10
- feat: 增加重命名选项
## 0.0.62025-02-28
- feat: 修复uniapp ios路径问题
## 0.0.52024-10-31
- feat: 修复uniapp ios无法使用
## 0.0.42024-10-26
- feat: 规范类型
## 0.0.32024-07-10
- fext: 兼容ios
## 0.0.22024-05-21
- fix: 修复uniapp找不到文件的错误
## 0.0.12024-04-15
- init

View File

@@ -0,0 +1,38 @@
<template>
<view @click="onClick">
<slot></slot>
</view>
</template>
<script>
import { chooseFile } from '@/uni_modules/lime-choose-file'
export default {
props: {
disabled: Boolean
},
emits: ['success', 'fail'],
data() {
return {
images: []
}
},
methods: {
onClick() {
if(this.disabled) return
chooseFile({
success:(res)=>{
this.$emit('success', res)
},
fail(err){
this.$emit('fail', err)
}
})
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,103 @@
<template>
<view class="demo-block">
<text class="demo-block__title-text ultra">ChooseFile 文件选择</text>
<text class="demo-block__desc-text">打开系统文件管理器选择文件。</text>
<view class="demo-block__body">
<view class="demo-block card">
<text class="demo-block__title-text large">基础使用</text>
<view class="demo-block__body row">
<button @click="onClick">选择图片</button>
<image v-for="(item, index) in images" :key="index" :src="item"></image>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { chooseFile, ChooseFileOption } from '@/uni_modules/lime-choose-file'
const images = ref<string[]>([])
const onClick = () => {
chooseFile({
// filename: 'xxx',
type: 'image',
success(res) {
images.value = res.tempFiles.map((item) : string => item.path)
console.log('res', res.tempFiles)
console.log('reserrMsg', res)
},
fail(err) {
console.log('err', err)
}
} as ChooseFileOption)
}
</script>
<style lang="scss">
.row {
flex-direction: row;
flex-wrap: wrap;
}
.btn {
margin-bottom: 20rpx;
margin-right: 20rpx;
}
.demo-block {
margin: 32px 10px 0;
// overflow: visible;
&.card {
background-color: white;
padding: 30rpx;
margin-bottom: 20rpx !important;
}
&__title {
margin: 0;
margin-top: 8px;
&-text {
color: rgba(0, 0, 0, 0.6);
font-weight: 400;
font-size: 14px;
line-height: 16px;
display: flex;
&.large {
color: rgba(0, 0, 0, 0.9);
font-size: 18px;
font-weight: 700;
line-height: 26px;
}
&.ultra {
color: rgba(0, 0, 0, 0.9);
font-size: 24px;
font-weight: 700;
line-height: 32px;
}
}
}
&__desc-text {
color: rgba(0, 0, 0, 0.6);
margin: 8px 16px 0 0;
font-size: 14px;
line-height: 22px;
}
&__body {
margin: 16px 0;
overflow: visible;
.demo-block {
// margin-top: 0px;
margin: 0;
}
}
}
</style>

View File

@@ -0,0 +1,36 @@
<template>
<view>
<button @click="onClick">选图</button>
<image v-for="(item, index) in images" :key="index" :src="item"></image>
</view>
</template>
<script>
import { chooseFile } from '@/uni_modules/lime-choose-file'
export default {
data() {
return {
images: []
}
},
methods: {
onClick() {
chooseFile({
type: 'image',
success:(res)=>{
this.images = res.tempFiles.map((item) => item.path)
console.log('res', res.tempFiles)
},
fail(err){
console.log('err', err)
}
})
}
}
}
</script>
<style>
</style>

View File

@@ -0,0 +1,2 @@
<EFBFBD>,<2C>P<EFBFBD><50>=<3D>[&<26>۸<>6<EFBFBD>
<1B>I<EFBFBD>T<EFBFBD> ]<5D><>r<EFBFBD><72><EFBFBD><EFBFBD>*<2A>I<EFBFBD>F<EFBFBD>܃<EFBFBD>C咺+<16><>E<>|<7C>q<EFBFBD>`(<28><><EFBFBD><EFBFBD>I_<49>+D<><16>Zs<5A>f<EFBFBD>V<EFBFBD><56><EFBFBD><EFBFBD>q<EFBFBD><71>gqݰ<71><DDB0><EFBFBD>IC*<2A>N<EFBFBD><4E>R<EFBFBD>W<EFBFBD>O<EFBFBD><17><>5<EFBFBD>@\7<>ta<74><61> `e<>7<EFBFBD><37><EFBFBD>H<EFBFBD><48>F:D<><44><EFBFBD>r<EFBFBD><72>|<7C><>#

View File

@@ -0,0 +1,105 @@
{
"id": "lime-choose-file",
"displayName": "lime-choose-file 文件选择",
"version": "0.1.3",
"description": "lime-choose-file 文件选择参考uni.chooseFile API实现的UTS API用法保持一致从本地选择文件。兼容uniapp/uniappX",
"keywords": [
"chooseFile",
"文件选择",
"uts"
],
"repository": "",
"engines": {
"HBuilderX": "^4.11",
"uni-app": "^4.61",
"uni-app-x": "^4.61"
},
"dcloudext": {
"type": "uts",
"sale": {
"regular": {
"price": "29.00"
},
"sourcecode": {
"price": "268.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "",
"darkmode": "x",
"i18n": "x",
"widescreen": "x"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "√",
"aliyun": "√",
"alipay": "√"
},
"client": {
"uni-app": {
"vue": {
"vue2": "√",
"vue3": "√"
},
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"vue": "√",
"nvue": "√",
"android": {
"extVersion": "",
"minVersion": "21"
},
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": "√",
"alipay": "-",
"toutiao": "-",
"baidu": "-",
"kuaishou": "-",
"jd": "-",
"harmony": "-",
"qq": "-",
"lark": "-"
},
"quickapp": {
"huawei": "-",
"union": "-"
}
},
"uni-app-x": {
"web": {
"safari": "√",
"chrome": "√"
},
"app": {
"android": {
"extVersion": "",
"minVersion": "21"
},
"ios": "√",
"harmony": "√"
},
"mp": {
"weixin": "√"
}
}
}
}
}
}

View File

@@ -0,0 +1,61 @@
# lime-choosefile 文件选择
文件选择UTS API系参考小程序chooseFile API实现的用法保持一致目前仅支持uniappX(web,ios,安卓,鸿蒙)
## 文档
🚀 [choose-file【站点1】](https://limex.qcoon.cn/native/choose-file.html)
🌍 [choose-file【站点2】](https://limeui.netlify.app/native/choose-file.html)
🔥 [choose-file【站点3】](https://limeui.familyzone.top/native/choose-file.html)
## 安装
插件市场导入APP需要在页面上引入然后自定义基座完成自定义基座后选择自定义基座运行
## 使用
### UNIAPPX
```js
import { chooseFile, type ChooseFileOption } from '@/uni_modules/lime-choose-file'
const images = ref<string[]>([])
const onClick = () => {
chooseFile({
filename: 'xxxx', // 可选 用于给文件重命名安卓、IOS
type: 'image',
success(res){
images.value = res.tempFiles.map((item):string => item.path)
console.log('res', res.tempFiles)
},
fail(err){
console.log('err', err)
}
} as ChooseFileOption)
}
```
### UNIAPP
```js
import { chooseFile } from '@/uni_modules/lime-choose-file'
const images = ref<string[]>([])
const onClick = () => {
chooseFile({
filename: 'xxxx', // 可选 用于给文件重命名安卓、IOS
type: 'image',
success(res){
images.value = res.tempFiles.map((item):string => item.path)
console.log('res', res.tempFiles)
},
fail(err){
console.log('err', err)
}
})
}
```
## 常见问题
- 1、IOS路径是中文时无法上传到服务器这时候需要设置`filename`给文件重命名
## API
因为直接参照小程序`chooseFile`API所以可以直接按[chooseFile](https://uniapp.dcloud.net.cn/api/media/file.html#choosefile)文档来

View File

@@ -0,0 +1,126 @@
# lime-choose-file 文件选择组件
一个基于UTS实现的文件选择插件参考小程序chooseFile API实现用法保持一致。支持安卓、iOS、鸿蒙和H5平台。提供了选择图片、视频和其他文件类型的功能。组件提供了简单易用的API使开发者能够方便地在应用中集成文件选择功能。
## 文档链接
📚 组件详细文档请访问以下站点:
- [文件选择组件文档 - 站点1](https://limex.qcoon.cn/native/choose-file.html)
- [文件选择组件文档 - 站点2](https://limeui.netlify.app/native/choose-file.html)
- [文件选择组件文档 - 站点3](https://limeui.familyzone.top/native/choose-file.html)
## 安装方法
1. 在uni-app插件市场中搜索并导入`lime-choose-file`
2. 导入后在页面引入相关方法
3. 需要自定义基座才能使用
4. 试用符合需求后才购买,插件无法退款
## 代码演示
### UNIAPPX 使用方式
```ts
import { chooseFile, type ChooseFileOption } from '@/uni_modules/lime-choose-file'
const images = ref<string[]>([])
const onClick = () => {
chooseFile({
filename: 'xxxx', // 可选 用于给文件重命名安卓、iOS
type: 'image',
success(res){
images.value = res.tempFiles.map((item):string => item.path)
console.log('选择结果:', res.tempFiles)
},
fail(err){
console.log('选择失败:', err)
}
} as ChooseFileOption)
}
```
### UNIAPP 使用方式
```ts
import { chooseFile } from '@/uni_modules/lime-choose-file'
const images = ref<string[]>([])
const onClick = () => {
chooseFile({
filename: 'xxxx', // 可选 用于给文件重命名安卓、iOS
type: 'image',
success(res){
images.value = res.tempFiles.map((item):string => item.path)
console.log('选择结果:', res.tempFiles)
},
fail(err){
console.log('选择失败:', err)
}
})
}
```
## API文档
### chooseFile 方法
| 参数 | 说明 | 类型 | 必填 |
| --- | --- | --- | --- |
| options | 文件选择选项 | _ChooseFileOption_ | 是 |
### ChooseFileOption 选项
| 参数 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| filename | _string_ | 否 | 指定文件名用于给文件重命名安卓、iOS |
| count | _number_ | 否 | 最多可以选择的文件数量默认为100 |
| type | _string_ | 否 | 所选文件类型,默认为'all' |
| extension | _string[]_ | 否 | 根据文件拓展名过滤每一项都不能是空字符串。默认不过滤。仅H5支持 |
| success | _(result: ChooseFileSuccessCallbackResult) => void_ | 否 | 接口调用成功的回调函数 |
| fail | _(res: GeneralCallbackResult) => void_ | 否 | 接口调用失败的回调函数 |
| complete | _(res: GeneralCallbackResult) => void_ | 否 | 接口调用结束的回调函数 |
### ChooseFileSuccessCallbackResult 返回参数
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| tempFiles | _ChooseFile[]_ | 返回选择的文件的本地临时文件对象数组 |
| errMsg | _string_ | 错误信息 |
### ChooseFile 对象结构
| 参数 | 类型 | 说明 |
| --- | --- | --- |
| name | _string_ | 选择的文件名称 |
| path | _string_ | 本地临时文件路径 (本地路径) |
| size | _number_ | 本地临时文件大小,单位 B |
| time | _number_ | 选择的文件的会话发送时间Unix时间戳 |
| type | _'video' \| 'image' \| 'file' \| 'all'_ | 选择的文件类型 |
### 文件类型说明
| 类型值 | 说明 |
| --- | --- |
| video | 视频文件 |
| image | 图片文件 |
| file | 除图片和视频外的其他文件 |
| all | 所有类型文件 |
## 功能特点
- 支持多种文件类型的选择,包括图片、视频和其他文件
- 支持文件重命名功能
- 兼容安卓、iOS、鸿蒙和H5平台
- 提供简单易用的API接口
- 支持指定最大选择数量
- 支持文件扩展名过滤H5平台
## 常见问题
- iOS路径是中文时无法上传到服务器这时候需要设置`filename`给文件重命名
- APP端需要自定义基座才能使用
- 文件选择后会返回临时文件路径,需要及时使用或保存
- H5端可以通过extension参数过滤文件类型
## 支持与赞赏
如果你觉得本插件解决了你的问题,可以考虑支持作者:
| 支付宝赞助 | 微信赞助 |
|------------|------------|
| ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/alipay.png) | ![](https://testingcf.jsdelivr.net/gh/liangei/image@1.9/wpay.png) |

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.limeui.chooseFile">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>

View File

@@ -0,0 +1,3 @@
{
"minSdkVersion": "21"
}

View File

@@ -0,0 +1,206 @@
// @ts-nocheck
import Intent from 'android.content.Intent';
import ClipData from 'android.content.ClipData';
import Uri from 'android.net.Uri';
import InputStream from 'java.io.InputStream';
import OpenableColumns from 'android.provider.OpenableColumns';
import Cursor from 'android.database.Cursor';
import File from 'java.io.File';
import FileInputStream from 'java.io.FileInputStream';
import FileOutputStream from 'java.io.FileOutputStream';
import BufferedOutputStream from 'java.io.BufferedOutputStream';
import ByteArrayInputStream from 'java.io.ByteArrayInputStream';
import { ChooseFileOption, ChooseFile, ChooseFileSuccessCallbackResult } from '../interface'
import { GeneralCallbackResultImpl } from '../unierror'
const REQUEST_CODE_CHOOSE_FILE : Int = 42
let resultFunction : ((requestCode : Int, resultCode : Int, data ?: Intent) => void) | null = null
class ChooseFileImpl implements ChooseFile {
name : string = ''
path : string = ''
// private _path : string = ''
size : number = 0
time : number = 0
type : string = 'file'
// private uri : Uri
private options: ChooseFileOption
constructor(uri : Uri, options : ChooseFileOption) {
// this.uri = uri
this.options = options
this.time = Date.now()
this.type = this.getFileTypeFromUri(uri);
// this._path = uri.getPath() ?? ''
this.getFileInfoFromUri(uri)
if (this.isCache(options)) {
this.copyFileToCache(uri)
}
}
private isCache(options : ChooseFileOption) : boolean {
const extension = this.getFileExtension(this.name)
const extensions = options.extension
const type = options.type ?? 'all'
const hasExtension = extensions != null && extension != '' && extensions.includes(extension)
const isVideoOrImage = ['video', 'image'].includes(type)
const isFileAndNotVideoOrImage = type == 'file' && !['video', 'image'].includes(this.type);
if ((type == 'all' || isVideoOrImage || isFileAndNotVideoOrImage) && !hasExtension) {
return true
} else {
return false
}
}
private getFileExtension(fileName : string) : string {
const lastDotIndex = fileName.lastIndexOf(".");
if (lastDotIndex == -1) {
return "";
}
return fileName.substring(lastDotIndex + 1);
}
private copyFileToCache(uri : Uri) {
const cacheDir = UTSAndroid.getAppCachePath();
const context = UTSAndroid.getAppContext();
if(cacheDir != null) {
const path = new File(cacheDir);
if (!path.exists()) {
path.mkdir();
}
}
let fileName = this.name
if(this.options.filename != null) {
fileName = this.options.filename!;
if(this.options.count != null && this.options.count! > 1) {
fileName = `${fileName}_${Date.now()}`;
}
const extension = this.getFileExtension(this.name)
fileName = `${fileName}.${extension}`
}
const destFile = new File(cacheDir, fileName);
try {
const inputStream = context!.getContentResolver().openInputStream(uri)
const outputStream = new FileOutputStream(destFile)
if (inputStream != null) {
let buffer = ByteArray(1024);
let c = inputStream.read(buffer)
while (c > 0) {
outputStream.write(buffer, 0, c);
c = inputStream.read(buffer)
}
}
this.path = cacheDir + fileName//this.name
} catch (e) {
}
}
private getFileTypeFromUri(uri : Uri) : string {
const context = UTSAndroid.getAppContext();
let fileType = 'file'
let mimeType = context!.getContentResolver().getType(uri);
if (mimeType != null) {
if (mimeType.startsWith("video")) {
fileType = "video";
} else if (mimeType.startsWith("image")) {
fileType = "image";
}
}
return fileType;
}
private getFileInfoFromUri(uri : Uri) {
const context = UTSAndroid.getAppContext();
let cursor = context!.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
this.name = cursor.getString(cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME))
const fileSize = cursor.getLong(cursor.getColumnIndexOrThrow(OpenableColumns.SIZE));
this.size = Number.from(fileSize)
cursor.close();
} else if ("file".equals(uri.getScheme())) {
this.name = uri.getLastPathSegment() ?? '';
const file = new File(uri.getPath() ?? '');
const fileSize = file.length();
this.size = Number.from(fileSize)
}
}
}
export function chooseFile(options : ChooseFileOption) {
if (resultFunction != null) {
UTSAndroid.offAppActivityResult(resultFunction!)
}
const type = options.type ?? 'all'
const intent = new Intent(Intent.ACTION_GET_CONTENT);
if (type.equals("all") || type.equals("file")) {
intent.setType("*/*");
} else if (type.equals("video")) {
intent.setType("video/*");
} else if (type.equals("image")) {
intent.setType("image/*");
}
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, options.count == 1 ? false : true); // 允许多选
resultFunction = (requestCode : Int, resultCode : Int, data ?: Intent) => {
if (requestCode == REQUEST_CODE_CHOOSE_FILE) {
UTSAndroid.offAppActivityResult(resultFunction!);
if (resultCode == -1 && data != null) {
const clipData = data.getClipData();
const tempFiles : ChooseFile[] = []
if (clipData != null) {
// 多选
// const itemCount = clipData.getItemCount();
// if (options.count != null && options.count! > itemCount) {
// const err = new GeneralCallbackResultImpl(9010002, `选中文件数量超过${options.count}`)
// options.fail?.(err)
// options.complete?.(err)
// return
// }
for (let i = 0; i < clipData.getItemCount(); i++) {
const uri = clipData.getItemAt(i.toInt()).getUri();
const chooseFile = new ChooseFileImpl(uri, options);
if(chooseFile.path !=''){
tempFiles.push(chooseFile)
}
}
} else {
// 单选
const uri = data.getData();
if (uri != null) {
const chooseFile = new ChooseFileImpl(uri, options)
if(chooseFile.path !='' ){
tempFiles.push(chooseFile)
}
}
}
const count = options.count ?? Integer.MAX_VALUE // Number.MAX_VALUE
if(tempFiles.length > 0 && count >= tempFiles.length){
options.success?.({
tempFiles,
errMsg: 'chooseFile:ok'
} as ChooseFileSuccessCallbackResult)
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件或文件超过设置数量`)
options.fail?.(err)
options.complete?.(err)
}
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件`)
options.fail?.(err)
options.complete?.(err)
}
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件`)
options.fail?.(err)
options.complete?.(err)
}
}
UTSAndroid.onAppActivityResult(resultFunction!)
UTSAndroid.getUniActivity()!.startActivityForResult(Intent.createChooser(intent, "选择文件"), REQUEST_CODE_CHOOSE_FILE)
// UTSAndroid.getUniActivity()!.overridePendingTransition((10).toInt(), (0).toInt());
}

View File

@@ -0,0 +1,3 @@
{
"deploymentTarget": "9"
}

View File

@@ -0,0 +1,138 @@
// @ts-nocheck
import { ChooseFileOption, ChooseFile, ChooseFileSuccessCallbackResult } from '../interface'
import { UIDocumentPickerDelegate, UIDocumentPickerMode } from "UIKit"
import { URL, FileManager } from 'Foundation';
import { GeneralCallbackResultImpl } from '../unierror'
import { DispatchQueue } from 'Dispatch';
const documentTypes : Map<string, string[]> = new Map([
["all", ["public.item"]],
["file", [
"public.text",
"public.zip-archive",
"public.data",
"com.adobe.pdf",
"com.microsoft.word.doc",
"com.microsoft.word.docx",
"com.microsoft.excel.xls",
"com.microsoft.excel.xlsx"
]
],
["video", ["public.movie"]],
["image", ["public.image"]],
])
class ChooseFileImpl {
name : string = ''
path : string = ''
size : number = 0
time : number = 0
type : string = 'file'
constructor(uri : URL, options : ChooseFileOption) {
try {
const originalFileName = uri.lastPathComponent;
const attributes = UTSiOS.try(FileManager.default.attributesOfItem(atPath = uri.path))
const fileSize = attributes[FileAttributeKey.size] as number
const pathExtension = `${uri.pathExtension}`
const imageFormats = ['jpeg', 'jpg', 'png', 'gif', 'bmp', 'tiff', 'svg']
const videoFormats = ['mov', 'm4v', 'mp4', 'avi']
let fileName = originalFileName
if(options.filename != null) {
fileName = options.filename!
if(options.count != null && options.count! > 1) {
fileName = `${fileName}_${Date.now()}`;
}
fileName = `${fileName}.${pathExtension}`
}
// #ifdef UNI-APP-X
const dataPath = UTSiOS.getDataPath()
// #endif
// #ifndef UNI-APP-X
const dataPath = UTSiOS.getDataPath().replace(/data$/, "doc");
// #endif
const file = new URL(fileURLWithPath = dataPath).appendingPathComponent(fileName)//.absoluteString
const fileData = FileManager.default.contents(atPath = uri.path);
UTSiOS.try(fileData?.write(to = file))
if (imageFormats.includes(pathExtension)) {
this.type = 'image'
} else if (videoFormats.includes(pathExtension)) {
this.type = 'video'
} else {
this.type = 'file'
}
this.name = `${originalFileName}`
this.size = fileSize
this.path = `${file.absoluteString}`
} catch (e) {
}
}
}
class FilePickerManager implements UIDocumentPickerDelegate {
options : ChooseFileOption = {}
constructor() { }
chooseFile(options : ChooseFileOption) {
DispatchQueue.main.async(execute = () : void => {
this.options = options
const type = options.type ?? 'all'
const count = options.count ?? 1
const types = (documentTypes.get(type) ?? documentTypes.get('all')) as string[]
let documentPicker = UIDocumentPickerViewController(
documentTypes = types,
in = UIDocumentPickerMode.import
)
documentPicker.delegate = this
// 多选要大于 ios11
if (UTSiOS.available("iOS 11.0, *")) {
documentPicker.allowsMultipleSelection = count > 1
}
UTSiOS.getCurrentViewController().present(documentPicker, animated = true)
})
}
documentPicker(controller : UIDocumentPickerViewController, @argumentLabel("didPickDocumentsAt") urls : URL[]) {
DispatchQueue.main.async(execute = () : void => {
const tempFiles : ChooseFile[] = []
for (let i = 0; i < urls.length; i++) {
const url = urls[i]
const chooseFile = new ChooseFileImpl(url, this.options);
// IOS -> js 无法传class?
const file : ChooseFile = {
name: chooseFile.name,
path: chooseFile.path,
size: chooseFile.size,
time: chooseFile.time,
type: chooseFile.type,
}
if (chooseFile.path != '') {
tempFiles.push(file)
}
}
const count = this.options.count ?? Number.from(Double.greatestFiniteMagnitude) //Number.from(Double.MAX_VALUE)
if (tempFiles.length > 0 && count >= tempFiles.length) {
const res : ChooseFileSuccessCallbackResult = {
tempFiles,
errMsg: 'chooseFile:ok'
}
this.options.success?.(res)
} else {
const err = new GeneralCallbackResultImpl(9010002, `没有可用的文件或文件超过设置数量`)
this.options.fail?.(err)
this.options.complete?.(err)
}
})
}
}
const fileManager = new FilePickerManager()
export function chooseFile(options : ChooseFileOption) {
fileManager.chooseFile(options)
}

View File

@@ -0,0 +1,35 @@
// @ts-nocheck
export * from './interface';
import { type ChooseFileOption } from './interface';
export function chooseFile(options: ChooseFileOption){
// #ifdef WEB || APP-HARMONY
uni.chooseFile({
count: options.count ?? 100,
type: options.type,
extension: options.extension,
success(res) {
options.success?.({
// tempFilePaths
errMsg : 'ok',
tempFiles: res.tempFiles
})
},
fail(err) {
options.fail?.({
errCode: err.errCode,
errSubject: 'lime-choose-file'
})
},
complete(res) {
// options.complete?.(res)
}
})
// #endif
// #ifdef MP-WEIXIN
uni.chooseMessageFile(options)
// #endif
// #ifndef WEB || MP-WEIXIN || APP-HARMONY
console.error('chooseFile 不支持该平台')
// #endif
}

View File

@@ -0,0 +1,108 @@
// @ts-nocheck
/**
* 错误码
* 根据uni错误码规范要求建议错误码以90开头以下是错误码示例
* - 9010001 错误信息1
* - 9010002 错误信息2
*/
export type ChooseFileErrorCode = 9010001 | 9010002 | 1101001 | 1101002 | 1101003 | 1101004 | 1101005 | 1101006 | 1101007 | 1101008 | 1101009 | 1101010;
/**
* myApi 的错误回调参数
*/
export interface GeneralCallbackResult extends IUniError {
errCode : ChooseFileErrorCode
};
/** 返回选择的文件的本地临时文件对象数组 */
// #ifdef APP-ANDROID
export interface ChooseFile {
/** 选择的文件名称 */
name : string
/** 本地临时文件路径 (本地路径) */
path : string
/** 本地临时文件大小,单位 B */
size : number
/** 选择的文件的会话发送时间Unix时间戳工具暂不支持此属性 */
time : number
/** 选择的文件类型
*
* 可选值:
* - 'video': 选择了视频文件;
* - 'image': 选择了图片文件;
* - 'file': 选择了除图片和视频的文件; */
type : 'video' | 'image' | 'file' | 'all'
}
// #endif
// #ifndef APP-ANDROID
export type ChooseFile = {
/** 选择的文件名称 */
name : string
/** 本地临时文件路径 (本地路径) */
path : string
/** 本地临时文件大小,单位 B */
size : number
/** 选择的文件的会话发送时间Unix时间戳工具暂不支持此属性 */
time : number
/** 选择的文件类型
*
* 可选值:
* - 'video': 选择了视频文件;
* - 'image': 选择了图片文件;
* - 'file': 选择了除图片和视频的文件; */
type : 'video' | 'image' | 'file' | 'all'
}
// #endif
export type ChooseFileSuccessCallbackResult = {
/** 返回选择的文件的本地临时文件对象数组 */
tempFiles : ChooseFile[],
errMsg : string
}
/** 接口调用成功的回调函数 */
export type ChooseFileSuccessCallback = (
result : ChooseFileSuccessCallbackResult
) => void
/** 接口调用失败的回调函数 */
export type ChooseFileFailCallback = (res : GeneralCallbackResult) => void
/** 接口调用结束的回调函数(调用成功、失败都会执行) */
export type ChooseFileCompleteCallback = (
res : GeneralCallbackResult
) => void
export type ChooseFileOption = {
/**
* 指定文件名,如果是多选就在后面增加上时间
*/
filename?: string
/**
* 最多可以选择的文件数量。
* @defaultValue 100
*/
count ?: number | null,
/**
* 所选文件类型
* @defaultValue all
*/
type ?: string | null,
/**
* 根据文件拓展名过滤每一项都不能是空字符串。默认不过滤。仅H5支持
*/
extension ?: (string[]) | null,
/**
* 成功则返回图片的本地文件路径列表 tempFilePaths
*/
success ?: ChooseFileSuccessCallback | null,
/**
* 接口调用失败的回调函数
*/
fail ?: ChooseFileFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete ?: ChooseFileCompleteCallback | null
}

View File

@@ -0,0 +1,40 @@
// @ts-nocheck
/* 此规范为 uni 规范,可以按照自己的需要选择是否实现 */
import { ChooseFileErrorCode, GeneralCallbackResult } from "./interface.uts"
/**
* 错误主题
* 注意:错误主题一般为插件名称,每个组件不同,需要使用时请更改。
* [可选实现]
*/
export const UniErrorSubject = 'chooseFile"';
/**
* 错误信息
* @UniError
* [可选实现]
*/
export const UniErrors : Map<ChooseFileErrorCode, string> = new Map([
/**
* 错误码及对应的错误信息
*/
[9010001, 'chooseFile:ok'],
[9010002, 'ChooseFile:failed'],
]);
/**
* 错误对象实现
*/
export class GeneralCallbackResultImpl extends UniError implements GeneralCallbackResult {
/**
* 错误对象构造函数
*/
constructor(errCode : ChooseFileErrorCode, errMsg: string|null = null) {
super();
this.errSubject = UniErrorSubject;
this.errCode = errCode;
this.errMsg = errMsg ?? UniErrors[errCode] ?? "";
}
}

View File

@@ -0,0 +1 @@
"use strict";function t(t){for(var e=Object.create(null),n=t.attributes.length;n--;)e[t.attributes[n].name]=t.attributes[n].value;return e}function e(){a[1]&&(this.src=a[1],this.onerror=null),this.onclick=null,this.ontouchstart=null,uni.postMessage({data:{action:"onError",source:"img",attrs:t(this)}})}function n(){window.unloadimgs-=1,0===window.unloadimgs&&uni.postMessage({data:{action:"onReady"}})}function o(r,s,c){for(var d=0;d<r.length;d++)!function(){var u,l=r[d];if(l.type&&"node"!==l.type)u=document.createTextNode(l.text.replace(/&amp;/g,"&"));else{var g=l.name;"svg"===g&&(c="http://www.w3.org/2000/svg"),"html"!==g&&"body"!==g||(g="div"),u=c?document.createElementNS(c,g):document.createElement(g);for(var p in l.attrs)u.setAttribute(p,l.attrs[p]);if(l.children&&o(l.children,u,c),"img"===g){if(window.unloadimgs+=1,u.onload=n,u.onerror=n,!u.src&&u.getAttribute("data-src")&&(u.src=u.getAttribute("data-src")),l.attrs.ignore||(u.onclick=function(e){e.stopPropagation(),uni.postMessage({data:{action:"onImgTap",attrs:t(this)}})}),a[2]){var h=new Image;h.src=u.src,u.src=a[2],h.onload=function(){u.src=this.src},h.onerror=function(){u.onerror()}}u.onerror=e}else if("a"===g)u.addEventListener("click",function(e){e.stopPropagation(),e.preventDefault();var n,o=this.getAttribute("href");o&&"#"===o[0]&&(n=(document.getElementById(o.substr(1))||{}).offsetTop),uni.postMessage({data:{action:"onLinkTap",attrs:t(this),offset:n}})},!0);else if("video"===g||"audio"===g)i.push(u),l.attrs.autoplay||l.attrs.controls||u.setAttribute("controls","true"),u.onplay=function(){if(uni.postMessage({data:{action:"onPlay"}}),a[3])for(var t=0;t<i.length;t++)i[t]!==this&&i[t].pause()},u.onerror=function(){uni.postMessage({data:{action:"onError",source:g,attrs:t(this)}})};else if("table"===g&&a[4]&&!u.style.cssText.includes("inline")){var f=document.createElement("div");f.style.overflow="auto",f.appendChild(u),u=f}else"svg"===g&&(c=void 0)}s.appendChild(u)}()}document.addEventListener("UniAppJSBridgeReady",function(){document.body.onclick=function(){return uni.postMessage({data:{action:"onClick"}})},uni.postMessage({data:{action:"onJSBridgeReady"}})});var a,i=[];window.setContent=function(t,e,n){var r=document.getElementById("content");e[0]&&(document.body.style.cssText=e[0]),e[5]||(r.style.userSelect="none"),n||(r.innerHTML="",i=[]),a=e,window.unloadimgs=0;var s=document.createDocumentFragment();o(t,s),r.appendChild(s);var c=r.scrollHeight;uni.postMessage({data:{action:"onLoad",height:c}}),window.unloadimgs||uni.postMessage({data:{action:"onReady",height:c}}),clearInterval(window.timer),window.timer=setInterval(function(){r.scrollHeight!==c&&(c=r.scrollHeight,uni.postMessage({data:{action:"onHeightChange",height:c}}))},350)},window.onunload=function(){clearInterval(window.timer)};

View File

@@ -0,0 +1 @@
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function t(e,t){return n.call(e,t)}var i=[],a=function(e,n){var t={options:{timestamp:+new Date},name:e,arg:n};if(window.__dcloud_weex_postMessage||window.__dcloud_weex_){if("postMessage"===e){var a={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(a):window.__dcloud_weex_.postMessage(JSON.stringify(a))}var o={type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(o):window.__dcloud_weex_.postMessageToService(JSON.stringify(o))}if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:t,pageId:""},"*");if(0===i.length){var r=plus.webview.currentWebview();if(!r)throw new Error("plus.webview.currentWebview() is undefined");var d=r.parent(),s="";s=d?d.id:r.id,i.push(s)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}},"__uniapp__service");else{var w=JSON.stringify(t);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(w,",").concat(JSON.stringify(i),");"))}},o={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;a("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("redirectTo",{url:encodeURI(n)})},getEnv:function(e){window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a("postMessage",e.data||{})}},r=/uni-app/i.test(navigator.userAgent),d=/Html5Plus/i.test(navigator.userAgent),s=/complete|loaded|interactive/;var w=window.my&&navigator.userAgent.indexOf("AlipayClient")>-1;var u=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var v=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.qa&&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},f=[function(e){if(r||d)return window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&s.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),o},function(e){if(v)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(w){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(u)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(g)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(p){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){return document.addEventListener("DOMContentLoaded",e),o}],m=0;m<f.length&&!(l=f[m](_));m++);l||(l={});var E="undefined"!=typeof uni?uni:{};if(!E.navigateTo)for(var b in l)t(l,b)&&(E[b]=l[b]);return E.webView=l,E}));

View File

@@ -0,0 +1 @@
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><style>body,html{width:100%;height:100%;overflow-x:scroll;overflow-y:hidden}body{margin:0}video{width:300px;height:225px}img{max-width:100%;-webkit-touch-callout:none}</style></head><body><div id="content" style="overflow:hidden"></div><script type="text/javascript" src="./js/uni.webview.min.js"></script><script type="text/javascript" src="./js/handler.js"></script></body>