Преглед на файлове

添加了菜单中的类型选择以及商品点击后的sku列表
暂时还没做排序以及相关功能

gujiheimao преди 1 година
родител
ревизия
131a7e8db9

+ 1 - 0
data/domain/DoMain.go

@@ -146,6 +146,7 @@ type Goods struct {
 	Id             int64  `xorm:"id" json:"id"`                          //注释:id
 	TypeId         int64  `xorm:"type_id" json:"typeId"`                 //注释:分类id
 	GoodsName      string `xorm:"goods_name" json:"goodsName"`           //注释:商品名字
+	ImageUrl       string `xorm:"image_url" json:"imageUrl"`             //注释:商品图标
 	IntroductionId int64  `xorm:"introduction_id" json:"introductionId"` //注释:商品介绍id
 	SalesVolume    int64  `xorm:"sales_volume" json:"salesVolume"`       //注释:近30天销量
 	TagIds         string `xorm:"tag_ids" json:"tagIds"`                 //注释:商品标签

+ 1 - 0
data/domain/Query.go

@@ -105,6 +105,7 @@ type GoodsQuery struct {
 	Id               int64  `xorm:"id"  json:"id"`                          // id
 	TypeId           int64  `xorm:"type_id"  json:"typeId"`                 // 分类id
 	GoodsName        string `xorm:"goods_name"  json:"goodsName"`           // 商品名字
+	ImageUrl         string `xorm:"image_url"  json:"imageUrl"`             // 商品名字
 	IntroductionId   int64  `xorm:"introduction_id"  json:"introductionId"` // 商品介绍id
 	SalesVolumeStart int64  `xorm:"sales_volume"  json:"salesVolume"`       // 近30天销量
 	SalesVolumeEnd   int64  `xorm:"sales_volume"  json:"salesVolume"`       // 近30天销量

+ 7 - 0
data/domain/vo/CategoryGoodsVo.go

@@ -0,0 +1,7 @@
+package vo
+
+type CategoryGoodsVo struct {
+	Id        int64  `json:"id"`
+	GoodsName string `json:"name"`
+	Image     string `json:"image"`
+}

BIN
file/resources/20241011200200yqOp-fynnnsc8452611.jpg


+ 228 - 6
file/resources/css/category.css

@@ -1,23 +1,245 @@
-*{
+* {
     font-family: -apple-system, blinkmacsystemfont, "Helvetica Neue", helvetica, segoe ui, arial, roboto, "PingFang SC", "miui", "Hiragino Sans GB", "Microsoft Yahei", sans-serif;
 }
 
-.category-page{
+.category-page {
     display: flex;
     align-items: start;
 }
-.category-page-menu{
+
+.category-page-menu {
     min-width: calc(100% / 5 + 2.02666666vw);
     width: calc(100% / 5 + 2.02666666vw);
-    height: calc(100VH - 15.666VW - 60px);
+    min-height: calc(100VH - 15.666VW - 60px);
+    height: 100%;
+    display: block;
     background-color: #f0f0f0;
 }
-.category-menu-item{
+
+.category-menu-item {
     width: 100%;
     height: calc(10VH - 1.5666VW - 6px);
     line-height: calc(10VH - 1.5666VW - 6px);
     text-align: center;
 }
-.category-menu-item-select{
+
+.category-menu-item-select {
     background-color: white;
+}
+
+.category-page-body {
+    display: grid;
+    grid-template-columns: repeat(3, 24VW );
+    gap: 10px;
+}
+
+.category-page-body .category-page-item {
+    padding: 10px;
+    display: flex;
+    flex-direction: column;
+    justify-content: start;
+
+}
+
+.category-page-body .category-page-item .category-page-item-image {
+    width: calc(24VW - 20px);
+    height: calc(24VW - 20px);
+    border-radius: calc(5VW - 4px);
+}
+
+.category-page-body .category-page-item .category-page-item-image img {
+    border-radius: inherit;
+    width: 100%;
+    height: 100%;
+}
+
+.category-page-body .category-page-item .category-page-item-name {
+    margin-top: calc(1.6VW);
+    font-weight: bold;
+    line-height: 1.5;
+
+    display: -webkit-box; /* 创建弹性盒子模型 */
+    -webkit-box-orient: vertical; /* 垂直排列子元素 */
+    overflow: hidden; /* 隐藏溢出的内容 */
+    text-overflow: ellipsis; /* 溢出的部分显示省略号 */
+    -webkit-line-clamp: 3; /* 限制显示的行数,这里限制为3行 */
+    max-height: calc(1.5em * 3); /* 计算出元素的最大高度(行高乘以行数) */
+}
+
+.category-page-goods-detail {
+    position: fixed;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    width: 100VW;
+    height: 100VH;
+    display: block;
+    background-color: white;
+    z-index: 12;
+}
+
+.category-page-goods-detail .category-goods-detail-header {
+    width: 100VW;
+    height: 13VW;
+    background-color: #dddddd;
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+}
+
+.category-page-goods-detail .category-goods-detail-header-interval {
+    height: 13VW;
+}
+
+.category-page-goods-detail .category-goods-detail-header .header-return {
+    width: 6VW;
+    height: 6VW;
+    position: fixed;
+    font-size: 24px;
+    line-height: 6VW;
+    text-align: center;
+    color: #666666;
+    padding: 2VW;
+    margin: 1.5VW;
+    border-radius: 50%;
+    user-select: none;
+
+}
+
+.category-page-goods-detail .category-goods-detail-header .header-return::after {
+    content: "<";
+}
+
+.category-page-goods-detail .category-goods-detail-header .header-title {
+    height: 6VW;
+    font-size: 1.6em;
+    line-height: 6VW;
+    text-align: center;
+    color: #666666;
+    padding: 0 15VW;
+    margin: 3.5VW 1.5VW;
+    border-radius: 50%;
+    user-select: none;
+
+
+    display: -webkit-box; /* 创建弹性盒子模型 */
+    -webkit-box-orient: vertical; /* 垂直排列子元素 */
+    overflow: hidden; /* 隐藏溢出的内容 */
+    text-overflow: ellipsis; /* 溢出的部分显示省略号 */
+    -webkit-line-clamp: 1; /* 限制显示的行数,这里限制为3行 */
+    max-height: calc(1.5em * 3); /* 计算出元素的最大高度(行高乘以行数) */
+}
+
+.category-page-goods-detail .category-goods-detail-handler {
+    margin: 3VW 0 6VW;
+    height: 7VW;
+    line-height: 7VW;
+    width: calc(100% - 8VW);
+    display: flex;
+    padding: 0 4VW;
+    justify-content: space-evenly;
+
+}
+
+.category-page-goods-detail .category-goods-detail-handler .cgdh-tab-item {
+    background-color: #f0f0f0;
+    padding: 0 2.6VW;
+    font-size: 3.4VW;
+    color: #444444;
+    border-radius: 1.1VW;
+}
+
+.category-page-goods-detail .category-goods-detail-handler .cgdh-tab-item-selected {
+    /*反色*/
+    /*filter: invert(0.9);*/
+    background-color: #444444;
+    color: #f0f0f0;
+
+}
+
+.category-page-goods-detail .category-goods-detail-skus {
+    display: flex;
+    flex-direction: column;
+    align-items: start;
+
+}
+
+.category-page-goods-detail .category-goods-detail-skus .category-goods-detail-sku {
+    margin: 0 auto 5.2VW;
+    display: flex;
+    width: 92VW;
+}
+
+.category-page-goods-detail .category-goods-detail-skus .cgds-left-img {
+    display: flex;
+    width: 22VW;
+    height: 29.5VW;
+    border-radius: 1.1VW;
+    background-color: #444444;
+    flex-direction: column;
+    align-items: start;
+    margin-right: 3.2VW;
+}
+
+.category-page-goods-detail .category-goods-detail-skus .cgds-left-img img {
+    width: 100%;
+    height: 100%;
+    border-radius: inherit;
+    box-shadow: #444444 0 0 5px;
+}
+
+.category-page-goods-detail .category-goods-detail-skus .cgds-right-detail {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+
+
+}
+
+.category-goods-detail-sku .cgds-right-detail .cgds-right-detail-name {
+    color: #1a1a1a;
+    font-size: 4VW;
+    font-weight: bold;
+    line-height: 5.05VW;
+}
+
+.category-goods-detail-sku .cgds-right-detail .cgds-right-detail-salesnum {
+    font-size: 3.5VW;
+    color: #aaaaaa;
+    font-weight: bold;
+    height: 14.4VW;
+}
+
+.category-goods-detail-sku .cgds-right-detail .cgds-right-detail-price {
+    height: 6.4VW;
+    line-height: 6.4VW;
+    display: flex;
+    font-size: 4.3VW;
+    font-weight: bold;
+}
+
+.category-goods-detail-sku .cgds-right-detail .cgds-right-detail-price .cgds-right-detail-price-now {
+    color: #ea0000;
+    font-size: 4.3VW;
+    font-weight: bold;
+}
+
+.category-goods-detail-sku .cgds-right-detail .cgds-right-detail-price .cgds-right-detail-price-now::before {
+    content: "¥";
+}
+
+.category-goods-detail-sku .cgds-right-detail .cgds-right-detail-price .cgds-right-detail-price-history {
+    display: flex;
+    color: #aaaaaa;
+    font-size: 3.2VW;
+    font-weight: bold;
+    /*    删除线*/
+    text-decoration: line-through;
+    padding: 0 10px;
+}
+
+.category-goods-detail-sku .cgds-right-detail .cgds-right-detail-price .cgds-right-detail-price-history::before {
+    content: "¥";
 }

+ 1 - 2
file/resources/css/index.css

@@ -124,7 +124,7 @@
     }
 
     .footer-interval {
-        height: 40px;
+        height: calc(5.666VW + 16px + 1em);
     }
 
     .footer-bar {
@@ -152,7 +152,6 @@
         padding: 0 10px;
         border-radius: 5px;
         background-color: rgba(0, 0, 0, 0);
-
     }
 
     .footer-item-img {

BIN
file/resources/image/20240816235846yqOp-fynnnsc8452611.jpg


BIN
file/resources/image/20240816235931Icon.png


BIN
file/resources/image/def_image.png


BIN
file/resources/video/20240816235856卡拉彼丘 2023-12-22 18-07-49.mp4


+ 255 - 3
file/static/category.html

@@ -16,12 +16,52 @@
         <div class="category-menu-item" data-value="{{$menu.id}}">{{$menu.typeName}}</div>
         {{- end}}
     </div>
-    <div class="category-page-body">{{.menus}}</div>
+    <div class="category-page-body" id="category-page-body">
+        <div class="category-page-item" data-value="1">
+            <div class="category-page-item-image">
+                <img src="" alt="">
+            </div>
+            <div class="category-page-item-name"></div>
+        </div>
+    </div>
+</div>
+<!--商品详情-->
+<div class="category-page-goods-detail" id="category-page-goods-detail" style="display: none">
+    <div class="category-goods-detail-header">
+        <div class="header-return" id="category-goods-detail-header-return"></div>
+        <div class="header-title">一个朴实无华的标题 一个朴实无华的标题一个朴实无华的标题</div>
+    </div>
+    <div class="category-goods-detail-header-interval"></div>
+    <div class="category-goods-detail-handler">
+        <div class="cgdh-tab-item cgdh-tab-item-selected">按销量由高到低</div>
+        <div class="cgdh-tab-item">按价格由高到低</div>
+        <div class="cgdh-tab-item">按价格由低到高</div>
+    </div>
+    <div class="category-goods-detail-skus" id="category-goods-detail-skus">
+        <div class="category-goods-detail-sku">
+            <div class="cgds-left-img">
+                <img src=""/>
+            </div>
+            <div class="cgds-right-detail">
+                <div class="cgds-right-detail-name">steam充值卡</div>
+                <div class="cgds-right-detail-salesnum">销量:233</div>
+                <div class="cgds-right-detail-price">
+                    <div class="cgds-right-detail-price-now">2199</div>
+                    <div class="cgds-right-detail-price-history">2666</div>
+                </div>
+            </div>
+        </div>
+    </div>
 </div>
 {{template "FooterBar.tmpl" .}}
 </body>
 <script>
     let categoryMenuItems = document.getElementsByClassName("category-menu-item")
+    let cpd = document.getElementById("category-page-body");
+    let cpgd = document.getElementById("category-page-goods-detail");
+    let categoryData = null
+    let categoryGoodsData = null
+    let nowGoodsId = null
     for (let i = 0; i < categoryMenuItems.length; i++) {
         let item = categoryMenuItems[i]
 
@@ -34,12 +74,224 @@
             }
             this.className = "category-menu-item category-menu-item-select"
             var newUrl = window.location.origin + '/category/';
-            history.pushState(null, null, newUrl + "666");
+            history.pushState(null, null, newUrl + item.dataset.value);
+            postCategoryData(item.dataset.value, 1, 30)
+
         })
-        if (i === 0){
+        if (i === 0) {
             item.click()
         }
     }
 
+    function showOrNoneCPGD() {
+        if (cpgd.style.display) {
+            cpgd.style.display = ""
+            cpd.style.display = "none"
+            getSkuList()
+        } else {
+            cpgd.style.display = "none"
+            cpd.style.display = ""
+            var newUrl = window.location + '/' + nowGoodsId;
+            let number = newUrl.lastIndexOf('/');
+            newUrl = newUrl.substring(0, number)
+            history.pushState(null, null, newUrl);
+        }
+    }
+
+    function getSkuList() {
+        var newUrl = window.location + '/' + nowGoodsId;
+        history.pushState(null, null, newUrl);
+        postCategoryGoodsData(nowGoodsId)
+    }
+
+    document.getElementById("category-goods-detail-header-return").addEventListener("click", function () {
+        showOrNoneCPGD()
+    })
+
+    function postCategoryData(typeId, pageNum, pageSize) {
+        // 创建 XMLHttpRequest 对象
+        var xhr = new XMLHttpRequest();
+
+        // 设置请求方法和 URL
+        xhr.open("POST", "/category", true);
+
+        // 设置请求头,告知服务器数据的类型为 JSON
+        xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
+        // 定义请求完成后的回调函数
+        xhr.onreadystatechange = function () {
+            // 检查请求是否完成且成功
+            if (xhr.readyState === 4 && xhr.status === 200) {
+                try {
+                    // 解析服务器返回的 JSON 数据
+                    var response = JSON.parse(xhr.responseText);
+                    categoryData = response.data
+                    // 在此处理返回的数据对象
+                    addItemsToPage(categoryData)
+                } catch (e) {
+                    console.error("解析响应时出错:", e);
+                }
+            }
+        };
+
+        // 创建请求发送的数据对象
+        var data = {
+            typeId: typeId,
+            pageNum: pageNum,
+            pageSize: pageSize
+        };
+
+        // 将数据对象转换为 JSON 字符串并发送
+        xhr.send(JSON.stringify(data));
+    }
+
+    function postCategoryGoodsData(goodsId) {
+        // 创建 XMLHttpRequest 对象
+        var xhr = new XMLHttpRequest();
+
+        // 设置请求方法和 URL
+        xhr.open("POST", "/category/goods", true);
+
+        // 设置请求头,告知服务器数据的类型为 JSON
+        xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
+        // 定义请求完成后的回调函数
+        xhr.onreadystatechange = function () {
+            // 检查请求是否完成且成功
+            if (xhr.readyState === 4 && xhr.status === 200) {
+                try {
+                    // 解析服务器返回的 JSON 数据
+                    var response = JSON.parse(xhr.responseText);
+                    categoryGoodsData = response.data
+                    console.log(categoryGoodsData)
+                    generateGoodsStructure(categoryGoodsData)
+                    // 在此处理返回的数据对象
+                } catch (e) {
+                    console.error("解析响应时出错:", e);
+                }
+            }
+        };
+
+        // 创建请求发送的数据对象
+        var data = {
+            goodsId: goodsId,
+        };
+
+        // 将数据对象转换为 JSON 字符串并发送
+        xhr.send(JSON.stringify(data));
+    }
+
+    // 这个函数用于生成 HTML 结构并添加到页面中
+    function addItemsToPage() {
+        // 选择页面中 class 为 "first" 的 div
+        let container = document.getElementById("category-page-body")
+        container.innerHTML = ""
+        if (!container) {
+            console.error("未找到 .first 容器");
+            return;
+        }
+        console.log(categoryData)
+        for (let i = 0; i < categoryData.list.length; i++) {
+            let item = categoryData.list[i]
+            // 创建外层 div
+            var itemDiv = document.createElement("div");
+            itemDiv.classList.add("category-page-item");
+            itemDiv.setAttribute("data-value", item.id);
+
+            // 创建图片 div,并设置背景图(如果有)
+            var imageDiv = document.createElement("div");
+            imageDiv.classList.add("category-page-item-image");
+            let img = document.createElement("img");
+            if (item.image) {
+                img.src = item.image
+            } else {
+                img.src = "/api/static/image/def_image.png"
+            }
+            imageDiv.appendChild(img)
+
+            // 创建名称 div,并设置文本
+            var nameDiv = document.createElement("div");
+            nameDiv.classList.add("category-page-item-name");
+            nameDiv.textContent = item.name;
+
+            itemDiv.addEventListener("click", function () {
+                nowGoodsId = item.id
+                showOrNoneCPGD()
+            })
+
+            // 将图片和名称 div 添加到外层 div
+            itemDiv.appendChild(imageDiv);
+            itemDiv.appendChild(nameDiv);
+
+            // 将生成的 item div 添加到 .first 容器中
+            container.appendChild(itemDiv);
+        }
+    }
+
+    function generateGoodsStructure(data) {
+        const container = document.getElementById('category-goods-detail-skus');
+
+        // 清空容器,确保不会重复添加
+        container.innerHTML = '';
+
+        // 遍历返回的商品列表
+        data.list.forEach(function (item) {
+            // 创建外层 div
+            const skuDiv = document.createElement('div');
+            skuDiv.classList.add('category-goods-detail-sku');
+
+            // 左侧图片 div
+            const leftImgDiv = document.createElement('div');
+            leftImgDiv.classList.add('cgds-left-img');
+            const imgElement = document.createElement('img');
+            imgElement.src = item.skuImage; // 设置图片地址
+            leftImgDiv.appendChild(imgElement);
+
+            // 右侧详细信息 div
+            const rightDetailDiv = document.createElement('div');
+            rightDetailDiv.classList.add('cgds-right-detail');
+
+            // 名称 div
+            const nameDiv = document.createElement('div');
+            nameDiv.classList.add('cgds-right-detail-name');
+            nameDiv.textContent = item.skuName; // 设置商品名称
+
+            // 销量 div
+            const salesNumDiv = document.createElement('div');
+            salesNumDiv.classList.add('cgds-right-detail-salesnum');
+            salesNumDiv.textContent = `销量:${item.inventoryNumber}`; // 设置库存信息
+
+            // 价格 div
+            const priceDiv = document.createElement('div');
+            priceDiv.classList.add('cgds-right-detail-price');
+
+            const priceNowDiv = document.createElement('div');
+            priceNowDiv.classList.add('cgds-right-detail-price-now');
+            priceNowDiv.textContent = item.price; // 当前价格
+
+            const priceHistoryDiv = document.createElement('div');
+            priceHistoryDiv.classList.add('cgds-right-detail-price-history');
+            priceHistoryDiv.textContent = item.historicalPrices; // 历史价格
+
+            // 将价格 divs 添加到价格容器
+            priceDiv.appendChild(priceNowDiv);
+            priceDiv.appendChild(priceHistoryDiv);
+
+            // 将名称、销量、价格 div 添加到右侧详细信息 div
+            rightDetailDiv.appendChild(nameDiv);
+            rightDetailDiv.appendChild(salesNumDiv);
+            rightDetailDiv.appendChild(priceDiv);
+
+            // 将左侧图片和右侧详细信息 div 添加到外层 sku div
+            skuDiv.appendChild(leftImgDiv);
+            skuDiv.appendChild(rightDetailDiv);
+
+            // 将生成的 sku div 添加到页面容器中
+            container.appendChild(skuDiv);
+        });
+    }
+
+    // 调用函数,传入实际数据
+    postCategoryData(1, 1, 10);
+
+
 </script>
 </html>

Файловите разлики са ограничени, защото са твърде много
+ 1 - 1
file/virtual_mall.sql


+ 45 - 0
router/TestRouter.go

@@ -4,6 +4,7 @@ import (
 	"demo/data/dao"
 	"demo/data/dao/manage"
 	"demo/data/domain"
+	"demo/data/domain/vo"
 	"demo/share"
 	"demo/util/templatefunc"
 	"encoding/json"
@@ -30,6 +31,9 @@ func TestRouth(engine *gin.RouterGroup) {
 
 		PushRouter(user, "GET", "/category/:category", CategoryPage)
 		PushRouter(user, "GET", "/category", CategoryPage)
+
+		PushRouter(user, "POST", "/category", GetCategoryListByTypeId)
+		PushRouter(user, "POST", "/category/goods", GetCategoryGoodsSkuListByGoodsId)
 	}
 
 }
@@ -201,6 +205,7 @@ func GetUserId(c *gin.Context) int64 {
 	i, err := strconv.ParseInt(claims["iss"].(string), 10, 32)
 	return i
 }
+
 func CategoryPage(c *gin.Context) {
 	data := share.GetJsonAnyParam(c)
 	categoryPath := c.Param("category")
@@ -229,3 +234,43 @@ func CategoryPage(c *gin.Context) {
 
 	c.HTML(http.StatusOK, "category.html", dm)
 }
+
+//================存json请求======================
+
+func GetCategoryGoodsSkuListByGoodsId(c *gin.Context) {
+	data := share.GetJsonAnyParam(c)
+	goodsId, _ := data("goodsId")
+	list, i, err := dao.GetGoodsSkuList(domain.GoodsSku{GoodsId: cast.ToInt64(goodsId)}, 1, 99999)
+	if err != nil {
+		c.JSON(200, CreateResultError(401, "未查询到结果"))
+		return
+	}
+	m := make(map[string]interface{})
+	m["list"] = list
+	m["count"] = i
+	c.JSON(200, CreateResultData(m))
+}
+
+func GetCategoryListByTypeId(c *gin.Context) {
+	data := share.GetJsonAnyParam(c)
+	typeId, _ := data("typeId")
+	pageNum, _ := data("pageNum")
+	pageSize, _ := data("pageSize")
+	list, err := manage.GetGoodsList(domain.Goods{TypeId: cast.ToInt64(typeId)}, cast.ToInt(pageNum), cast.ToInt(pageSize))
+	if err != nil {
+		c.JSON(200, CreateResultError(401, "未查询到结果"))
+		return
+	}
+	vos := make([]any, 0)
+	for i := range list.List {
+		var item = list.List[i].(domain.Goods)
+		goodsVo := vo.CategoryGoodsVo{
+			Id:        item.Id,
+			GoodsName: item.GoodsName,
+			Image:     item.ImageUrl,
+		}
+		vos = append(vos, goodsVo)
+	}
+	list.List = vos
+	c.JSON(200, CreateResultData(list))
+}

Някои файлове не бяха показани, защото твърде много файлове са промени