提交代码

This commit is contained in:
zlwu committed 2025-08-08 03:59:16 +08:00
1 parent d9f760fe1c
commit 01588bf87d
484 files changed
+7228 -104711

No files matched your search

+725
View File
@@ -0,0 +1,725 @@
/**
* 页面模板生成器
* 支持动态创建标准页面模板
*/
/**
* 页面模板生成器类
*/
class PageGenerator {
/**
* 生成标准列表页面模板
* @param {string} serviceName - 服务名称
* @param {string} route - 路由路径
* @param {object} options - 选项
*/
static generateListPage(serviceName, route, options = {}) {
const template = `<template>
<view class="page-container">
<!-- 页面头部 -->
<view class="page-header">
<view class="header-content">
<text class="page-title">${serviceName}</text>
<view class="header-actions">
<u-button
v-if="hasPermi(['${this.getPermissionKey(serviceName)}:add'])"
type="primary"
size="small"
@click="handleAdd"
>
<u-icon name="plus" size="16" />
新增
</u-button>
</view>
</view>
</view>
<!-- 搜索区域 -->
<view class="search-section">
<u-form :model="searchForm" ref="searchFormRef">
<u-form-item label="关键词">
<u-input
v-model="searchForm.keyword"
placeholder="请输入关键词"
clearable
/>
</u-form-item>
<u-form-item>
<u-button type="primary" @click="handleSearch">搜索</u-button>
<u-button @click="handleReset">重置</u-button>
</u-form-item>
</u-form>
</view>
<!-- 数据列表 -->
<view class="list-section">
<u-list
:data="dataList"
:loading="loading"
:empty="dataList.length === 0"
@loadmore="handleLoadMore"
>
<template #item="{ item, index }">
<view class="list-item" @click="handleItemClick(item)">
<view class="item-content">
<text class="item-title">{{ item.title || item.name }}</text>
<text class="item-desc">{{ item.description || item.remark }}</text>
</view>
<view class="item-actions">
<u-button
v-if="hasPermi(['${this.getPermissionKey(serviceName)}:edit'])"
type="primary"
size="mini"
@click.stop="handleEdit(item)"
>
编辑
</u-button>
<u-button
v-if="hasPermi(['${this.getPermissionKey(serviceName)}:remove'])"
type="error"
size="mini"
@click.stop="handleDelete(item)"
>
删除
</u-button>
</view>
</view>
</template>
</u-list>
</view>
<!-- 分页组件 -->
<view class="pagination-section" v-if="total > 0">
<u-pagination
:total="total"
:current="currentPage"
:page-size="pageSize"
@change="handlePageChange"
/>
</view>
</view>
</template>
<script>
import { hasPermi, permissionMixin } from '@/utils/permission';
import { api } from '@/common/request';
export default {
name: '${this.getComponentName(serviceName)}',
mixins: [permissionMixin],
data() {
return {
// 搜索表单
searchForm: {
keyword: '',
status: '',
dateRange: []
},
// 列表数据
dataList: [],
loading: false,
// 分页参数
currentPage: 1,
pageSize: 10,
total: 0,
// 权限标识
permissionKey: '${this.getPermissionKey(serviceName)}'
};
},
onLoad() {
this.loadData();
},
methods: {
// 权限检查
hasPermi(permissions) {
return hasPermi(permissions);
},
// 加载数据
async loadData() {
try {
this.loading = true;
const params = {
pageNum: this.currentPage,
pageSize: this.pageSize,
...this.searchForm
};
// 这里需要根据实际API调整
const response = await api.get('/${this.getApiPath(serviceName)}/list', { params });
if (response.code === 200) {
this.dataList = response.rows || [];
this.total = response.total || 0;
} else {
uni.showToast({
title: response.msg || '加载失败',
icon: 'none'
});
}
} catch (error) {
console.error('加载数据失败:', error);
uni.showToast({
title: '网络错误',
icon: 'none'
});
} finally {
this.loading = false;
}
},
// 搜索
handleSearch() {
this.currentPage = 1;
this.loadData();
},
// 重置
handleReset() {
this.searchForm = {
keyword: '',
status: '',
dateRange: []
};
this.currentPage = 1;
this.loadData();
},
// 新增
handleAdd() {
uni.navigateTo({
url: '/pages/${this.getFormPath(serviceName)}/add'
});
},
// 编辑
handleEdit(item) {
uni.navigateTo({
url: \`/pages/${this.getFormPath(serviceName)}/edit?id=\${item.id}\`
});
},
// 删除
async handleDelete(item) {
try {
const confirmed = await this.showConfirm('确认删除', \`确定删除"\${item.title || item.name}"吗?\`);
if (!confirmed) return;
const response = await api.delete(\`/${this.getApiPath(serviceName)}/\${item.id}\`);
if (response.code === 200) {
uni.showToast({
title: '删除成功',
icon: 'success'
});
this.loadData();
} else {
uni.showToast({
title: response.msg || '删除失败',
icon: 'none'
});
}
} catch (error) {
console.error('删除失败:', error);
uni.showToast({
title: '网络错误',
icon: 'none'
});
}
},
// 点击列表项
handleItemClick(item) {
uni.navigateTo({
url: \`/pages/${this.getFormPath(serviceName)}/detail?id=\${item.id}\`
});
},
// 加载更多
handleLoadMore() {
if (this.dataList.length < this.total) {
this.currentPage++;
this.loadData();
}
},
// 分页变化
handlePageChange(page) {
this.currentPage = page;
this.loadData();
},
// 确认对话框
showConfirm(title, content) {
return new Promise((resolve) => {
uni.showModal({
title,
content,
success: (res) => {
resolve(res.confirm);
},
fail: () => {
resolve(false);
}
});
});
}
}
};
</script>
<style lang="scss" scoped>
.page-container {
min-height: 100vh;
background-color: #f5f5f5;
display: flex;
flex-direction: column;
}
.page-header {
background: linear-gradient(135deg, #007aff, #0051d9);
padding: calc(var(--status-bar-height) + 12px) 16px 16px;
color: #ffffff;
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.page-title {
font-size: 20px;
font-weight: 600;
}
.search-section {
background-color: #ffffff;
margin: 16px;
padding: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.list-section {
flex: 1;
margin: 0 16px;
}
.list-item {
background-color: #ffffff;
margin-bottom: 12px;
padding: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
justify-content: space-between;
align-items: center;
}
.item-content {
flex: 1;
}
.item-title {
font-size: 16px;
font-weight: 600;
color: #333333;
margin-bottom: 4px;
display: block;
}
.item-desc {
font-size: 14px;
color: #666666;
display: block;
}
.item-actions {
display: flex;
gap: 8px;
}
.pagination-section {
background-color: #ffffff;
margin: 16px;
padding: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
display: flex;
justify-content: center;
}
</style>`;
return template;
}
/**
* 生成表单页面模板
* @param {string} serviceName - 服务名称
* @param {string} route - 路由路径
* @param {object} options - 选项
*/
static generateFormPage(serviceName, route, options = {}) {
const template = `<template>
<view class="page-container">
<!-- 页面头部 -->
<view class="page-header">
<view class="header-content">
<u-button
type="text"
@click="handleBack"
class="back-btn"
>
<u-icon name="arrow-left" size="20" color="#ffffff" />
</u-button>
<text class="page-title">{{ isEdit ? '编辑' : '新增' }}${serviceName}</text>
<view class="header-actions">
<u-button
type="primary"
size="small"
@click="handleSave"
:loading="saving"
>
保存
</u-button>
</view>
</view>
</view>
<!-- 表单内容 -->
<view class="form-section">
<u-form
:model="formData"
:rules="formRules"
ref="formRef"
label-width="100px"
>
<u-form-item label="名称" prop="name">
<u-input
v-model="formData.name"
placeholder="请输入名称"
clearable
/>
</u-form-item>
<u-form-item label="描述" prop="description">
<u-textarea
v-model="formData.description"
placeholder="请输入描述"
:maxlength="200"
show-count
/>
</u-form-item>
<u-form-item label="状态" prop="status">
<u-radio-group v-model="formData.status">
<u-radio label="启用" value="1" />
<u-radio label="禁用" value="0" />
</u-radio-group>
</u-form-item>
<u-form-item label="排序" prop="sort">
<u-number-box
v-model="formData.sort"
:min="0"
:max="999"
/>
</u-form-item>
</u-form>
</view>
</view>
</template>
<script>
import { api } from '@/common/request';
export default {
name: '${this.getComponentName(serviceName)}Form',
data() {
return {
// 表单数据
formData: {
id: null,
name: '',
description: '',
status: '1',
sort: 0
},
// 表单验证规则
formRules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' }
],
status: [
{ required: true, message: '请选择状态', trigger: 'change' }
]
},
// 页面状态
isEdit: false,
saving: false,
// API路径
apiPath: '${this.getApiPath(serviceName)}'
};
},
onLoad(options) {
if (options.id) {
this.isEdit = true;
this.formData.id = options.id;
this.loadData();
}
},
methods: {
// 加载数据
async loadData() {
try {
const response = await api.get(\`/\${this.apiPath}/\${this.formData.id}\`);
if (response.code === 200) {
this.formData = { ...this.formData, ...response.data };
} else {
uni.showToast({
title: response.msg || '加载失败',
icon: 'none'
});
}
} catch (error) {
console.error('加载数据失败:', error);
uni.showToast({
title: '网络错误',
icon: 'none'
});
}
},
// 保存
async handleSave() {
try {
// 表单验证
const valid = await this.$refs.formRef.validate();
if (!valid) return;
this.saving = true;
const url = this.isEdit
? \`/\${this.apiPath}/\${this.formData.id}\`
: \`/\${this.apiPath}\`;
const method = this.isEdit ? 'put' : 'post';
const response = await api[method](url, this.formData);
if (response.code === 200) {
uni.showToast({
title: this.isEdit ? '更新成功' : '创建成功',
icon: 'success'
});
// 返回上一页
setTimeout(() => {
this.handleBack();
}, 1500);
} else {
uni.showToast({
title: response.msg || '保存失败',
icon: 'none'
});
}
} catch (error) {
console.error('保存失败:', error);
uni.showToast({
title: '网络错误',
icon: 'none'
});
} finally {
this.saving = false;
}
},
// 返回
handleBack() {
uni.navigateBack();
}
}
};
</script>
<style lang="scss" scoped>
.page-container {
min-height: 100vh;
background-color: #f5f5f5;
display: flex;
flex-direction: column;
}
.page-header {
background: linear-gradient(135deg, #007aff, #0051d9);
padding: calc(var(--status-bar-height) + 12px) 16px 16px;
color: #ffffff;
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.back-btn {
padding: 0;
margin: 0;
background: transparent;
}
.page-title {
font-size: 20px;
font-weight: 600;
}
.form-section {
flex: 1;
background-color: #ffffff;
margin: 16px;
padding: 16px;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
</style>`;
return template;
}
/**
* 获取权限标识
* @param {string} serviceName - 服务名称
*/
static getPermissionKey(serviceName) {
const permissionMap = {
学生信息: 'student:info',
宿舍管理: 'student:dorm',
学生请假: 'student:leave',
心理健康: 'student:psychology',
社团管理: 'student:club',
心理咨询: 'student:counsel',
物业报修: 'logistics:repair',
场地预约: 'logistics:venue',
报告厅预约: 'logistics:hall',
满意度调查: 'logistics:survey',
食堂管理: 'logistics:canteen',
物业管理: 'logistics:property',
学生管理: 'recruitment:student',
毕业生信息: 'recruitment:graduate',
就业信息: 'recruitment:job',
员工管理: 'hr:staff',
出国申请: 'hr:abroad',
培训管理: 'hr:training',
预算管理: 'finance:budget',
费用报销: 'finance:expense',
发票管理: 'finance:invoice',
用户管理: 'system:user',
角色管理: 'system:role',
菜单管理: 'system:menu',
部门管理: 'system:dept',
参数设置: 'system:config',
在线用户: 'monitor:online',
};
return permissionMap[serviceName] || 'system:default';
}
/**
* 获取组件名称
* @param {string} serviceName - 服务名称
*/
static getComponentName(serviceName) {
return serviceName.replace(/\s+/g, '');
}
/**
* 获取API路径
* @param {string} serviceName - 服务名称
*/
static getApiPath(serviceName) {
const apiMap = {
学生信息: 'student/info',
宿舍管理: 'student/dorm',
学生请假: 'student/leave',
心理健康: 'student/psychology',
社团管理: 'student/club',
心理咨询: 'student/counsel',
物业报修: 'logistics/repair',
场地预约: 'logistics/venue',
报告厅预约: 'logistics/hall',
满意度调查: 'logistics/survey',
食堂管理: 'logistics/canteen',
物业管理: 'logistics/property',
学生管理: 'recruitment/student',
毕业生信息: 'recruitment/graduate',
就业信息: 'recruitment/job',
员工管理: 'hr/staff',
出国申请: 'hr/abroad',
培训管理: 'hr/training',
预算管理: 'finance/budget',
费用报销: 'finance/expense',
发票管理: 'finance/invoice',
用户管理: 'system/user',
角色管理: 'system/role',
菜单管理: 'system/menu',
部门管理: 'system/dept',
参数设置: 'system/config',
在线用户: 'monitor/online',
};
return apiMap[serviceName] || 'system/default';
}
/**
* 获取表单路径
* @param {string} serviceName - 服务名称
*/
static getFormPath(serviceName) {
const pathMap = {
学生信息: 'student/info',
宿舍管理: 'student/dorm',
学生请假: 'student/leave',
心理健康: 'student/psychology',
社团管理: 'student/club',
心理咨询: 'student/counsel',
物业报修: 'logistics/repair',
场地预约: 'logistics/venue',
报告厅预约: 'logistics/hall',
满意度调查: 'logistics/survey',
食堂管理: 'logistics/canteen',
物业管理: 'logistics/property',
学生管理: 'recruitment/student',
毕业生信息: 'recruitment/graduate',
就业信息: 'recruitment/job',
员工管理: 'hr/staff',
出国申请: 'hr/abroad',
培训管理: 'hr/training',
预算管理: 'finance/budget',
费用报销: 'finance/expense',
发票管理: 'finance/invoice',
用户管理: 'system/user',
角色管理: 'system/role',
菜单管理: 'system/menu',
部门管理: 'system/dept',
参数设置: 'system/config',
在线用户: 'monitor/online',
};
return pathMap[serviceName] || 'system/default';
}
}
export default PageGenerator;
+238
View File
@@ -0,0 +1,238 @@
/**
* 路由管理工具类
* 支持动态路由跳转,无需在pages.json中预先配置
*/
// 服务路由映射配置
const SERVICE_ROUTES = {
// 学工管理
'student:info': '/pages/student/info/index',
'student:dorm': '/pages/student/dorm/index',
'student:leave': '/pages/student/leave/index',
'student:psychology': '/pages/student/psychology/index',
'student:club': '/pages/student/club/index',
'student:counsel': '/pages/student/counsel/index',
// 后勤管理
'logistics:repair': '/pages/logistics/repair/index',
'logistics:venue': '/pages/logistics/venue/index',
'logistics:hall': '/pages/logistics/hall/index',
'logistics:survey': '/pages/logistics/survey/index',
'logistics:canteen': '/pages/logistics/canteen/index',
'logistics:property': '/pages/logistics/property/index',
// 招生就业
'recruitment:student': '/pages/recruitment/student/index',
'recruitment:graduate': '/pages/recruitment/graduate/index',
'recruitment:job': '/pages/recruitment/job/index',
// 人事管理
'hr:staff': '/pages/hr/staff/index',
'hr:abroad': '/pages/hr/abroad/index',
'hr:training': '/pages/hr/training/index',
// 财务管理
'finance:budget': '/pages/finance/budget/index',
'finance:expense': '/pages/finance/expense/index',
'finance:invoice': '/pages/finance/invoice/index',
// 系统管理
'system:user': '/pages/system/user/index',
'system:role': '/pages/system/role/index',
'system:menu': '/pages/system/menu/index',
'system:dept': '/pages/system/dept/index',
'system:config': '/pages/system/config/index',
'monitor:online': '/pages/monitor/online/index',
};
// 服务名称映射
const SERVICE_NAMES = {
学生信息: 'student:info',
宿舍管理: 'student:dorm',
学生请假: 'student:leave',
心理健康: 'student:psychology',
社团管理: 'student:club',
心理咨询: 'student:counsel',
物业报修: 'logistics:repair',
场地预约: 'logistics:venue',
报告厅预约: 'logistics:hall',
满意度调查: 'logistics:survey',
食堂管理: 'logistics:canteen',
物业管理: 'logistics:property',
学生管理: 'recruitment:student',
毕业生信息: 'recruitment:graduate',
就业信息: 'recruitment:job',
员工管理: 'hr:staff',
出国申请: 'hr:abroad',
培训管理: 'hr:training',
预算管理: 'finance:budget',
费用报销: 'finance:expense',
发票管理: 'finance:invoice',
用户管理: 'system:user',
角色管理: 'system:role',
菜单管理: 'system:menu',
部门管理: 'system:dept',
参数设置: 'system:config',
在线用户: 'monitor:online',
};
/**
* 路由管理类
*/
class RouterManager {
/**
* 根据服务名称跳转到对应页面
* @param {string} serviceName - 服务名称
* @param {object} options - 跳转选项
*/
static navigateToService(serviceName, options = {}) {
const serviceKey = SERVICE_NAMES[serviceName];
if (!serviceKey) {
this.showServiceNotConfigured(serviceName);
return;
}
const route = SERVICE_ROUTES[serviceKey];
if (!route) {
this.showServiceNotConfigured(serviceName);
return;
}
// 构建完整URL(支持参数传递)
let url = route;
if (options.params) {
const queryString = Object.keys(options.params)
.map((key) => `${key}=${encodeURIComponent(options.params[key])}`)
.join('&');
url += `?${queryString}`;
}
// 执行跳转
uni.navigateTo({
url,
success: () => {
console.log(`✅ 成功跳转到: ${url}`);
if (options.onSuccess) {
options.onSuccess();
}
},
fail: (error) => {
console.warn(`⚠️ 页面跳转失败: ${url}`, error);
this.handlePageNotExist(serviceName, route, options);
},
});
}
/**
* 处理页面不存在的情况
* @param {string} serviceName - 服务名称
* @param {string} route - 路由路径
* @param {object} options - 选项
*/
static handlePageNotExist(serviceName, route, options = {}) {
uni.showModal({
title: '页面不存在',
content: `${serviceName}页面尚未创建,是否创建该页面?`,
confirmText: '创建页面',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
this.createPageTemplate(serviceName, route, options);
} else {
this.showServiceNotImplemented(serviceName);
}
},
});
}
/**
* 创建页面模板
* @param {string} serviceName - 服务名称
* @param {string} route - 路由路径
* @param {object} options - 选项
*/
static createPageTemplate(serviceName, route, options = {}) {
// 这里可以实现页面创建逻辑
// 1. 调用后端API创建页面文件
// 2. 跳转到页面创建向导
// 3. 生成标准页面模板
console.log(`📝 需要创建页面: ${route} - ${serviceName}`);
// 临时提示
uni.showToast({
title: '页面创建功能开发中',
icon: 'none',
duration: 2000,
});
// 可以在这里添加实际的页面创建逻辑
if (options.onCreatePage) {
options.onCreatePage(serviceName, route);
}
}
/**
* 显示服务未配置提示
* @param {string} serviceName - 服务名称
*/
static showServiceNotConfigured(serviceName) {
uni.showToast({
title: `服务未配置: ${serviceName}`,
icon: 'none',
duration: 2000,
});
}
/**
* 显示服务未实现提示
* @param {string} serviceName - 服务名称
*/
static showServiceNotImplemented(serviceName) {
uni.showToast({
title: `功能开发中: ${serviceName}`,
icon: 'none',
duration: 2000,
});
}
/**
* 检查页面是否存在
* @param {string} route - 路由路径
* @returns {Promise<boolean>}
*/
static async checkPageExists(route) {
return new Promise((resolve) => {
// 尝试跳转但不实际跳转,用于检查页面是否存在
uni.navigateTo({
url: route,
success: () => {
// 立即返回,避免实际跳转
uni.navigateBack();
resolve(true);
},
fail: () => {
resolve(false);
},
});
});
}
/**
* 获取所有可用的服务路由
* @returns {object}
*/
static getAvailableRoutes() {
return { ...SERVICE_ROUTES };
}
/**
* 获取服务名称映射
* @returns {object}
*/
static getServiceNames() {
return { ...SERVICE_NAMES };
}
}
export default RouterManager;
+1 -1
View File
@@ -35,7 +35,7 @@ export const userManager = {
// 部门信息
deptId: user.deptId,
deptName: user.dept?.deptName || '',
deptName: user?.deptName || '',
// 状态信息
status: user.status,