chore: initialize mini program frontend
This commit is contained in:
@@ -0,0 +1,216 @@
|
||||
const api = require('../../utils/api')
|
||||
|
||||
const emptyForm = {
|
||||
attendancePointName: '',
|
||||
deviceNo: '',
|
||||
deviceType: '冲压设备',
|
||||
remark: '',
|
||||
}
|
||||
|
||||
const deviceTypeOptions = ['冲压设备', '清洗设备']
|
||||
|
||||
Page({
|
||||
data: {
|
||||
keyword: '',
|
||||
rows: [],
|
||||
page: 1,
|
||||
pageInput: '1',
|
||||
totalPages: 1,
|
||||
form: { ...emptyForm },
|
||||
formVisible: false,
|
||||
formTitle: '新增设备',
|
||||
attendancePoints: [],
|
||||
attendancePointLabels: [],
|
||||
attendancePointIndex: 0,
|
||||
filterAttendancePointLabels: ['全部考勤点'],
|
||||
filterAttendancePointIndex: 0,
|
||||
filterAttendancePointName: '',
|
||||
deviceTypeOptions,
|
||||
refreshing: false,
|
||||
},
|
||||
onShow() {
|
||||
this.init()
|
||||
},
|
||||
async init() {
|
||||
await this.loadAttendancePoints()
|
||||
await this.load()
|
||||
},
|
||||
async loadAttendancePoints() {
|
||||
try {
|
||||
const points = await api.listAccessibleAttendancePoints()
|
||||
const attendancePoints = points || []
|
||||
this.setData({
|
||||
attendancePoints,
|
||||
attendancePointLabels: attendancePoints.map(item => item.name),
|
||||
filterAttendancePointLabels: ['全部考勤点'].concat(attendancePoints.map(item => item.name)),
|
||||
})
|
||||
if (!this.data.form.attendancePointName && attendancePoints.length) {
|
||||
this.setData({
|
||||
'form.attendancePointName': attendancePoints[0].name,
|
||||
attendancePointIndex: 0,
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
wx.showToast({ title: error.message || '加载考勤点失败', icon: 'none' })
|
||||
}
|
||||
},
|
||||
async load(page = this.data.page) {
|
||||
try {
|
||||
const result = await api.listEquipment({
|
||||
keyword: this.data.keyword,
|
||||
attendancePointName: this.data.filterAttendancePointName,
|
||||
page,
|
||||
pageSize: 8,
|
||||
})
|
||||
this.setData({
|
||||
rows: result.rows,
|
||||
page: result.page,
|
||||
pageInput: String(result.page || 1),
|
||||
totalPages: result.totalPages,
|
||||
})
|
||||
} catch (error) {
|
||||
wx.showToast({ title: error.message || '加载失败', icon: 'none' })
|
||||
}
|
||||
},
|
||||
async onPullDownRefresh() {
|
||||
this.setData({ refreshing: true })
|
||||
try {
|
||||
await this.load(1)
|
||||
} finally {
|
||||
this.setData({ refreshing: false })
|
||||
if (wx.stopPullDownRefresh) {
|
||||
wx.stopPullDownRefresh()
|
||||
}
|
||||
}
|
||||
},
|
||||
onKeywordInput(e) {
|
||||
this.setData({ keyword: e.detail.value, page: 1 })
|
||||
this.load(1)
|
||||
},
|
||||
onFilterAttendancePointChange(e) {
|
||||
const filterAttendancePointIndex = Number(e.detail.value)
|
||||
const point = this.data.attendancePoints[filterAttendancePointIndex - 1]
|
||||
this.setData({
|
||||
filterAttendancePointIndex,
|
||||
filterAttendancePointName: point ? point.name : '',
|
||||
page: 1,
|
||||
})
|
||||
this.load(1)
|
||||
},
|
||||
onInput(e) {
|
||||
const field = e.currentTarget.dataset.field
|
||||
this.setData({
|
||||
[`form.${field}`]: e.detail.value,
|
||||
})
|
||||
},
|
||||
onDeviceTypeChange(e) {
|
||||
const index = Number(e.detail.value)
|
||||
this.setData({
|
||||
'form.deviceType': deviceTypeOptions[index] || '冲压设备',
|
||||
})
|
||||
},
|
||||
onAttendancePointChange(e) {
|
||||
const attendancePointIndex = Number(e.detail.value)
|
||||
const point = this.data.attendancePoints[attendancePointIndex]
|
||||
this.setData({
|
||||
attendancePointIndex,
|
||||
'form.attendancePointName': point ? point.name : '',
|
||||
})
|
||||
},
|
||||
noop() {},
|
||||
openCreate() {
|
||||
const firstPoint = this.data.attendancePoints[0]
|
||||
this.setData({
|
||||
form: { ...emptyForm, attendancePointName: firstPoint ? firstPoint.name : '' },
|
||||
attendancePointIndex: 0,
|
||||
formTitle: '新增设备',
|
||||
formVisible: true,
|
||||
})
|
||||
},
|
||||
edit(e) {
|
||||
const index = e.currentTarget.dataset.index
|
||||
const equipment = this.data.rows[index]
|
||||
const attendancePointIndex = Math.max(0, this.data.attendancePoints.findIndex(item => item.name === equipment.attendancePointName))
|
||||
this.setData({
|
||||
form: {
|
||||
...equipment,
|
||||
originalAttendancePointName: equipment.attendancePointName,
|
||||
originalDeviceNo: equipment.deviceNo,
|
||||
},
|
||||
attendancePointIndex,
|
||||
formTitle: '编辑设备',
|
||||
formVisible: true,
|
||||
})
|
||||
},
|
||||
closeForm() {
|
||||
this.setData({
|
||||
formVisible: false,
|
||||
form: { ...emptyForm, attendancePointName: this.data.attendancePoints[0] ? this.data.attendancePoints[0].name : '' },
|
||||
})
|
||||
},
|
||||
clearForm() {
|
||||
const firstPoint = this.data.attendancePoints[0]
|
||||
this.setData({
|
||||
form: { ...emptyForm, attendancePointName: firstPoint ? firstPoint.name : '' },
|
||||
attendancePointIndex: 0,
|
||||
})
|
||||
},
|
||||
async save() {
|
||||
try {
|
||||
if (!this.data.form.attendancePointName) {
|
||||
wx.showToast({ title: '请选择考勤点', icon: 'none' })
|
||||
return
|
||||
}
|
||||
await api.saveEquipment(this.data.form)
|
||||
wx.showToast({ title: '已保存', icon: 'success' })
|
||||
this.setData({ form: { ...emptyForm }, formVisible: false })
|
||||
await this.load(1)
|
||||
} catch (error) {
|
||||
wx.showToast({ title: error.message || '保存失败', icon: 'none' })
|
||||
}
|
||||
},
|
||||
remove(e) {
|
||||
const index = e.currentTarget.dataset.index
|
||||
const equipment = this.data.rows[index]
|
||||
wx.showModal({
|
||||
title: '删除设备',
|
||||
content: equipment.deviceNo,
|
||||
confirmText: '删除',
|
||||
confirmColor: '#d92d20',
|
||||
success: async res => {
|
||||
if (!res.confirm) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await api.deleteEquipment(equipment)
|
||||
await this.load(1)
|
||||
} catch (error) {
|
||||
wx.showToast({ title: error.message || '删除失败', icon: 'none' })
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
prevPage() {
|
||||
if (this.data.page > 1) {
|
||||
this.load(this.data.page - 1)
|
||||
}
|
||||
},
|
||||
nextPage() {
|
||||
if (this.data.page < this.data.totalPages) {
|
||||
this.load(this.data.page + 1)
|
||||
}
|
||||
},
|
||||
onPageInput(e) {
|
||||
this.setData({ pageInput: e.detail.value })
|
||||
},
|
||||
jumpToPage(e) {
|
||||
wx.hideKeyboard()
|
||||
const inputValue = e && e.detail && e.detail.value !== undefined ? e.detail.value : this.data.pageInput
|
||||
const target = Math.max(1, Math.min(Number(inputValue) || this.data.page, this.data.totalPages))
|
||||
if (target === this.data.page) {
|
||||
this.setData({ pageInput: String(this.data.page || 1) })
|
||||
return
|
||||
}
|
||||
this.load(target)
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"navigationBarTitleText": "设备管理"
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<scroll-view
|
||||
class="page safe-bottom"
|
||||
scroll-y
|
||||
type="list"
|
||||
refresher-enabled
|
||||
refresher-triggered="{{refreshing}}"
|
||||
bindrefresherrefresh="onPullDownRefresh"
|
||||
>
|
||||
<view class="header">
|
||||
<text class="title">设备管理</text>
|
||||
<text class="subtitle">维护员工报工可选择的设备号和设备类型</text>
|
||||
</view>
|
||||
|
||||
<view class="card">
|
||||
<button class="btn primary full add-btn" bindtap="openCreate">新增设备</button>
|
||||
</view>
|
||||
|
||||
<view class="equipment-filter-card">
|
||||
<input class="input search" placeholder="搜索考勤点、设备号、类型、备注" value="{{keyword}}" bindinput="onKeywordInput" />
|
||||
<picker
|
||||
range="{{filterAttendancePointLabels}}"
|
||||
value="{{filterAttendancePointIndex}}"
|
||||
bindchange="onFilterAttendancePointChange"
|
||||
>
|
||||
<view class="picker filter-picker">{{filterAttendancePointLabels[filterAttendancePointIndex] || '全部考勤点'}}</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{!rows.length}}" class="list-empty">暂无设备</view>
|
||||
<view wx:for="{{rows}}" wx:key="uniqueKey" wx:for-index="index" class="card equipment-card">
|
||||
<view class="row">
|
||||
<view class="row-left">
|
||||
<text class="value">{{item.deviceNo}}</text>
|
||||
<text class="subtitle">考勤点 {{item.attendancePointName || '-'}}</text>
|
||||
<text class="subtitle">{{item.remark || '暂无备注'}}</text>
|
||||
</view>
|
||||
<text class="pill primary">{{item.deviceType || '冲压设备'}}</text>
|
||||
</view>
|
||||
<view class="button-row">
|
||||
<button class="btn secondary full" data-index="{{index}}" bindtap="edit">编辑</button>
|
||||
<button class="btn danger full" data-index="{{index}}" bindtap="remove">删除</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="button-row pager-row" wx:if="{{rows.length}}">
|
||||
<button class="btn secondary pager-nav" bindtap="prevPage" disabled="{{page <= 1}}">上一页</button>
|
||||
<view class="page-jump-control">
|
||||
<input class="page-jump-input" type="number" confirm-type="done" value="{{pageInput}}" bindinput="onPageInput" bindconfirm="jumpToPage" />
|
||||
<text class="page-total-label">/ {{totalPages}}</text>
|
||||
<text class="page-jump-action" bindtap="jumpToPage">跳</text>
|
||||
</view>
|
||||
<button class="btn secondary pager-nav" bindtap="nextPage" disabled="{{page >= totalPages}}">下一页</button>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view wx:if="{{formVisible}}" class="modal-mask" catchtap="closeForm">
|
||||
<view class="modal-panel" catchtap="noop">
|
||||
<view class="modal-head">
|
||||
<text class="modal-title">{{formTitle}}</text>
|
||||
<button class="btn mini secondary modal-close" bindtap="clearForm">清空</button>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">考勤点</text>
|
||||
<picker
|
||||
wx:if="{{attendancePoints.length}}"
|
||||
range="{{attendancePointLabels}}"
|
||||
value="{{attendancePointIndex}}"
|
||||
bindchange="onAttendancePointChange"
|
||||
>
|
||||
<view class="picker">{{form.attendancePointName || '请选择考勤点'}}</view>
|
||||
</picker>
|
||||
<view wx:else class="readonly">暂无可选考勤点</view>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">设备号</text>
|
||||
<input class="input" value="{{form.deviceNo}}" data-field="deviceNo" bindinput="onInput" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">设备类型</text>
|
||||
<picker range="{{deviceTypeOptions}}" value="{{form.deviceType === '清洗设备' ? 1 : 0}}" bindchange="onDeviceTypeChange">
|
||||
<view class="picker">{{form.deviceType || '冲压设备'}}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">备注</text>
|
||||
<textarea class="textarea" value="{{form.remark}}" data-field="remark" bindinput="onInput"></textarea>
|
||||
</view>
|
||||
<view class="button-row">
|
||||
<button class="btn secondary full" bindtap="closeForm">关闭</button>
|
||||
<button class="btn primary full" bindtap="save">保存设备</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -0,0 +1,72 @@
|
||||
.search {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.equipment-filter-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.filter-picker {
|
||||
min-height: 82rpx;
|
||||
line-height: 82rpx;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.equipment-card {
|
||||
border-left: 6rpx solid #1463ff;
|
||||
}
|
||||
|
||||
.modal-mask {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 50;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32rpx;
|
||||
background: rgba(15, 23, 42, 0.48);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.modal-panel {
|
||||
width: 100%;
|
||||
max-height: 82vh;
|
||||
overflow-y: auto;
|
||||
padding: 30rpx;
|
||||
border: 1rpx solid #e4e9f1;
|
||||
border-radius: 18rpx;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #fbfdff 100%);
|
||||
box-shadow:
|
||||
0 16rpx 0 rgba(170, 184, 204, 0.62),
|
||||
0 30rpx 64rpx rgba(15, 23, 42, 0.24),
|
||||
inset 0 2rpx 0 rgba(255, 255, 255, 0.96);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.modal-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 18rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
color: #162232;
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
flex: 0 0 auto;
|
||||
margin: 0;
|
||||
}
|
||||
Reference in New Issue
Block a user