| | |
| | | <u-navbar :is-back="true" :title="title" title-color="#333" back-icon-color="#333"></u-navbar> |
| | | <!-- 表单区域 --> |
| | | <view class="form-card"> |
| | | <u-form :model="form" ref="uForm1" label-width="150rpx"> |
| | | <u-form :model="form" ref="uForm1" label-width="150rpx" :rules="rules"> |
| | | |
| | | <!-- 真实姓名 --> |
| | | <u-form-item label="真实姓名" prop="realName" borderBottom required="true"> |
| | |
| | | <u-form-item label="电话" prop="mobile" borderBottom required="true"> |
| | | <u-input v-model="form.mobile" placeholder="请输入手机号码" border="none" type="number" /> |
| | | </u-form-item> |
| | | <!-- 旧密码 --> |
| | | <u-form-item label="旧密码" prop="password" borderBottom required="true" v-if="false"> |
| | | <u-input v-model="form.oldPassword" placeholder="请输入密码" border="none" type="password" /> |
| | | </u-form-item> |
| | | <!-- 密码 --> |
| | | <u-form-item label="新密码" prop="password" borderBottom required="true"> |
| | | <u-form-item label="密码" prop="password" borderBottom required="true" v-if="!form.id"> |
| | | <u-input v-model="form.password" placeholder="请输入密码" border="none" type="password" /> |
| | | </u-form-item> |
| | | |
| | | <!-- 角色选择 --> |
| | | <u-form-item label="角色" prop="role" borderBottom required="true"> |
| | | <!-- 复选框组,增加布局和间距 --> |
| | | <u-form-item label="超级管理员" prop="isSuper" borderBottom required="true"> |
| | | <view class="switch-wrapper"> |
| | | <u-switch v-model="form.isSuper"></u-switch> |
| | | </view> |
| | | </u-form-item> |
| | | <u-form-item label="角色" prop="role" v-if="!form.isSuper"> |
| | | <u-checkbox-group @change="checkboxGroupChange" class="checkbox-group"> |
| | | <u-checkbox @change="checkboxChange" v-model="item.checked" v-for="(item, index) in list" |
| | | :key="index" :name="item.name" class="custom-checkbox"> |
| | | <u-checkbox @change="checkboxChange" v-model="item.checked" v-for="(item, index) in roleList" |
| | | :key="index" :name="item.id" class="custom-checkbox"> |
| | | <span class="checkbox-label">{{ item.name }}</span> |
| | | </u-checkbox> |
| | | |
| | | </u-checkbox-group> |
| | | <!-- 全选按钮,增加间距和样式 --> |
| | | <!-- <u-button type="text" @click="checkedAll" class="select-all-btn"> |
| | | 全选 |
| | | </u-button> --> |
| | | </u-form-item> |
| | | <u-form-item label="所属部门" prop="departmentId" borderBottom> |
| | | </u-form-item> |
| | | <DaTreeVue2 :data="roomTreeData" labelField="name" valueField="id" defaultExpandAll |
| | | :defaultCheckedKeys="defaultCheckedKeysValue" @change="handleTreeChange" |
| | | @expand="handleExpandChange" /> |
| | | <!-- 角色选择 --> |
| | | |
| | | |
| | | </u-form> |
| | | |
| | |
| | | import { |
| | | add, |
| | | update, |
| | | getDetail |
| | | getDetail, |
| | | getStoreRoleList, |
| | | getDeptTree, |
| | | check |
| | | } from "@/api/userPermissions.js" |
| | | import UIcon from '@/uview-components/uview-ui/components/u-icon/u-icon.vue'; |
| | | import UButton from '@/uview-components/uview-ui/components/u-button/u-button.vue'; |
| | | import UForm from '@/uview-components/uview-ui/components/u-form/u-form.vue'; |
| | | import UFormItem from '@/uview-components/uview-ui/components/u-form-item/u-form-item.vue'; |
| | | import UInput from '@/uview-components/uview-ui/components/u-input/u-input.vue'; |
| | | import USearch from '@/uview-components/uview-ui/components/u-search/u-search.vue'; |
| | | import UPopup from '@/uview-components/uview-ui/components/u-popup/u-popup.vue'; |
| | | import ULoading from '@/uview-components/uview-ui/components/u-loading/u-loading.vue'; |
| | | import '@/components/uview-components/uview-ui'; |
| | | |
| | | import UCheckbox from '@/uview-components/uview-ui/components/u-checkbox/u-checkbox.vue'; |
| | | import UCheckboxGroup from '@/uview-components/uview-ui/components/u-checkbox-group/u-checkbox-group.vue'; |
| | | import DaTreeVue2 from '@/components/da-tree-vue2/index.vue' |
| | | |
| | | export default { |
| | | components: { |
| | | UIcon, |
| | | UButton, |
| | | UForm, |
| | | UFormItem, |
| | | UInput, |
| | | USearch, |
| | | UPopup, |
| | | ULoading, |
| | | UCheckbox, |
| | | UCheckboxGroup |
| | | DaTreeVue2, |
| | | }, |
| | | data() { |
| | | return { |
| | | checking: false, // 检查状态 |
| | | lastRequest: null, // 最后一次请求的标识(用于防抖) |
| | | |
| | | rules: { |
| | | realName: { |
| | | required: true, |
| | | trigger: ['blur'], |
| | | message: '姓名不能为空' |
| | | |
| | | }, |
| | | mobile: [{ |
| | | required: true, |
| | | trigger: ['blur'], |
| | | message: '电话号码不能为空' |
| | | }, |
| | | { |
| | | pattern: /^1[3-9]\d{9}$/, |
| | | message: "手机号格式不正确(必须是11位中国大陆手机号)", |
| | | trigger: ["blur"] |
| | | }, |
| | | { |
| | | validator: this.checkPhoneUsage, |
| | | trigger: ['blur'] |
| | | } |
| | | ], |
| | | |
| | | |
| | | password: { |
| | | required: true, |
| | | trigger: ['blur', 'change'], |
| | | message: '密码不能为空' |
| | | |
| | | }, |
| | | }, |
| | | defaultCheckedKeysValue: '', |
| | | title: '', |
| | | // 表单数据 |
| | | form: { |
| | | id: '', |
| | | id: '',//属于店员表id |
| | | mobile: '', |
| | | realName: '', |
| | | password: '', |
| | | role: '', |
| | | oldPassword: '' |
| | | role: [], |
| | | isSuper: true, |
| | | departmentId: '' |
| | | }, |
| | | memberId:'', |
| | | |
| | | role: [], |
| | | // 加载状态 |
| | | loading: false, |
| | | // 角色选项 |
| | | list: [{ |
| | | name: '管理员', |
| | | checked: false, |
| | | disabled: false |
| | | }, |
| | | { |
| | | name: '管理员2', |
| | | checked: false, |
| | | disabled: false |
| | | }, |
| | | { |
| | | name: '管理员3', |
| | | checked: false, |
| | | disabled: false |
| | | } |
| | | ], |
| | | |
| | | roleList: [], |
| | | roomTreeData: [], |
| | | }; |
| | | }, |
| | | onReady() { |
| | | //onReady 为uni-app支持的生命周期之一 |
| | | |
| | | }, |
| | | onLoad(options) { |
| | | // 接收 URL 参数 |
| | |
| | | } else { |
| | | this.title = '新增用户'; |
| | | } |
| | | this.getRole() |
| | | this.getDeptTree() |
| | | setTimeout(() => { |
| | | this.$refs.uForm1.setRules(this.rules) |
| | | }, 500) |
| | | }, |
| | | methods: { |
| | | // 自定义异步验证方法 |
| | | checkPhoneUsage(rule, value, callback) { |
| | | if (!value || !/^1[3-9]\d{9}$/.test(value)) { |
| | | return callback() // 格式错误时跳过接口检查 |
| | | } |
| | | |
| | | this.checking = true |
| | | const currentRequest = Symbol() // 生成唯一标识 |
| | | this.lastRequest = currentRequest |
| | | |
| | | // 调用API检查手机号(示例使用uni.request) |
| | | const form ={ |
| | | mobile:value, |
| | | memberId:this.memberId |
| | | } |
| | | check(form) |
| | | .then(res => { |
| | | // 3.1 如果不是最后一次请求,忽略结果 |
| | | if (this.lastRequest !== currentRequest) return; |
| | | console.log(res) |
| | | // 3.2 根据业务逻辑判断是否可用 |
| | | if (res.statusCode === 200) { |
| | | //判断是否已存在 |
| | | callback(); // 验证通过 |
| | | } else { |
| | | callback(new Error(res.message || '该手机号已被使用')); |
| | | } |
| | | }) |
| | | .catch(err => { |
| | | // 3.3 网络错误处理 |
| | | callback(new Error('验证失败,请稍后重试')); |
| | | }) |
| | | .finally(() => { |
| | | // 3.4 无论成功失败都取消加载状态 |
| | | if (this.lastRequest === currentRequest) { |
| | | this.checking = false; |
| | | } |
| | | }); |
| | | |
| | | }, |
| | | change(e) { |
| | | console.log('change', e); |
| | | }, |
| | | //转换树状结构 |
| | | renameTitleToName(treeData) { |
| | | return treeData.map(item => { |
| | | const newItem = { |
| | | ...item, |
| | | name: item.title // 将title赋值给name |
| | | } |
| | | delete newItem.title // 删除原title字段 |
| | | |
| | | if (item.children && item.children.length > 0) { |
| | | newItem.children = this.renameTitleToName(item.children) |
| | | } |
| | | |
| | | return newItem |
| | | }) |
| | | }, |
| | | |
| | | getDeptTree() { |
| | | getDeptTree().then(res => { |
| | | if (res.statusCode === 200) { |
| | | console.log(res.data.data) |
| | | this.roomTreeData = this.renameTitleToName(res.data.data) |
| | | } |
| | | }) |
| | | console.log(this.roomTreeData) |
| | | }, |
| | | doExpandTree(keys, expand) { |
| | | this.$refs.DaTreeRef?.setExpandedKeys(keys, expand) |
| | | |
| | | const gek = this.$refs.DaTreeRef?.getExpandedKeys() |
| | | console.log('当前已展开的KEY ==>', gek) |
| | | }, |
| | | doCheckedTree(keys, checked) { |
| | | this.$refs.DaTreeRef?.setCheckedKeys(keys, checked) |
| | | |
| | | const gek = this.$refs.DaTreeRef?.getCheckedKeys() |
| | | console.log('当前已选中的KEY ==>', gek) |
| | | }, |
| | | handleTreeChange(allSelectedKeys, currentItem) { |
| | | console.log('handleTreeChange ==>', allSelectedKeys, currentItem) |
| | | this.form.departmentId = allSelectedKeys |
| | | }, |
| | | handleExpandChange(expand, currentItem) { |
| | | console.log('handleExpandChange ==>', expand, currentItem) |
| | | }, |
| | | getRole() { |
| | | getStoreRoleList().then(res => { |
| | | if (res.statusCode === 200) { |
| | | this.roleList = res.data.data |
| | | } |
| | | }) |
| | | }, |
| | | //获得详情 |
| | | getDetail() { |
| | | uni.showLoading({ |
| | |
| | | if (res.statusCode === 200) { |
| | | this.form.mobile = res.data.data.mobile; |
| | | this.form.realName = res.data.data.realName; |
| | | this.form.password = res.data.data.password; |
| | | this.form.isSuper = res.data.data.isSuper; |
| | | this.defaultCheckedKeysValue = res.data.data.departmentId; |
| | | this.memberId = res.data.data.memberId |
| | | // 解析角色数组 |
| | | const roles = JSON.parse(res.data.data.role); |
| | | const roles = res.data.data.roleIds.split(','); |
| | | |
| | | // 更新复选框选中状态 |
| | | this.list = this.list.map(item => { |
| | | this.roleList = this.roleList.map(item => { |
| | | return { |
| | | ...item, |
| | | checked: roles.includes(item.name) |
| | | checked: roles.includes(item.id) |
| | | }; |
| | | }); |
| | | |
| | | |
| | | this.form.role = roles; |
| | | } |
| | | |
| | | }) |
| | | }, |
| | | // 角色选择变化 |
| | | checkboxChange(e) { |
| | | // console.log(e); |
| | | console.log(e); |
| | | }, |
| | | checkboxGroupChange(e) { |
| | | this.role = e; |
| | | console.log(e) |
| | | this.form.role = e; |
| | | }, |
| | | // 全选 |
| | | checkedAll() { |
| | |
| | | async submitForm() { |
| | | // 1. 手动触发表单验证 |
| | | this.$refs.uForm1.validate(valid => { |
| | | |
| | | if (valid) { |
| | | this.loading = true; |
| | | // 2. 处理角色数据(将 checked=true 的项转为 role 数组) |
| | | const form = { |
| | | |
| | | this.form.role = JSON.stringify(this.role); |
| | | console.log(this.form) |
| | | if (this.form.id) { |
| | | update(this.form).then(res => { |
| | | id: this.form.id, |
| | | mobile: this.form.mobile, |
| | | realName: this.form.realName, |
| | | password: this.form.password, |
| | | role: this.form.role, |
| | | isSuper:this.form.isSuper, |
| | | departmentId:this.form.departmentId, |
| | | } |
| | | |
| | | if (form.id) { |
| | | update(form).then(res => { |
| | | this.loading = false; |
| | | if (res.statusCode === 200) { |
| | | uni.showToast({ |
| | |
| | | } |
| | | }) |
| | | } else { |
| | | add(this.form).then(res => { |
| | | add(form).then(res => { |
| | | this.loading = false; |
| | | if (res.statusCode === 200) { |
| | | uni.showToast({ |
| | |
| | | |
| | | <style lang="scss" scoped> |
| | | .checkbox-group { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 16px; |
| | | /* 选项间距 */ |
| | | margin-bottom: 16px; |
| | | /* 与按钮的间距 */ |
| | | |
| | | } |
| | | |
| | | .switch-wrapper { |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | width: 100%; |
| | | } |
| | | |
| | | /* 单个复选框样式 */ |