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:
1 parent
5b1367c775
commit
a8ee0fcebd
7 files changed
+445
-51
No files matched your search
@@ -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, {})
|
||||
})
|
||||
Reference in new issue
Block a user