630 lines
20 KiB
JavaScript
630 lines
20 KiB
JavaScript
const api = require('../../utils/api')
|
||
const locationGuard = require('../../utils/locationGuard')
|
||
const { buildErpLoginConfirmUrlFromScanResult } = require('../../utils/scanRouting')
|
||
|
||
const avatarKey = phone => `jh_wrs_avatar_${phone}`
|
||
|
||
Page({
|
||
data: {
|
||
activeTab: 'home',
|
||
currentUser: null,
|
||
currentRoleName: '',
|
||
currentRolesText: '',
|
||
canSwitchRole: false,
|
||
avatarPath: '',
|
||
avatarText: '',
|
||
roleChoices: [],
|
||
selectionToken: '',
|
||
summary: {},
|
||
showOverview: false,
|
||
showWorkerTrend: false,
|
||
workerTrend: {
|
||
total: 0,
|
||
max: 0,
|
||
points: [],
|
||
segments: [],
|
||
},
|
||
notices: [],
|
||
noticeList: [],
|
||
actions: [],
|
||
currentAttendancePointName: '',
|
||
locationStatusText: '当前位置:未进入考勤点',
|
||
locationEntered: false,
|
||
locationInitialized: false,
|
||
loading: false,
|
||
refreshing: false,
|
||
temporaryWorkerModalVisible: false,
|
||
temporaryWorkerPrompt: '',
|
||
temporaryWorkerName: '',
|
||
},
|
||
onShow() {
|
||
this.load({ refreshLocation: !this.data.locationInitialized }).catch(error => {
|
||
wx.showToast({ title: error.message || '加载失败', icon: 'none' })
|
||
})
|
||
},
|
||
async load(options = {}) {
|
||
let currentUser = api.getCurrentUser()
|
||
let summary = {}
|
||
let showOverview = false
|
||
let showWorkerTrend = false
|
||
let workerTrend = { total: 0, max: 0, points: [], segments: [] }
|
||
let notices = []
|
||
let locationView = {
|
||
currentAttendancePointName: this.data.currentAttendancePointName,
|
||
locationStatusText: this.data.locationStatusText,
|
||
locationEntered: this.data.locationEntered,
|
||
}
|
||
let locationInitialized = this.data.locationInitialized
|
||
if (currentUser) {
|
||
try {
|
||
currentUser = await api.refreshCurrentUser() || currentUser
|
||
showOverview = currentUser.role !== 'worker'
|
||
showWorkerTrend = currentUser.role === 'worker'
|
||
if (showOverview) {
|
||
summary = await api.getHomeSummary(currentUser)
|
||
}
|
||
if (showWorkerTrend) {
|
||
workerTrend = await this.loadWorkerTrend()
|
||
}
|
||
} catch (error) {
|
||
wx.showToast({ title: error.message, icon: 'none' })
|
||
currentUser = api.getCurrentUser()
|
||
showOverview = !!currentUser && currentUser.role !== 'worker'
|
||
showWorkerTrend = !!currentUser && currentUser.role === 'worker'
|
||
}
|
||
if (currentUser) {
|
||
notices = await this.loadNotices()
|
||
if (options.refreshLocation || !locationInitialized) {
|
||
locationView = await this.refreshLocationStatus()
|
||
locationInitialized = true
|
||
}
|
||
}
|
||
} else {
|
||
locationInitialized = false
|
||
locationView = {
|
||
currentAttendancePointName: '',
|
||
locationStatusText: '当前位置:未进入考勤点',
|
||
locationEntered: false,
|
||
}
|
||
}
|
||
const actions = this.buildActions(currentUser)
|
||
const overviewItems = this.buildOverviewItems(currentUser, summary)
|
||
const userView = this.buildUserView(currentUser)
|
||
this.setData({
|
||
currentUser,
|
||
summary,
|
||
overviewItems,
|
||
showOverview,
|
||
showWorkerTrend,
|
||
workerTrend,
|
||
notices,
|
||
noticeList: notices.slice(0, 3),
|
||
actions,
|
||
...locationView,
|
||
locationInitialized,
|
||
...userView,
|
||
})
|
||
},
|
||
async onPullDownRefresh() {
|
||
this.setData({ refreshing: true })
|
||
try {
|
||
await this.load({ refreshLocation: true })
|
||
} finally {
|
||
this.setData({ refreshing: false })
|
||
if (wx.stopPullDownRefresh) {
|
||
wx.stopPullDownRefresh()
|
||
}
|
||
}
|
||
},
|
||
async loadNotices() {
|
||
try {
|
||
const result = await api.listNotices({ page: 1, pageSize: 6 })
|
||
return result.rows || []
|
||
} catch (error) {
|
||
return []
|
||
}
|
||
},
|
||
async refreshLocationStatus() {
|
||
try {
|
||
const result = await locationGuard.getCurrentAttendancePoint()
|
||
if (result && result.factory) {
|
||
return {
|
||
currentAttendancePointName: result.factory.name,
|
||
locationStatusText: `当前位置:已进入 ${result.factory.name} 考勤点`,
|
||
locationEntered: true,
|
||
}
|
||
}
|
||
} catch (error) {
|
||
return {
|
||
currentAttendancePointName: '',
|
||
locationStatusText: '当前位置:未进入考勤点',
|
||
locationEntered: false,
|
||
}
|
||
}
|
||
return {
|
||
currentAttendancePointName: '',
|
||
locationStatusText: '当前位置:未进入考勤点',
|
||
locationEntered: false,
|
||
}
|
||
},
|
||
buildUserView(user) {
|
||
if (!user) {
|
||
return {
|
||
currentRoleName: '',
|
||
currentRolesText: '',
|
||
canSwitchRole: false,
|
||
avatarPath: '',
|
||
avatarText: '',
|
||
}
|
||
}
|
||
|
||
return {
|
||
currentRoleName: user.roleName || api.roleNames[user.role] || user.role,
|
||
currentRolesText: (user.roleNames || []).join('、') || user.roleName || '',
|
||
canSwitchRole: !!(user.rolesDisplay && user.rolesDisplay.length > 1),
|
||
avatarPath: wx.getStorageSync(avatarKey(user.phone)) || '',
|
||
avatarText: this.buildDefaultAvatarText(user.name),
|
||
}
|
||
},
|
||
buildOverviewItems(user, summary = {}) {
|
||
if (!user || user.role === 'worker') {
|
||
return []
|
||
}
|
||
const today = this.formatDate(new Date())
|
||
return [
|
||
{
|
||
key: 'products',
|
||
label: '产品',
|
||
value: summary.productCount || 0,
|
||
url: '/pages/manageProducts/manageProducts?readonly=1',
|
||
},
|
||
{
|
||
key: 'people',
|
||
label: '人员',
|
||
value: summary.peopleCount || 0,
|
||
url: '/pages/managePeople/managePeople?readonly=1',
|
||
},
|
||
...(user.role === 'admin' ? [{
|
||
key: 'pending',
|
||
label: '待审核',
|
||
value: summary.pendingCount || 0,
|
||
alert: (summary.pendingCount || 0) > 0,
|
||
url: '/pages/records/records?mode=pending&status=pending',
|
||
}] : []),
|
||
...(user.role === 'admin' ? [{
|
||
key: 'approved',
|
||
label: '今日通过',
|
||
value: summary.approvedToday || 0,
|
||
url: `/pages/records/records?mode=audit&status=approved&startDate=${today}&endDate=${today}`,
|
||
}] : []),
|
||
]
|
||
},
|
||
buildDefaultAvatarText(name) {
|
||
const text = String(name || '').trim()
|
||
if (!text) {
|
||
return '嘉'
|
||
}
|
||
const givenName = text.length > 1 ? text.slice(1) : text
|
||
return givenName.slice(0, 2)
|
||
},
|
||
switchTab(e) {
|
||
const activeTab = e.currentTarget.dataset.tab
|
||
this.setData({ activeTab })
|
||
},
|
||
buildRecentDates(days = 7) {
|
||
const dates = []
|
||
const today = new Date()
|
||
for (let index = days - 1; index >= 0; index -= 1) {
|
||
const date = new Date(today)
|
||
date.setDate(today.getDate() - index)
|
||
const value = this.formatDate(date)
|
||
dates.push({
|
||
value,
|
||
label: value.slice(5),
|
||
})
|
||
}
|
||
return dates
|
||
},
|
||
formatDate(date) {
|
||
const year = date.getFullYear()
|
||
const monthValue = date.getMonth() + 1
|
||
const dayValue = date.getDate()
|
||
const month = monthValue < 10 ? `0${monthValue}` : `${monthValue}`
|
||
const day = dayValue < 10 ? `0${dayValue}` : `${dayValue}`
|
||
return `${year}-${month}-${day}`
|
||
},
|
||
async loadWorkerTrend() {
|
||
const dates = this.buildRecentDates(7)
|
||
const result = await api.listReports({
|
||
startDate: dates[0].value,
|
||
endDate: dates[dates.length - 1].value,
|
||
page: 1,
|
||
pageSize: 100,
|
||
})
|
||
const totals = dates.reduce((map, item) => {
|
||
map[item.value] = 0
|
||
return map
|
||
}, {})
|
||
;(result.rows || []).forEach(report => {
|
||
if (totals[report.reportDate] === undefined) {
|
||
return
|
||
}
|
||
totals[report.reportDate] += Number(report.metrics && report.metrics.totalGood || 0)
|
||
})
|
||
const points = dates.map(item => ({
|
||
date: item.value,
|
||
label: item.label,
|
||
value: totals[item.value] || 0,
|
||
}))
|
||
const total = points.reduce((sum, item) => sum + item.value, 0)
|
||
const max = points.reduce((largest, item) => Math.max(largest, item.value), 0)
|
||
return this.buildTrendView(total, max, points)
|
||
},
|
||
buildTrendView(total, max, points) {
|
||
const maxValue = Math.max(1, max || 0)
|
||
const lastIndex = Math.max(1, points.length - 1)
|
||
const chartInset = 8
|
||
const chartSpan = 100 - chartInset * 2
|
||
const plottedPoints = points.map((item, index) => {
|
||
const left = chartInset + (index * chartSpan / lastIndex)
|
||
const top = 82 - (Number(item.value || 0) / maxValue) * 68
|
||
return {
|
||
...item,
|
||
left: left.toFixed(2),
|
||
top: top.toFixed(2),
|
||
edgeClass: index === 0 ? 'first' : (index === points.length - 1 ? 'last' : ''),
|
||
valueText: String(item.value || 0),
|
||
}
|
||
})
|
||
const segments = []
|
||
for (let index = 0; index < plottedPoints.length - 1; index += 1) {
|
||
const start = plottedPoints[index]
|
||
const end = plottedPoints[index + 1]
|
||
const dx = Number(end.left) - Number(start.left)
|
||
const dy = Number(end.top) - Number(start.top)
|
||
const dxRpx = dx * 5.6
|
||
const dyRpx = dy * 2.2
|
||
const width = Math.sqrt(dxRpx * dxRpx + dyRpx * dyRpx) / 5.6
|
||
const angle = Math.atan2(dyRpx, dxRpx) * 180 / Math.PI
|
||
segments.push({
|
||
left: start.left,
|
||
top: start.top,
|
||
width: width.toFixed(2),
|
||
angle: angle.toFixed(2),
|
||
})
|
||
}
|
||
return { total, max, points: plottedPoints, segments }
|
||
},
|
||
buildActions(user) {
|
||
if (!user) {
|
||
return []
|
||
}
|
||
|
||
if (user.role === 'worker') {
|
||
return [
|
||
{ key: 'records', icon: '记', title: '我的报工记录', desc: '按日期查看提交和审核状态', url: '/pages/records/records' },
|
||
]
|
||
}
|
||
|
||
if (user.role === 'admin') {
|
||
return [
|
||
{ key: 'products', icon: '产', title: '产品清单', desc: '导入、添加、修改产品', url: '/pages/manageProducts/manageProducts' },
|
||
{ key: 'people', icon: '人', title: '人员清单', desc: '维护员工、管理员和经理', url: '/pages/managePeople/managePeople' },
|
||
{ key: 'review', icon: '审', title: '报工审核', desc: '处理待审核报工', url: '/pages/review/review' },
|
||
{ key: 'audit', icon: '核', title: '审核记录', desc: '查看已审核报工', url: '/pages/records/records?mode=audit' },
|
||
{ key: 'monitor', icon: '监', title: '智能监控', desc: '查看模具占用和反馈', url: '/pages/smartMonitor/smartMonitor' },
|
||
{ key: 'usageStats', icon: '统', title: '设备模具使用统计', desc: '按时间统计设备和模具使用', url: '/pages/usageStats/usageStats' },
|
||
{ key: 'moldQr', icon: '码', title: '模具二维码', desc: '生成模具扫码入口', url: '/pages/deviceQr/deviceQr' },
|
||
{ key: 'equipment', icon: '设', title: '设备管理', desc: '维护设备号和备注', url: '/pages/manageEquipment/manageEquipment' },
|
||
{ key: 'notices', icon: '通', title: '通知配置', desc: '维护首页通知公告', url: '/pages/manageNotices/manageNotices' },
|
||
]
|
||
}
|
||
|
||
return [
|
||
{ key: 'products', icon: '产', title: '产品清单', desc: '导入或添加新产品', url: '/pages/manageProducts/manageProducts' },
|
||
{ key: 'people', icon: '人', title: '人员清单', desc: '维护员工、管理员和经理', url: '/pages/managePeople/managePeople' },
|
||
{ key: 'schedule', icon: '勤', title: '考勤设置', desc: '维护作息时间和考勤范围', url: '/pages/workSchedule/workSchedule' },
|
||
{ key: 'ledger', icon: '账', title: '对账小账本', desc: '按月核对最后工序成品数量', url: '/pages/reconciliationLedger/reconciliationLedger' },
|
||
{ key: 'dashboard', icon: '看', title: '报工看板', desc: '按日期查看工人日报', url: '/pages/dashboard/dashboard' },
|
||
{ key: 'usageStats', icon: '统', title: '设备模具使用统计', desc: '按时间统计设备和模具使用', url: '/pages/usageStats/usageStats' },
|
||
{ key: 'notices', icon: '通', title: '通知配置', desc: '维护首页通知公告', url: '/pages/manageNotices/manageNotices' },
|
||
]
|
||
},
|
||
decodeRepeated(value) {
|
||
let text = String(value || '').trim()
|
||
for (let index = 0; index < 3; index += 1) {
|
||
try {
|
||
const decoded = decodeURIComponent(text)
|
||
if (decoded === text) {
|
||
break
|
||
}
|
||
text = decoded
|
||
} catch (error) {
|
||
break
|
||
}
|
||
}
|
||
return text
|
||
},
|
||
extractMoldName(scanResult) {
|
||
const raw = this.decodeRepeated(scanResult)
|
||
if (!raw) {
|
||
return ''
|
||
}
|
||
|
||
const patterns = [
|
||
/(?:^|[?&])moldName=([^&]+)/i,
|
||
/(?:^|[?&])mold_name=([^&]+)/i,
|
||
/(?:^|[?&])deviceNo=([^&]+)/i,
|
||
/(?:^|[?&])device_no=([^&]+)/i,
|
||
/(?:^|[?&])scene=([^&]+)/i,
|
||
/moldName=([^&]+)/i,
|
||
/deviceNo=([^&]+)/i,
|
||
]
|
||
for (let index = 0; index < patterns.length; index += 1) {
|
||
const matched = raw.match(patterns[index])
|
||
if (matched && matched[1]) {
|
||
const value = this.decodeRepeated(matched[1])
|
||
if (value.includes('moldName=') || value.includes('deviceNo=')) {
|
||
return this.extractMoldName(value)
|
||
}
|
||
return String(value || '').trim()
|
||
}
|
||
}
|
||
|
||
return raw
|
||
},
|
||
async scanDevice() {
|
||
wx.scanCode({
|
||
onlyFromCamera: false,
|
||
success: async res => {
|
||
const erpLoginUrl = buildErpLoginConfirmUrlFromScanResult(res)
|
||
if (erpLoginUrl) {
|
||
wx.navigateTo({ url: erpLoginUrl })
|
||
return
|
||
}
|
||
const candidates = [res.path, res.result, res.rawData]
|
||
const moldName = candidates.reduce((found, item) => (
|
||
found || this.extractMoldName(item)
|
||
), '')
|
||
if (!moldName) {
|
||
wx.showToast({ title: '未识别模具名称', icon: 'none' })
|
||
return
|
||
}
|
||
const paramName = moldName.startsWith('mold=') ? 'scene' : 'moldName'
|
||
try {
|
||
wx.showLoading({ title: paramName === 'scene' ? '校验中' : '定位中' })
|
||
if (paramName === 'scene') {
|
||
const resolved = await api.resolveMoldScene(moldName)
|
||
await locationGuard.ensureFactoryLocation(resolved.attendancePointName)
|
||
} else {
|
||
await locationGuard.ensureFactoryLocation()
|
||
}
|
||
} catch (error) {
|
||
wx.showModal({
|
||
title: '无法扫码报工',
|
||
content: error.message || '当前位置不在允许范围内',
|
||
showCancel: false,
|
||
})
|
||
return
|
||
} finally {
|
||
wx.hideLoading()
|
||
}
|
||
wx.navigateTo({
|
||
url: `/pages/clock/clock?${paramName}=${encodeURIComponent(moldName)}`,
|
||
})
|
||
},
|
||
fail: error => {
|
||
if (error.errMsg && error.errMsg.includes('cancel')) {
|
||
return
|
||
}
|
||
wx.showToast({ title: '扫码失败', icon: 'none' })
|
||
},
|
||
})
|
||
},
|
||
async wechatLogin(e) {
|
||
const phoneCode = e.detail && e.detail.code
|
||
if (!phoneCode) {
|
||
wx.showToast({ title: '未获得手机号授权', icon: 'none' })
|
||
return
|
||
}
|
||
wx.showLoading({ title: '登录中' })
|
||
try {
|
||
const result = await api.loginWithPhoneCode(phoneCode)
|
||
if (result.needsTemporaryWorker) {
|
||
wx.hideLoading()
|
||
await this.confirmTemporaryWorker(result)
|
||
return
|
||
}
|
||
if (result.needsSelection) {
|
||
this.setData({
|
||
roleChoices: result.matchedPeople,
|
||
selectionToken: result.selectionToken,
|
||
})
|
||
return
|
||
}
|
||
await this.load({ refreshLocation: true })
|
||
} catch (error) {
|
||
wx.showToast({ title: error.message, icon: 'none' })
|
||
} finally {
|
||
wx.hideLoading()
|
||
}
|
||
},
|
||
confirmTemporaryWorker(result) {
|
||
return new Promise(resolve => {
|
||
this.temporaryWorkerResult = result
|
||
this.temporaryWorkerResolve = resolve
|
||
this.setData({
|
||
temporaryWorkerModalVisible: true,
|
||
temporaryWorkerPrompt: `该手机号${result.temporaryPhone || ''}不在人员清单中。临时工账号有效期只有24小时,请填写姓名后创建。`,
|
||
temporaryWorkerName: '',
|
||
})
|
||
})
|
||
},
|
||
onTemporaryWorkerNameInput(e) {
|
||
this.setData({ temporaryWorkerName: e.detail.value })
|
||
},
|
||
closeTemporaryWorkerModal() {
|
||
this.setData({
|
||
temporaryWorkerModalVisible: false,
|
||
temporaryWorkerPrompt: '',
|
||
temporaryWorkerName: '',
|
||
})
|
||
this.temporaryWorkerResult = null
|
||
if (this.temporaryWorkerResolve) {
|
||
this.temporaryWorkerResolve()
|
||
this.temporaryWorkerResolve = null
|
||
}
|
||
},
|
||
async submitTemporaryWorker() {
|
||
const result = this.temporaryWorkerResult
|
||
const name = String(this.data.temporaryWorkerName || '').trim()
|
||
if (!name) {
|
||
wx.showToast({ title: '请输入姓名', icon: 'none' })
|
||
return
|
||
}
|
||
if (!result || !result.temporaryToken) {
|
||
wx.showToast({ title: '临时工注册信息已失效,请重新登录', icon: 'none' })
|
||
this.closeTemporaryWorkerModal()
|
||
return
|
||
}
|
||
this.setData({ temporaryWorkerModalVisible: false })
|
||
wx.showLoading({ title: '定位中' })
|
||
try {
|
||
const attendancePoint = await locationGuard.ensureTemporaryWorkerLocation()
|
||
wx.showLoading({ title: '创建中' })
|
||
await api.createTemporaryWorker(result.temporaryToken, name, attendancePoint)
|
||
await this.load({ refreshLocation: true })
|
||
wx.showToast({ title: '临时工已生效', icon: 'success' })
|
||
} catch (error) {
|
||
wx.showToast({ title: error.message, icon: 'none' })
|
||
} finally {
|
||
wx.hideLoading()
|
||
this.closeTemporaryWorkerModal()
|
||
}
|
||
},
|
||
logout() {
|
||
api.logout()
|
||
this.setData({ locationInitialized: false })
|
||
this.load()
|
||
},
|
||
chooseAvatar() {
|
||
const user = this.data.currentUser
|
||
if (!user) {
|
||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
const save = tempFilePath => {
|
||
const saveToStorage = path => {
|
||
wx.setStorageSync(avatarKey(user.phone), path)
|
||
this.setData({ avatarPath: path })
|
||
}
|
||
if (wx.saveFile) {
|
||
wx.saveFile({
|
||
tempFilePath,
|
||
success: res => saveToStorage(res.savedFilePath),
|
||
fail: () => saveToStorage(tempFilePath),
|
||
})
|
||
return
|
||
}
|
||
saveToStorage(tempFilePath)
|
||
}
|
||
|
||
if (wx.chooseMedia) {
|
||
wx.chooseMedia({
|
||
count: 1,
|
||
mediaType: ['image'],
|
||
sourceType: ['album', 'camera'],
|
||
success: res => {
|
||
const file = res.tempFiles && res.tempFiles[0]
|
||
if (file && file.tempFilePath) {
|
||
save(file.tempFilePath)
|
||
}
|
||
},
|
||
})
|
||
return
|
||
}
|
||
|
||
wx.chooseImage({
|
||
count: 1,
|
||
sourceType: ['album', 'camera'],
|
||
success: res => {
|
||
const path = res.tempFilePaths && res.tempFilePaths[0]
|
||
if (path) {
|
||
save(path)
|
||
}
|
||
},
|
||
})
|
||
},
|
||
switchCurrentRole() {
|
||
const user = this.data.currentUser
|
||
const choices = (user && user.rolesDisplay ? user.rolesDisplay : [])
|
||
.filter(item => item.role !== user.role)
|
||
if (!choices.length) {
|
||
wx.showToast({ title: '没有可切换的角色', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
wx.showActionSheet({
|
||
itemList: choices.map(item => item.roleName),
|
||
success: async res => {
|
||
const target = choices[res.tapIndex]
|
||
if (!target) {
|
||
return
|
||
}
|
||
wx.showLoading({ title: '切换中' })
|
||
try {
|
||
await api.switchRole(target.role)
|
||
await this.load({ refreshLocation: true })
|
||
wx.showToast({ title: '已切换角色', icon: 'success' })
|
||
} catch (error) {
|
||
wx.showToast({ title: error.message, icon: 'none' })
|
||
} finally {
|
||
wx.hideLoading()
|
||
}
|
||
},
|
||
})
|
||
},
|
||
async chooseRole(e) {
|
||
const role = e.currentTarget.dataset.role
|
||
wx.showLoading({ title: '登录中' })
|
||
try {
|
||
await api.selectRole(this.data.selectionToken, role)
|
||
this.setData({ roleChoices: [], selectionToken: '' })
|
||
await this.load({ refreshLocation: true })
|
||
} catch (error) {
|
||
wx.showToast({ title: error.message, icon: 'none' })
|
||
} finally {
|
||
wx.hideLoading()
|
||
}
|
||
},
|
||
openAction(e) {
|
||
wx.navigateTo({
|
||
url: e.currentTarget.dataset.url,
|
||
})
|
||
},
|
||
openOverview(e) {
|
||
const url = e.currentTarget.dataset.url
|
||
const disabledText = e.currentTarget.dataset.disabledText
|
||
if (!url) {
|
||
wx.showToast({ title: disabledText || '当前角色无权限', icon: 'none' })
|
||
return
|
||
}
|
||
wx.navigateTo({ url })
|
||
},
|
||
noop() {},
|
||
resetDemo() {
|
||
wx.showModal({
|
||
title: '退出登录',
|
||
content: '退出当前账号后需要重新进行手机号快捷登录。',
|
||
success: res => {
|
||
if (res.confirm) {
|
||
api.logout()
|
||
this.setData({ roleChoices: [], selectionToken: '', locationInitialized: false })
|
||
this.load()
|
||
}
|
||
},
|
||
})
|
||
},
|
||
})
|