Files
shanxia2.0/mobile-h5/src/views/user/detail.vue
T
zlwuandCursor a4b13fa2bc chore(mobile-h5): add existing H5 app sources to the monorepo
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>
2026-08-03 22:28:53 +08:00

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>