feat: 注册页加部门选择/用户管理修部门下拉/超管可跨店建用户/公开部门接口
This commit is contained in:
@@ -7,12 +7,15 @@ import axios from 'axios'
|
||||
const router = useRouter()
|
||||
const loading = ref(false)
|
||||
const packagesLoading = ref(false)
|
||||
const deptLoading = ref(false)
|
||||
const packages = ref([])
|
||||
const stores = ref([])
|
||||
const departments = ref([])
|
||||
|
||||
const form = reactive({
|
||||
store_id: '',
|
||||
registration_package_id: '',
|
||||
department_id: '',
|
||||
username: '',
|
||||
password: '',
|
||||
name: '',
|
||||
@@ -22,7 +25,7 @@ const form = reactive({
|
||||
const formRef = ref(null)
|
||||
const rules = {
|
||||
store_id: [{ required: true, message: '请选择门店', trigger: 'change' }],
|
||||
registration_package_id: [{ required: true, message: '请选择岗位套餐', trigger: 'change' }],
|
||||
registration_package_id: [{ required: true, message: '请选择申请岗位', trigger: 'change' }],
|
||||
username: [
|
||||
{ required: true, message: '请输入登录账号', trigger: 'blur' },
|
||||
{ min: 2, max: 50, message: '2-50个字符', trigger: 'blur' },
|
||||
@@ -47,19 +50,29 @@ async function fetchStores() {
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchPackages() {
|
||||
if (!form.store_id) return
|
||||
packagesLoading.value = true
|
||||
async function onStoreChange() {
|
||||
form.registration_package_id = ''
|
||||
form.department_id = ''
|
||||
packages.value = []
|
||||
departments.value = []
|
||||
if (!form.store_id) return
|
||||
|
||||
packagesLoading.value = true
|
||||
deptLoading.value = true
|
||||
|
||||
try {
|
||||
const res = await axios.get('/api/v1/auth/register/packages', {
|
||||
params: { store_id: form.store_id },
|
||||
})
|
||||
packages.value = res.data?.data || []
|
||||
const [pkgRes, deptRes] = await Promise.all([
|
||||
axios.get('/api/v1/auth/register/packages', { params: { store_id: form.store_id } }),
|
||||
axios.get('/api/v1/auth/register/departments', { params: { store_id: form.store_id } }),
|
||||
])
|
||||
packages.value = pkgRes.data?.data || []
|
||||
departments.value = deptRes.data?.data || []
|
||||
} catch {
|
||||
packages.value = []
|
||||
departments.value = []
|
||||
} finally {
|
||||
packagesLoading.value = false
|
||||
deptLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,22 +108,19 @@ onMounted(fetchStores)
|
||||
</div>
|
||||
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-position="top">
|
||||
<!-- 门店 -->
|
||||
<el-form-item label="所属门店" prop="store_id">
|
||||
<el-select
|
||||
v-model="form.store_id"
|
||||
placeholder="请选择门店"
|
||||
style="width: 100%"
|
||||
@change="fetchPackages"
|
||||
@change="onStoreChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="s in stores"
|
||||
:key="s.id"
|
||||
:label="s.name"
|
||||
:value="s.id"
|
||||
/>
|
||||
<el-option v-for="s in stores" :key="s.id" :label="s.name" :value="s.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 申请岗位套餐 -->
|
||||
<el-form-item label="申请岗位" prop="registration_package_id">
|
||||
<el-select
|
||||
v-model="form.registration_package_id"
|
||||
@@ -129,7 +139,24 @@ onMounted(fetchStores)
|
||||
<span v-if="p.description" class="text-gray-400 text-xs ml-2">{{ p.description }}</span>
|
||||
</el-option>
|
||||
<template v-if="packages.length === 0 && form.store_id && !packagesLoading" #empty>
|
||||
<div class="text-center py-4 text-gray-400 text-sm">该门店暂无可用套餐</div>
|
||||
<div class="text-center py-4 text-gray-400 text-sm">该门店暂无可用套餐,请联系管理员</div>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 所属部门 -->
|
||||
<el-form-item label="所属部门" prop="department_id">
|
||||
<el-select
|
||||
v-model="form.department_id"
|
||||
placeholder="请先选择门店"
|
||||
style="width: 100%"
|
||||
:loading="deptLoading"
|
||||
:disabled="!form.store_id"
|
||||
clearable
|
||||
>
|
||||
<el-option v-for="d in departments" :key="d.id" :label="d.name" :value="d.id" />
|
||||
<template v-if="departments.length === 0 && form.store_id && !deptLoading" #empty>
|
||||
<div class="text-center py-4 text-gray-400 text-sm">该门店暂无部门数据</div>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { userApi, roleApi, departmentApi } from '@/api/system.js'
|
||||
import { userApi, roleApi, departmentApi, storeApi } from '@/api/system.js'
|
||||
import { useUserStore } from '@/stores/user.js'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const isSuper = computed(() => userStore.userInfo?.is_super)
|
||||
|
||||
// ─── State ───────────────────────────────────────────────────────────────────
|
||||
|
||||
const tableData = ref([])
|
||||
const stores = ref([])
|
||||
const total = ref(0)
|
||||
const loading = ref(false)
|
||||
const dialogVisible = ref(false)
|
||||
@@ -42,7 +47,8 @@ const form = reactive({
|
||||
role_ids: [],
|
||||
status: 1,
|
||||
password: '',
|
||||
password_confirm: ''
|
||||
password_confirm: '',
|
||||
store_id: ''
|
||||
})
|
||||
|
||||
const isEdit = ref(false)
|
||||
@@ -99,6 +105,14 @@ const resetPwdRules = {
|
||||
|
||||
// ─── Methods ──────────────────────────────────────────────────────────────────
|
||||
|
||||
function flattenDeptTree(nodes, result = []) {
|
||||
for (const n of nodes) {
|
||||
result.push({ id: n.id, name: n.name })
|
||||
if (n.children?.length) flattenDeptTree(n.children, result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
async function fetchList() {
|
||||
loading.value = true
|
||||
try {
|
||||
@@ -124,7 +138,9 @@ async function fetchRoles() {
|
||||
async function fetchDepartments() {
|
||||
try {
|
||||
const res = await departmentApi.getList({ per_page: 500 })
|
||||
departments.value = res.data?.list || res.data?.data || []
|
||||
// API returns tree array directly in res.data, flatten it for selects
|
||||
const raw = Array.isArray(res.data) ? res.data : (res.data?.list || res.data?.data || [])
|
||||
departments.value = flattenDeptTree(raw)
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
@@ -146,7 +162,7 @@ function handleAdd() {
|
||||
Object.assign(form, {
|
||||
id: null, username: '', name: '', phone: '', email: '',
|
||||
department_id: '', position_id: '', role_ids: [], status: 1,
|
||||
password: '', password_confirm: ''
|
||||
password: '', password_confirm: '', store_id: ''
|
||||
})
|
||||
dialogVisible.value = true
|
||||
}
|
||||
@@ -276,6 +292,11 @@ onMounted(() => {
|
||||
fetchList()
|
||||
fetchRoles()
|
||||
fetchDepartments()
|
||||
if (isSuper.value) {
|
||||
storeApi.getList({ page_size: 200 }).then(res => {
|
||||
stores.value = res.data?.list || []
|
||||
}).catch(() => {})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -411,6 +432,13 @@ onMounted(() => {
|
||||
label-position="right"
|
||||
>
|
||||
<el-row :gutter="16">
|
||||
<el-col v-if="isSuper && !isEdit" :span="24">
|
||||
<el-form-item label="所属门店" prop="store_id">
|
||||
<el-select v-model="form.store_id" placeholder="超管可指定门店(不选则为当前门店)" clearable style="width:100%">
|
||||
<el-option v-for="s in stores" :key="s.id" :label="s.name" :value="s.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="form.username" placeholder="请输入用户名" :disabled="isEdit" />
|
||||
@@ -433,14 +461,9 @@ onMounted(() => {
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="部门" prop="department_id">
|
||||
<el-tree-select
|
||||
v-model="form.department_id"
|
||||
:data="departments"
|
||||
:props="{ label: 'name', value: 'id', children: 'children' }"
|
||||
placeholder="选择部门"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-select v-model="form.department_id" placeholder="选择部门" clearable style="width:100%">
|
||||
<el-option v-for="d in departments" :key="d.id" :label="d.name" :value="d.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
|
||||
Reference in New Issue
Block a user