提交
This commit is contained in:
1 parent
417d6c9c51
commit
c8fe0cdc20
102 files changed
+19847
-12224
No files matched your search
@@ -238,18 +238,42 @@ function buildFlowItems(detail: any): OaPrintFlowItem[] {
|
||||
ccBuf = null
|
||||
}
|
||||
|
||||
const peopleNames = (p: any): string[] => {
|
||||
const people = Array.isArray(p?.people) ? p.people : []
|
||||
const fromPeople = people
|
||||
.map((x: any) => {
|
||||
const n = String(x?.nickName || x?.id || '').trim()
|
||||
if (!n) return ''
|
||||
const st = String(x?.status || '')
|
||||
if (st === 'approved') return `${n}(已同意)`
|
||||
if (st === 'rejected') return `${n}(已拒绝)`
|
||||
if (st === 'returned') return `${n}(已打回)`
|
||||
if (st === 'pending' || st === 'running') return `${n}(待处理)`
|
||||
if (st === 'done') return `${n}(无需处理)`
|
||||
return n
|
||||
})
|
||||
.filter(Boolean)
|
||||
if (fromPeople.length) return fromPeople
|
||||
const name = String(p.assigneeUserName || p.assigneeUserId || '').trim()
|
||||
return name ? [name] : []
|
||||
}
|
||||
|
||||
for (const p of list) {
|
||||
const kind = String(p.kind || '')
|
||||
const taskType = String(p.taskType || '')
|
||||
const title = String(p.title || '-').trim()
|
||||
const name = String(p.assigneeUserName || p.assigneeUserId || '').trim()
|
||||
const names = peopleNames(p)
|
||||
const name = names.join(',')
|
||||
const ts = String(p.timestamp || '').trim()
|
||||
const comment = String(p.commentText || '').trim()
|
||||
const st = statusText(String(p.status || ''))
|
||||
const signMode = String(p.signMode || '')
|
||||
const signLabel = signMode === 'and' ? '会签' : signMode === 'or' ? '或签' : ''
|
||||
|
||||
if (taskType === 'cc') {
|
||||
if (!ccBuf) ccBuf = { names: [], ts }
|
||||
if (name) ccBuf.names.push(name)
|
||||
if (names.length) ccBuf.names.push(...names.map((n) => n.replace(/\(.*?\)\s*$/, '')))
|
||||
else if (name) ccBuf.names.push(name)
|
||||
if (ts) ccBuf.ts = ts
|
||||
continue
|
||||
}
|
||||
@@ -277,9 +301,10 @@ function buildFlowItems(detail: any): OaPrintFlowItem[] {
|
||||
})
|
||||
continue
|
||||
}
|
||||
// task
|
||||
// task(或签/会签同节点多人已合并)
|
||||
const head = signLabel ? `【${title}·${signLabel}】` : `【${title}】`
|
||||
items.push({
|
||||
left: name ? `【${title}】 ${name} ${st}` : `【${title}】 ${st}`,
|
||||
left: name ? `${head} ${name} ${st}` : `${head} ${st}`,
|
||||
right: ts,
|
||||
comment: comment || undefined
|
||||
})
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* FormCreate 运行时补丁:
|
||||
* - 内置 upload 默认 action 为「/」,会 POST 到前端原点导致 404;接管为附件上传 API
|
||||
* - 运行时注册 FcRow(flex ._fd-row),间距与铺满由 oa-fc-runtime.scss 处理
|
||||
*/
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { fetchUploadAttachment } from '@/api/business'
|
||||
import { attachmentFullUrl } from '@/composables/useAttachmentActions'
|
||||
import OaFcRow from '@/components/oa-approval/OaFcRow.vue'
|
||||
|
||||
type FcFetchOptions = {
|
||||
source?: string
|
||||
file?: File
|
||||
filename?: string
|
||||
data?: Record<string, unknown>
|
||||
action?: string
|
||||
onSuccess?: (res: unknown) => void
|
||||
onError?: (err: unknown) => void
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
const FLAG = '__oaUploadConfigured'
|
||||
|
||||
const UPLOAD_TYPES = new Set(['upload', 'fcUpload'])
|
||||
|
||||
/** 与业务表单 `.form-grid-2` 横向间距对齐(顶层 option.row.gutter / CSS --oa-fc-gutter) */
|
||||
export const OA_FC_DEFAULT_GUTTER = 20
|
||||
|
||||
/** 从上传接口响应中取出可回显的 url(兼容 FormCreate 默认 onSuccess) */
|
||||
export function resolveUploadResponseUrl(res: any): string {
|
||||
const raw = String(
|
||||
res?.data?.url || res?.data?.fileUrl || res?.fileUrl || res?.url || ''
|
||||
).trim()
|
||||
if (!raw) return ''
|
||||
return attachmentFullUrl(raw) || raw
|
||||
}
|
||||
|
||||
function ensureUploadRule(rule: any) {
|
||||
if (!UPLOAD_TYPES.has(String(rule.type || ''))) return
|
||||
const props = { ...(rule.props || {}) }
|
||||
if (!props.action || props.action === '/') {
|
||||
props.action = '#'
|
||||
}
|
||||
const prevSuccess = props.onSuccess
|
||||
// `$FNX:...` 须留给 FormCreate 编译;替换成函数会丢掉官方 file.url = res.data.url
|
||||
if (typeof prevSuccess === 'string' && prevSuccess.includes('$FNX')) {
|
||||
// keep
|
||||
} else if (typeof prevSuccess === 'function') {
|
||||
props.onSuccess = (res: any, file: any) => {
|
||||
try {
|
||||
prevSuccess(res, file)
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
const url = resolveUploadResponseUrl(res)
|
||||
// Element Plus 选文件时已写入 blob: URL,必须强制覆盖
|
||||
if (url && file) {
|
||||
file.url = url
|
||||
}
|
||||
}
|
||||
} else if (!prevSuccess) {
|
||||
props.onSuccess = (res: any, file: any) => {
|
||||
const url = resolveUploadResponseUrl(res)
|
||||
if (url && file) {
|
||||
file.url = url
|
||||
}
|
||||
}
|
||||
}
|
||||
rule.props = props
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行时补齐 FormCreate rule(upload action / onSuccess)
|
||||
*/
|
||||
export function ensureOaUploadRuleProps(rules: unknown): any[] {
|
||||
if (!Array.isArray(rules)) return []
|
||||
return rules.map((raw) => {
|
||||
if (!raw || typeof raw !== 'object') return raw
|
||||
const rule: any = { ...(raw as object) }
|
||||
ensureUploadRule(rule)
|
||||
if (Array.isArray(rule.children)) {
|
||||
rule.children = ensureOaUploadRuleProps(rule.children)
|
||||
}
|
||||
if (Array.isArray(rule.props?.rule)) {
|
||||
rule.props = {
|
||||
...rule.props,
|
||||
rule: ensureOaUploadRuleProps(rule.props.rule)
|
||||
}
|
||||
}
|
||||
if (Array.isArray(rule.control)) {
|
||||
rule.control = rule.control.map((c: any) => {
|
||||
if (!c || typeof c !== 'object') return c
|
||||
if (Array.isArray(c.rule)) {
|
||||
return { ...c, rule: ensureOaUploadRuleProps(c.rule) }
|
||||
}
|
||||
return c
|
||||
})
|
||||
}
|
||||
return rule
|
||||
})
|
||||
}
|
||||
|
||||
export function setupFormCreateUpload(formCreate: {
|
||||
fetch?: (opts: FcFetchOptions) => void
|
||||
component?: (name: string, component: unknown) => void
|
||||
}) {
|
||||
if (!formCreate || (formCreate as any)[FLAG]) return
|
||||
|
||||
// 主应用 formCreate 默认未挂设计器 FcRow;用 flex 行保证栅格铺满,间距走 CSS
|
||||
if (typeof formCreate.component === 'function') {
|
||||
formCreate.component('fcRow', OaFcRow)
|
||||
formCreate.component('FcRow', OaFcRow)
|
||||
}
|
||||
|
||||
const prevFetch = formCreate.fetch
|
||||
|
||||
formCreate.fetch = (options: FcFetchOptions) => {
|
||||
const isUpload = options?.source === 'upload' || !!options?.file
|
||||
if (!isUpload) {
|
||||
if (typeof prevFetch === 'function') {
|
||||
return prevFetch(options)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
const file = options.file
|
||||
if (!file) {
|
||||
throw new Error('未选择文件')
|
||||
}
|
||||
const fd = new FormData()
|
||||
fd.append('file', file)
|
||||
fd.append('folder', 'oa-approval')
|
||||
const extra = options.data
|
||||
if (extra && typeof extra === 'object') {
|
||||
Object.entries(extra).forEach(([k, v]) => {
|
||||
if (v != null && k !== 'file' && k !== 'folder') {
|
||||
fd.append(k, String(v))
|
||||
}
|
||||
})
|
||||
}
|
||||
const res: any = await fetchUploadAttachment(fd)
|
||||
const rawUrl = String(res?.fileUrl || res?.data?.fileUrl || '').trim()
|
||||
if (!rawUrl) {
|
||||
throw new Error('上传失败:未返回文件地址')
|
||||
}
|
||||
// 预览用完整 URL;设计器默认 onSuccess 为 file.url = res.data.url
|
||||
const url = attachmentFullUrl(rawUrl) || rawUrl
|
||||
options.onSuccess?.({
|
||||
data: { url, fileUrl: rawUrl },
|
||||
fileUrl: rawUrl,
|
||||
url
|
||||
})
|
||||
} catch (e) {
|
||||
const msg = e instanceof Error ? e.message : '上传失败'
|
||||
ElMessage.error(msg)
|
||||
options.onError?.(e)
|
||||
}
|
||||
})()
|
||||
}
|
||||
|
||||
;(formCreate as any)[FLAG] = true
|
||||
}
|
||||
Reference in new issue
Block a user