refactor: 合并 biz_support_unit/biz_execution_unit/biz_service_org 为 biz_org, 删除 2 张孤儿表, 改 biz_person.work_unit → org_id FK

主要改动:
- SQL: biz_support_unit → biz_org, 加 org_type, 加 business_nature; 删 biz_execution_unit, biz_service_org
- SQL: biz_project.support_unit_id/name + service_org_id/name → org_id/name/type
- SQL: biz_meeting.support_unit_name → org_name
- SQL: biz_person.work_unit → org_id (FK)
- 后端: 新 BizOrg entity/mapper/service/controller
- 后端: BizProject/BizMeeting 字段重命名
- 后端: 删 12 个 BizSupportUnit/BizExecutionUnit/BizServiceOrg Java 文件
- 后端: BizPersonImportVO.workUnit → orgName (导入时查 biz_org 取 org_id)
- 后端: BizAuthController.registerExecutor 完整实现 (原 registerSupplier stub)
- 前端: 新 admin/Orgs.vue + manager/Orgs.vue (原 SupportUnits)
- 前端: RegisterExecutor.vue (原 RegisterSupplier, 单页 2 步)
- 前端: sponsor/executor/manager 多个文件 workUnit → orgId/orgName 重命名
- 前端: 统一 supplier → executor, 业务命名 sponsor(赞助方) / executor(执行方=供应商)
- 前端: 全工程 execution → executor (company type / role / person unit_type)
This commit is contained in:
郭庆泰
2026-08-15 12:41:10 +08:00
commit cf5790229a
694 changed files with 102090 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
// OSS 直传工具 - 配合后端 /common/oss/sign
// 流程: 1) GET /common/oss/sign?dir=xxx 拿签名
// 2) POST 到 OSS bucket, formData 携带 policy/signature/key/accessKeyId
// 3) 拿回 OSS URL 写回表单
import request from '@/utils/request'
/**
* 获取 OSS 上传签名
* @param {string} dir 上传目录 (如 'ry8080/invitation/')
* @returns {Promise<{host, dir, accessKeyId, policy, signature, expire}>}
*/
export async function getOssSign(dir) {
const res = await request({
url: '/common/oss/sign',
method: 'get',
params: { dir }
})
if (res.code !== 200) {
throw new Error(res.msg || 'OSS 签名失败')
}
return res
}
/**
* 直接上传 File 到 OSS bucket
* @param {File} file 要上传的文件
* @param {string} dir 上传目录
* @returns {Promise<string>} 完整 URL (https://bucket.xxx/key)
*/
// 根据文件扩展名返回正确的 MIME,避免 OSS 默认给 application/octet-stream
function getMimeByExt(name) {
const ext = (name || '').split('.').pop().toLowerCase()
const map = {
pdf: 'application/pdf',
doc: 'application/msword',
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
png: 'image/png',
jpg: 'image/jpeg',
jpeg: 'image/jpeg',
gif: 'image/gif',
webp: 'image/webp'
}
return map[ext] || 'application/octet-stream'
}
export async function uploadToOss(file, dir) {
const sign = await getOssSign(dir)
const ext = (file.name || '').split('.').pop() || 'bin'
const key = sign.dir + Date.now() + '_' + Math.random().toString(36).slice(2, 8) + '.' + ext
// 显式传 Content-Type,让 OSS 按此存文件元数据, 浏览器拿到 application/pdf 即可内嵌预览
const mime = getMimeByExt(file.name)
const fd = new FormData()
fd.append('key', key)
fd.append('policy', sign.policy)
fd.append('OSSAccessKeyId', sign.accessKeyId)
fd.append('signature', sign.signature)
fd.append('success_action_status', '200')
fd.append('Content-Type', mime)
fd.append('file', file)
// ⚠️ 不要手动设置 Content-Type header,会让 multipart/form-data boundary 丢失
// FormData 会自动生成正确的 multipart 格式
const resp = await fetch(sign.host, {
method: 'POST',
body: fd
})
if (!resp.ok) {
throw new Error('OSS 上传失败: HTTP ' + resp.status)
}
return sign.host + '/' + key
}