sc
This commit is contained in:
42
src/api/account/index.js
Normal file
42
src/api/account/index.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 添加增删改查接口
|
||||
export const addAccount = async data => {
|
||||
return request({
|
||||
url: '/applet/xunjia/account/create',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteAccount = async id => {
|
||||
return request({
|
||||
url: '/applet/xunjia/account/delete',
|
||||
method: 'delete',
|
||||
params: { id }
|
||||
});
|
||||
};
|
||||
|
||||
export const updateAccount = async data => {
|
||||
return request({
|
||||
url: '/applet/xunjia/account/update',
|
||||
method: 'put',
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
export const getAccountPage = async params => {
|
||||
return request({
|
||||
url: '/applet/xunjia/account/page',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
};
|
||||
|
||||
export const getAccountInfo = async id => {
|
||||
return request({
|
||||
url: '/applet/xunjia/account/get',
|
||||
method: 'get',
|
||||
params: { id }
|
||||
});
|
||||
};
|
||||
167
src/components/tree-select-item.vue
Normal file
167
src/components/tree-select-item.vue
Normal file
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="submenu-item">
|
||||
<view class="submenu-item-content" @click.stop="handleMenuClick">
|
||||
<view
|
||||
class="custom-checkbox"
|
||||
:class="{ 'checked': isMenuChecked }"
|
||||
></view>
|
||||
<view class="submenu-name">{{ menu[nameField] }}</view>
|
||||
</view>
|
||||
<view v-if="hasChildren" class="menu-arrow" :class="{ 'expanded': isExpanded }" @click.stop="handleToggleMenu">{{ isExpanded ? '▼' : '▶' }}</view>
|
||||
<view v-else class="menu-arrow-placeholder"></view>
|
||||
</view>
|
||||
<view v-if="hasChildren && isExpanded" class="submenu-list">
|
||||
<TreeSelectItem
|
||||
v-for="submenu in menu.children"
|
||||
:key="submenu[idField]"
|
||||
:menu="submenu"
|
||||
:id-field="idField"
|
||||
:name-field="nameField"
|
||||
:selected-ids="selectedIds"
|
||||
@update:selected-ids="$emit('update:selected-ids', $event)"
|
||||
:expanded-menus="expandedMenus"
|
||||
@toggle-menu="$emit('toggle-menu', $event)"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'TreeSelectItem'
|
||||
}
|
||||
</script>
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue"
|
||||
import TreeSelectItem from './tree-select-item.vue'
|
||||
|
||||
const props = defineProps({
|
||||
menu: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
idField: {
|
||||
type: String,
|
||||
default: 'id'
|
||||
},
|
||||
nameField: {
|
||||
type: String,
|
||||
default: 'name'
|
||||
},
|
||||
selectedIds: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
expandedMenus: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:selected-ids', 'toggle-menu'])
|
||||
|
||||
// 计算属性
|
||||
const hasChildren = computed(() => {
|
||||
return props.menu.children && props.menu.children.length > 0
|
||||
})
|
||||
|
||||
const isMenuChecked = computed(() => {
|
||||
return props.selectedIds.includes(props.menu[props.idField])
|
||||
})
|
||||
|
||||
const isExpanded = computed(() => {
|
||||
return props.expandedMenus.includes(props.menu[props.idField])
|
||||
})
|
||||
|
||||
// 处理菜单点击
|
||||
function handleMenuClick() {
|
||||
const menuId = props.menu[props.idField]
|
||||
const checked = !isMenuChecked.value
|
||||
emit('update:selected-ids', { menuId, checked })
|
||||
}
|
||||
|
||||
// 处理菜单展开/折叠
|
||||
function handleToggleMenu() {
|
||||
const menuId = props.menu[props.idField]
|
||||
emit('toggle-menu', menuId)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 自定义checkbox样式 */
|
||||
.custom-checkbox {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border: 2rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
background-color: #ffffff;
|
||||
transition: all 0.3s ease-in-out;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.custom-checkbox.checked {
|
||||
border-color: #409eff;
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.custom-checkbox.checked::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 10rpx;
|
||||
height: 16rpx;
|
||||
border: 2rpx solid #ffffff;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
transform: translate(-50%, -60%) rotate(45deg);
|
||||
}
|
||||
|
||||
.submenu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12rpx 16rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.submenu-item-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.submenu-name {
|
||||
flex: 1;
|
||||
font-size: 22rpx;
|
||||
color: #606266;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.menu-arrow {
|
||||
font-size: 20rpx;
|
||||
color: #909399;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu-arrow.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.menu-arrow-placeholder {
|
||||
width: 20rpx;
|
||||
}
|
||||
|
||||
.submenu-list {
|
||||
margin-left: 40rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
</style>
|
||||
327
src/components/tree-select.vue
Normal file
327
src/components/tree-select.vue
Normal file
@@ -0,0 +1,327 @@
|
||||
<template>
|
||||
<view class="tree-select">
|
||||
<!-- 递归渲染菜单树 -->
|
||||
<template v-for="menu in treeData" :key="getMenuId(menu)">
|
||||
<view class="menu-item">
|
||||
<view class="menu-header" @click="toggleMenu(getMenuId(menu))">
|
||||
<view
|
||||
class="custom-checkbox"
|
||||
:class="{ 'checked': isMenuChecked(getMenuId(menu)) }"
|
||||
@click.stop="onMenuChange(getMenuId(menu), !isMenuChecked(getMenuId(menu)))">
|
||||
</view>
|
||||
<view class="menu-name">{{ getMenuName(menu) }}</view>
|
||||
<view v-if="hasChildren(menu)" class="menu-arrow" :class="{ 'expanded': expandedMenus.includes(getMenuId(menu)) }">{{ expandedMenus.includes(getMenuId(menu)) ? '▼' : '▶' }}</view>
|
||||
<view v-else class="menu-arrow-placeholder"></view>
|
||||
</view>
|
||||
<view v-if="hasChildren(menu) && expandedMenus.includes(getMenuId(menu))" class="submenu-list">
|
||||
<!-- 递归渲染子菜单 -->
|
||||
<TreeSelectItem
|
||||
v-for="submenu in menu.children"
|
||||
:key="getMenuId(submenu)"
|
||||
:menu="submenu"
|
||||
:id-field="idField"
|
||||
:name-field="nameField"
|
||||
:selected-ids="modelValue"
|
||||
@update:selected-ids="handleSubMenuChange"
|
||||
:expanded-menus="expandedMenus"
|
||||
@toggle-menu="toggleMenu"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TreeSelectItem from './tree-select-item.vue'
|
||||
import { ref, computed, watch } from "vue"
|
||||
|
||||
// 组件props
|
||||
const props = defineProps({
|
||||
// 树数据
|
||||
treeData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// id字段名
|
||||
idField: {
|
||||
type: String,
|
||||
default: 'id'
|
||||
},
|
||||
// name字段名
|
||||
nameField: {
|
||||
type: String,
|
||||
default: 'name'
|
||||
},
|
||||
// 选中字段(双向绑定)
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
// 事件
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
// 展开的菜单
|
||||
const expandedMenus = ref([])
|
||||
|
||||
// 获取菜单ID
|
||||
function getMenuId(menu) {
|
||||
return menu[props.idField]
|
||||
}
|
||||
|
||||
// 获取菜单名称
|
||||
function getMenuName(menu) {
|
||||
return menu[props.nameField]
|
||||
}
|
||||
|
||||
// 检查菜单是否有子菜单
|
||||
function hasChildren(menu) {
|
||||
return menu.children && menu.children.length > 0
|
||||
}
|
||||
|
||||
// 检查菜单是否被选中
|
||||
function isMenuChecked(menuId) {
|
||||
return props.modelValue.includes(menuId)
|
||||
}
|
||||
|
||||
// 切换菜单展开状态
|
||||
function toggleMenu(menuId) {
|
||||
const index = expandedMenus.value.indexOf(menuId)
|
||||
if (index > -1) {
|
||||
expandedMenus.value.splice(index, 1)
|
||||
} else {
|
||||
expandedMenus.value.push(menuId)
|
||||
}
|
||||
}
|
||||
|
||||
// 菜单权限变更
|
||||
function onMenuChange(menuId, checked) {
|
||||
// 创建新的选中数组
|
||||
const newSelected = [...props.modelValue]
|
||||
|
||||
if (checked) {
|
||||
// 选中当前菜单
|
||||
if (!newSelected.includes(menuId)) {
|
||||
newSelected.push(menuId)
|
||||
}
|
||||
|
||||
// 找到当前菜单
|
||||
const menu = findMenuById(menuId, props.treeData)
|
||||
|
||||
// 如果是上级菜单,选中所有子菜单
|
||||
if (menu && hasChildren(menu)) {
|
||||
menu.children.forEach(child => {
|
||||
const childId = getMenuId(child)
|
||||
if (!newSelected.includes(childId)) {
|
||||
newSelected.push(childId)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 检查并选中上级菜单
|
||||
checkParentMenu(menuId, newSelected)
|
||||
} else {
|
||||
// 取消选中当前菜单
|
||||
const index = newSelected.indexOf(menuId)
|
||||
if (index > -1) {
|
||||
newSelected.splice(index, 1)
|
||||
}
|
||||
|
||||
// 找到当前菜单
|
||||
const menu = findMenuById(menuId, props.treeData)
|
||||
|
||||
// 如果是上级菜单,取消选中所有子菜单
|
||||
if (menu && hasChildren(menu)) {
|
||||
menu.children.forEach(child => {
|
||||
const childId = getMenuId(child)
|
||||
const childIndex = newSelected.indexOf(childId)
|
||||
if (childIndex > -1) {
|
||||
newSelected.splice(childIndex, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 检查并取消选中上级菜单
|
||||
uncheckParentMenu(menuId, newSelected)
|
||||
}
|
||||
|
||||
// 触发更新事件
|
||||
emit('update:modelValue', newSelected)
|
||||
}
|
||||
|
||||
// 根据ID查找菜单
|
||||
function findMenuById(menuId, menus) {
|
||||
for (const menu of menus) {
|
||||
if (getMenuId(menu) === menuId) {
|
||||
return menu
|
||||
}
|
||||
if (hasChildren(menu)) {
|
||||
const found = findMenuById(menuId, menu.children)
|
||||
if (found) {
|
||||
return found
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// 检查并选中上级菜单
|
||||
function checkParentMenu(menuId, selected) {
|
||||
// 找到当前菜单的父菜单
|
||||
const parentMenu = findParentMenu(menuId, props.treeData)
|
||||
if (parentMenu) {
|
||||
const parentId = getMenuId(parentMenu)
|
||||
if (!selected.includes(parentId)) {
|
||||
selected.push(parentId)
|
||||
}
|
||||
// 递归检查更上级的菜单
|
||||
checkParentMenu(parentId, selected)
|
||||
}
|
||||
}
|
||||
|
||||
// 检查并取消选中上级菜单
|
||||
function uncheckParentMenu(menuId, selected) {
|
||||
// 找到当前菜单的父菜单
|
||||
const parentMenu = findParentMenu(menuId, props.treeData)
|
||||
if (parentMenu) {
|
||||
const parentId = getMenuId(parentMenu)
|
||||
// 检查父菜单的所有子菜单是否都未选中
|
||||
const allChildrenUnchecked = parentMenu.children.every(child => {
|
||||
return !selected.includes(getMenuId(child))
|
||||
})
|
||||
|
||||
if (allChildrenUnchecked) {
|
||||
const parentIndex = selected.indexOf(parentId)
|
||||
if (parentIndex > -1) {
|
||||
selected.splice(parentIndex, 1)
|
||||
// 递归检查更上级的菜单
|
||||
uncheckParentMenu(parentId, selected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查找父菜单
|
||||
function findParentMenu(menuId, menus) {
|
||||
for (const menu of menus) {
|
||||
if (hasChildren(menu)) {
|
||||
if (menu.children.some(child => getMenuId(child) === menuId)) {
|
||||
return menu
|
||||
}
|
||||
const found = findParentMenu(menuId, menu.children)
|
||||
if (found) {
|
||||
return found
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// 处理子菜单变更
|
||||
function handleSubMenuChange(data) {
|
||||
onMenuChange(data.menuId, data.checked)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 自定义checkbox样式 */
|
||||
.custom-checkbox {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border: 2rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
background-color: #ffffff;
|
||||
transition: all 0.3s ease-in-out;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.custom-checkbox.checked {
|
||||
border-color: #409eff;
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.custom-checkbox.checked::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 10rpx;
|
||||
height: 16rpx;
|
||||
border: 2rpx solid #ffffff;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
transform: translate(-50%, -60%) rotate(45deg);
|
||||
}
|
||||
|
||||
/* 菜单列表 */
|
||||
.menu-list {
|
||||
space-y: 16rpx;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.menu-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 8rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu-name {
|
||||
flex: 1;
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.menu-arrow {
|
||||
font-size: 20rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.menu-arrow.expanded {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
.menu-arrow-placeholder {
|
||||
width: 20rpx;
|
||||
}
|
||||
|
||||
.submenu-list {
|
||||
margin-left: 40rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.submenu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12rpx 16rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.submenu-item-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.submenu-name {
|
||||
flex: 1;
|
||||
font-size: 22rpx;
|
||||
color: #606266;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -102,6 +102,12 @@
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/account/accountForm",
|
||||
"style": {
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/student/list",
|
||||
"style": {
|
||||
|
||||
341
src/pages/account/accountForm.vue
Normal file
341
src/pages/account/accountForm.vue
Normal file
@@ -0,0 +1,341 @@
|
||||
<template>
|
||||
<view class="account-form-container">
|
||||
<!-- 页面标题 -->
|
||||
<view class="page-header">
|
||||
<view class="header-left" @click="goBack">
|
||||
<view class="back-icon">←</view>
|
||||
</view>
|
||||
<view class="header-title">{{ isEdit ? '编辑账号' : '添加账号' }}</view>
|
||||
<view class="header-right" @click="submitForm">
|
||||
<view class="save-btn">保存</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 表单内容 -->
|
||||
<view class="form-content">
|
||||
<!-- 基本信息 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">基本信息</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">姓名</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="form.nickname"
|
||||
class="form-input"
|
||||
placeholder="请输入姓名"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<view class="form-label">手机号</view>
|
||||
<view class="form-control">
|
||||
<input
|
||||
v-model="form.mobile"
|
||||
class="form-input"
|
||||
maxlength="11"
|
||||
placeholder="请输入手机号"
|
||||
type="number"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 菜单权限 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">菜单权限</view>
|
||||
<view class="menu-list">
|
||||
<!-- 使用tree-select组件 -->
|
||||
<tree-select
|
||||
:tree-data="menuList"
|
||||
id-field="id"
|
||||
name-field="name"
|
||||
v-model="form.menuIds"
|
||||
/>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据权限 -->
|
||||
<view class="form-section">
|
||||
<view class="section-title">数据权限</view>
|
||||
<view class="data-scope-list">
|
||||
<radio-group v-model="form.dataScope">
|
||||
<view
|
||||
v-for="scope in dataScopeOptions"
|
||||
:key="scope.value"
|
||||
class="data-scope-item"
|
||||
>
|
||||
<radio
|
||||
:value="scope.value"
|
||||
:checked="form.dataScope == scope.value"
|
||||
/>
|
||||
<view class="data-scope-label">
|
||||
<view class="scope-name">{{ scope.label }}</view>
|
||||
<view class="scope-desc">{{ scope.desc }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</radio-group>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from "vue"
|
||||
import { addAccount, updateAccount, getAccountInfo } from "@/api/account/index.js"
|
||||
import { useUserStore }from "@/store/modules/user.js"
|
||||
import treeSelect from "@/components/tree-select.vue"
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 路由参数
|
||||
const id = ref('');
|
||||
const isEdit = computed(() => !!id.value);
|
||||
|
||||
// 表单数据
|
||||
const form = ref({
|
||||
nickname: '',
|
||||
mobile: '',
|
||||
menuIds: [],
|
||||
dataScope: '1' // 默认全部数据
|
||||
});
|
||||
|
||||
// 菜单列表
|
||||
const menuList = computed(() => userStore.userMenus);
|
||||
|
||||
// 数据权限选项
|
||||
const dataScopeOptions = [
|
||||
{ value: '1', label: '全部数据', desc: '可以查看和管理所有数据' },
|
||||
{ value: '5', label: '个人数据', desc: '只能查看和管理自己及下级数据' },
|
||||
];
|
||||
|
||||
// 页面加载时获取参数
|
||||
onMounted(() => {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
id.value = currentPage.options.id || '';
|
||||
|
||||
if (isEdit.value) {
|
||||
// 编辑模式,加载账号数据
|
||||
loadAccountData();
|
||||
}
|
||||
});
|
||||
|
||||
// 加载账号数据
|
||||
function loadAccountData() {
|
||||
getAccountInfo(id.value).then(res => {
|
||||
if (res.code == '0000') {
|
||||
form.value = res.data;
|
||||
} else {
|
||||
uni.showToast({ title: res.msg || '加载账号数据失败', icon: 'none' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 提交表单
|
||||
function submitForm() {
|
||||
// 表单验证
|
||||
if (!form.value.nickname) {
|
||||
uni.showToast({ title: '请输入姓名', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (!form.value.mobile || form.value.mobile.length !== 11) {
|
||||
uni.showToast({ title: '请输入有效的手机号', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
|
||||
// 实际项目中应调用接口提交表单
|
||||
if (isEdit.value) {
|
||||
updateAccount(form.value).then(res => {
|
||||
if (res.code == '0000') {
|
||||
uni.showToast({ title: '保存成功', icon: 'success' });
|
||||
setTimeout(() => {
|
||||
goBack();
|
||||
}, 1000);
|
||||
} else {
|
||||
uni.showToast({ title: res.msg || '保存失败', icon: 'none' });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
addAccount(form.value).then(res => {
|
||||
if (res.code == '0000') {
|
||||
uni.showToast({ title: '添加成功', icon: 'success' });
|
||||
setTimeout(() => {
|
||||
goBack();
|
||||
}, 1000);
|
||||
} else {
|
||||
uni.showToast({ title: res.msg || '添加失败', icon: 'none' });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 });
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* #ifndef APP-NVUE */
|
||||
page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: 14px;
|
||||
line-height: inherit;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.account-form-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 120rpx;
|
||||
background-color: #fff;
|
||||
padding: 0 32rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
width: 60rpx;
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 40rpx;
|
||||
color: #303133;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 100rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
font-size: 24rpx;
|
||||
color: #409eff;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 表单内容 */
|
||||
.form-content {
|
||||
flex: 1;
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
/* 表单 section */
|
||||
.form-section {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
/* 表单 item */
|
||||
.form-item {
|
||||
display: flex;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
width: 120rpx;
|
||||
font-size: 24rpx;
|
||||
color: #606266;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
flex: 1;
|
||||
background-color: #f9f9f9;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
padding: 16rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 选择器 */
|
||||
.picker {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.picker-text {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* 数据权限 */
|
||||
.data-scope-list {
|
||||
space-y: 16rpx;
|
||||
}
|
||||
|
||||
.data-scope-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 16rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 8rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.data-scope-label {
|
||||
flex: 1;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.scope-name {
|
||||
font-size: 24rpx;
|
||||
color: #303133;
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.scope-desc {
|
||||
font-size: 20rpx;
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
@@ -7,7 +7,7 @@
|
||||
</view>
|
||||
<view class="header-title">账号创建与管控</view>
|
||||
<view class="header-right" @click="addAccount">
|
||||
<view class="add-btn">+ 添加</view>
|
||||
<view class="add-btn">添加</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -15,25 +15,23 @@
|
||||
<view class="filter-section">
|
||||
<view class="filter-row">
|
||||
<view class="filter-item">
|
||||
<view class="filter-label">账号状态</view>
|
||||
<view class="filter-label">姓名</view>
|
||||
<view class="filter-control">
|
||||
<picker
|
||||
:range="statusOptions"
|
||||
:value="statusIndex"
|
||||
@change="onStatusChange"
|
||||
class="picker"
|
||||
>
|
||||
<view class="picker-text">{{ statusOptions[statusIndex] }}</view>
|
||||
</picker>
|
||||
<input
|
||||
v-model="nickname"
|
||||
class="search-input"
|
||||
placeholder="请输入姓名"
|
||||
@input="onSearch"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item">
|
||||
<view class="filter-label">搜索</view>
|
||||
<view class="filter-label">手机号</view>
|
||||
<view class="filter-control">
|
||||
<input
|
||||
v-model="searchKeyword"
|
||||
v-model="mobile"
|
||||
class="search-input"
|
||||
placeholder="请输入账号名称或手机号"
|
||||
placeholder="请输入手机号"
|
||||
@input="onSearch"
|
||||
/>
|
||||
</view>
|
||||
@@ -49,11 +47,11 @@
|
||||
class="account-item"
|
||||
>
|
||||
<view class="account-info">
|
||||
<view class="account-name">{{ account.name }}</view>
|
||||
<view class="account-name">{{ account.nickname }}</view>
|
||||
<view class="account-meta">
|
||||
<view class="meta-item">{{ account.phone }}</view>
|
||||
<view class="meta-item">{{ account.role }}</view>
|
||||
<view class="meta-item status-{{ account.status }}">{{ account.statusText }}</view>
|
||||
<view class="meta-item">{{ account.mobile }}</view>
|
||||
<view class="meta-item">{{ account.isDistributor ? '分销员' : '' }}</view>
|
||||
<view class="meta-item" :class="`status-${account.status}`">{{ ['启用', '禁用'][account.status] }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="account-actions">
|
||||
@@ -61,11 +59,10 @@
|
||||
编辑
|
||||
</view>
|
||||
<view
|
||||
class="action-btn"
|
||||
:class="account.status === 'active' ? 'disable-btn' : 'enable-btn'"
|
||||
@click="toggleAccountStatus(account.id, account.status)"
|
||||
class="action-btn delete-btn"
|
||||
@click="handleDelete(account.id)"
|
||||
>
|
||||
{{ account.status === 'active' ? '冻结' : '启用' }}
|
||||
删除
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -76,52 +73,57 @@
|
||||
<view class="empty-icon">👥</view>
|
||||
<view class="empty-text">暂无账号数据</view>
|
||||
</view>
|
||||
|
||||
<!-- 分页信息 -->
|
||||
<view class="pagination-info" v-if="accountList.length > 0">
|
||||
<view class="info-text">共 {{ total }} 条记录</view>
|
||||
<view class="page-controls">
|
||||
<view class="page-btn" :disabled="pageNo <= 1" @click="changePage(pageNo - 1)">上一页</view>
|
||||
<view class="page-info">{{ pageNo }} / {{ totalPages }}</view>
|
||||
<view class="page-btn" :disabled="pageNo >= totalPages" @click="changePage(pageNo + 1)">下一页</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue"
|
||||
import { ref, onMounted, computed } from "vue"
|
||||
import { getAccountPage, deleteAccount } from '@/api/account'
|
||||
|
||||
// 状态选项
|
||||
const statusOptions = ['全部', '启用', '冻结']
|
||||
const statusIndex = ref(0)
|
||||
// 筛选条件
|
||||
const nickname = ref('')
|
||||
const mobile = ref('')
|
||||
|
||||
// 搜索关键词
|
||||
const searchKeyword = ref('')
|
||||
// 分页参数
|
||||
const pageNo = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const total = ref(0)
|
||||
|
||||
// 计算总页数
|
||||
const totalPages = computed(() => {
|
||||
return Math.ceil(total.value / pageSize.value)
|
||||
})
|
||||
|
||||
// 账号列表
|
||||
const accountList = ref([
|
||||
{
|
||||
id: 1,
|
||||
name: '张教练',
|
||||
phone: '138****1234',
|
||||
role: '分销员',
|
||||
status: 'active',
|
||||
statusText: '启用'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '李教练',
|
||||
phone: '139****5678',
|
||||
role: '分销员',
|
||||
status: 'active',
|
||||
statusText: '启用'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '王教练',
|
||||
phone: '137****9012',
|
||||
role: '分销员',
|
||||
status: 'inactive',
|
||||
statusText: '冻结'
|
||||
}
|
||||
])
|
||||
const accountList = ref([])
|
||||
|
||||
onMounted(() => {
|
||||
// 实际项目中应从接口获取账号列表
|
||||
// loadAccountList()
|
||||
loadAccountList()
|
||||
})
|
||||
|
||||
const loadAccountList = async () => {
|
||||
const params = {
|
||||
nickname: nickname.value,
|
||||
mobile: mobile.value,
|
||||
pageNo: pageNo.value,
|
||||
pageSize: pageSize.value
|
||||
}
|
||||
const { data } = await getAccountPage(params)
|
||||
accountList.value = data.list
|
||||
total.value = data.total
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
function goBack() {
|
||||
uni.navigateBack({ delta: 1 })
|
||||
@@ -130,55 +132,59 @@
|
||||
// 添加账号
|
||||
function addAccount() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/account/add'
|
||||
url: '/pages/account/accountForm'
|
||||
})
|
||||
}
|
||||
|
||||
// 编辑账号
|
||||
function editAccount(accountId) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/account/edit?id=${accountId}`
|
||||
url: `/pages/account/accountForm?id=${accountId}`
|
||||
})
|
||||
}
|
||||
|
||||
// 切换账号状态
|
||||
function toggleAccountStatus(accountId, currentStatus) {
|
||||
const newStatus = currentStatus === 'active' ? 'inactive' : 'active'
|
||||
const newStatusText = newStatus === 'active' ? '启用' : '冻结'
|
||||
|
||||
// 删除账号
|
||||
function handleDelete(accountId) {
|
||||
uni.showModal({
|
||||
title: '确认操作',
|
||||
content: `确定要${newStatusText}该账号吗?`,
|
||||
success: function(res) {
|
||||
title: '确认删除',
|
||||
content: '确定要删除该账号吗?',
|
||||
success: async function(res) {
|
||||
if (res.confirm) {
|
||||
// 实际项目中应调用接口切换账号状态
|
||||
const account = accountList.value.find(item => item.id === accountId)
|
||||
if (account) {
|
||||
account.status = newStatus
|
||||
account.statusText = newStatusText
|
||||
try {
|
||||
await deleteAccount(accountId)
|
||||
uni.showToast({
|
||||
title: '删除成功',
|
||||
icon: 'success'
|
||||
})
|
||||
// 删除成功后刷新账号列表
|
||||
loadAccountList()
|
||||
} catch (error) {
|
||||
uni.showToast({
|
||||
title: error.message || '删除失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
uni.showToast({
|
||||
title: `账号已${newStatusText}`,
|
||||
icon: 'success'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 状态变更
|
||||
function onStatusChange(e) {
|
||||
const value = e.detail.value
|
||||
statusIndex.value = value
|
||||
// 实际项目中应根据状态筛选账号列表
|
||||
// filterAccountList()
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function onSearch() {
|
||||
// 重置页码
|
||||
pageNo.value = 1
|
||||
// 实际项目中应根据关键词搜索账号列表
|
||||
// searchAccountList()
|
||||
}
|
||||
|
||||
// 切换页码
|
||||
function changePage(newPage) {
|
||||
if (newPage >= 1 && newPage <= totalPages.value) {
|
||||
pageNo.value = newPage
|
||||
// 实际项目中应根据新页码加载账号列表
|
||||
// loadAccountList()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -325,6 +331,7 @@
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
@@ -332,11 +339,11 @@
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.status-active {
|
||||
.status-0 {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.status-inactive {
|
||||
.status-1 {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
@@ -358,16 +365,11 @@
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.disable-btn {
|
||||
.delete-btn {
|
||||
background-color: #fef0f0;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.enable-btn {
|
||||
background-color: #f0f9eb;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.empty-state {
|
||||
flex: 1;
|
||||
@@ -388,61 +390,56 @@
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 平板和大屏响应式 */
|
||||
@media screen and (min-width: 768px) {
|
||||
.account-manage-container {
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
/* 分页信息样式 */
|
||||
.pagination-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16rpx 32rpx;
|
||||
background-color: #fff;
|
||||
border-top: 1rpx solid #e4e7ed;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
margin: 0 32rpx 24rpx;
|
||||
padding: 32rpx;
|
||||
}
|
||||
.info-text {
|
||||
font-size: 20rpx;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.account-list {
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
.page-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.account-item {
|
||||
margin-bottom: 24rpx;
|
||||
padding: 32rpx;
|
||||
}
|
||||
.page-btn {
|
||||
padding: 6rpx 16rpx;
|
||||
border: 1rpx solid #dcdfe6;
|
||||
border-radius: 4rpx;
|
||||
font-size: 20rpx;
|
||||
color: #606266;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
gap: 32rpx;
|
||||
}
|
||||
.page-btn:hover {
|
||||
border-color: #409eff;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.page-btn[disabled] {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.picker-text,
|
||||
.search-input {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
.page-btn[disabled]:hover {
|
||||
border-color: #dcdfe6;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.filter-control {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.account-name {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
font-size: 22rpx;
|
||||
padding: 12rpx 24rpx;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.page-info {
|
||||
font-size: 20rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 大屏设备响应式 */
|
||||
|
||||
@@ -91,15 +91,11 @@
|
||||
<view class="vip-list">
|
||||
<label v-for="vip in vipList" :key="vip.memberId" class="vip-item checkbox-item"
|
||||
@click="onVipChange(idx, vip.memberId)">
|
||||
<checkbox
|
||||
:value="vip.memberId"
|
||||
:checked="rule.selectedVips.includes(vip.memberId)"
|
||||
:disabled="isVipSelectedInOtherRules(idx, vip.memberId)"
|
||||
/>
|
||||
<view class="custom-checkbox" :class="{ 'checked': rule.selectedVips && rule.selectedVips.includes(vip.memberId), 'disabled': isVipSelectedInOtherRules(idx, vip.memberId) }"></view>
|
||||
<view class="checkbox-label" :class="{ 'disabled': isVipSelectedInOtherRules(idx, vip.memberId) }">
|
||||
<text>{{ vip.carName || '' }}</text>
|
||||
<view v-if="vip.carName" class="car-tag">{{ vip.carName }}</view>
|
||||
<text>{{ vip.memberName || '' }}</text>
|
||||
<text>{{ vip.discount ? ' ' + vip.discount : '' }}</text>
|
||||
<text v-if="vip.discount" class="discount-text">¥{{ vip.discount }}</text>
|
||||
</view>
|
||||
</label>
|
||||
</view>
|
||||
@@ -227,17 +223,22 @@ const vipList = ref([])
|
||||
// VIP选择变更(确保会员类型不重复)
|
||||
function onVipChange(idx, vipId) {
|
||||
if (profitRules.value[idx]) {
|
||||
const vipIndex = profitRules.value[idx].selectedVips.indexOf(vipId)
|
||||
const rule = profitRules.value[idx]
|
||||
// 确保selectedVips存在
|
||||
if (!rule.selectedVips) {
|
||||
rule.selectedVips = []
|
||||
}
|
||||
|
||||
const vipIndex = rule.selectedVips.indexOf(vipId)
|
||||
if (vipIndex > -1) {
|
||||
// 取消选择
|
||||
profitRules.value[idx].selectedVips.splice(vipIndex, 1)
|
||||
console.log('取消选择',idx+1, profitRules.value[idx].selectedVips.length)
|
||||
rule.selectedVips.splice(vipIndex, 1)
|
||||
} else {
|
||||
// 检查是否在其他消费分润规则中已选中
|
||||
const isDuplicate = isVipSelectedInOtherRules(idx, vipId)
|
||||
|
||||
if (!isDuplicate) {
|
||||
profitRules.value[idx].selectedVips.push(vipId)
|
||||
rule.selectedVips.push(vipId)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '该会员类型已在其他规则中选中',
|
||||
@@ -307,7 +308,6 @@ const vipList = ref([])
|
||||
}
|
||||
|
||||
.header-right {
|
||||
width: 60rpx;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@@ -540,24 +540,75 @@ const vipList = ref([])
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 自定义checkbox样式 */
|
||||
.custom-checkbox {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border: 2rpx solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
background-color: #ffffff;
|
||||
transition: all 0.3s ease-in-out;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.custom-checkbox.checked {
|
||||
border-color: #409eff;
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.custom-checkbox.checked::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 12rpx;
|
||||
height: 20rpx;
|
||||
border: 3rpx solid #ffffff;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
transform: translate(-50%, -60%) rotate(45deg);
|
||||
}
|
||||
|
||||
.custom-checkbox.disabled {
|
||||
border-color: #dcdfe6;
|
||||
background-color: #f5f7fa;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.custom-checkbox.disabled.checked {
|
||||
border-color: #dcdfe6;
|
||||
background-color: #dcdfe6;
|
||||
}
|
||||
.checkbox-label {
|
||||
margin: 0 10rpx;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
/* 禁用状态样式 */
|
||||
.checkbox-label.disabled {
|
||||
color: #c0c4cc !important;
|
||||
opacity: 0.5 !important;
|
||||
}
|
||||
|
||||
/* 禁用的checkbox样式 */
|
||||
checkbox[disabled] {
|
||||
opacity: 0.5 !important;
|
||||
/* 车辆标签样式 */
|
||||
.car-tag {
|
||||
display: inline-block;
|
||||
padding: 2rpx 8rpx;
|
||||
background-color: #ecf5ff;
|
||||
color: #409eff;
|
||||
font-size: 16rpx;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
checkbox[disabled] .uni-checkbox-input {
|
||||
border-color: #dcdfe6 !important;
|
||||
background-color: #f5f7fa !important;
|
||||
}
|
||||
|
||||
checkbox[disabled] .uni-checkbox-input.uni-checkbox-input-checked {
|
||||
border-color: #dcdfe6 !important;
|
||||
background-color: #dcdfe6 !important;
|
||||
/* 折扣价格样式 */
|
||||
.discount-text {
|
||||
color: #67c23a !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
@@ -52,7 +52,7 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="checkPermi(['work:distribution:profitRule'])" class="feature-card" @click="goToProfitRule">
|
||||
<!-- <view v-if="checkPermi(['work:distribution:profitRule'])" class="feature-card" @click="goToProfitRule">
|
||||
<view class="feature-icon user-icon">
|
||||
<view class="icon-text">💰</view>
|
||||
</view>
|
||||
@@ -60,7 +60,7 @@
|
||||
<view class="feature-title">分润规则配置</view>
|
||||
<view class="feature-desc">配置扫码注册、购买会员分润比例</view>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<view v-if="checkPermi(['work:distribution:profitRecord'])" class="feature-card" @click="goToDistributionData">
|
||||
<view class="feature-icon dept-icon">
|
||||
|
||||
@@ -18,6 +18,7 @@ export const useUserStore = defineStore('user', () => {
|
||||
const avatar = ref(storage.get(constant.avatar));
|
||||
const roles = ref(storage.get(constant.roles));
|
||||
const permissions = ref(storage.get(constant.permissions));
|
||||
const userMenus = ref([]);
|
||||
|
||||
const SET_TOKEN = val => {
|
||||
token.value = val;
|
||||
@@ -77,6 +78,7 @@ export const useUserStore = defineStore('user', () => {
|
||||
const userid = isEmpty(user) || isEmpty(user.id) ? '' : user.id;
|
||||
const username = isEmpty(user) || isEmpty(user.nickname) ? '' : user.nickname;
|
||||
const role = isEmpty(user) || isEmpty(user.currentRole) ? '' : user.currentRole;
|
||||
userMenus.value = res.data.menus || [];
|
||||
if (res.data.roles && res.data.roles.length > 0) {
|
||||
SET_ROLES(res.data.roles);
|
||||
SET_PERMISSIONS(res.data.permissions);
|
||||
@@ -121,6 +123,7 @@ export const useUserStore = defineStore('user', () => {
|
||||
currentRole,
|
||||
avatar,
|
||||
roles,
|
||||
userMenus,
|
||||
permissions,
|
||||
SET_AVATAR,
|
||||
login: loginAction,
|
||||
|
||||
Reference in New Issue
Block a user