diff --git a/.env b/.env
new file mode 100644
index 0000000..f9faf53
--- /dev/null
+++ b/.env
@@ -0,0 +1,2 @@
+# API
+VITE_SYSTEM_URL = "http://ge465bd9.natappfree.cc"
\ No newline at end of file
diff --git a/components/cb-file-picker/cb-file-picker.vue b/components/cb-file-picker/cb-file-picker.vue
new file mode 100644
index 0000000..a052557
--- /dev/null
+++ b/components/cb-file-picker/cb-file-picker.vue
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 上传
+
+
+
+ 身份证{{ props.isFront ? '人像面' : '国徽面' }}
+
+
+
+
+
diff --git a/pages.json b/pages.json
index 0a82779..f0cfc60 100644
--- a/pages.json
+++ b/pages.json
@@ -87,6 +87,20 @@
"navigationBarBackgroundColor": "#ffffff"
}
},
+ {
+ "path": "pages/my-index/wallet/real-id",
+ "style": {
+ "navigationBarTitleText": "实名认证",
+ "navigationBarBackgroundColor": "#ffffff"
+ }
+ },
+ {
+ "path": "pages/my-index/my-team",
+ "style": {
+ "navigationBarTitleText": "我的团队",
+ "navigationBarBackgroundColor": "#ffffff"
+ }
+ },
{
"path": "pages/my-index/wallet/bank-card/card-details",
"style": {
diff --git a/pages/my-index/components/card-input.vue b/pages/my-index/components/card-input.vue
index 1e5c8ff..c58d350 100644
--- a/pages/my-index/components/card-input.vue
+++ b/pages/my-index/components/card-input.vue
@@ -1,4 +1,11 @@
+
+
+
+
+
+
+ 我的团队(人)
+ 2933
+
+
+
+
+
+
+
diff --git a/pages/my-index/wallet/bank-card/card-details.vue b/pages/my-index/wallet/bank-card/card-details.vue
index 3e9cff5..341a90a 100644
--- a/pages/my-index/wallet/bank-card/card-details.vue
+++ b/pages/my-index/wallet/bank-card/card-details.vue
@@ -51,6 +51,9 @@
stateData.state === '101' ? '支付宝账号' : '微信账号'
}`"
>
+
+
+
diff --git a/pages/my-index/wallet/index.vue b/pages/my-index/wallet/index.vue
index 6b241c0..2926ccf 100644
--- a/pages/my-index/wallet/index.vue
+++ b/pages/my-index/wallet/index.vue
@@ -13,7 +13,7 @@
key: '3',
url: '/pages/my-index/wallet/edit-password'
},
- { title: '实名认证', key: '4', url: '' }
+ { title: '实名认证', key: '4', url: '/pages/my-index/wallet/real-id' }
]
@@ -23,7 +23,7 @@
我的资产
- 2222
+ 1222
diff --git a/pages/my-index/wallet/real-id.vue b/pages/my-index/wallet/real-id.vue
new file mode 100644
index 0000000..2fab6d3
--- /dev/null
+++ b/pages/my-index/wallet/real-id.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+ *为保证您的账户安全,请先完成实名认证
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static/images/my-index/id-front.png b/static/images/my-index/id-front.png
new file mode 100644
index 0000000..6c2c3ac
Binary files /dev/null and b/static/images/my-index/id-front.png differ
diff --git a/static/images/my-index/id-opposite.png b/static/images/my-index/id-opposite.png
new file mode 100644
index 0000000..5d68e90
Binary files /dev/null and b/static/images/my-index/id-opposite.png differ
diff --git a/static/images/my-index/team-bg.png b/static/images/my-index/team-bg.png
new file mode 100644
index 0000000..a15d0d9
Binary files /dev/null and b/static/images/my-index/team-bg.png differ
diff --git a/uni_modules/uni-file-picker/changelog.md b/uni_modules/uni-file-picker/changelog.md
new file mode 100644
index 0000000..5320eb2
--- /dev/null
+++ b/uni_modules/uni-file-picker/changelog.md
@@ -0,0 +1,91 @@
+## 1.1.3(2025-12-03)
+- 修复: 腾讯云目录错误导致的上传错误问题
+## 1.1.2(2025-09-17)
+- 修复 设置readonly属性后内容插槽失效的问题。
+## 1.1.1(2025-09-03)
+- 修复 动态dir目录,不生效的问题
+## 1.1.0(2025-09-02)
+- 新增 dir 属性,可以选择上传目录
+## 1.0.13(2025-08-18)
+- 修复 删除文件后,返回信息不包含file对象的问题
+## 1.0.12(2025-04-14)
+- 修复 支付宝小程序 上传样式问题
+## 1.0.10(2024-07-09)
+- 优化 vue3兼容性
+## 1.0.9(2024-07-09)
+- 修复 value 属性不兼容vue3的bug
+## 1.0.8(2024-03-20)
+- 补充 删除文件时返回文件下标
+## 1.0.7(2024-02-21)
+- 新增 微信小程序选择视频时改用chooseMedia,并返回视频缩略图
+## 1.0.6(2024-01-06)
+- 新增 微信小程序不再调用chooseImage,而是调用chooseMedia
+## 1.0.5(2024-01-03)
+- 新增 上传文件至云存储携带本地文件名称
+## 1.0.4(2023-03-29)
+- 修复 手动上传删除一个文件后不能再上传的bug
+## 1.0.3(2022-12-19)
+- 新增 sourceType 属性, 可以自定义图片和视频选择的来源
+## 1.0.2(2022-07-04)
+- 修复 在uni-forms下样式不生效的bug
+## 1.0.1(2021-11-23)
+- 修复 参数为对象的情况下,url在某些情况显示错误的bug
+## 1.0.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-file-picker](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
+## 0.2.16(2021-11-08)
+- 修复 传入空对象 ,显示错误的Bug
+## 0.2.15(2021-08-30)
+- 修复 return-type="object" 时且存在v-model时,无法删除文件的Bug
+## 0.2.14(2021-08-23)
+- 新增 参数中返回 fileID 字段
+## 0.2.13(2021-08-23)
+- 修复 腾讯云传入fileID 不能回显的bug
+- 修复 选择图片后,不能放大的问题
+## 0.2.12(2021-08-17)
+- 修复 由于 0.2.11 版本引起的不能回显图片的Bug
+## 0.2.11(2021-08-16)
+- 新增 clearFiles(index) 方法,可以手动删除指定文件
+- 修复 v-model 值设为 null 报错的Bug
+## 0.2.10(2021-08-13)
+- 修复 return-type="object" 时,无法删除文件的Bug
+## 0.2.9(2021-08-03)
+- 修复 auto-upload 属性失效的Bug
+## 0.2.8(2021-07-31)
+- 修复 fileExtname属性不指定值报错的Bug
+## 0.2.7(2021-07-31)
+- 修复 在某种场景下图片不回显的Bug
+## 0.2.6(2021-07-30)
+- 修复 return-type为object下,返回值不正确的Bug
+## 0.2.5(2021-07-30)
+- 修复(重要) H5 平台下如果和uni-forms组件一同使用导致页面卡死的问题
+## 0.2.3(2021-07-28)
+- 优化 调整示例代码
+## 0.2.2(2021-07-27)
+- 修复 vue3 下赋值错误的Bug
+- 优化 h5平台下上传文件导致页面卡死的问题
+## 0.2.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 0.1.1(2021-07-02)
+- 修复 sourceType 缺少默认值导致 ios 无法选择文件
+## 0.1.0(2021-06-30)
+- 优化 解耦与uniCloud的强绑定关系 ,如不绑定服务空间,默认autoUpload为false且不可更改
+## 0.0.11(2021-06-30)
+- 修复 由 0.0.10 版本引发的 returnType 属性失效的问题
+## 0.0.10(2021-06-29)
+- 优化 文件上传后进度条消失时机
+## 0.0.9(2021-06-29)
+- 修复 在uni-forms 中,删除文件 ,获取的值不对的Bug
+## 0.0.8(2021-06-15)
+- 修复 删除文件时无法触发 v-model 的Bug
+## 0.0.7(2021-05-12)
+- 新增 组件示例地址
+## 0.0.6(2021-04-09)
+- 修复 选择的文件非 file-extname 字段指定的扩展名报错的Bug
+## 0.0.5(2021-04-09)
+- 优化 更新组件示例
+## 0.0.4(2021-04-09)
+- 优化 file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔
+## 0.0.3(2021-02-05)
+- 调整为uni_modules目录规范
+- 修复 微信小程序不指定 fileExtname 属性选择失败的Bug
diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js b/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
new file mode 100644
index 0000000..9c6bcdf
--- /dev/null
+++ b/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
@@ -0,0 +1,287 @@
+'use strict';
+
+const ERR_MSG_OK = 'chooseAndUploadFile:ok';
+const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
+
+function chooseImage(opts) {
+ const {
+ count,
+ sizeType = ['original', 'compressed'],
+ sourceType,
+ extension
+ } = opts
+ return new Promise((resolve, reject) => {
+ // 微信由于旧接口不再维护,针对微信小程序平台改用chooseMedia接口
+ // #ifdef MP-WEIXIN
+ uni.chooseMedia({
+ count,
+ sizeType,
+ sourceType,
+ mediaType: ['image'],
+ extension,
+ success(res) {
+ res.tempFiles.forEach(item => {
+ item.path = item.tempFilePath;
+ })
+ resolve(normalizeChooseAndUploadFileRes(res, 'image'));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
+ });
+ },
+ })
+ // #endif
+ // #ifndef MP-WEIXIN
+ uni.chooseImage({
+ count,
+ sizeType,
+ sourceType,
+ extension,
+ success(res) {
+ resolve(normalizeChooseAndUploadFileRes(res, 'image'));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ // #endif
+
+ });
+}
+
+function chooseVideo(opts) {
+ const {
+ count,
+ camera,
+ compressed,
+ maxDuration,
+ sourceType,
+ extension
+ } = opts;
+ return new Promise((resolve, reject) => {
+ // 微信由于旧接口不再维护,针对微信小程序平台改用chooseMedia接口
+ // #ifdef MP-WEIXIN
+ uni.chooseMedia({
+ count,
+ compressed,
+ maxDuration,
+ sourceType,
+ extension,
+ mediaType: ['video'],
+ success(res) {
+ const {
+ tempFiles,
+ } = res;
+ resolve(normalizeChooseAndUploadFileRes({
+ errMsg: 'chooseVideo:ok',
+ tempFiles: tempFiles.map(item => {
+ return {
+ name: item.name || '',
+ path: item.tempFilePath,
+ thumbTempFilePath: item.thumbTempFilePath,
+ size:item.size,
+ type: (res.tempFile && res.tempFile.type) || '',
+ width:item.width,
+ height:item.height,
+ duration:item.duration,
+ fileType: 'video',
+ cloudPath: '',
+ }
+ }),
+ }, 'video'));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
+ });
+ },
+ })
+ // #endif
+ // #ifndef MP-WEIXIN
+ uni.chooseVideo({
+ camera,
+ compressed,
+ maxDuration,
+ sourceType,
+ extension,
+ success(res) {
+ const {
+ tempFilePath,
+ duration,
+ size,
+ height,
+ width
+ } = res;
+ resolve(normalizeChooseAndUploadFileRes({
+ errMsg: 'chooseVideo:ok',
+ tempFilePaths: [tempFilePath],
+ tempFiles: [{
+ name: (res.tempFile && res.tempFile.name) || '',
+ path: tempFilePath,
+ size,
+ type: (res.tempFile && res.tempFile.type) || '',
+ width,
+ height,
+ duration,
+ fileType: 'video',
+ cloudPath: '',
+ }, ],
+ }, 'video'));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ // #endif
+ });
+}
+
+function chooseAll(opts) {
+ const {
+ count,
+ extension
+ } = opts;
+ return new Promise((resolve, reject) => {
+ let chooseFile = uni.chooseFile;
+ if (typeof wx !== 'undefined' &&
+ typeof wx.chooseMessageFile === 'function') {
+ chooseFile = wx.chooseMessageFile;
+ }
+ if (typeof chooseFile !== 'function') {
+ return reject({
+ errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
+ });
+ }
+ chooseFile({
+ type: 'all',
+ count,
+ extension,
+ success(res) {
+ resolve(normalizeChooseAndUploadFileRes(res));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ });
+}
+
+function normalizeChooseAndUploadFileRes(res, fileType) {
+ res.tempFiles.forEach((item, index) => {
+ if (!item.name) {
+ item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
+ }
+ if (fileType) {
+ item.fileType = fileType;
+ }
+ item.cloudPath =
+ Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
+ });
+ if (!res.tempFilePaths) {
+ res.tempFilePaths = res.tempFiles.map((file) => file.path);
+ }
+ return res;
+}
+
+function uploadCloudFiles(files, max = 5, onUploadProgress) {
+ files = JSON.parse(JSON.stringify(files))
+ const len = files.length
+ let count = 0
+ let self = this
+ return new Promise(resolve => {
+ while (count < max) {
+ next()
+ }
+
+ function next() {
+ let cur = count++
+ if (cur >= len) {
+ !files.find(item => !item.url && !item.errMsg) && resolve(files)
+ return
+ }
+ const fileItem = files[cur]
+ const index = self.files.findIndex(v => v.uuid === fileItem.uuid)
+ fileItem.url = ''
+ delete fileItem.errMsg
+
+ uniCloud
+ .uploadFile({
+ filePath: fileItem.path,
+ cloudPath: fileItem.cloudPath,
+ fileType: fileItem.fileType,
+ onUploadProgress: res => {
+ res.index = index
+ onUploadProgress && onUploadProgress(res)
+ }
+ })
+ .then(res => {
+ fileItem.url = res.fileID
+ fileItem.index = index
+ if (cur < len) {
+ next()
+ }
+ })
+ .catch(res => {
+ fileItem.errMsg = res.errMsg || res.message
+ fileItem.index = index
+ if (cur < len) {
+ next()
+ }
+ })
+ }
+ })
+}
+
+
+
+
+
+function uploadFiles(choosePromise, {
+ onChooseFile,
+ onUploadProgress
+}) {
+ return choosePromise
+ .then((res) => {
+ if (onChooseFile) {
+ const customChooseRes = onChooseFile(res);
+ if (typeof customChooseRes !== 'undefined') {
+ return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ?
+ res : chooseRes);
+ }
+ }
+ return res;
+ })
+ .then((res) => {
+ if (res === false) {
+ return {
+ errMsg: ERR_MSG_OK,
+ tempFilePaths: [],
+ tempFiles: [],
+ };
+ }
+ return res
+ })
+}
+
+function chooseAndUploadFile(opts = {
+ type: 'all'
+}) {
+ if (opts.type === 'image') {
+ return uploadFiles(chooseImage(opts), opts);
+ } else if (opts.type === 'video') {
+ return uploadFiles(chooseVideo(opts), opts);
+ }
+ return uploadFiles(chooseAll(opts), opts);
+}
+
+export {
+ chooseAndUploadFile,
+ uploadCloudFiles
+};
diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue b/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
new file mode 100644
index 0000000..cf67ac7
--- /dev/null
+++ b/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
@@ -0,0 +1,680 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue b/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
new file mode 100644
index 0000000..0d26379
--- /dev/null
+++ b/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
@@ -0,0 +1,323 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.name}}
+
+
+
+
+
+
+
+
+
+ 点击重试
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue b/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue
new file mode 100644
index 0000000..0ce5eb7
--- /dev/null
+++ b/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue
@@ -0,0 +1,285 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 点击重试
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/utils.js b/uni_modules/uni-file-picker/components/uni-file-picker/utils.js
new file mode 100644
index 0000000..1bc9259
--- /dev/null
+++ b/uni_modules/uni-file-picker/components/uni-file-picker/utils.js
@@ -0,0 +1,110 @@
+/**
+ * 获取文件名和后缀
+ * @param {String} name
+ */
+export const get_file_ext = (name) => {
+ const last_len = name.lastIndexOf('.')
+ const len = name.length
+ return {
+ name: name.substring(0, last_len),
+ ext: name.substring(last_len + 1, len)
+ }
+}
+
+/**
+ * 获取扩展名
+ * @param {Array} fileExtname
+ */
+export const get_extname = (fileExtname) => {
+ if (!Array.isArray(fileExtname)) {
+ let extname = fileExtname.replace(/(\[|\])/g, '')
+ return extname.split(',')
+ } else {
+ return fileExtname
+ }
+ return []
+}
+
+/**
+ * 获取文件和检测是否可选
+ */
+export const get_files_and_is_max = (res, _extname) => {
+ let filePaths = []
+ let files = []
+ if(!_extname || _extname.length === 0){
+ return {
+ filePaths,
+ files
+ }
+ }
+ res.tempFiles.forEach(v => {
+ let fileFullName = get_file_ext(v.name)
+ const extname = fileFullName.ext.toLowerCase()
+ if (_extname.indexOf(extname) !== -1) {
+ files.push(v)
+ filePaths.push(v.path)
+ }
+ })
+ if (files.length !== res.tempFiles.length) {
+ uni.showToast({
+ title: `当前选择了${res.tempFiles.length}个文件 ,${res.tempFiles.length - files.length} 个文件格式不正确`,
+ icon: 'none',
+ duration: 5000
+ })
+ }
+
+ return {
+ filePaths,
+ files
+ }
+}
+
+
+/**
+ * 获取图片信息
+ * @param {Object} filepath
+ */
+export const get_file_info = (filepath) => {
+ return new Promise((resolve, reject) => {
+ uni.getImageInfo({
+ src: filepath,
+ success(res) {
+ resolve(res)
+ },
+ fail(err) {
+ reject(err)
+ }
+ })
+ })
+}
+/**
+ * 获取封装数据
+ */
+export const get_file_data = async (files, type = 'image') => {
+ // 最终需要上传数据库的数据
+ let fileFullName = get_file_ext(files.name)
+ const extname = fileFullName.ext.toLowerCase()
+ let filedata = {
+ name: files.name,
+ uuid: files.uuid,
+ extname: extname || '',
+ cloudPath: files.cloudPath,
+ fileType: files.fileType,
+ thumbTempFilePath: files.thumbTempFilePath,
+ url: files.path || files.path,
+ size: files.size, //单位是字节
+ image: {},
+ path: files.path,
+ video: {}
+ }
+ if (type === 'image') {
+ const imageinfo = await get_file_info(files.path)
+ delete filedata.video
+ filedata.image.width = imageinfo.width
+ filedata.image.height = imageinfo.height
+ filedata.image.location = imageinfo.path
+ } else {
+ delete filedata.image
+ }
+ return filedata
+}
diff --git a/uni_modules/uni-file-picker/package.json b/uni_modules/uni-file-picker/package.json
new file mode 100644
index 0000000..b13e315
--- /dev/null
+++ b/uni_modules/uni-file-picker/package.json
@@ -0,0 +1,105 @@
+{
+ "id": "uni-file-picker",
+ "displayName": "uni-file-picker 文件选择上传",
+ "version": "1.1.3",
+ "description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "图片上传",
+ "文件上传"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": "",
+ "uni-app": "^4.33",
+ "uni-app-x": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue",
+ "darkmode": "x",
+ "i18n": "x",
+ "widescreen": "x"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "√",
+ "aliyun": "√",
+ "alipay": "√"
+ },
+ "client": {
+ "uni-app": {
+ "vue": {
+ "vue2": "√",
+ "vue3": "√"
+ },
+ "web": {
+ "safari": "√",
+ "chrome": "√"
+ },
+ "app": {
+ "vue": "√",
+ "nvue": "-",
+ "android": "√",
+ "ios": "√",
+ "harmony": "√"
+ },
+ "mp": {
+ "weixin": "√",
+ "alipay": "√",
+ "toutiao": "√",
+ "baidu": "√",
+ "kuaishou": "√",
+ "jd": "-",
+ "harmony": "-",
+ "qq": "√",
+ "lark": "-"
+ },
+ "quickapp": {
+ "huawei": "√",
+ "union": "√"
+ }
+ },
+ "uni-app-x": {
+ "web": {
+ "safari": "-",
+ "chrome": "-"
+ },
+ "app": {
+ "android": "-",
+ "ios": "-",
+ "harmony": "-"
+ },
+ "mp": {
+ "weixin": "-"
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-file-picker/readme.md b/uni_modules/uni-file-picker/readme.md
new file mode 100644
index 0000000..7393e6c
--- /dev/null
+++ b/uni_modules/uni-file-picker/readme.md
@@ -0,0 +1,10 @@
+
+## FilePicker 文件选择上传
+
+> **组件名:uni-file-picker**
+> 代码块: `uFilePicker`
+
+
+文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
\ No newline at end of file
diff --git a/utils/request.js b/utils/request.js
index dc54999..3a0ff57 100644
--- a/utils/request.js
+++ b/utils/request.js
@@ -1,6 +1,6 @@
import { getToken, removeToken } from './storage'
-const BASE_URL = 'http://c36bd4b4.natappfree.cc'
+const BASE_URL = import.meta.env.VITE_SYSTEM_URL
/**
* 网络请求封装
@@ -14,7 +14,7 @@ const request = options => {
method: 'GET',
data: {},
header: {
- 'deviceId': uni.getDeviceInfo().deviceId,
+ deviceId: uni.getDeviceInfo().deviceId,
'Content-Type': 'application/json' // 默认请求内容类型
}
}
diff --git a/utils/uploadFile.js b/utils/uploadFile.js
new file mode 100644
index 0000000..61e69a3
--- /dev/null
+++ b/utils/uploadFile.js
@@ -0,0 +1,134 @@
+import { getToken } from './storage'
+
+/**
+ * 二次封装的uni.uploadFile方法 (Promise化)
+ * @param {string} filePath - 要上传的文件路径
+ * @param {Object} [config] - 可选配置项
+ * @param {string} [config.url] - 上传接口地址,若不传则使用默认或全局配置
+ * @param {string} [config.name='file'] - 文件对应的 key
+ * @param {Object} [config.formData={}] - 额外的 form data
+ * @param {Object} [config.header] - 请求头,可覆盖默认头
+ * @param {number} [config.timeout] - 超时时间(ms)
+ * @returns {Promise} 返回一个Promise对象,成功时解析上传响应数据
+ */
+export const uploadSingleFile = (filePath, config = {}) => {
+ // 默认配置,可从全局导入或在此定义
+ const DEFAULT_CONFIG = {
+ baseURL: import.meta.env.VITE_SYSTEM_URL,
+ // timeout: 30000,
+ name: 'file',
+ header: {
+ deviceId: uni.getDeviceInfo().deviceId,
+ Authorization: `Bearer ${getToken()}`
+ }
+ }
+
+ // 合并配置
+ const mergedConfig = {
+ ...DEFAULT_CONFIG,
+ ...config,
+ header: {
+ ...DEFAULT_CONFIG.header
+ }
+ }
+
+ const { baseURL, ...uploadOptions } = mergedConfig
+ const finalUrl = baseURL
+ ? `${baseURL}${uploadOptions.url || ''}`
+ : uploadOptions.url
+
+ if (!finalUrl) {
+ return Promise.reject(new Error('上传接口地址不能为空'))
+ }
+
+ return new Promise((resolve, reject) => {
+ uni.showLoading({
+ title: '上传中...',
+ mask: true // 防止触摸穿透
+ })
+ const uploadTask = uni.uploadFile({
+ url: finalUrl,
+ filePath: filePath,
+ name: uploadOptions.name,
+ formData: uploadOptions.formData,
+ header: uploadOptions.header,
+ timeout: uploadOptions.timeout,
+ success: res => {
+ uni.hideLoading()
+ if (res.statusCode === 200) {
+ try {
+ // 尝试解析返回数据,假设是
+ const data =
+ typeof res.data === 'string'
+ ? JSON.parse(res.data)
+ : res.data
+ // 验证失效去登录页
+ if (data.code === 401) {
+ uni.removeStorage({
+ key: 'token'
+ })
+ uni.reLaunch({
+ url: '/pages/login/login'
+ })
+ return
+ }
+ if (data.code === 200) {
+ console.log('上传成功:', data)
+ resolve(data.url) // 根据后端实际结构,可能需进一步处理,如 data.data.url
+ return
+ }
+
+ uni.showToast({
+ title: data.msg || '请求失败',
+ icon: 'none'
+ })
+ } catch (e) {
+ // 解析失败可能返回的是字符串,直接返回
+ resolve(res.data)
+ }
+ return
+ }
+
+ reject(new Error(`上传失败,状态码: ${res.statusCode}`))
+ },
+ fail: err => {
+ uni.hideLoading()
+ reject(err)
+ }
+ })
+
+ // 可选:监听上传进度事件[6](@ref)
+ uploadTask.onProgressUpdate(res => {
+ console.log('上传进度:', res.progress)
+ console.log('已上传:', res.totalBytesSent, '字节')
+ console.log('总大小:', res.totalBytesExpectedToSend, '字节')
+ if (res.progress !== 100) {
+ uni.showLoading({
+ title: `업로드 진행: ${res.progress}`,
+ mask: true // 防止触摸穿透
+ })
+ }
+ // 可通过自定义事件或回调函数将进度传递出去
+ if (typeof config.onProgress === 'function') {
+ config.onProgress(res)
+ }
+ })
+ })
+}
+
+/**
+ * 多文件上传
+ * @param {Array} filePaths - 文件路径数组
+ * @param {Object} config - 同uploadSingleFile的config
+ * @returns {Promise} 返回一个Promise,解析为所有上传结果数组
+ */
+export const uploadMultipleFiles = (filePaths, config = {}) => {
+ // 使用Promise.all同时发起所有上传请求[3,4](@ref)
+ const uploadPromises = filePaths.map(
+ filePath =>
+ uploadSingleFile(filePath, config)
+ .then(res => ({ status: 'fulfilled', value: res })) // 成功,记录结果
+ .catch(err => ({ status: 'rejected', reason: err })) // 失败,记录原因
+ )
+ return Promise.all(uploadPromises)
+}