feat(oa): add shared OA webview and detail URL builder
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
2dac9d6fbd
commit
cf4994ef53
8 files changed
+273
No files matched your search
@@ -56,6 +56,54 @@
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/oa/webview/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "审批详情",
|
||||
"navigationBarBackgroundColor": "#ecfdf5",
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/oa/drafts/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "草稿箱",
|
||||
"navigationBarBackgroundColor": "#ecfdf5",
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/oa/pending/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "待办中心",
|
||||
"navigationBarBackgroundColor": "#ecfdf5",
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/oa/done/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "已办中心",
|
||||
"navigationBarBackgroundColor": "#ecfdf5",
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/oa/mine/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "我发起的",
|
||||
"navigationBarBackgroundColor": "#ecfdf5",
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/oa/cc/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "抄送我的",
|
||||
"navigationBarBackgroundColor": "#ecfdf5",
|
||||
"navigationBarTextStyle": "black"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/demo/list",
|
||||
"style": {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<view class="page-shell" style="padding:24rpx">
|
||||
<text>{{ title }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return { title: '抄送我的' }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<view class="page-shell" style="padding:24rpx">
|
||||
<text>{{ title }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return { title: '已办中心' }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<view class="page-shell" style="padding:24rpx">
|
||||
<text>{{ title }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return { title: '草稿箱' }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<view class="page-shell" style="padding:24rpx">
|
||||
<text>{{ title }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return { title: '我发起的' }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<view class="page-shell" style="padding:24rpx">
|
||||
<text>{{ title }}</text>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return { title: '待办中心' }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<!-- 通用 OA web-view:发起 + 详情共用;结构对齐 start/webview -->
|
||||
<web-view v-if="src" :src="src" @message="onMessage" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
buildOaDetailUrl,
|
||||
buildOaStartUrl,
|
||||
takeOaDetailTitle,
|
||||
takeOaStartTitle
|
||||
} from '../../../utils/oa-h5.js'
|
||||
import { forceRelogin, getToken } from '../../../utils/auth.js'
|
||||
import { fetchOaTemplateDetail } from '../../../utils/oa-api.js'
|
||||
|
||||
const CLOSE_ACTIONS = new Set([
|
||||
'oa-start-close',
|
||||
'oa-start-cancel',
|
||||
'oa-start-draft',
|
||||
'oa-start-submitted',
|
||||
'oa-detail-close',
|
||||
'oa-detail-done',
|
||||
'oa-detail-withdraw',
|
||||
'oa-detail-restart'
|
||||
])
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { src: '', _closing: false }
|
||||
},
|
||||
onLoad(query) {
|
||||
if (!getToken()) {
|
||||
forceRelogin('请先登录')
|
||||
return
|
||||
}
|
||||
|
||||
const instanceId = String((query && query.instanceId) || '')
|
||||
const taskId = String((query && query.taskId) || '')
|
||||
const mode = String((query && query.mode) || '') || 'view'
|
||||
const appId = String((query && query.appId) || '')
|
||||
const draftId = String((query && query.draftId) || '')
|
||||
|
||||
let src = ''
|
||||
|
||||
if (instanceId) {
|
||||
const cachedName = takeOaDetailTitle()
|
||||
if (cachedName) {
|
||||
uni.setNavigationBarTitle({ title: cachedName })
|
||||
}
|
||||
src = buildOaDetailUrl({ instanceId, taskId, mode })
|
||||
} else if (draftId || appId) {
|
||||
const cachedName = takeOaStartTitle()
|
||||
if (cachedName) {
|
||||
uni.setNavigationBarTitle({ title: cachedName })
|
||||
} else if (appId) {
|
||||
this.resolveTitle(appId)
|
||||
}
|
||||
src = buildOaStartUrl({ appId, draftId })
|
||||
} else {
|
||||
uni.showToast({ title: '参数错误', icon: 'none' })
|
||||
setTimeout(() => {
|
||||
uni.navigateBack({
|
||||
fail: () => {}
|
||||
})
|
||||
}, 400)
|
||||
return
|
||||
}
|
||||
|
||||
if (!/\btoken=/.test(src)) {
|
||||
forceRelogin('请先登录')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('[oa webview] src=', src)
|
||||
this.src = src
|
||||
|
||||
// H5:OA 页在 iframe 内,靠 postMessage 通知本页 uni.navigateBack
|
||||
// (微信小程序由 OA 内 wx.miniProgram.navigateBack,勿在此再退一层)
|
||||
// #ifdef H5
|
||||
this._onParentMessage = (e) => {
|
||||
const d = e && e.data
|
||||
if (!d || d.source !== 'zkxw-oa-h5') return
|
||||
this.navigateBackFromOa(d)
|
||||
}
|
||||
window.addEventListener('message', this._onParentMessage)
|
||||
// #endif
|
||||
},
|
||||
onUnload() {
|
||||
// #ifdef H5
|
||||
if (this._onParentMessage) {
|
||||
window.removeEventListener('message', this._onParentMessage)
|
||||
this._onParentMessage = null
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
async resolveTitle(appId) {
|
||||
try {
|
||||
const detail = await fetchOaTemplateDetail(appId)
|
||||
const name = String(
|
||||
(detail && (detail.appName || detail.name)) || ''
|
||||
).trim()
|
||||
if (name) uni.setNavigationBarTitle({ title: name })
|
||||
} catch (_) {
|
||||
/* 保留 pages.json 兜底标题 */
|
||||
}
|
||||
},
|
||||
navigateBackFromOa(payload) {
|
||||
if (this._closing) return
|
||||
const action = String((payload && payload.action) || '')
|
||||
if (action && !CLOSE_ACTIONS.has(action)) return
|
||||
this._closing = true
|
||||
const msg = String((payload && payload.message) || '').trim()
|
||||
if (msg) {
|
||||
uni.showToast({ title: msg, icon: 'none', duration: 1200 })
|
||||
}
|
||||
setTimeout(() => {
|
||||
uni.navigateBack({
|
||||
fail: () => {
|
||||
this._closing = false
|
||||
}
|
||||
})
|
||||
}, msg ? 400 : 0)
|
||||
},
|
||||
onMessage(e) {
|
||||
/* 微信:多在后退/销毁时触发;列表页 onShow 可刷新。勿再 navigateBack */
|
||||
console.log('[oa webview] message', e && e.detail)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -38,6 +38,17 @@ export function buildOaStartUrl({ appId, draftId } = {}) {
|
||||
return withQuery('/oa-start', params)
|
||||
}
|
||||
|
||||
/** 审批详情页 URL(须带 token;mode 为 view | approve) */
|
||||
export function buildOaDetailUrl({ instanceId, taskId, mode } = {}) {
|
||||
const token = getToken()
|
||||
const params = {}
|
||||
if (instanceId) params.instanceId = instanceId
|
||||
if (taskId) params.taskId = taskId
|
||||
if (mode) params.mode = mode // view | approve
|
||||
if (token) params.token = token
|
||||
return withQuery('/oa-detail', params)
|
||||
}
|
||||
|
||||
const TITLE_KEY = 'oa_start_nav_title'
|
||||
|
||||
/** 跳转前缓存流程名(勿把中文放进 navigateTo / web-view URL,微信易白屏) */
|
||||
@@ -60,3 +71,26 @@ export function takeOaStartTitle() {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const DETAIL_TITLE_KEY = 'oa_detail_nav_title'
|
||||
|
||||
/** 跳转前缓存详情标题(勿把中文放进 navigateTo / web-view URL) */
|
||||
export function stashOaDetailTitle(name) {
|
||||
const t = String(name || '').trim()
|
||||
try {
|
||||
if (t) uni.setStorageSync(DETAIL_TITLE_KEY, t)
|
||||
else uni.removeStorageSync(DETAIL_TITLE_KEY)
|
||||
} catch (_) {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
export function takeOaDetailTitle() {
|
||||
try {
|
||||
const t = String(uni.getStorageSync(DETAIL_TITLE_KEY) || '').trim()
|
||||
uni.removeStorageSync(DETAIL_TITLE_KEY)
|
||||
return t
|
||||
} catch (_) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user