using System;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.Configuration;
namespace WebApplication1
{
public partial class WebForm3 : System.Web.UI.Page
{
private int currentProductId;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (!ValidateRequestParameters())
{
Response.Redirect("~/Default.aspx");
return;
}
LoadProductDetails(currentProductId);
LoadRelatedProducts(currentProductId);
LogPageVisit(currentProductId);
}
}
/// <summary>
/// 验证请求参数并获取商品ID
/// </summary>
private bool ValidateRequestParameters()
{
if (!int.TryParse(Request.QueryString["id"], out currentProductId))
{
ShowErrorMessage("无效的商品ID参数");
return false;
}
if (currentProductId <= 0)
{
ShowErrorMessage("商品ID必须为正整数");
return false;
}
return true;
}
/// <summary>
/// 加载商品详情
/// </summary>
private void LoadProductDetails(int productId)
{
string connString = GetConnectionString();
if (string.IsNullOrEmpty(connString))
{
ShowErrorMessage("数据库连接配置错误");
return;
}
try
{
using (var conn = new SqlConnection(connString))
{
// 获取商品基本信息和图片
string query = @"
SELECT
p.ProductID, p.ProductName, p.Subtitle, p.Description, p.Price,
p.DiscountPrice, p.StockQuantity, p.CategoryID, p.Rating, p.ReviewCount,
c.CategoryName,
pi.ImagePath,
STRING_AGG(pv.VariantName, ', ') AS AvailableVariants
FROM Products p
INNER JOIN Categories c ON p.CategoryID = c.CategoryID
LEFT JOIN ProductImages pi ON p.ProductID = pi.ProductID AND pi.IsDefault = 1
LEFT JOIN ProductVariants pv ON p.ProductID = pv.ProductID
WHERE p.ProductID = @ProductID
GROUP BY
p.ProductID, p.ProductName, p.Subtitle, p.Description, p.Price,
p.DiscountPrice, p.StockQuantity, p.CategoryID, p.Rating, p.ReviewCount,
c.CategoryName, pi.ImagePath";
using (var cmd = new SqlCommand(query, conn))
{
cmd.Parameters.AddWithValue("@ProductID", productId);
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
DisplayProductDetails(reader);
productContainer.Visible = true;
}
else
{
ShowErrorMessage("找不到指定的商品");
}
}
}
}
}
catch (SqlException sqlEx)
{
LogError($"SQL错误: {sqlEx.Message}", sqlEx);
ShowErrorMessage("数据库连接错误,请稍后再试");
}
catch (Exception ex)
{
LogError($"加载商品信息失败: {ex.Message}", ex);
ShowErrorMessage("加载商品信息时出错");
}
}
/// <summary>
/// 显示商品详情到页面控件
/// </summary>
private void DisplayProductDetails(SqlDataReader reader)
{
// 基本信息
ltProductName.Text = HttpUtility.HtmlEncode(reader["ProductName"].ToString());
ltSubtitle.Text = HttpUtility.HtmlEncode(reader["Subtitle"].ToString());
ltCategory.Text = HttpUtility.HtmlEncode(reader["CategoryName"].ToString());
// 价格
decimal price = Convert.ToDecimal(reader["Price"]);
ltPrice.Text = price.ToString("C");
if (!Convert.IsDBNull(reader["DiscountPrice"]) && price > Convert.ToDecimal(reader["DiscountPrice"]))
{
ltDiscountPrice.Text = Convert.ToDecimal(reader["DiscountPrice"]).ToString("C");
}
// 库存
int stock = Convert.ToInt32(reader["StockQuantity"]);
ltStock.Text = stock.ToString();
ltStockStatus.Text = stock > 0 ? "<span class='text-success'><i class='bi bi-check-circle'></i>有货</span>" :
"<span class='text-danger'><i class='bi bi-x-circle'></i>缺货</span>";
// 评分
decimal rating = Convert.ToDecimal(reader["Rating"]);
ltRating.Text = GenerateRatingStars(rating);
ltReviewCount.Text = reader["ReviewCount"].ToString();
// 图片
string imagePath = reader["ImagePath"]?.ToString() ?? "";
imgProduct.ImageUrl = !string.IsNullOrEmpty(imagePath) ? imagePath : "~/Images/default-product.jpg";
// 描述
ltDescription.Text = HttpUtility.HtmlEncode(reader["Description"].ToString());
// 商品型号
if (!reader.IsDBNull(reader.GetOrdinal("AvailableVariants")))
{
ltAvailableVariants.Text = reader["AvailableVariants"].ToString();
}
}
/// <summary>
/// 生成评分星星HTML
/// </summary>
private string GenerateRatingStars(decimal rating)
{
int fullStars = (int)rating;
bool hasHalfStar = (rating - fullStars) >= 0.5M;
int emptyStars = 5 - fullStars - (hasHalfStar ? 1 : 0);
return $@"
{string.Concat(Enumerable.Repeat("<i class='bi bi-star-fill text-warning'></i>", fullStars))}
{(hasHalfStar ? "<i class='bi bi-star-half text-warning'></i>" : "")}
{string.Concat(Enumerable.Repeat("<i class='bi bi-star text-warning'></i>", emptyStars))}
<span class='ms-2'>{rating:F1}</span>";
}
/// <summary>
/// 加载相关商品
/// </summary>
private void LoadRelatedProducts(int productId)
{
string connString = GetConnectionString();
if (string.IsNullOrEmpty(connString)) return;
try
{
using (var conn = new SqlConnection(connString))
{
// 获取同类别的前4个相关商品
string query = @"
SELECT TOP 4 p.ProductID, p.ProductName, p.Price, pi.ImagePath
FROM Products p
INNER JOIN Categories c ON p.CategoryID = c.CategoryID
CROSS APPLY (
SELECT TOP 1 ImagePath
FROM ProductImages
WHERE ProductID = p.ProductID
ORDER BY IsDefault DESC
) pi
WHERE p.CategoryID = (
SELECT CategoryID FROM Products WHERE ProductID = @ProductID
)
AND p.ProductID <> @ProductID
ORDER BY NEWID()";
using (var cmd = new SqlCommand(query, conn))
{
cmd.Parameters.AddWithValue("@ProductID", productId);
conn.Open();
rptRelatedProducts.DataSource = cmd.ExecuteReader();
rptRelatedProducts.DataBind();
}
}
}
catch (Exception ex)
{
LogError($"加载相关商品失败: {ex.Message}", ex);
}
}
/// <summary>
/// 添加到购物车按钮点击事件
/// </summary>
protected void btnAddToCart_Click(object sender, EventArgs e)
{
if (!ValidateRequestParameters()) return;
try
{
// 获取用户选择的型号
string variant = Request.Form["product_variant"];
// 获取数量
int quantity;
if (!int.TryParse(txtQuantity.Value, out quantity) || quantity < 1)
{
quantity = 1;
}
// 添加到购物车
Cart cart = GetOrCreateCart();
cart.AddItem(currentProductId, quantity, variant);
// 更新购物车数量显示
UpdateCartBadge(cart.TotalItems);
// 显示成功消息
ClientScript.RegisterStartupScript(GetType(), "AddToCartSuccess",
"showToast('success', '商品已添加到购物车!');", true);
}
catch (Exception ex)
{
LogError($"添加到购物车失败: {ex.Message}", ex);
ClientScript.RegisterStartupScript(GetType(), "AddToCartError",
"showToast('error', '添加到购物车失败,请重试');", true);
}
}
/// <summary>
/// 记录页面访问
/// </summary>
private void LogPageVisit(int productId)
{
try
{
string connString = GetConnectionString();
using (var conn = new SqlConnection(connString))
{
string query = @"
INSERT INTO ProductVisits (ProductID, UserIP, VisitDate)
VALUES (@ProductID, @UserIP, GETDATE())";
using (var cmd = new SqlCommand(query, conn))
{
cmd.Parameters.AddWithValue("@ProductID", productId);
cmd.Parameters.AddWithValue("@UserIP", GetUserIP());
conn.Open();
cmd.ExecuteNonQuery();
}
}
}
catch
{
// 访问日志记录失败不影响主流程
}
}
/// <summary>
/// 获取或创建用户购物车
/// </summary>
private Cart GetOrCreateCart()
{
Cart cart = Session["ShoppingCart"] as Cart;
if (cart == null)
{
cart = new Cart();
Session["ShoppingCart"] = cart;
}
return cart;
}
/// <summary>
/// 更新页面购物车徽章显示
/// </summary>
private void UpdateCartBadge(int count)
{
// 查找母版页中的购物车徽章
var cartBadge = Master?.FindControl("cartBadge") as System.Web.UI.HtmlControls.HtmlGenericControl;
if (cartBadge != null)
{
cartBadge.InnerText = count.ToString();
cartBadge.Visible = count > 0;
}
}
/// <summary>
/// 获取数据库连接字符串
/// </summary>
private string GetConnectionString()
{
return WebConfigurationManager.ConnectionStrings["DB-NetShopsConnectionString"]?.ConnectionString;
}
/// <summary>
/// 获取用户IP地址
/// </summary>
private string GetUserIP()
{
string ip = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(ip))
{
ip = Request.ServerVariables["REMOTE_ADDR"];
}
else
{
string[] addresses = ip.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}
return ip;
}
/// <summary>
/// 显示错误消息
/// </summary>
private void ShowErrorMessage(string message)
{
if (ltErrorMessage != null)
{
ltErrorMessage.Text = $"<div class='alert alert-danger'>{HttpUtility.HtmlEncode(message)}</div>";
ltErrorMessage.Visible = true;
productContainer.Visible = false;
}
}
/// <summary>
/// 记录错误日志
/// </summary>
private void LogError(string message, Exception ex)
{
// 实际项目中应使用日志框架(如log4net/NLog)
System.Diagnostics.Debug.WriteLine($"{message}\n{ex}");
// 也可以保存到数据库或文件
try
{
string logMessage = $"[{DateTime.Now}] {message}\nException: {ex}\n\n";
System.IO.File.AppendAllText(Server.MapPath("~/App_Data/error.log"), logMessage);
}
catch
{
// 文件记录失败时不中断
}
}
}
/// <summary>
/// 购物车项
/// </summary>
public class CartItem
{
public int ProductId { get; set; }
public int Quantity { get; set; }
public string Variant { get; set; }
public DateTime AddedTime { get; set; } = DateTime.Now;
}
/// <summary>
/// 购物车类
/// </summary>
public class Cart
{
public List<CartItem> Items { get; } = new List<CartItem>();
public int TotalItems => Items.Sum(item => item.Quantity);
public decimal TotalPrice
{
get
{
// 实际项目中应从数据库获取当前价格
return 0; // 简化为0
}
}
/// <summary>
/// 添加商品到购物车
/// </summary>
public void AddItem(int productId, int quantity, string variant = "")
{
var existingItem = Items.FirstOrDefault(i =>
i.ProductId == productId && i.Variant == variant);
if (existingItem != null)
{
existingItem.Quantity += quantity;
}
else
{
Items.Add(new CartItem
{
ProductId = productId,
Quantity = quantity,
Variant = variant
});
}
}
/// <summary>
/// 从购物车移除商品
/// </summary>
public void RemoveItem(int productId, string variant = "")
{
var itemToRemove = Items.FirstOrDefault(i =>
i.ProductId == productId && i.Variant == variant);
if (itemToRemove != null)
{
Items.Remove(itemToRemove);
}
}
/// <summary>
/// 清空购物车
/// </summary>
public void Clear()
{
Items.Clear();
}
}
}
根据后端代码更新数据库代码,使网页能够正常运行
最新发布