diff --git a/mobile-h5/pages/oa/mine/index.vue b/mobile-h5/pages/oa/mine/index.vue index 96238147..1fcd2820 100644 --- a/mobile-h5/pages/oa/mine/index.vue +++ b/mobile-h5/pages/oa/mine/index.vue @@ -41,9 +41,9 @@ :status-text="statusText(row.instanceStatus || row.status)" :status-tone="statusTone(row.instanceStatus || row.status)" :meta-lines="metaLines(row)" - :actions="cardActions" + :actions="rowActions(row)" @open="openView(row)" - @action="openView(row)" + @action="onCardAction($event, row)" /> 加载更多… 已经到底了 @@ -55,10 +55,12 @@ import OaTaskCard from '../../../components/OaTaskCard.vue' import { fetchOaTasks } from '../../../utils/oa-api.js' import { forceRelogin, getToken } from '../../../utils/auth.js' - import { stashOaDetailTitle } from '../../../utils/oa-h5.js' + import { stashOaDetailTitle, stashOaStartTitle } from '../../../utils/oa-h5.js' const PAGE_SIZE = 20 + const COPY_RESTART_STATUSES = ['returned', 'cancelled', 'rejected'] + const STATUS_MAP = { pending: '待处理', running: '进行中', @@ -83,8 +85,7 @@ loading: false, loadingMore: false, hasMore: true, - _searchTimer: null, - cardActions: [{ key: 'view', label: '查看', primary: true }] + _searchTimer: null } }, onShow() { @@ -141,6 +142,15 @@ } ] }, + rowActions(row) { + const actions = [{ key: 'view', label: '查看', primary: true }] + const status = String((row && (row.instanceStatus || row.status)) || '') + const appId = String((row && row.appId) || '').trim() + if (COPY_RESTART_STATUSES.includes(status) && appId) { + actions.push({ key: 'copyRestart', label: '复制并重新发起' }) + } + return actions + }, onSearchInput(e) { const v = e && e.detail && e.detail.value != null @@ -165,6 +175,14 @@ this.appName = '' this.onSearchConfirm() }, + onCardAction(act, row) { + if (!act || !row) return + if (act.key === 'copyRestart') { + this.openCopyRestart(row) + return + } + this.openView(row) + }, openView(row) { if (!row) return // mine 行是实例:Web 用 row.id;兼容 instanceId @@ -181,6 +199,23 @@ '&mode=view' }) }, + openCopyRestart(row) { + if (!row) return + const appId = String(row.appId || '').trim() + const fromInstanceId = String(row.instanceId || row.id || '').trim() + if (!appId || !fromInstanceId) { + uni.showToast({ title: '无法复制:缺少应用或实例', icon: 'none' }) + return + } + stashOaStartTitle(row.appName || row.title) + uni.navigateTo({ + url: + '/pages/oa/webview/index?appId=' + + encodeURIComponent(appId) + + '&fromInstanceId=' + + encodeURIComponent(fromInstanceId) + }) + }, async loadList(reset) { if (!getToken()) { forceRelogin('请先登录') diff --git a/mobile-h5/pages/oa/webview/index.vue b/mobile-h5/pages/oa/webview/index.vue index 30ccd5b1..d2b658a2 100644 --- a/mobile-h5/pages/oa/webview/index.vue +++ b/mobile-h5/pages/oa/webview/index.vue @@ -39,6 +39,7 @@ export default { const mode = String((query && query.mode) || '') || 'view' const appId = String((query && query.appId) || '') const draftId = String((query && query.draftId) || '') + const fromInstanceId = String((query && query.fromInstanceId) || '') let src = '' @@ -48,14 +49,14 @@ export default { uni.setNavigationBarTitle({ title: cachedName }) } src = buildOaDetailUrl({ instanceId, taskId, mode }) - } else if (draftId || appId) { + } else if (draftId || appId || fromInstanceId) { const cachedName = takeOaStartTitle() if (cachedName) { uni.setNavigationBarTitle({ title: cachedName }) } else if (appId) { this.resolveTitle(appId) } - src = buildOaStartUrl({ appId, draftId }) + src = buildOaStartUrl({ appId, draftId, fromInstanceId }) } else { uni.showToast({ title: '参数错误', icon: 'none' }) setTimeout(() => { @@ -109,6 +110,35 @@ export default { if (this._closing) return const action = String((payload && payload.action) || '') if (action && !CLOSE_ACTIONS.has(action)) return + + // 复制重开:离开详情 webview 栈时,改开发起页(同页 redirect) + if (action === 'oa-detail-restart') { + const appId = String((payload && payload.appId) || '').trim() + const fromInstanceId = String( + (payload && (payload.fromInstanceId || payload.instanceId)) || '' + ).trim() + if (!appId && !fromInstanceId) return + this._closing = true + const q = [] + if (appId) q.push('appId=' + encodeURIComponent(appId)) + if (fromInstanceId) { + q.push('fromInstanceId=' + encodeURIComponent(fromInstanceId)) + } + uni.redirectTo({ + url: '/pages/oa/webview/index?' + q.join('&'), + fail: () => { + this._closing = false + uni.navigateTo({ + url: '/pages/oa/webview/index?' + q.join('&'), + fail: () => { + this._closing = false + } + }) + } + }) + return + } + this._closing = true const msg = String((payload && payload.message) || '').trim() if (msg) { diff --git a/mobile-h5/utils/oa-h5.js b/mobile-h5/utils/oa-h5.js index 8f317521..d01f0256 100644 --- a/mobile-h5/utils/oa-h5.js +++ b/mobile-h5/utils/oa-h5.js @@ -28,12 +28,13 @@ export function buildFormSinkUrl() { return withQuery('/oa-form-sink', token ? { token } : {}) } -/** 正式发起页 URL(与水槽同一套拼法,仅多 appId/draftId) */ -export function buildOaStartUrl({ appId, draftId } = {}) { +/** 正式发起页 URL(与水槽同一套拼法,仅多 appId/draftId/fromInstanceId) */ +export function buildOaStartUrl({ appId, draftId, fromInstanceId } = {}) { const token = getToken() const params = {} if (appId) params.appId = appId if (draftId) params.draftId = draftId + if (fromInstanceId) params.fromInstanceId = fromInstanceId if (token) params.token = token return withQuery('/oa-start', params) } diff --git a/mobile-oa-h5/src/views/OaDetail.vue b/mobile-oa-h5/src/views/OaDetail.vue index 6e2f3cab..d098a9c3 100644 --- a/mobile-oa-h5/src/views/OaDetail.vue +++ b/mobile-oa-h5/src/views/OaDetail.vue @@ -4,7 +4,13 @@ - + {{ detail?.title || '审批详情' }} + + 撤销 + + + 复制并重新发起 + @@ -166,8 +190,8 @@