From e76028bf43b15bdfbd3a168b67bee31bbf80cb80 Mon Sep 17 00:00:00 2001 From: 86156 <823267011@qq.com> Date: Fri, 17 Apr 2026 12:07:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E5=8A=9E=E5=85=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/common/upload.js | 77 +- api/hrm/flow.js | 8 + package (2).json | 25 + pages.json | 45 +- pages/hrm/approve/approve.vue | 1158 +++++++++-------- pages/workbench/hrm/apply/apply.vue | 654 +--------- pages/workbench/hrm/leave/leave.vue | 978 +------------- pages/workbench/hrm/reimburse/reimburse.vue | 52 +- pages/workbench/hrm/seal/seal.vue | 51 +- pages/workbench/hrm/travel/travel.vue | 56 +- uni_modules/uni-file-picker/changelog.md | 10 + .../uni-file-picker/uni-file-picker.vue | 72 +- .../uni-file-picker/upload-file.vue | 16 +- .../uni-file-picker/upload-image.vue | 5 +- uni_modules/uni-file-picker/package.json | 101 +- uni_modules/uni-file-picker/readme.md | 3 +- util/oaRequest.js | 6 +- 17 files changed, 1008 insertions(+), 2309 deletions(-) create mode 100644 package (2).json diff --git a/api/common/upload.js b/api/common/upload.js index 9e4b7e3..9476d7b 100644 --- a/api/common/upload.js +++ b/api/common/upload.js @@ -1,7 +1,5 @@ import { getToken } from '@/util/auth' -import request from "@/util/oaRequest" - -const BASE_URL = 'http://110.41.139.73:8080' +import request, { BASE_URL } from "@/util/oaRequest" export function uploadImage(filePath) { console.log('[uploadImage] 开始上传:', filePath) @@ -53,81 +51,74 @@ export function uploadImage(filePath) { export function uploadFile(file, options = {}) { const { allowedTypes = ['doc', 'xls', 'ppt', 'txt', 'pdf', 'docx', 'xlsx', 'png', 'jpg', 'jpeg', 'zip', 'rar', '7z', 'dwg'], - maxSize = 200, // 默认200MB + maxSize = 200, extraData = 1 } = options return new Promise((resolve, reject) => { - // 文件类型验证 - const ext = file.name.split('.').pop().toLowerCase() - if (allowedTypes && !allowedTypes.includes(ext)) { - reject(new Error(`文件格式不正确,请上传${allowedTypes.join('/')}格式文件!`)) - return - } + const fileName = file?.name || file?.fileName || file?.originalName || '' + const filePath = file?.path || file?.tempFilePath || file?.url || file?.filePath || '' + const fileSize = Number(file?.size || 0) - // 文件大小验证 - if (maxSize && file.size / 1024 / 1024 > maxSize) { - reject(new Error(`上传文件大小不能超过 ${maxSize} MB!`)) - return - } + console.log('[uploadFile] 入参:', { fileName, filePath, fileSize, type: file?.type, raw: file }) - // 验证文件路径 - if (!file.path) { + if (!filePath) { reject(new Error('文件路径为空')) return } - console.log('[uploadFile] 开始上传文件:', { - name: file.name, - size: file.size, - path: file.path, - type: file.type - }) + const ext = (fileName.split('.').pop() || '').toLowerCase() + if (allowedTypes && ext && !allowedTypes.includes(ext)) { + reject(new Error(`文件格式不正确,请上传 ${allowedTypes.join('/')} 格式文件!`)) + return + } - // 处理文件路径(安卓平台) - let filePath = file.path + if (maxSize && fileSize > 0 && fileSize / 1024 / 1024 > maxSize) { + reject(new Error(`上传文件大小不能超过 ${maxSize} MB!`)) + return + } + + let realPath = filePath // #ifdef APP-PLUS - if (typeof plus !== 'undefined' && plus.io) { - if (!filePath.startsWith('/') && !filePath.startsWith('file://')) { - filePath = plus.io.convertLocalFileSystemURL(filePath) + if (typeof plus !== 'undefined' && plus.io && realPath && !realPath.startsWith('file://') && !realPath.startsWith('/')) { + try { + realPath = plus.io.convertLocalFileSystemURL(realPath) + } catch (e) { + console.warn('[uploadFile] 路径转换失败,使用原始路径', e) } } // #endif + console.log('[uploadFile] 开始上传文件:', { fileName, realPath, fileSize, type: file?.type }) + uni.uploadFile({ url: BASE_URL + '/system/oss/upload', - filePath, + filePath: realPath, name: 'file', - formData: { - isPublic: extraData - }, - header: { - 'Authorization': 'Bearer ' + getToken() - }, + formData: { isPublic: extraData }, + header: { Authorization: 'Bearer ' + getToken() }, success: (res) => { console.log('[uploadFile] 上传响应:', res) try { const data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data if (data.code === 200) { - console.log('[uploadFile] 上传成功:', data.data) resolve({ ossId: data.data.ossId, url: data.data.url, fileName: data.data.fileName, - originalName: file.name + originalName: fileName }) } else { - console.error('[uploadFile] 上传失败:', data) - reject(data.msg || '上传失败') + reject(new Error(data.msg || '上传失败')) } } catch (e) { console.error('[uploadFile] 解析返回数据失败:', e, res.data) - reject('上传返回格式错误') + reject(new Error('上传返回格式错误')) } }, fail: (err) => { console.error('[uploadFile] 上传接口调用失败:', err) - reject(err) + reject(new Error(err?.errMsg || err?.message || '上传失败')) } }) }) @@ -139,7 +130,7 @@ export function uploadFile(file, options = {}) { * @param {Object} options - 上传选项 * @returns {Promise} 返回上传结果数组 */ -export function uploadFiles(files, options = {}) { +export async function uploadFiles(files, options = {}) { const { allowedTypes = ['doc', 'xls', 'ppt', 'txt', 'pdf', 'docx', 'xlsx', 'png', 'jpg', 'jpeg', 'zip', 'rar', '7z', 'dwg'], maxSize = 200, @@ -205,7 +196,7 @@ export function listByIds(ossId) { * @param {Array} ossIds - OSS ID数组 * @returns {Promise} 返回文件信息数组 */ -export function getFilesByIds(ossIds) { +export async function getFilesByIds(ossIds) { if (!ossIds || ossIds.length === 0) { return Promise.resolve([]) } diff --git a/api/hrm/flow.js b/api/hrm/flow.js index 7880b75..2416c9e 100644 --- a/api/hrm/flow.js +++ b/api/hrm/flow.js @@ -25,6 +25,14 @@ export function listTodoFlowTask(assigneeUserId) { }) } +export function listDoneFlowTask(userId, query) { + return request({ + url: '/hrm/flow/task/historyList', + method: 'get', + params: { pageNum: 1, pageSize: 200, ...query } + }) +} + // 业务维度:按 bizType + bizId 查询当前待办任务(后端需提供) export function getTodoTaskByBiz(bizType, bizId, assigneeUserId) { return request({ diff --git a/package (2).json b/package (2).json new file mode 100644 index 0000000..709d6b8 --- /dev/null +++ b/package (2).json @@ -0,0 +1,25 @@ +{ + "id": "x-native-uploader", + "name": "x-native-uploader 原生文件上传组件", + "displayName": "x-native-uploader 原生文件上传组件", + "version": "1.0.2", + "description": "跨平台的文件上传组件,专为解决 UniApp 在 App 端文件选择与上传的痛点而设计。它集成了 Native.js 的能力,支持在 Android 和 iOS 上调用原生文件选择器", + "keywords": [ + "文件上传" + ], + "dcloudext": { + "type": "component-vue", + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + } + }, + "uni_modules": { + "dependencies": [], + "encrypt": [] + } +} \ No newline at end of file diff --git a/pages.json b/pages.json index da8d436..935ca99 100644 --- a/pages.json +++ b/pages.json @@ -1,6 +1,5 @@ { "pages": [ - //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages { "path": "pages/login/index" }, @@ -558,6 +557,41 @@ "navigationStyle": "default" } }, + { + "path": "pages/workbench/hrm/leave/leave", + "style": { + "navigationBarTitleText": "请假申请", + "navigationStyle": "default" + } + }, + { + "path": "pages/workbench/hrm/travel/travel", + "style": { + "navigationBarTitleText": "出差申请", + "navigationStyle": "default" + } + }, + { + "path": "pages/workbench/hrm/seal/seal", + "style": { + "navigationBarTitleText": "用印申请", + "navigationStyle": "default" + } + }, + { + "path": "pages/workbench/hrm/reimburse/reimburse", + "style": { + "navigationBarTitleText": "报销申请", + "navigationStyle": "default" + } + }, + { + "path": "pages/workbench/hrm/apply/apply", + "style": { + "navigationBarTitleText": "拨款申请", + "navigationStyle": "default" + } + }, { "path": "pages/workbench/hrm/approve/approve", "style": { @@ -579,18 +613,11 @@ "navigationStyle": "default" } }, - { - "path": "pages/workbench/hrm/apply/apply", - "style": { - "navigationBarTitleText": "我的申请", - "navigationStyle": "default" - } - }, { "path": "pages/hrm/approve/approve", "style": { "navigationBarTitleText": "办公审批", - "navigationStyle": "default" + "navigationStyle": "custom" } } ], diff --git a/pages/hrm/approve/approve.vue b/pages/hrm/approve/approve.vue index 89d0569..fba72ec 100644 --- a/pages/hrm/approve/approve.vue +++ b/pages/hrm/approve/approve.vue @@ -1,632 +1,640 @@ \ No newline at end of file diff --git a/pages/workbench/hrm/apply/apply.vue b/pages/workbench/hrm/apply/apply.vue index 120c987..560bf52 100644 --- a/pages/workbench/hrm/apply/apply.vue +++ b/pages/workbench/hrm/apply/apply.vue @@ -1,627 +1,43 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/pages/workbench/hrm/leave/leave.vue b/pages/workbench/hrm/leave/leave.vue index 1f29314..fa45e4d 100644 --- a/pages/workbench/hrm/leave/leave.vue +++ b/pages/workbench/hrm/leave/leave.vue @@ -1,946 +1,50 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/pages/workbench/hrm/reimburse/reimburse.vue b/pages/workbench/hrm/reimburse/reimburse.vue index 87b6899..e4c7fcb 100644 --- a/pages/workbench/hrm/reimburse/reimburse.vue +++ b/pages/workbench/hrm/reimburse/reimburse.vue @@ -1,22 +1,44 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/pages/workbench/hrm/seal/seal.vue b/pages/workbench/hrm/seal/seal.vue index 87b6899..9571623 100644 --- a/pages/workbench/hrm/seal/seal.vue +++ b/pages/workbench/hrm/seal/seal.vue @@ -1,22 +1,43 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/pages/workbench/hrm/travel/travel.vue b/pages/workbench/hrm/travel/travel.vue index 87b6899..0e84c10 100644 --- a/pages/workbench/hrm/travel/travel.vue +++ b/pages/workbench/hrm/travel/travel.vue @@ -1,22 +1,48 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/uni_modules/uni-file-picker/changelog.md b/uni_modules/uni-file-picker/changelog.md index fa33677..5320eb2 100644 --- a/uni_modules/uni-file-picker/changelog.md +++ b/uni_modules/uni-file-picker/changelog.md @@ -1,3 +1,13 @@ +## 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) 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 index 872cf74..cf67ac7 100644 --- 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 @@ -4,17 +4,13 @@ {{ title }} {{ filesList.length }}/{{ limitLength }} - + - + @@ -181,18 +177,23 @@ sourceType: { type: Array, default () { - return ['album', 'camera'] + return ['album', 'camera'] } }, provider: { type: String, default: '' // 默认上传到 unicloud 内置存储 extStorage 扩展存储 + }, + dir: { + type: String, + default: '' } }, data() { return { files: [], - localValue: [] + localValue: [], + dirPath: '' } }, watch: { @@ -208,6 +209,12 @@ }, immediate: true }, + dir: { + handler(newVal) { + this.dirPath = newVal + }, + immediate: true + }, }, computed: { filesList() { @@ -282,19 +289,19 @@ return this.uploadFiles(files) }, async setValue(newVal, oldVal) { - const newData = async (v) => { + const newData = async (v) => { const reg = /cloud:\/\/([\w.]+\/?)\S*/ let url = '' - if(v.fileID){ + if (v.fileID) { url = v.fileID - }else{ + } else { url = v.url } if (reg.test(url)) { v.fileID = url v.url = await this.getTempFileURL(url) } - if(v.url) v.path = v.url + if (v.url) v.path = v.url return v } if (this.returnType === 'object') { @@ -305,13 +312,13 @@ } } else { if (!newVal) newVal = [] - for(let i =0 ;i < newVal.length ;i++){ + for (let i = 0; i < newVal.length; i++) { let v = newVal[i] await newData(v) } } this.localValue = newVal - if (this.form && this.formItem &&!this.is_reset) { + if (this.form && this.formItem && !this.is_reset) { this.is_reset = false this.formItem.setValue(this.localValue) } @@ -368,7 +375,9 @@ * @param {Object} res */ async chooseFileCallback(res) { + const _extname = get_extname(this.fileExtname) + const is_one = (Number(this.limitLength) === 1 && this.disablePreview && !this.disabled) || @@ -394,11 +403,13 @@ let filedata = await get_file_data(files[i], this.fileMediatype) filedata.progress = 0 filedata.status = 'ready' - this.files.push(filedata) - currentData.push({ + // fix by mehaotian ,统一返回,删除也包含file对象 + let fileTempData = { ...filedata, file: files[i] - }) + } + this.files.push(fileTempData) + currentData.push(fileTempData) } this.$emit('select', { tempFiles: currentData, @@ -409,13 +420,24 @@ if (!this.autoUpload || this.noSpace) { res.tempFiles = [] } - res.tempFiles.forEach((fileItem, index) => { + res.tempFiles.map((fileItem, index) => { this.provider && (fileItem.provider = this.provider); const fileNameSplit = fileItem.name.split('.') const ext = fileNameSplit.pop() const fileName = fileNameSplit.join('.').replace(/[\s\/\?<>\\:\*\|":]/g, '_') - fileItem.cloudPath = fileName + '_' + Date.now() + '_' + index + '.' + ext + // 选择文件目录上传 + let dir = this.dirPath || ''; // 防止用户传入的 dir 不正常 + // 检查最后一个字符是否为 '/'(同时处理空字符串情况) + if (dir && dir[dir.length - 1] !== '/') { + dir += '/'; + } + + fileItem.cloudPath = dir + fileName + '_' + Date.now() + '_' + index + '.' + ext + fileItem.cloudPathAsRealPath = true + + return fileItem }) + return res }, /** @@ -462,7 +484,7 @@ const reg = /cloud:\/\/([\w.]+\/?)\S*/ if (reg.test(item.url)) { this.files[index].url = await this.getTempFileURL(item.url) - }else{ + } else { this.files[index].url = item.url } @@ -551,7 +573,7 @@ let data = [] if (this.returnType === 'object') { data = this.backObject(this.files)[0] - this.localValue = data?data:null + this.localValue = data ? data : null } else { data = this.backObject(this.files) if (!this.localValue) { @@ -581,12 +603,12 @@ name: v.name, path: v.path, size: v.size, - fileID:v.fileID, + fileID: v.fileID, url: v.url, // 修改删除一个文件后不能再上传的bug, #694 - uuid: v.uuid, - status: v.status, - cloudPath: v.cloudPath + uuid: v.uuid, + status: v.status, + cloudPath: v.cloudPath }) }) return newFilesData 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 index 625d92e..0d26379 100644 --- 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 @@ -8,8 +8,7 @@ + 'files-border':index !== 0 && styles.dividline}" :style="index !== 0 && styles.dividline &&borderLineStyle">