fix(mobile): polish finance remark dialog from approved Figma design

Use compact layout, independent buttons and keyboard-aware viewport; retain drafts on failure and block closing during save. Require Figma approval for future screens and dialogs unless explicitly waived.
This commit is contained in:
zlwu committed 2026-10-30 22:17:49 +08:00
1 parent 5b1367c775
commit a8ee0fcebd
7 files changed
+445 -51

No files matched your search

+91 -3
View File
@@ -31,7 +31,7 @@ function evaluate(source, deps, tail = '') {
exports
)
}
function harness(platform) {
function harness(platform, overrides = {}) {
const calls = []
const hooks = {}
const api = {
@@ -58,7 +58,7 @@ function harness(platform) {
useMenuPerm: () => ({ hasMenuPerm: () => false }),
useUserStore: () => ({}),
ElMessage: { success() {}, error() {}, warning() {} },
uni: { showToast() {}, navigateTo() {} },
uni: { showToast() {}, navigateTo() {}, getSystemInfoSync: () => ({ windowHeight: 800 }) },
VanEmpty: {},
getToken: () => 'token',
forceRelogin() {},
@@ -73,7 +73,8 @@ function harness(platform) {
fetchUpdateOaFinanceRemark: async (id, text) => {
calls.push(['put', id, text])
return api.put(id, text)
}
},
...overrides
}
const path =
platform === 'web'
@@ -297,3 +298,90 @@ test('web: delayed refresh on an inactive cached page cannot restore finance dat
assert.equal(h.vm.canManageFinanceRemark, false)
assert.equal(h.calls.length, count)
})
test('mobile: save errors remain inline until retry or cancellation', async () => {
const h = harness('mobile')
await h.load()
await h.vm.openFinanceRemark(h.rows()[0])
h.vm.financeRemarkText = '保留输入'
h.api.put = async () => {
throw new Error('failure')
}
await h.vm.saveFinanceRemark()
assert.equal(h.vm.financeRemarkError, '保存失败,请稍后重试,输入已保留。')
assert.equal(h.vm.financeRemarkText, '保留输入')
let resolve
h.api.put = () =>
new Promise((r) => {
resolve = r
})
const retry = h.vm.saveFinanceRemark()
assert.equal(h.vm.financeRemarkError, '')
resolve({})
await retry
assert.equal(h.vm.financeRemarkVisible, false)
})
test('mobile: saving blocks user cancellation but page cleanup invalidates the response', async () => {
const h = harness('mobile')
await h.load()
await h.vm.openFinanceRemark(h.rows()[0])
let resolve
h.api.put = () =>
new Promise((r) => {
resolve = r
})
const saving = h.vm.saveFinanceRemark()
h.vm.cancelFinanceRemark()
assert.equal(h.vm.financeRemarkVisible, true)
assert.equal(h.vm.financeRemarkSaving, true)
h.hooks.hide()
assert.equal(h.vm.financeRemarkVisible, false)
assert.equal(h.vm.financeRemarkText, '')
const callCount = h.calls.length
resolve({})
await saving
assert.equal(h.calls.length, callCount)
})
test('mobile: keyboard height keeps the dialog inside available viewport and resets on close', async () => {
const h = harness('mobile')
await h.load()
await h.vm.openFinanceRemark(h.rows()[0])
assert.equal(h.vm.financeRemarkViewportStyle?.height, '800px')
h.vm.onFinanceRemarkKeyboardChange({ detail: { height: 320 } })
assert.equal(h.vm.financeRemarkViewportStyle.height, '480px')
h.vm.onFinanceRemarkKeyboardChange({ detail: { height: 0 } })
assert.equal(h.vm.financeRemarkViewportStyle.height, '800px')
h.vm.cancelFinanceRemark()
assert.deepEqual(h.vm.financeRemarkViewportStyle, {})
h.vm.onFinanceRemarkKeyboardChange({ detail: { height: 320 } })
assert.deepEqual(h.vm.financeRemarkViewportStyle, {})
})
test('mobile: H5 viewport resize and scroll track keyboard geometry and listeners are released', async () => {
const listeners = new Map()
const viewport = {
height: 800,
offsetTop: 0,
addEventListener: (name, fn) => listeners.set(name, fn),
removeEventListener: (name, fn) => {
assert.equal(listeners.get(name), fn)
listeners.delete(name)
}
}
const h = harness('mobile', { window: { visualViewport: viewport } })
await h.load()
await h.vm.openFinanceRemark(h.rows()[0])
assert.equal(listeners.size, 2)
viewport.height = 420
viewport.offsetTop = 20
listeners.get('resize')()
assert.deepEqual(h.vm.financeRemarkViewportStyle, { height: '420px', top: '20px' })
// A native keyboard notification must not subtract the same keyboard twice on H5.
h.vm.onFinanceRemarkKeyboardChange({ detail: { height: 380 } })
assert.equal(h.vm.financeRemarkViewportStyle.height, '420px')
h.hooks.hide()
assert.equal(listeners.size, 0)
assert.deepEqual(h.vm.financeRemarkViewportStyle, {})
})