XTAPP 二次开发完整指南
版本: 1.0
适用项目: XTAPP 仓储管理系统
技术栈: ASP.NET MVC 4 + Entity Framework 5.0 + SQL Server
📋 目录
1. 项目架构详解
1.1 整体架构
XTAPP (ASP.NET MVC 4 Web应用)
├── Controllers/ # 控制器层 (82个控制器)
├── Models/ # 数据模型层 (230+个模型)
├── Views/ # 视图层 (Razor视图)
├── DAL/ # 数据访问层
├── WebHelp/ # Web辅助类
│ ├── Filter/ # 过滤器(登录、权限验证)
│ └── Attri/ # 特性类(跳过验证)
├── PublicDLL/ # 公共DLL和工具类
├── Commom/ # 公共工具类
├── App_Start/ # 应用启动配置
└── Scripts/ # JavaScript文件
1.2 技术架构层次
┌─────────────────────────────────────┐
│ 前端层 (LayUI + jQuery) │
├─────────────────────────────────────┤
│ 控制器层 (Controllers) │
│ ├── 业务逻辑处理 │
│ ├── 权限验证 (Filter) │
│ └── 数据返回 (JSON/View) │
├─────────────────────────────────────┤
│ 数据访问层 (DAL + GetPageListData)│
│ ├── Entity Framework 5.0 │
│ ├── 存储过程调用 │
│ └── 原生SQL执行 │
├─────────────────────────────────────┤
│ 数据模型层 (Models) │
│ ├── EF实体模型 │
│ ├── 视图模型 │
│ └── 存储过程结果模型 │
├─────────────────────────────────────┤
│ 数据库层 (SQL Server) │
│ └── MPWMS数据库 │
└─────────────────────────────────────┘
1.3 核心类说明
GetPageListData (数据访问核心类)
位置: XTAPP/WebHelp/GetPageListData.cs
主要功能:
- 封装了所有数据库操作的泛型方法
- 提供增删改查的统一接口
- 支持分页查询
- 支持存储过程调用
- 提供日志记录功能
常用方法:
// 分页查询
GetPageList<T, TKey>(pageIndex, pageSize, out totalCount, where, order)
// 添加数据
AddData<T, TKey>(Table)
// 修改数据
UpdateData<T, TKey>(Table)
// 查询单条数据
GetEditData<T, TKey>(where)
// 执行存储过程
RunProc<T, Key>(sql, parms)
// 执行SQL语句
_SqlAlter<T, Key>(id, reason, dataTable, dataTime, username)
BaseController (基础控制器)
位置: XTAPP/WebHelp/BaseController.cs
主要功能:
- 封装统一的JSON响应方法
- 所有控制器可以继承此类
方法:
WriteError(string msg) // 返回错误JSON
WriteSuccess(string msg) // 返回成功JSON
WriteSuccess(string msg, object obj) // 返回成功JSON带数据
SqlHelper (SQL辅助类)
位置: XTAPP/PublicDLL/SqlHelper.cs
主要功能:
- 执行原生SQL语句
- 支持参数化查询
- 防止SQL注入
2. 开发环境搭建
2.1 必需软件
-
Visual Studio 2015 或更高版本
- 推荐: Visual Studio 2017/2019
- 必需组件: .NET Framework 4.7.2 SDK
-
SQL Server
- 版本: SQL Server 2008 或更高
- 数据库名: MPWMS
-
IIS (可选,用于本地调试)
- IIS 7.0 或更高版本
- 启用 ASP.NET 4.0
2.2 项目配置步骤
步骤1: 打开项目
# 双击打开解决方案文件
XTAPP.sln
步骤2: 配置数据库连接
编辑 Web.config 文件,修改连接字符串:
<connectionStrings>
<!-- 开发环境连接 -->
<add name="MPWMSConnectionString"
connectionString="Data Source=.;Initial Catalog=MPWMS;User ID=sa;Password=your_password"
providerName="System.Data.SqlClient"/>
<add name="MPWMSEntitiesReport"
connectionString="Data Source=.;Initial Catalog=MPWMS;User ID=sa;Password=your_password" />
<add name="MPWMSEntities"
connectionString="metadata=res://*/Models.XTAPP.csdl|res://*/Models.XTAPP.ssdl|res://*/Models.XTAPP.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=MPWMS;user id=sa;password=your_password;MultipleActiveResultSets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
<add name="MPWMSEntitiesNew"
connectionString="metadata=res://*/Models.XTAPP.csdl|res://*/Models.XTAPP.ssdl|res://*/Models.XTAPP.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=MPWMS;user id=sa;password=your_password;multipleactiveresultsets=True;application name=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
步骤3: 还原NuGet包
# 在Visual Studio中
右键解决方案 -> 还原NuGet包
步骤4: 编译项目
# 快捷键: Ctrl+Shift+B
# 或菜单: 生成 -> 生成解决方案
2.3 运行项目
方式1: IIS Express (推荐)
# 按F5启动调试
# 或点击"运行"按钮
方式2: 本地IIS
- 在IIS中创建应用程序池(.NET Framework 4.0)
- 创建网站,指向项目目录
- 设置端口和绑定
3. 核心开发模式
3.1 MVC模式
项目严格遵循MVC模式:
- Model: 数据模型,位于
Models/目录 - View: 视图文件,位于
Views/目录 - Controller: 控制器,位于
Controllers/目录
3.2 控制器开发模式
标准控制器结构
using System;
using System.Web.Mvc;
using XTAPP.Models;
using XTAPP.WebHelp;
using XTAPP.WebHelp.Attri;
namespace XTAPP.Controllers
{
// 继承BaseController或Controller
public class YourController : BaseController
{
// 数据访问对象
GetPageListData getPageListData = new GetPageListData();
// EF上下文 (可选)
MPWMSEntitiesNew xt = new MPWMSEntitiesNew();
// 1. 列表页面
public ActionResult Index()
{
return View();
}
// 2. 获取列表数据 (AJAX)
[HttpPost]
public JsonResult GetList()
{
try
{
// 获取分页参数
int pageIndex = int.Parse(Request["page"] ?? "1");
int pageSize = int.Parse(Request["limit"] ?? "10");
// 查询条件
Func<YourModel, bool> where = x => x.IsDel == 1;
// 排序
Func<YourModel, int> order = x => x.ID;
// 分页查询
int totalCount;
var list = getPageListData.GetPageList<YourModel, int>(
pageIndex, pageSize, out totalCount, where, order);
return Json(new {
code = 0,
msg = "成功",
count = totalCount,
data = list
});
}
catch (Exception ex)
{
return WriteError(ex.Message);
}
}
// 3. 添加/编辑页面
public ActionResult Add(int? id)
{
YourModel model = new YourModel();
if (id.HasValue)
{
// 编辑模式,加载数据
model = getPageListData.GetEditData<YourModel, object>(
x => x.ID == id.Value);
}
return View(model);
}
// 4. 保存数据
[HttpPost]
public JsonResult Save(YourModel model)
{
try
{
if (model.ID > 0)
{
// 更新
getPageListData.UpdateData<YourModel, object>(model);
}
else
{
// 新增
getPageListData.AddData<YourModel, object>(model);
}
// 记录日志
var user = Session["UserInfo"] as SysUser;
getPageListData.Log("模块名", "操作", "描述", user.UserName);
return WriteSuccess("保存成功");
}
catch (Exception ex)
{
return WriteError(ex.Message);
}
}
// 5. 删除数据
[HttpPost]
public JsonResult Delete(int id)
{
try
{
// 逻辑删除 (更新IsDel字段)
getPageListData._SqlDel<YourModel, object>(id, "YourTable");
return WriteSuccess("删除成功");
}
catch (Exception ex)
{
return WriteError(ex.Message);
}
}
}
}
3.3 权限控制机制
全局过滤器
项目在 FilterConfig.cs 中注册了两个全局过滤器:
- CheckLoginAttribute: 登录验证
- CheckPermissAttrbute: 权限验证
跳过验证
如果某个Action不需要验证,使用特性:
using XTAPP.WebHelp.Attri;
[SkipCkeckLogin] // 跳过登录验证
[SkipCheckPermiss] // 跳过权限验证
public ActionResult PublicAction()
{
return View();
}
权限验证原理
- 获取当前用户ID
- 获取控制器名称和Action名称
- 调用存储过程
Usp_GetFunctionData检查权限 - 如果没有权限,返回无权限页面或JSON
存储过程调用:
string procName = $"Usp_GetFunctionData {userId},'{controllerName}','{actionName}'";
var list = getPageListData.RunProc<SysPermission, object>(procName);
4. 如何添加新功能
4.1 添加新功能模块的完整流程
步骤1: 创建数据模型
在 Models/ 目录下创建模型类:
// Models/YourModel.cs
namespace XTAPP.Models
{
public class YourModel
{
public int ID { get; set; }
public string Name { get; set; }
public int IsDel { get; set; } // 1-有效, 0-删除
public DateTime CreateTime { get; set; }
// ... 其他字段
}
}
步骤2: 创建控制器
在 Controllers/ 目录下创建控制器:
// Controllers/YourController.cs
using System;
using System.Web.Mvc;
using XTAPP.Models;
using XTAPP.WebHelp;
using XTAPP.Commom;
namespace XTAPP.Controllers
{
public class YourController : BaseController
{
GetPageListData getPageListData = new GetPageListData();
// 列表页面
public ActionResult Index()
{
return View();
}
// 获取列表数据
[HttpPost]
public JsonResult GetList()
{
// 实现逻辑
}
// 添加/编辑页面
public ActionResult Add(int? id)
{
// 实现逻辑
}
// 保存
[HttpPost]
public JsonResult Save(YourModel model)
{
// 实现逻辑
}
// 删除
[HttpPost]
public JsonResult Delete(int id)
{
// 实现逻辑
}
}
}
步骤3: 创建视图
在 Views/Your/ 目录下创建视图文件:
Index.cshtml (列表页):
@{
ViewBag.Title = "功能名称";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="layui-card">
<div class="layui-card-body">
<table class="layui-hide" id="table" lay-filter="table"></table>
</div>
</div>
<script>
layui.use(['table', 'form'], function(){
var table = layui.table;
// 渲染表格
table.render({
elem: '#table',
url: '/Your/GetList',
cols: [[
{type: 'checkbox'},
{field: 'ID', title: 'ID', width: 80},
{field: 'Name', title: '名称'},
{title: '操作', toolbar: '#barDemo', width: 200}
]],
page: true
});
});
</script>
Add.cshtml (添加/编辑页):
@model XTAPP.Models.YourModel
@{
ViewBag.Title = Model.ID > 0 ? "编辑" : "添加";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<form class="layui-form">
<input type="hidden" name="ID" value="@Model.ID" />
<div class="layui-form-item">
<label class="layui-form-label">名称</label>
<div class="layui-input-block">
<input type="text" name="Name" value="@Model.Name" required lay-verify="required" />
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" lay-submit lay-filter="save">保存</button>
</div>
</div>
</form>
<script>
layui.use(['form', 'layer'], function(){
var form = layui.form;
var layer = layui.layer;
form.on('submit(save)', function(data){
$.ajax({
url: '/Your/Save',
type: 'POST',
data: data.field,
success: function(res){
if(res.status == 0){
layer.msg('保存成功', {icon: 1});
setTimeout(function(){
parent.location.reload();
}, 1000);
} else {
layer.msg(res.msg, {icon: 2});
}
}
});
return false;
});
});
</script>
步骤4: 配置路由 (可选)
默认路由规则: {controller}/{action}/{id}
如果需要自定义路由,在 RouteConfig.cs 中添加:
routes.MapRoute(
name: "YourRoute",
url: "your/{action}/{id}",
defaults: new { controller = "Your", action = "Index", id = UrlParameter.Optional }
);
步骤5: 配置菜单权限
- 在数据库中添加菜单记录 (
SysMenu表) - 在数据库中添加功能权限记录 (
SysFunction表) - 为用户分配权限
5. 数据库操作详解
5.1 Entity Framework 操作
使用EF上下文
MPWMSEntitiesNew xt = new MPWMSEntitiesNew();
// 查询
var list = xt.YourTable.Where(x => x.IsDel == 1).ToList();
// 添加
var entity = new YourTable { Name = "test" };
xt.YourTable.Add(entity);
xt.SaveChanges();
// 修改
var entity = xt.YourTable.FirstOrDefault(x => x.ID == 1);
entity.Name = "new name";
xt.SaveChanges();
// 删除 (物理删除)
var entity = xt.YourTable.FirstOrDefault(x => x.ID == 1);
xt.YourTable.Remove(entity);
xt.SaveChanges();
5.2 使用GetPageListData操作
分页查询
GetPageListData getPageListData = new GetPageListData();
int pageIndex = 1;
int pageSize = 10;
int totalCount;
// 查询条件
Func<YourModel, bool> where = x => x.IsDel == 1 && x.Name.Contains("test");
// 排序
Func<YourModel, int> order = x => x.ID;
// 执行查询
var list = getPageListData.GetPageList<YourModel, int>(
pageIndex, pageSize, out totalCount, where, order);
添加数据
var model = new YourModel
{
Name = "test",
IsDel = 1,
CreateTime = DateTime.Now
};
int result = getPageListData.AddData<YourModel, object>(model);
// result > 0 表示成功
修改数据
var model = getPageListData.GetEditData<YourModel, object>(x => x.ID == 1);
model.Name = "new name";
int result = getPageListData.UpdateData<YourModel, object>(model);
查询单条数据
var model = getPageListData.GetEditData<YourModel, object>(x => x.ID == 1);
查询多条数据
var list = getPageListData.GetSinalData<YourModel, object>(x => x.IsDel == 1);
5.3 存储过程调用
调用存储过程返回列表
// 存储过程: Usp_GetYourData @param1, @param2
string procName = "Usp_GetYourData 1, 'test'";
var list = getPageListData.RunProc<YourResultModel, object>(procName);
调用存储过程返回单个值
string procName = "Usp_GetCount 1";
var count = getPageListData.RunProcs<YourModel, object>(procName);
5.4 原生SQL执行
使用SqlHelper执行SQL
using XTAPP.PublicDLL;
// 执行查询
string sql = "SELECT * FROM YourTable WHERE ID = @ID";
SqlParameter[] parameters = {
new SqlParameter("@ID", 1)
};
DataTable dt = SqlHelper.ExecuteDataTable(sql, parameters);
// 执行更新/删除/插入
string sql = "UPDATE YourTable SET Name = @Name WHERE ID = @ID";
SqlParameter[] parameters = {
new SqlParameter("@ID", 1),
new SqlParameter("@Name", "new name")
};
int result = SqlHelper.ExecuteNonQuery(sql, parameters);
使用GetPageListData执行SQL
// 更新操作
string sql = "UPDATE YourTable SET Name = 'test' WHERE ID = 1";
int result = getPageListData._UpdateStr<YourModel, object>(1, "YourTable", "Name='test'");
// 逻辑删除
int result = getPageListData._SqlDel<YourModel, object>(1, "YourTable");
5.5 事务处理
using System.Transactions;
using (var scope = new TransactionScope())
{
try
{
// 操作1
getPageListData.AddData<Model1, object>(model1);
// 操作2
getPageListData.AddData<Model2, object>(model2);
// 提交事务
scope.Complete();
}
catch (Exception ex)
{
// 事务自动回滚
throw ex;
}
}
6. 权限系统使用
6.1 权限系统架构
用户 (SysUser)
↓
用户角色关联 (SysUserRoles)
↓
角色 (SysRole)
↓
角色权限关联 (SysPermission)
↓
功能 (SysFunction)
↓
菜单 (SysMenu)
6.2 获取当前登录用户
// 在Controller中
var user = Session["UserInfo"] as SysUser;
if (user != null)
{
int userId = user.ID;
string userName = user.UserName;
string realName = user.RealName;
}
6.3 获取用户菜单
var user = Session["UserInfo"] as SysUser;
GetPageListData getPageListData = new GetPageListData();
// 调用存储过程获取菜单
var menuList = getPageListData.RunProc<SysMenu, object>(
$"Usp_GetPermissMenu {user.ID}");
6.4 检查用户权限
// 在Action中检查权限
var user = Session["UserInfo"] as SysUser;
GetPageListData getPageListData = new GetPageListData();
string controllerName = "YourController";
string actionName = "YourAction";
string procName = $"Usp_GetFunctionData {user.ID},'{controllerName}','{actionName}'";
var permission = getPageListData.RunProc<SysPermission, object>(procName);
if (permission == null || !permission.Any())
{
return Json(new { status = 3, msg = "您没有权限访问此操作" });
}
6.5 记录操作日志
var user = Session["UserInfo"] as SysUser;
GetPageListData getPageListData = new GetPageListData();
// 记录日志
getPageListData.Log(
"模块名称", // 模块
"操作类型", // 操作(增删改查)
"操作描述", // 内容
user.UserName // 用户名
);
7. 前端开发指南
7.1 前端技术栈
- LayUI: 主要UI框架
- jQuery: JavaScript库
- Knockout.js: MVVM框架 (部分页面使用)
7.2 LayUI使用
表格 (Table)
layui.use('table', function(){
var table = layui.table;
table.render({
elem: '#table',
url: '/Your/GetList',
cols: [[
{type: 'checkbox'},
{field: 'ID', title: 'ID', width: 80},
{field: 'Name', title: '名称'},
{title: '操作', toolbar: '#barDemo', width: 200}
]],
page: true,
limits: [10, 20, 50, 100],
limit: 10
});
// 监听工具条
table.on('tool(table)', function(obj){
var data = obj.data;
if(obj.event === 'edit'){
// 编辑
} else if(obj.event === 'del'){
// 删除
}
});
});
表单 (Form)
layui.use('form', function(){
var form = layui.form;
// 监听提交
form.on('submit(save)', function(data){
$.ajax({
url: '/Your/Save',
type: 'POST',
data: data.field,
success: function(res){
if(res.status == 0){
layer.msg('保存成功', {icon: 1});
} else {
layer.msg(res.msg, {icon: 2});
}
}
});
return false;
});
});
弹层 (Layer)
layui.use('layer', function(){
var layer = layui.layer;
// 提示
layer.msg('操作成功', {icon: 1});
// 确认框
layer.confirm('确定删除吗?', function(index){
// 执行删除
layer.close(index);
});
// 打开窗口
layer.open({
type: 2,
title: '编辑',
area: ['800px', '600px'],
content: '/Your/Add?id=1'
});
});
7.3 AJAX请求标准格式
请求格式
$.ajax({
url: '/Your/Action',
type: 'POST',
data: {
id: 1,
name: 'test'
},
dataType: 'json',
success: function(res){
if(res.status == 0){
// 成功
} else {
// 失败
layer.msg(res.msg, {icon: 2});
}
},
error: function(){
layer.msg('请求失败', {icon: 2});
}
});
响应格式
// Controller返回
return Json(new {
status = 0, // 0-成功, 1-失败
msg = "操作成功",
data = result // 数据(可选)
}, JsonRequestBehavior.AllowGet);
7.4 分页请求
// LayUI表格自动分页
table.render({
elem: '#table',
url: '/Your/GetList',
page: true,
// ...
});
// 后端接收参数
[HttpPost]
public JsonResult GetList()
{
int page = int.Parse(Request["page"] ?? "1");
int limit = int.Parse(Request["limit"] ?? "10");
// 计算
int pageIndex = page;
int pageSize = limit;
// 查询...
return Json(new {
code = 0,
msg = "成功",
count = totalCount,
data = list
});
}
8. 常见开发场景
8.1 添加新的业务模块
场景: 添加一个"供应商管理"模块
1. 创建数据库表
CREATE TABLE Supplier (
ID INT PRIMARY KEY IDENTITY(1,1),
Code NVARCHAR(50),
Name NVARCHAR(100),
Contact NVARCHAR(50),
Tel NVARCHAR(20),
IsDel INT DEFAULT 1,
CreateTime DATETIME DEFAULT GETDATE()
)
2. 创建Model
// Models/Supplier.cs
namespace XTAPP.Models
{
public class Supplier
{
public int ID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Contact { get; set; }
public string Tel { get; set; }
public int IsDel { get; set; }
public DateTime CreateTime { get; set; }
}
}
3. 创建Controller
// Controllers/SupplierController.cs
public class SupplierController : BaseController
{
GetPageListData getPageListData = new GetPageListData();
public ActionResult Index()
{
return View();
}
[HttpPost]
public JsonResult GetList()
{
// 实现列表查询
}
public ActionResult Add(int? id)
{
// 实现添加/编辑页面
}
[HttpPost]
public JsonResult Save(Supplier model)
{
// 实现保存
}
[HttpPost]
public JsonResult Delete(int id)
{
// 实现删除
}
}
4. 创建View
创建 Views/Supplier/Index.cshtml 和 Views/Supplier/Add.cshtml
8.2 添加新的报表功能
1. 创建报表存储过程
CREATE PROCEDURE Proc_GetSupplierReport
@StartDate DATETIME,
@EndDate DATETIME
AS
BEGIN
SELECT * FROM Supplier
WHERE CreateTime BETWEEN @StartDate AND @EndDate
AND IsDel = 1
END
2. 创建报表结果Model
// Models/Proc_GetSupplierReport_Result.cs
public class Proc_GetSupplierReport_Result
{
public int ID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
// ...
}
3. 创建报表Controller Action
[HttpPost]
public JsonResult GetReport(DateTime startDate, DateTime endDate)
{
string procName = $"Proc_GetSupplierReport '{startDate}', '{endDate}'";
var list = getPageListData.RunProc<Proc_GetSupplierReport_Result, object>(procName);
return Json(new { code = 0, data = list });
}
8.3 添加文件上传功能
1. 创建上传Action
[HttpPost]
public JsonResult UploadFile()
{
try
{
HttpPostedFileBase file = Request.Files[0];
if (file != null && file.ContentLength > 0)
{
string fileName = Path.GetFileName(file.FileName);
string path = Server.MapPath("~/UploadFile/");
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string filePath = Path.Combine(path, fileName);
file.SaveAs(filePath);
return Json(new {
status = 0,
msg = "上传成功",
url = "/UploadFile/" + fileName
});
}
return WriteError("文件为空");
}
catch (Exception ex)
{
return WriteError(ex.Message);
}
}
2. 前端上传
// 使用LayUI上传
layui.use('upload', function(){
var upload = layui.upload;
upload.render({
elem: '#uploadBtn',
url: '/Your/UploadFile',
done: function(res){
if(res.status == 0){
layer.msg('上传成功');
}
}
});
});
8.4 添加Excel导入导出
1. 导出Excel
[HttpPost]
public ActionResult ExportExcel()
{
// 查询数据
var list = getPageListData.GetSinalData<YourModel, object>(x => x.IsDel == 1);
// 使用NPOI或EPPlus生成Excel
// 返回File结果
return File(excelBytes, "application/vnd.ms-excel", "导出.xls");
}
2. 导入Excel
[HttpPost]
public JsonResult ImportExcel()
{
HttpPostedFileBase file = Request.Files[0];
// 读取Excel文件
// 解析数据
// 批量插入数据库
return WriteSuccess("导入成功");
}
9. 调试与部署
9.1 调试技巧
1. 使用断点
- 在代码行左侧点击设置断点
- 按F5启动调试
- 使用F10(单步跳过)和F11(单步进入)调试
2. 查看日志
- 日志文件位置:
log/年份/月份/日期.log - 使用log4net记录日志
3. 查看数据库
- 使用SQL Server Management Studio连接数据库
- 查看执行计划优化SQL
9.2 发布部署
1. 编译发布
1. 右键项目 -> 发布
2. 选择发布方式 (文件系统/IIS/FTP)
3. 配置发布设置
4. 发布
2. IIS部署
1. 在IIS中创建应用程序池 (.NET Framework 4.0)
2. 创建网站,指向发布目录
3. 设置端口和绑定
4. 配置Web.config连接字符串
5. 设置文件夹权限
3. 配置文件修改
发布后需要修改 Web.config:
- 数据库连接字符串
- 日志路径
- 其他配置项
10. 常见问题解决
10.1 编译错误
问题: 找不到类型或命名空间
解决:
- 检查using引用
- 检查项目引用
- 清理并重新生成解决方案
10.2 数据库连接错误
问题: 无法连接到数据库
解决:
- 检查连接字符串
- 检查SQL Server服务是否启动
- 检查防火墙设置
- 检查数据库用户权限
10.3 权限验证失败
问题: 提示"您没有权限访问此操作"
解决:
- 检查数据库中是否有对应权限记录
- 检查存储过程
Usp_GetFunctionData是否正确 - 使用
[SkipCheckPermiss]特性临时跳过验证
10.4 Session丢失
问题: 登录后Session丢失
解决:
- 检查Session超时设置 (Web.config中timeout)
- 检查IIS应用程序池回收设置
- 使用Cookie保存用户信息
10.5 EF模型更新
问题: 数据库表结构变化后EF模型未更新
解决:
- 右键
Models/XTAPP.edmx-> 从数据库更新模型 - 或删除edmx文件重新生成
10.6 前端页面不显示
问题: 页面样式或脚本未加载
解决:
- 检查静态资源路径
- 检查Bundle配置
- 检查浏览器控制台错误
附录
A. 常用代码片段
标准CRUD操作
// 列表查询
[HttpPost]
public JsonResult GetList()
{
int page = int.Parse(Request["page"] ?? "1");
int limit = int.Parse(Request["limit"] ?? "10");
int pageIndex = page;
int pageSize = limit;
Func<YourModel, bool> where = x => x.IsDel == 1;
Func<YourModel, int> order = x => x.ID;
int totalCount;
var list = getPageListData.GetPageList<YourModel, int>(
pageIndex, pageSize, out totalCount, where, order);
return Json(new { code = 0, msg = "成功", count = totalCount, data = list });
}
// 保存
[HttpPost]
public JsonResult Save(YourModel model)
{
try
{
var user = Session["UserInfo"] as SysUser;
if (model.ID > 0)
{
getPageListData.UpdateData<YourModel, object>(model);
getPageListData.Log("模块", "修改", $"修改了ID为{model.ID}的记录", user.UserName);
}
else
{
model.CreateTime = DateTime.Now;
getPageListData.AddData<YourModel, object>(model);
getPageListData.Log("模块", "新增", "新增了一条记录", user.UserName);
}
return WriteSuccess("保存成功");
}
catch (Exception ex)
{
return WriteError(ex.Message);
}
}
// 删除
[HttpPost]
public JsonResult Delete(int id)
{
try
{
var user = Session["UserInfo"] as SysUser;
getPageListData._SqlDel<YourModel, object>(id, "YourTable");
getPageListData.Log("模块", "删除", $"删除了ID为{id}的记录", user.UserName);
return WriteSuccess("删除成功");
}
catch (Exception ex)
{
return WriteError(ex.Message);
}
}
B. 数据库表结构说明
核心表
- SysUser: 用户表
- SysRole: 角色表
- SysMenu: 菜单表
- SysFunction: 功能表
- SysPermission: 权限表
业务表
- DeliveryPlan: 配送计划主表
- DeliveryPlan_Details: 配送计划明细表
- Storehouse: 仓库表
- Goods: 商品表
- Client: 客户表
C. 重要存储过程
- Usp_GetPermissMenu: 获取用户菜单
- Usp_GetFunctionData: 检查用户权限
- ProcEcharts_InOutStore: 获取出入库统计
D. 开发规范
-
命名规范:
- 控制器:
XxxController - 模型:
Xxx或Xxx_Result - 视图: 与Action同名
- 控制器:
-
代码规范:
- 使用中文注释
- 异常必须捕获并记录
- 重要操作必须记录日志
-
数据库规范:
- 表必须有
ID主键 - 表必须有
IsDel字段 (逻辑删除) - 表建议有
CreateTime字段
- 表必须有
总结
本指南涵盖了XTAPP项目二次开发的所有核心内容。在开发过程中:
- 遵循MVC模式: 保持代码结构清晰
- 使用统一的数据访问层: 使用GetPageListData进行数据库操作
- 注意权限控制: 确保新功能正确配置权限
- 记录操作日志: 重要操作都要记录日志
- 异常处理: 所有可能出错的地方都要try-catch
- 代码注释: 关键逻辑要有中文注释
如有问题,请参考现有代码实现或联系项目维护人员。
文档版本: 1.0
最后更新: 2025年
维护者: 开发团队
1万+

被折叠的 条评论
为什么被折叠?



