wms(BS版本)二开指南

XTAPP 二次开发完整指南

版本: 1.0
适用项目: XTAPP 仓储管理系统
技术栈: ASP.NET MVC 4 + Entity Framework 5.0 + SQL Server


📋 目录

  1. 项目架构详解
  2. 开发环境搭建
  3. 核心开发模式
  4. 如何添加新功能
  5. 数据库操作详解
  6. 权限系统使用
  7. 前端开发指南
  8. 常见开发场景
  9. 调试与部署
  10. 常见问题解决

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 必需软件

  1. Visual Studio 2015 或更高版本

    • 推荐: Visual Studio 2017/2019
    • 必需组件: .NET Framework 4.7.2 SDK
  2. SQL Server

    • 版本: SQL Server 2008 或更高
    • 数据库名: MPWMS
  3. 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=&quot;data source=.;initial catalog=MPWMS;user id=sa;password=your_password;MultipleActiveResultSets=True;App=EntityFramework&quot;" 
       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=&quot;data source=.;initial catalog=MPWMS;user id=sa;password=your_password;multipleactiveresultsets=True;application name=EntityFramework&quot;" 
       providerName="System.Data.EntityClient" />
</connectionStrings>
步骤3: 还原NuGet包
# 在Visual Studio中
右键解决方案 -> 还原NuGet包
步骤4: 编译项目
# 快捷键: Ctrl+Shift+B
# 或菜单: 生成 -> 生成解决方案

2.3 运行项目

方式1: IIS Express (推荐)
# 按F5启动调试
# 或点击"运行"按钮
方式2: 本地IIS
  1. 在IIS中创建应用程序池(.NET Framework 4.0)
  2. 创建网站,指向项目目录
  3. 设置端口和绑定

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 中注册了两个全局过滤器:

  1. CheckLoginAttribute: 登录验证
  2. CheckPermissAttrbute: 权限验证
跳过验证

如果某个Action不需要验证,使用特性:

using XTAPP.WebHelp.Attri;

[SkipCkeckLogin]      // 跳过登录验证
[SkipCheckPermiss]    // 跳过权限验证
public ActionResult PublicAction()
{
    return View();
}
权限验证原理
  1. 获取当前用户ID
  2. 获取控制器名称和Action名称
  3. 调用存储过程 Usp_GetFunctionData 检查权限
  4. 如果没有权限,返回无权限页面或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: 配置菜单权限
  1. 在数据库中添加菜单记录 (SysMenu 表)
  2. 在数据库中添加功能权限记录 (SysFunction 表)
  3. 为用户分配权限

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.cshtmlViews/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 编译错误

问题: 找不到类型或命名空间

解决:

  1. 检查using引用
  2. 检查项目引用
  3. 清理并重新生成解决方案

10.2 数据库连接错误

问题: 无法连接到数据库

解决:

  1. 检查连接字符串
  2. 检查SQL Server服务是否启动
  3. 检查防火墙设置
  4. 检查数据库用户权限

10.3 权限验证失败

问题: 提示"您没有权限访问此操作"

解决:

  1. 检查数据库中是否有对应权限记录
  2. 检查存储过程 Usp_GetFunctionData 是否正确
  3. 使用 [SkipCheckPermiss] 特性临时跳过验证

10.4 Session丢失

问题: 登录后Session丢失

解决:

  1. 检查Session超时设置 (Web.config中timeout)
  2. 检查IIS应用程序池回收设置
  3. 使用Cookie保存用户信息

10.5 EF模型更新

问题: 数据库表结构变化后EF模型未更新

解决:

  1. 右键 Models/XTAPP.edmx -> 从数据库更新模型
  2. 或删除edmx文件重新生成

10.6 前端页面不显示

问题: 页面样式或脚本未加载

解决:

  1. 检查静态资源路径
  2. 检查Bundle配置
  3. 检查浏览器控制台错误

附录

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. 开发规范

  1. 命名规范:

    • 控制器: XxxController
    • 模型: XxxXxx_Result
    • 视图: 与Action同名
  2. 代码规范:

    • 使用中文注释
    • 异常必须捕获并记录
    • 重要操作必须记录日志
  3. 数据库规范:

    • 表必须有 ID 主键
    • 表必须有 IsDel 字段 (逻辑删除)
    • 表建议有 CreateTime 字段

总结

本指南涵盖了XTAPP项目二次开发的所有核心内容。在开发过程中:

  1. 遵循MVC模式: 保持代码结构清晰
  2. 使用统一的数据访问层: 使用GetPageListData进行数据库操作
  3. 注意权限控制: 确保新功能正确配置权限
  4. 记录操作日志: 重要操作都要记录日志
  5. 异常处理: 所有可能出错的地方都要try-catch
  6. 代码注释: 关键逻辑要有中文注释

如有问题,请参考现有代码实现或联系项目维护人员。


文档版本: 1.0
最后更新: 2025年
维护者: 开发团队

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值