Track the weighbridge mobile-h5 codebase (excluding node_modules, dist, and local .env) so subsequent adaptation tasks can evolve it in-repo. Co-authored-by: Cursor <cursoragent@cursor.com>
170 lines
4.9 KiB
Vue
170 lines
4.9 KiB
Vue
<template>
|
|
<div class="page-content">
|
|
<div class="page-header">
|
|
<div class="page-header__back" @click="handleBack">
|
|
<div class="back-arrow"></div>
|
|
</div>
|
|
<div class="page-header__title">{{ isEdit ? '编辑用户' : isView ? '查看用户' : '新增用户' }}</div>
|
|
</div>
|
|
|
|
<div class="form-container">
|
|
<van-form @submit="handleSubmit">
|
|
<div class="form-section">
|
|
<div class="form-item">
|
|
<div class="form-label">用户名 <span class="required">*</span></div>
|
|
<div v-if="isView" class="form-input">
|
|
{{ formData.username || '--' }}
|
|
</div>
|
|
<van-field
|
|
v-else
|
|
v-model="formData.username"
|
|
placeholder="请输入用户名"
|
|
:disabled="!!editingUser"
|
|
/>
|
|
</div>
|
|
|
|
<div class="form-item">
|
|
<div class="form-label">{{ editingUser ? '新密码' : '密码' }} <span class="required" v-if="!editingUser">*</span></div>
|
|
<div v-if="isView" class="form-input">
|
|
******
|
|
</div>
|
|
<van-field
|
|
v-else
|
|
v-model="formData.password"
|
|
type="password"
|
|
:placeholder="editingUser ? '留空则不修改密码' : '请输入密码'"
|
|
/>
|
|
</div>
|
|
|
|
<div class="form-item">
|
|
<div class="form-label">角色 <span class="required">*</span></div>
|
|
<div v-if="isView" class="form-input">
|
|
{{ formData.role === 'admin' ? '管理员' : '操作员' }}
|
|
</div>
|
|
<div v-else class="form-input" @click="showRolePicker = true">
|
|
<span :class="{ placeholder: !formData.role }">
|
|
{{ formData.role === 'admin' ? '管理员' : formData.role === 'operator' ? '操作员' : '请选择角色' }}
|
|
</span>
|
|
<van-icon name="arrow" class="arrow-icon" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div v-if="!isView" class="form-actions">
|
|
<van-button block type="primary" native-type="submit" :loading="saving">
|
|
保存
|
|
</van-button>
|
|
<van-button block plain @click="handleBack">
|
|
取消
|
|
</van-button>
|
|
</div>
|
|
</van-form>
|
|
</div>
|
|
|
|
<!-- 角色选择器 -->
|
|
<van-popup v-model:show="showRolePicker" round position="bottom">
|
|
<van-picker
|
|
:columns="roleOptions"
|
|
show-toolbar
|
|
@confirm="onRoleConfirm"
|
|
@cancel="showRolePicker = false"
|
|
/>
|
|
</van-popup>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, computed, onMounted } from 'vue'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import { showToast } from 'vant'
|
|
import { userApi, type User, type UserCreate } from '@/api/usersApi'
|
|
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
|
|
const isView = computed(() => route.query.mode === 'view')
|
|
const isEdit = computed(() => route.query.mode === 'edit' || route.params.id)
|
|
// const isAdd = computed(() => !isView.value && !isEdit.value) // 未使用
|
|
|
|
const saving = ref(false)
|
|
const editingUser = ref<User | null>(null)
|
|
const showRolePicker = ref(false)
|
|
|
|
const roleOptions = [
|
|
{ text: '管理员', value: 'admin' },
|
|
{ text: '操作员', value: 'operator' }
|
|
]
|
|
|
|
const formData = reactive<UserCreate>({
|
|
username: '',
|
|
password: '',
|
|
role: 'operator'
|
|
})
|
|
|
|
const loadData = async () => {
|
|
if (isEdit.value && route.params.id) {
|
|
try {
|
|
const user = await userApi.get(Number(route.params.id))
|
|
editingUser.value = user
|
|
Object.assign(formData, {
|
|
username: user.username,
|
|
password: '',
|
|
role: user.role || 'operator'
|
|
})
|
|
} catch (error) {
|
|
showToast({ type: 'fail', message: '加载数据失败' })
|
|
router.back()
|
|
}
|
|
}
|
|
}
|
|
|
|
const onRoleConfirm = ({ selectedOptions }: any) => {
|
|
formData.role = selectedOptions[0].value
|
|
showRolePicker.value = false
|
|
}
|
|
|
|
const handleSubmit = async () => {
|
|
if (!formData.username || (!editingUser.value && !formData.password)) {
|
|
showToast({ type: 'fail', message: '请填写必填项' })
|
|
return
|
|
}
|
|
|
|
saving.value = true
|
|
try {
|
|
if (editingUser.value) {
|
|
const updateData: any = {
|
|
role: formData.role
|
|
}
|
|
if (formData.password) {
|
|
updateData.password = formData.password
|
|
}
|
|
await userApi.update(editingUser.value.id, updateData)
|
|
showToast({ type: 'success', message: '更新成功' })
|
|
} else {
|
|
await userApi.create(formData)
|
|
showToast({ type: 'success', message: '创建成功' })
|
|
}
|
|
router.back()
|
|
} catch (error: any) {
|
|
showToast({ type: 'fail', message: error.message || '操作失败' })
|
|
} finally {
|
|
saving.value = false
|
|
}
|
|
}
|
|
|
|
const handleBack = () => {
|
|
router.back()
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (isEdit.value || isView.value) {
|
|
loadData()
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
@import '@/assets/styles/detail-page.scss';
|
|
</style>
|
|
|