feat: Update .gitignore and enhance user management features
- Added new entries to .gitignore to exclude Vite cache, environment variable templates, and sensitive files. - Modified user management routes to allow access for both super admins and store staff, enabling store staff to add users for their respective stores. - Refactored dashboard navigation to include a function for routing with store context. - Enhanced user form to display current store information for non-super admin users.
This commit is contained in:
parent
8f9eb38666
commit
19784bddb9
35
.gitignore
vendored
35
.gitignore
vendored
@ -3,20 +3,27 @@
|
|||||||
# ============================================
|
# ============================================
|
||||||
node_modules/
|
node_modules/
|
||||||
**/node_modules/
|
**/node_modules/
|
||||||
|
# 子目录下 node_modules 内的缓存/预构建(避免被跟踪)
|
||||||
|
**/node_modules/.vite/
|
||||||
|
**/node_modules/.cache/
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# 环境变量(含敏感信息,勿提交)
|
# 环境变量(含敏感信息,勿提交)
|
||||||
# ============================================
|
# ============================================
|
||||||
.env
|
.env
|
||||||
|
.env.*
|
||||||
.env.local
|
.env.local
|
||||||
.env.*.local
|
.env.*.local
|
||||||
.env.production
|
.env.production
|
||||||
.env.development
|
.env.development
|
||||||
# 各子项目的环境变量
|
.env.test
|
||||||
|
# 各子项目的环境变量(保留 env-template.txt 作为模板)
|
||||||
server/.env
|
server/.env
|
||||||
admin/.env.local
|
admin/.env.local
|
||||||
admin/.env
|
admin/.env
|
||||||
miniprogram/.env
|
miniprogram/.env
|
||||||
|
# 不忽略环境变量模板文件
|
||||||
|
!**/env-template.txt
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# 构建产物
|
# 构建产物
|
||||||
@ -45,10 +52,12 @@ lerna-debug.log*
|
|||||||
# ============================================
|
# ============================================
|
||||||
.cache/
|
.cache/
|
||||||
.vite/
|
.vite/
|
||||||
|
**/.vite/
|
||||||
.parcel-cache/
|
.parcel-cache/
|
||||||
.eslintcache
|
.eslintcache
|
||||||
|
.prettiercache
|
||||||
*.local
|
*.local
|
||||||
# Vite 缓存
|
# Vite 预构建与缓存
|
||||||
admin/.vite/
|
admin/.vite/
|
||||||
admin/node_modules/.vite/
|
admin/node_modules/.vite/
|
||||||
|
|
||||||
@ -66,6 +75,8 @@ uploads/*
|
|||||||
# ============================================
|
# ============================================
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/settings.json.example
|
||||||
*.suo
|
*.suo
|
||||||
*.ntvs*
|
*.ntvs*
|
||||||
*.njsproj
|
*.njsproj
|
||||||
@ -77,6 +88,8 @@ uploads/*
|
|||||||
.project
|
.project
|
||||||
.classpath
|
.classpath
|
||||||
.settings/
|
.settings/
|
||||||
|
# Cursor
|
||||||
|
.cursor/
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# 系统文件
|
# 系统文件
|
||||||
@ -104,11 +117,13 @@ playwright-report/
|
|||||||
# ============================================
|
# ============================================
|
||||||
# 微信小程序
|
# 微信小程序
|
||||||
# ============================================
|
# ============================================
|
||||||
# 微信开发者工具本地配置(含工具偏好设置)
|
# 微信开发者工具本地配置(含工具偏好、AppID 等,勿提交)
|
||||||
miniprogram/project.private.config.json
|
miniprogram/project.private.config.json
|
||||||
# 小程序编译产物(如果有)
|
# 小程序 npm 构建产物
|
||||||
miniprogram/miniprogram_npm/
|
miniprogram/miniprogram_npm/
|
||||||
miniprogram/node_modules/
|
miniprogram/node_modules/
|
||||||
|
# 小程序本地密钥/私密配置
|
||||||
|
miniprogram/private/
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# 临时文件
|
# 临时文件
|
||||||
@ -128,6 +143,16 @@ temp/
|
|||||||
*.sqlite
|
*.sqlite
|
||||||
*.sqlite3
|
*.sqlite3
|
||||||
|
|
||||||
|
# ============================================
|
||||||
|
# 密钥与证书
|
||||||
|
# ============================================
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
*.crt
|
||||||
|
*.p12
|
||||||
|
*.pfx
|
||||||
|
secrets/
|
||||||
|
|
||||||
# ============================================
|
# ============================================
|
||||||
# 其他
|
# 其他
|
||||||
# ============================================
|
# ============================================
|
||||||
@ -135,3 +160,5 @@ temp/
|
|||||||
# package-lock.json
|
# package-lock.json
|
||||||
# yarn.lock
|
# yarn.lock
|
||||||
# pnpm-lock.yaml
|
# pnpm-lock.yaml
|
||||||
|
# 对话/代理生成目录(若存在)
|
||||||
|
agent-transcripts/
|
||||||
|
|||||||
@ -23,7 +23,7 @@ const routes = [
|
|||||||
path: "users",
|
path: "users",
|
||||||
name: "Users",
|
name: "Users",
|
||||||
component: () => import("@/views/user/index.vue"),
|
component: () => import("@/views/user/index.vue"),
|
||||||
meta: { title: "用户管理", icon: "User", superAdmin: true },
|
meta: { title: "用户管理", icon: "User" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "stores",
|
path: "stores",
|
||||||
|
|||||||
@ -51,15 +51,15 @@
|
|||||||
<el-icon class="icon"><View /></el-icon>
|
<el-icon class="icon"><View /></el-icon>
|
||||||
<span class="label">扫码核销</span>
|
<span class="label">扫码核销</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="quick-action-btn" @click="$router.push('/display/ranking')">
|
<div class="quick-action-btn" @click="goToDisplay('/display/ranking')">
|
||||||
<el-icon class="icon"><Monitor /></el-icon>
|
<el-icon class="icon"><Monitor /></el-icon>
|
||||||
<span class="label">天梯大屏(蓝)</span>
|
<span class="label">天梯大屏(蓝)</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="quick-action-btn" @click="$router.push('/display/ranking-orange')">
|
<div class="quick-action-btn" @click="goToDisplay('/display/ranking-orange')">
|
||||||
<el-icon class="icon"><Monitor /></el-icon>
|
<el-icon class="icon"><Monitor /></el-icon>
|
||||||
<span class="label">天梯大屏(橙)</span>
|
<span class="label">天梯大屏(橙)</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="quick-action-btn" @click="$router.push('/display/ladder-summary')">
|
<div class="quick-action-btn" @click="goToDisplay('/display/ladder-summary')">
|
||||||
<el-icon class="icon"><Monitor /></el-icon>
|
<el-icon class="icon"><Monitor /></el-icon>
|
||||||
<span class="label">天梯汇总大屏</span>
|
<span class="label">天梯汇总大屏</span>
|
||||||
</div>
|
</div>
|
||||||
@ -273,12 +273,29 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, nextTick, watch } from 'vue'
|
import { ref, onMounted, nextTick, watch, computed } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { View, Loading, InfoFilled, Search, User, Check, Monitor } from '@element-plus/icons-vue'
|
import { View, Loading, InfoFilled, Search, User, Check, Monitor } from '@element-plus/icons-vue'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
import { getDashboard, getPointActions, executePointAction, getMatches, getPointOrders, verifyOrder, verifyByCode, searchUsers } from '@/api/admin'
|
import { getDashboard, getPointActions, executePointAction, getMatches, getPointOrders, verifyOrder, verifyByCode, searchUsers } from '@/api/admin'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
// 当前门店 ID(门店店员进入时自动使用其所属门店)
|
||||||
|
const currentStoreId = computed(() => userStore.userInfo?.storeId ?? userStore.userInfo?.store_id ?? '')
|
||||||
|
|
||||||
|
// 跳转大屏时带上当前门店,使门店店员自动看到本门店大屏
|
||||||
|
const goToDisplay = (path) => {
|
||||||
|
const query = {}
|
||||||
|
if (currentStoreId.value) {
|
||||||
|
query.store_id = currentStoreId.value
|
||||||
|
}
|
||||||
|
router.push({ path, query })
|
||||||
|
}
|
||||||
|
|
||||||
const stats = ref({})
|
const stats = ref({})
|
||||||
const quickActions = ref([])
|
const quickActions = ref([])
|
||||||
const recentMatches = ref([])
|
const recentMatches = ref([])
|
||||||
|
|||||||
@ -158,6 +158,7 @@
|
|||||||
:rules="addLadderRules"
|
:rules="addLadderRules"
|
||||||
ref="addLadderFormRef"
|
ref="addLadderFormRef"
|
||||||
label-width="100px">
|
label-width="100px">
|
||||||
|
<!-- 超管可选择门店,门店店员自动使用当前门店 -->
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="userStore.isSuperAdmin"
|
v-if="userStore.isSuperAdmin"
|
||||||
label="门店"
|
label="门店"
|
||||||
@ -170,6 +171,9 @@
|
|||||||
:value="store.id" />
|
:value="store.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item v-else label="门店">
|
||||||
|
<span class="current-store-label">{{ currentStoreName || '当前门店' }}</span>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="手机号" prop="phone">
|
<el-form-item label="手机号" prop="phone">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="addLadderForm.phone"
|
v-model="addLadderForm.phone"
|
||||||
@ -258,6 +262,10 @@
|
|||||||
power_score: 1000,
|
power_score: 1000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const currentStoreName = computed(
|
||||||
|
() => userStore.userInfo?.storeName || ""
|
||||||
|
);
|
||||||
|
|
||||||
const addLadderRules = computed(() => ({
|
const addLadderRules = computed(() => ({
|
||||||
...(userStore.isSuperAdmin
|
...(userStore.isSuperAdmin
|
||||||
? {
|
? {
|
||||||
@ -323,8 +331,12 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleAddLadderUser = (row) => {
|
const handleAddLadderUser = (row) => {
|
||||||
|
const storeId =
|
||||||
|
userStore.isSuperAdmin
|
||||||
|
? ""
|
||||||
|
: userStore.userInfo?.storeId ?? userStore.userInfo?.store_id ?? "";
|
||||||
addLadderForm.value = {
|
addLadderForm.value = {
|
||||||
store_id: userStore.isSuperAdmin ? "" : userStore.userInfo?.storeId || "",
|
store_id: storeId,
|
||||||
phone: row.phone || "",
|
phone: row.phone || "",
|
||||||
real_name: row.nickname || "",
|
real_name: row.nickname || "",
|
||||||
gender: row.gender === 1 || row.gender === 2 ? row.gender : 1,
|
gender: row.gender === 1 || row.gender === 2 ? row.gender : 1,
|
||||||
@ -373,5 +385,10 @@
|
|||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.current-store-label {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -13,11 +13,11 @@ router.post('/login', adminController.login);
|
|||||||
// === 仪表盘 ===
|
// === 仪表盘 ===
|
||||||
router.get('/dashboard', authAdmin, adminController.getDashboard);
|
router.get('/dashboard', authAdmin, adminController.getDashboard);
|
||||||
|
|
||||||
// === 用户管理(超管) ===
|
// === 用户管理(超管与门店店员均可访问,店员可添加用户为当前门店天梯用户) ===
|
||||||
router.get('/users', authAdmin, requireSuperAdmin, adminController.getUsers);
|
router.get('/users', authAdmin, adminController.getUsers);
|
||||||
router.get('/users/search', authAdmin, adminController.searchUsers); // 搜索用户(用于积分操作,普通管理员可用)
|
router.get('/users/search', authAdmin, adminController.searchUsers); // 搜索用户(用于积分操作,普通管理员可用)
|
||||||
router.get('/users/:id', authAdmin, requireSuperAdmin, adminController.getUserDetail);
|
router.get('/users/:id', authAdmin, adminController.getUserDetail);
|
||||||
router.put('/users/:id/status', authAdmin, requireSuperAdmin, adminController.updateUserStatus);
|
router.put('/users/:id/status', authAdmin, adminController.updateUserStatus);
|
||||||
|
|
||||||
// === 门店管理(超管) ===
|
// === 门店管理(超管) ===
|
||||||
router.get('/stores', authAdmin, requireSuperAdmin, adminController.getStores);
|
router.get('/stores', authAdmin, requireSuperAdmin, adminController.getStores);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user