添加配置密码功能

This commit is contained in:
fenghp
2026-05-17 16:20:02 +08:00
parent 5cc544da47
commit b9a3ad37dc
7 changed files with 135 additions and 5 deletions
+1 -1
View File
@@ -179,7 +179,7 @@ export default [
name: '输入支付密码', name: '输入支付密码',
action: 'input', action: 'input',
locator: { type: 'css', value: '.pwdValidate__pwd input.my-passcode-input-native-input', requireInteractable: false }, locator: { type: 'css', value: '.pwdValidate__pwd input.my-passcode-input-native-input', requireInteractable: false },
value: '829475', value: '{{rechargePayPassword}}',
waitTimeout: 5000, waitTimeout: 5000,
inputOptions: { inputOptions: {
mode: 'nativeSetValue' mode: 'nativeSetValue'
+42 -2
View File
@@ -67,6 +67,14 @@
<view class="field-value">{{ currentRechargeAccount }}</view> <view class="field-value">{{ currentRechargeAccount }}</view>
</view> </view>
</view> </view>
<view class="list-item">
<view class="row">
<view class="row-left">
<view class="row-title">充值密码</view>
</view>
<view class="field-value">{{ rechargePayPasswordText }}</view>
</view>
</view>
<view class="list-item"> <view class="list-item">
<view class="row"> <view class="row">
<view class="row-left"> <view class="row-left">
@@ -97,7 +105,7 @@ import { logout as logoutApi } from '../../api/auth'
import { heartbeatDevice, offlineDevice, registerDevice, updateDeviceWorkStatus } from '../../api/device' import { heartbeatDevice, offlineDevice, registerDevice, updateDeviceWorkStatus } from '../../api/device'
import { pullTask, receiveTask } from '../../api/task' import { pullTask, receiveTask } from '../../api/task'
import { getDeviceProfile } from '../../services/device' import { getDeviceProfile } from '../../services/device'
import { clearAuth, getCurrentTaskStorage, getUserInfo, setDeviceInfo } from '../../utils/storage' import { clearAuth, getCurrentTaskStorage, getRechargePayPasswordStorage, getUserInfo, setDeviceInfo } from '../../utils/storage'
const HEARTBEAT_INTERVAL = 15000 const HEARTBEAT_INTERVAL = 15000
const PULL_INTERVAL = 8000 const PULL_INTERVAL = 8000
@@ -181,6 +189,12 @@ export default {
const task = this.currentTask || {} const task = this.currentTask || {}
return task.rechargeAccount || task.recharge_account || '--' return task.rechargeAccount || task.recharge_account || '--'
}, },
hasRechargePayPassword() {
return !!(this.$store.state.rechargePayPassword || getRechargePayPasswordStorage())
},
rechargePayPasswordText() {
return this.hasRechargePayPassword ? '已配置' : '未配置'
},
workStatus() { workStatus() {
return this.$store.state.workStatus || 'NOT_READY' return this.$store.state.workStatus || 'NOT_READY'
}, },
@@ -196,7 +210,7 @@ export default {
return task.status === 'RECEIVED' && this.$store.state.executionState === 'IDLE' return task.status === 'RECEIVED' && this.$store.state.executionState === 'IDLE'
}, },
canPullTask() { canPullTask() {
return this.workStatus === 'READY' return this.workStatus === 'READY' && this.hasRechargePayPassword
} }
}, },
onShow() { onShow() {
@@ -329,6 +343,10 @@ export default {
if (this.pullTimer || (!this.currentTask && this.workStatus !== 'READY')) { if (this.pullTimer || (!this.currentTask && this.workStatus !== 'READY')) {
return return
} }
if (!this.hasRechargePayPassword) {
this.pushTraceLog('PAY_PASSWORD_MISSING', '充值密码未配置,已暂停任务拉取')
return
}
this.tryPullTask() this.tryPullTask()
this.pullTimer = setInterval(() => { this.pullTimer = setInterval(() => {
this.tryPullTask() this.tryPullTask()
@@ -346,6 +364,9 @@ export default {
if (this.workStatus !== 'READY') { if (this.workStatus !== 'READY') {
return return
} }
if (!this.hasRechargePayPassword) {
return
}
const userName = this.userName const userName = this.userName
const deviceCode = this.deviceInfo.deviceCode const deviceCode = this.deviceInfo.deviceCode
@@ -437,6 +458,14 @@ export default {
if (!taskId || this.autoStarting) { if (!taskId || this.autoStarting) {
return return
} }
if (!this.hasRechargePayPassword) {
if (!silent) {
uni.showToast({ title: '请先配置充值密码', icon: 'none' })
}
this.pushTraceLog('PAY_PASSWORD_MISSING', `任务 ${task.taskNo || taskId} 等待充值密码配置`)
this.goRecharge()
return
}
this.autoStarting = true this.autoStarting = true
this.$store.commit('setCurrentTask', task) this.$store.commit('setCurrentTask', task)
this.$store.commit('upsertTaskHistory', task) this.$store.commit('upsertTaskHistory', task)
@@ -493,6 +522,12 @@ export default {
this.workStatusUpdating = true this.workStatusUpdating = true
const targetWorkStatus = this.workStatus === 'READY' ? 'NOT_READY' : 'READY' const targetWorkStatus = this.workStatus === 'READY' ? 'NOT_READY' : 'READY'
if (targetWorkStatus === 'READY' && !this.hasRechargePayPassword) {
this.workStatusUpdating = false
uni.showToast({ title: '请先配置充值密码', icon: 'none' })
this.goRecharge()
return
}
try { try {
const result = await updateDeviceWorkStatus({ const result = await updateDeviceWorkStatus({
userName, userName,
@@ -533,6 +568,11 @@ export default {
uni.showToast({ title: '当前无可执行任务', icon: 'none' }) uni.showToast({ title: '当前无可执行任务', icon: 'none' })
return return
} }
if (!this.hasRechargePayPassword) {
uni.showToast({ title: '请先配置充值密码', icon: 'none' })
this.goRecharge()
return
}
const task = this.currentTask const task = this.currentTask
const taskId = resolveTaskId(task) const taskId = resolveTaskId(task)
uni.navigateTo({ uni.navigateTo({
+52 -2
View File
@@ -71,13 +71,24 @@
<view class="field-label">充值页地址</view> <view class="field-label">充值页地址</view>
<view class="field-value">{{ rechargeUrl }}</view> <view class="field-value">{{ rechargeUrl }}</view>
</view> </view>
<button class="button-primary" @tap="openRechargePage">配置账号</button> <view class="field">
<view class="field-label">充值密码</view>
<input
v-model="rechargePayPassword"
class="input"
type="text"
maxlength="20"
placeholder="请输入充值支付密码"
/>
</view>
<button class="button-secondary button-space" @tap="saveRechargePayPassword">保存充值密码</button>
<button class="button-primary button-space" @tap="openRechargePage">配置账号</button>
<button class="button-secondary button-space" @tap="clearAccountConfig">清除已有账号</button> <button class="button-secondary button-space" @tap="clearAccountConfig">清除已有账号</button>
</view> </view>
<view v-if="!hasTask" class="section"> <view v-if="!hasTask" class="section">
<view class="section-title">说明</view> <view class="section-title">说明</view>
<view class="field-value">清除已有账号会清理 WebView 缓存并关闭当前配置页,之后可重新配置登录账号。</view> <view class="field-value">充值密码会保存在本地缓存中,清除已有账号会同时清理 WebView 缓存和充值密码。</view>
</view> </view>
</view> </view>
</template> </template>
@@ -90,6 +101,7 @@ import { startTask, reportTaskStep } from '../../api/task'
// dryRun 由 appConfig.dryRun 控制,true 时跳过所有后端上报 // dryRun 由 appConfig.dryRun 控制,true 时跳过所有后端上报
import { runStepEngine } from '../../services/stepEngine' import { runStepEngine } from '../../services/stepEngine'
import douyinSteps from '../../config/steps/douyin-recharge' import douyinSteps from '../../config/steps/douyin-recharge'
import { getRechargePayPasswordStorage } from '../../utils/storage'
/** /**
* 充值页。有 taskId 时进入执行模式,否则为账号配置模式。 * 充值页。有 taskId 时进入执行模式,否则为账号配置模式。
@@ -99,6 +111,7 @@ export default {
return { return {
taskId: null, taskId: null,
rechargeUrl: appConfig.rechargeUrl, rechargeUrl: appConfig.rechargeUrl,
rechargePayPassword: '',
failReason: '', failReason: '',
lastBlockedAppSchemeUrl: '', lastBlockedAppSchemeUrl: '',
lastBlockedAppSchemeAt: 0 lastBlockedAppSchemeAt: 0
@@ -122,6 +135,7 @@ export default {
} }
}, },
onLoad(options) { onLoad(options) {
this.rechargePayPassword = getRechargePayPasswordStorage()
if (options && options.taskId) { if (options && options.taskId) {
this.taskId = Number(options.taskId) || options.taskId this.taskId = Number(options.taskId) || options.taskId
this.$nextTick(() => { this.$nextTick(() => {
@@ -183,10 +197,16 @@ export default {
const task = this.task const task = this.task
const url = task.rechargeUrl || this.rechargeUrl const url = task.rechargeUrl || this.rechargeUrl
const rechargePayPassword = this.$store.state.rechargePayPassword || getRechargePayPasswordStorage()
if (!url) { if (!url) {
uni.showToast({ title: '充值页地址未配置', icon: 'none' }) uni.showToast({ title: '充值页地址未配置', icon: 'none' })
return return
} }
if (!rechargePayPassword) {
uni.showToast({ title: '请先配置充值密码', icon: 'none' })
this.goConfig()
return
}
this.$store.commit('setExecutionState', 'RUNNING') this.$store.commit('setExecutionState', 'RUNNING')
this.$store.commit('clearStepLogs') this.$store.commit('clearStepLogs')
@@ -233,6 +253,7 @@ export default {
const context = { const context = {
amount: task.amount, amount: task.amount,
rechargeAccount: task.rechargeAccount || task.recharge_account, rechargeAccount: task.rechargeAccount || task.recharge_account,
rechargePayPassword,
rechargeUrl: url, rechargeUrl: url,
globalGuards: [] globalGuards: []
} }
@@ -310,6 +331,9 @@ export default {
uni.showToast({ title: '请先配置充值页地址', icon: 'none' }) uni.showToast({ title: '请先配置充值页地址', icon: 'none' })
return return
} }
if (this.rechargePayPassword && !this.persistRechargePayPassword(false)) {
return
}
const currentWebview = this.$scope && this.$scope.$getAppWebview ? this.$scope.$getAppWebview() : null const currentWebview = this.$scope && this.$scope.$getAppWebview ? this.$scope.$getAppWebview() : null
const webview = openRechargeWebview(this.rechargeUrl, currentWebview, { const webview = openRechargeWebview(this.rechargeUrl, currentWebview, {
onBlockedAppScheme: this.handleBlockedAppScheme onBlockedAppScheme: this.handleBlockedAppScheme
@@ -318,6 +342,30 @@ export default {
uni.showToast({ title: '当前环境不支持打开原生页', icon: 'none' }) uni.showToast({ title: '当前环境不支持打开原生页', icon: 'none' })
} }
}, },
persistRechargePayPassword(showToast) {
const password = String(this.rechargePayPassword || '').trim()
if (!password) {
uni.showToast({ title: '请输入充值密码', icon: 'none' })
return false
}
this.rechargePayPassword = password
this.$store.commit('setRechargePayPassword', password)
if (showToast) {
uni.showToast({ title: '充值密码已保存', icon: 'none' })
}
return true
},
saveRechargePayPassword() {
this.persistRechargePayPassword(true)
},
goConfig() {
this.$store.commit('setExecutionState', 'IDLE')
this.$store.commit('setCurrentStepIndex', -1)
this.$store.commit('setCurrentStepCode', '')
uni.redirectTo({
url: '/pages/recharge/index'
})
},
/** /**
* 配置模式:清理已配置账号 * 配置模式:清理已配置账号
*/ */
@@ -326,6 +374,8 @@ export default {
closeRechargeWebview() closeRechargeWebview()
this.$store.commit('setDouyinLoginStatus', 'unknown') this.$store.commit('setDouyinLoginStatus', 'unknown')
this.$store.commit('setAlipayLoginStatus', 'unknown') this.$store.commit('setAlipayLoginStatus', 'unknown')
this.$store.commit('clearRechargePayPassword')
this.rechargePayPassword = ''
uni.showToast({ title: '已清除账号缓存,可重新配置', icon: 'none' }) uni.showToast({ title: '已清除账号缓存,可重新配置', icon: 'none' })
} }
} }
+12
View File
@@ -57,6 +57,8 @@
</template> </template>
<script> <script>
import { getRechargePayPasswordStorage } from '../../utils/storage'
/** /**
* 任务页负责展示当前任务和最近任务接收结果。 * 任务页负责展示当前任务和最近任务接收结果。
*/ */
@@ -70,6 +72,9 @@ export default {
}, },
executionState() { executionState() {
return this.$store.state.executionState || 'IDLE' return this.$store.state.executionState || 'IDLE'
},
hasRechargePayPassword() {
return !!(this.$store.state.rechargePayPassword || getRechargePayPasswordStorage())
} }
}, },
methods: { methods: {
@@ -107,6 +112,13 @@ export default {
startRecharge() { startRecharge() {
const task = this.currentTask const task = this.currentTask
if (!task) return if (!task) return
if (!this.hasRechargePayPassword) {
uni.showToast({ title: '请先配置充值密码', icon: 'none' })
uni.navigateTo({
url: '/pages/recharge/index'
})
return
}
const taskId = task.taskId || task.id || task.taskNo const taskId = task.taskId || task.id || task.taskNo
uni.navigateTo({ uni.navigateTo({
url: `/pages/recharge/index?taskId=${taskId}` url: `/pages/recharge/index?taskId=${taskId}`
+1
View File
@@ -46,6 +46,7 @@ function resolveStepValue(rawValue, context) {
value = value.replace(/\{\{amount\}\}/g, context.amount || '') value = value.replace(/\{\{amount\}\}/g, context.amount || '')
value = value.replace(/\{\{rechargeAccount\}\}/g, context.rechargeAccount || '') value = value.replace(/\{\{rechargeAccount\}\}/g, context.rechargeAccount || '')
value = value.replace(/\{\{rechargeUrl\}\}/g, context.rechargeUrl || '') value = value.replace(/\{\{rechargeUrl\}\}/g, context.rechargeUrl || '')
value = value.replace(/\{\{rechargePayPassword\}\}/g, context.rechargePayPassword || '')
return value return value
} }
+14
View File
@@ -3,13 +3,16 @@ import Vuex from 'vuex'
import { import {
getCurrentTaskStorage, getCurrentTaskStorage,
getExecutionStateStorage, getExecutionStateStorage,
getRechargePayPasswordStorage,
getTaskHistoryStorage, getTaskHistoryStorage,
getWorkStatusStorage, getWorkStatusStorage,
getToken, getToken,
getUserInfo, getUserInfo,
removeCurrentTaskStorage, removeCurrentTaskStorage,
removeRechargePayPasswordStorage,
setCurrentTaskStorage, setCurrentTaskStorage,
setExecutionStateStorage, setExecutionStateStorage,
setRechargePayPasswordStorage,
setTaskHistoryStorage, setTaskHistoryStorage,
setWorkStatusStorage setWorkStatusStorage
} from '../utils/storage' } from '../utils/storage'
@@ -30,6 +33,7 @@ export default new Vuex.Store({
logs: [], logs: [],
executionState: getExecutionStateStorage(), executionState: getExecutionStateStorage(),
workStatus: getWorkStatusStorage(), workStatus: getWorkStatusStorage(),
rechargePayPassword: getRechargePayPasswordStorage(),
cooldownUntil: '', cooldownUntil: '',
currentStepIndex: -1, currentStepIndex: -1,
currentStepCode: '', currentStepCode: '',
@@ -109,6 +113,14 @@ export default new Vuex.Store({
state.workStatus = value || 'NOT_READY' state.workStatus = value || 'NOT_READY'
setWorkStatusStorage(state.workStatus) setWorkStatusStorage(state.workStatus)
}, },
setRechargePayPassword(state, value) {
state.rechargePayPassword = value || ''
setRechargePayPasswordStorage(state.rechargePayPassword)
},
clearRechargePayPassword(state) {
state.rechargePayPassword = ''
removeRechargePayPasswordStorage()
},
setCooldownUntil(state, value) { setCooldownUntil(state, value) {
state.cooldownUntil = value || '' state.cooldownUntil = value || ''
}, },
@@ -143,6 +155,7 @@ export default new Vuex.Store({
state.logs = [] state.logs = []
state.executionState = 'IDLE' state.executionState = 'IDLE'
state.workStatus = 'NOT_READY' state.workStatus = 'NOT_READY'
state.rechargePayPassword = ''
state.cooldownUntil = '' state.cooldownUntil = ''
state.currentStepIndex = -1 state.currentStepIndex = -1
state.currentStepCode = '' state.currentStepCode = ''
@@ -152,6 +165,7 @@ export default new Vuex.Store({
setTaskHistoryStorage([]) setTaskHistoryStorage([])
setExecutionStateStorage('IDLE') setExecutionStateStorage('IDLE')
setWorkStatusStorage('NOT_READY') setWorkStatusStorage('NOT_READY')
removeRechargePayPasswordStorage()
} }
} }
}) })
+13
View File
@@ -6,6 +6,7 @@ const CURRENT_TASK_KEY = 'deposit_current_task'
const TASK_HISTORY_KEY = 'deposit_task_history' const TASK_HISTORY_KEY = 'deposit_task_history'
const EXECUTION_STATE_KEY = 'deposit_execution_state' const EXECUTION_STATE_KEY = 'deposit_execution_state'
const WORK_STATUS_KEY = 'deposit_work_status' const WORK_STATUS_KEY = 'deposit_work_status'
const RECHARGE_PAY_PASSWORD_KEY = 'deposit_recharge_pay_password'
/** /**
* 保存登录 token,供请求封装自动携带。 * 保存登录 token,供请求封装自动携带。
@@ -99,6 +100,18 @@ export function getWorkStatusStorage() {
return uni.getStorageSync(WORK_STATUS_KEY) || 'NOT_READY' return uni.getStorageSync(WORK_STATUS_KEY) || 'NOT_READY'
} }
export function setRechargePayPasswordStorage(password) {
uni.setStorageSync(RECHARGE_PAY_PASSWORD_KEY, password || '')
}
export function getRechargePayPasswordStorage() {
return uni.getStorageSync(RECHARGE_PAY_PASSWORD_KEY) || ''
}
export function removeRechargePayPasswordStorage() {
uni.removeStorageSync(RECHARGE_PAY_PASSWORD_KEY)
}
/** /**
* 保存记住账号时的用户名。 * 保存记住账号时的用户名。
*/ */