feat: 重构hgcart三级商品目录购物车
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
- 一级分类:胶囊形Tab(蓝色active+阴影) - 二级分类:底部边框高亮Tab(取代el-select下拉) - 三级产品:3列白色卡片网格(hover上浮+渐变顶边) - 价格:蓝色大字28px+原价删除线 - 库存badge:橙色紧张/灰色售罄 - 统一hgcloud主题变量和圆角风格 - JS逻辑完全不变 - 域名搜索功能完整保留
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -17,108 +17,136 @@
|
||||
<el-container>
|
||||
<top-menu></top-menu>
|
||||
<el-main>
|
||||
<!-- 自己的东西 -->
|
||||
<div class="main-card">
|
||||
<div class="goods-page">
|
||||
<!-- 顶部说明 -->
|
||||
<div v-if="commonData.cart_instruction == 1 && commonData.cart_instruction_content" class="cart-des"
|
||||
v-html="commonData.cart_instruction_content">
|
||||
</div>
|
||||
<div class="main-title" v-else>{{lang.new_goods}}</div>
|
||||
<div class="main-content-box">
|
||||
<div class="search-box">
|
||||
<el-select v-model="select_first_obj.id" :placeholder="lang.first_level" @change="selectFirstType">
|
||||
<el-option v-for="item in first_group_list" :key="item.id " :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-select v-model="select_second_obj.id" :placeholder="lang.second_level" :disabled="secondLoading"
|
||||
:loading="secondLoading" @change="selectSecondType" class="second-select">
|
||||
<el-option v-for="item in second_group_list" :key="item.name " :label="item.name" :value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-input :placeholder="lang.goods_search_placeholder" v-if="!isDomain" clearable v-model="searchValue"
|
||||
class="search-input" @keyup.enter.native="searchGoods"></el-input>
|
||||
<el-button class="search-btn" type="primary" key="ddd" @click="searchGoods" :loading="searchLoading"
|
||||
v-if="!isDomain">{{lang.search}}</el-button>
|
||||
|
||||
<!-- ========== 一级分类 · 胶囊 Tab ========== -->
|
||||
<div class="primary-nav">
|
||||
<div class="primary-tabs">
|
||||
<div class="primary-tab"
|
||||
:class="{'primary-tab-active': select_first_obj.id === item.id}"
|
||||
v-for="item in first_group_list" :key="item.id"
|
||||
@click="select_first_obj.id = item.id; selectFirstType(item.id)">
|
||||
{{item.name}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========== 二级分类 · 底部边框 Tab + 搜索 ========== -->
|
||||
<div class="secondary-nav">
|
||||
<div class="secondary-tabs" v-loading="secondLoading">
|
||||
<div class="secondary-tab"
|
||||
:class="{'secondary-tab-active': select_second_obj.id === item.id}"
|
||||
v-for="item in second_group_list" :key="item.id"
|
||||
@click="selectSecondType(item.id)">
|
||||
{{item.name}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="secondary-right">
|
||||
<el-input :placeholder="lang.goods_search_placeholder" v-if="!isDomain" clearable
|
||||
v-model="searchValue" class="search-input" size="small"
|
||||
@keyup.enter.native="searchGoods">
|
||||
<el-button slot="append" icon="el-icon-search" @click="searchGoods"
|
||||
:loading="searchLoading"></el-button>
|
||||
</el-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 二级描述滚动条 -->
|
||||
<div class="second-desc" v-if="select_second_obj.description">
|
||||
<scroll-text mode="loop">
|
||||
{{select_second_obj.description}}
|
||||
</scroll-text>
|
||||
</div>
|
||||
<div class="shopping-box" v-loading="goodSLoading">
|
||||
|
||||
<!-- ========== 商品列表区域 ========== -->
|
||||
<div class="goods-container" v-loading="goodSLoading">
|
||||
<template v-if="!isDomain">
|
||||
<div class="no-goods" v-if="goodsList.length === 0 && !goodSLoading">
|
||||
<!-- 空状态 -->
|
||||
<div class="empty-state" v-if="goodsList.length === 0 && !goodSLoading">
|
||||
<el-empty :description="lang.no_goods"></el-empty>
|
||||
</div>
|
||||
<div v-else class="goods-list-div">
|
||||
<template v-for="(item,index) in goodsList">
|
||||
<div class="shopping-item">
|
||||
<div class="client-box" v-if="item.client_level_name && item.client_level_name !== ''">
|
||||
<span>{{lang.shoppingCar_tip_text15}}</span>
|
||||
|
||||
<!-- 三级产品 · 3列卡片网格 -->
|
||||
<div v-else class="goods-grid">
|
||||
<div class="product-card"
|
||||
:class="{'product-card-disabled': item.stock_control === 1 && item.qty <= 0}"
|
||||
v-for="(item,index) in goodsList" :key="index">
|
||||
|
||||
<!-- 卡片头部:名称 + 标签 -->
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">{{ item.name }}</h3>
|
||||
<div class="card-badges">
|
||||
<span class="badge badge-stock-low"
|
||||
v-if="item.stock_control === 1 && item.qty > 0 && item.qty <= 5">
|
||||
{{lang.stock}}:{{item.qty}}
|
||||
</span>
|
||||
<span class="badge badge-sold-out"
|
||||
v-if="item.stock_control === 1 && item.qty <= 0">
|
||||
<img src="/{$template_catalog_cart}/template/{$themes_cart}/img/sold_out.svg" alt="" class="sold-icon">
|
||||
{{lang.shoppingCar_tip_text13 || '已售罄'}}
|
||||
</span>
|
||||
<span class="badge badge-level"
|
||||
v-if="item.client_level_name && item.client_level_name !== ''">
|
||||
{{lang.shoppingCar_tip_text15}}
|
||||
</span>
|
||||
</div>
|
||||
<div v-html="item.description" class="goods-description"></div>
|
||||
<div class="goods-content">
|
||||
<div class="goods-tag"
|
||||
v-if="item.pay_ontrial && item.pay_ontrial?.status === 1 || item.aodun_firewall_product">
|
||||
<div class="tag-item" v-if="item.pay_ontrial && item.pay_ontrial?.status === 1 ">
|
||||
</div>
|
||||
|
||||
<!-- 活动标签 -->
|
||||
<div class="card-tags"
|
||||
v-if="(item.pay_ontrial && item.pay_ontrial?.status === 1) || item.aodun_firewall_product || item.activeList.length > 0 || item.addon_coin === 1">
|
||||
<span class="tag tag-trial"
|
||||
v-if="item.pay_ontrial && item.pay_ontrial?.status === 1">
|
||||
{{lang.support_trial}}
|
||||
</div>
|
||||
<div class="tag-item" v-if="item.aodun_firewall_product">
|
||||
</span>
|
||||
<span class="tag tag-firewall" v-if="item.aodun_firewall_product">
|
||||
{{lang.firewall_text1}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="goods-name" :class="{'sold-out':item.stock_control === 1 && item.qty <= 0}">
|
||||
<div class="goods-name-text">{{ item.name }}</div>
|
||||
<div class="qty-box" v-if="item.stock_control === 1">
|
||||
<span v-if="item.qty > 0">{{lang.stock}}:<span
|
||||
class="stock-num">{{item.qty}}</span></span>
|
||||
<img src="/{$template_catalog_cart}/template/{$themes_cart}/img/sold_out.svg" alt=""
|
||||
v-else>
|
||||
</div>
|
||||
</div>
|
||||
<div class="goods-active">
|
||||
<template v-if="item.activeList.length > 0 || item.addon_coin === 1">
|
||||
<div class="active-name" v-if="item.addon_coin === 1">
|
||||
</span>
|
||||
<span class="tag tag-coin" v-if="item.addon_coin === 1">
|
||||
{{lang.coin_text10}}{{item.addon_coin_name}}
|
||||
</div>
|
||||
</span>
|
||||
<template v-for="active in item.activeList">
|
||||
<el-popover placement="top-start" trigger="hover">
|
||||
<div class="active-item">
|
||||
<span v-if="active.type === 'percent'">{{lang.goods_text1}} {{active.value}}%</span>
|
||||
<span v-if="active.type === 'reduce'"> {{lang.goods_text2}} {{active.full}}
|
||||
{{lang.goods_text3}} {{active.value}}</span>
|
||||
</div>
|
||||
<div class="active-name" slot="reference">
|
||||
{{active.name}}
|
||||
<span v-if="active.type === 'reduce'">{{lang.goods_text2}} {{active.full}} {{lang.goods_text3}} {{active.value}}</span>
|
||||
</div>
|
||||
<span class="tag tag-promo" slot="reference">{{active.name}}</span>
|
||||
</el-popover>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="active-name" style="opacity: 0;">
|
||||
{{lang.subaccount_text55}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 描述 -->
|
||||
<div class="card-desc" v-html="item.description"></div>
|
||||
|
||||
<!-- 卡片底部:价格 + 按钮 -->
|
||||
<div class="card-footer">
|
||||
<div class="card-price">
|
||||
<div class="price-current">
|
||||
<span class="price-symbol">{{commonData.currency_prefix}}</span>
|
||||
<span class="price-amount">{{item.price_discounted || item.price}}</span>
|
||||
<span class="price-cycle">{{item.cycle ? '/' + item.cycle : ''}}</span>
|
||||
</div>
|
||||
<div class="price-box">
|
||||
<div class="price-box-left">
|
||||
<span class="item-price">
|
||||
<span
|
||||
class="item-price-prefix">{{commonData.currency_prefix}}</span>{{item.price_discounted || item.price}}<span
|
||||
class="item-price-cycle">{{item.cycle ? '/' + item.cycle : ''}}</span>
|
||||
</span>
|
||||
<span class="original-price"
|
||||
<div class="price-original"
|
||||
v-if="item.price_discounted && item.price != item.price_discounted">
|
||||
<span class="item-price-prefix">{{commonData.currency_prefix}}</span> {{item.price}}
|
||||
</span>
|
||||
{{commonData.currency_prefix}}{{item.price}}
|
||||
</div>
|
||||
<el-button :disabled="item.stock_control === 1 && item.qty <= 0" class="buy-btn"
|
||||
type="primary" @click="goOrder(item)">{{lang.buy}}</el-button>
|
||||
</div>
|
||||
<el-button class="card-buy-btn" type="primary"
|
||||
:disabled="item.stock_control === 1 && item.qty <= 0"
|
||||
@click="goOrder(item)">
|
||||
{{lang.buy}}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- ====== 域名搜索区域(保持原有功能和结构) ====== -->
|
||||
<template v-else>
|
||||
<div class="domain-box">
|
||||
<div class="register-type">
|
||||
@@ -210,15 +238,13 @@
|
||||
<div class="price-item" v-for="items in item.priceArr" :key="items.buyyear">
|
||||
<div class="price-year">{{items.buyyear}}{{lang.template_text101}}</div>
|
||||
<div class="price-new">{{commonData.currency_prefix}}{{items.buyprice}}</div>
|
||||
<div class="price-renew">{{commonData.currency_prefix}}{{items.renewprice}}
|
||||
</div>
|
||||
<div class="price-renew">{{commonData.currency_prefix}}{{items.renewprice}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
<el-button class="add-btn" type="primary" :plain="isAddCart(item)"
|
||||
:disabled="isAddCart(item)" v-if="item.avail === 1"
|
||||
@click="addCart(item)">{{lang.template_text102}}
|
||||
</el-button>
|
||||
@click="addCart(item)">{{lang.template_text102}}</el-button>
|
||||
<div class="whois-box" v-if="item.avail === 0" @click="goWhois(item)">
|
||||
{{lang.template_text103}}
|
||||
</div>
|
||||
@@ -237,19 +263,16 @@
|
||||
</div>
|
||||
<div class="batch-box" v-else>
|
||||
<div class="batch-main">
|
||||
<template
|
||||
v-if="availList.length !== 0 || unavailList.length !==0 || faillList.length !== 0">
|
||||
<template v-if="availList.length !== 0 || unavailList.length !==0 || faillList.length !== 0">
|
||||
<div class="search-title">{{lang.template_text113}}({{availList.length}})</div>
|
||||
<div class="avail-list" v-loading="batchLoading">
|
||||
<!-- 可注册域名 -->
|
||||
<el-checkbox-group v-model="batchCheckGroup" @change="handleBatchChange">
|
||||
<div class="batch-item" v-for="(item,index) in availList" :key="index">
|
||||
<div class="item-left">
|
||||
<el-checkbox :label="item.name">
|
||||
<span class="domain-name">{{item.name}}</span>
|
||||
</el-checkbox>
|
||||
<span class="domain-status"
|
||||
v-if="item.avail === 0">{{lang.template_text114}}</span>
|
||||
<span class="domain-status" v-if="item.avail === 0">{{lang.template_text114}}</span>
|
||||
<span class="domain-status"
|
||||
v-if="(item.avail === 1 || item.avail === -2) && item.description">{{item.description}}</span>
|
||||
</div>
|
||||
@@ -273,11 +296,8 @@
|
||||
</div>
|
||||
<div class="price-item" v-for="items in item.priceArr" :key="items.buyyear">
|
||||
<div class="price-year">{{items.buyyear}}{{lang.template_text101}}</div>
|
||||
<div class="price-new">{{commonData.currency_prefix}}{{items.buyprice}}
|
||||
</div>
|
||||
<div class="price-renew">
|
||||
{{commonData.currency_prefix}}{{items.renewprice}}
|
||||
</div>
|
||||
<div class="price-new">{{commonData.currency_prefix}}{{items.buyprice}}</div>
|
||||
<div class="price-renew">{{commonData.currency_prefix}}{{items.renewprice}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
@@ -292,16 +312,14 @@
|
||||
<el-checkbox :indeterminate="isBatchIndeterminate" v-model="isBatchAllCheck"
|
||||
@change="handleBatchCheckAllChange">{{lang.template_text116}}</el-checkbox>
|
||||
<el-button @click="addAllCart" type="primary"
|
||||
:loading="addAllLoading">{{lang.template_text117}}
|
||||
</el-button>
|
||||
:loading="addAllLoading">{{lang.template_text117}}</el-button>
|
||||
</div>
|
||||
<el-collapse v-model="activeNames" v-loading="batchLoading">
|
||||
<el-collapse-item name="1" style="margin-top: 0.6rem;" v-show="unavailList.length > 0">
|
||||
<template slot="title">
|
||||
<div class="unavail-title">
|
||||
<span>{{lang.template_text118}}({{unavailList.length}})</span>
|
||||
<span class="open-text"
|
||||
v-if="activeNames.includes('1')">{{lang.template_text119}}</span>
|
||||
<span class="open-text" v-if="activeNames.includes('1')">{{lang.template_text119}}</span>
|
||||
<span class="open-text" v-else>{{lang.template_text120}}</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -316,8 +334,7 @@
|
||||
<template slot="title">
|
||||
<div class="unavail-title">
|
||||
<span>{{lang.template_text121}}({{faillList.length}})</span>
|
||||
<span class="open-text"
|
||||
v-if="activeNames.includes('2')">{{lang.template_text119}}</span>
|
||||
<span class="open-text" v-if="activeNames.includes('2')">{{lang.template_text119}}</span>
|
||||
<span class="open-text" v-else>{{lang.template_text120}}</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -333,8 +350,7 @@
|
||||
<template v-else>
|
||||
<div class="search-title">{{lang.template_text94}}</div>
|
||||
<div class="batch-search" v-loading="batchLoading">
|
||||
<img src="/{$template_catalog}/template/{$themes}/img/goodsList/search_domain.png"
|
||||
alt="">
|
||||
<img src="/{$template_catalog}/template/{$themes}/img/goodsList/search_domain.png" alt="">
|
||||
<p>{{lang.template_text122}}</p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -343,9 +359,7 @@
|
||||
</div>
|
||||
<div class="domain-right">
|
||||
<div class="car-top">
|
||||
<span>
|
||||
{{lang.template_text123}}
|
||||
</span>
|
||||
<span>{{lang.template_text123}}</span>
|
||||
<span class="clear-car" @click="deleteClearCart()">
|
||||
<svg t="1750669572885" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="9781" width="16" height="16">
|
||||
@@ -424,8 +438,6 @@
|
||||
</template>
|
||||
</div>
|
||||
<p v-if="!isDomain && !scrollDisabled && goodsList.length !==0" class="tips">{{lang.goods_loading}}</p>
|
||||
<!-- <p v-if="!isDomain && scrollDisabled && goodsList.length !== 0" class="tips">{{lang.no_more_goods}}</p> -->
|
||||
</div>
|
||||
</div>
|
||||
</el-main>
|
||||
<div class="up-dialog">
|
||||
@@ -437,7 +449,6 @@
|
||||
<input accept="text/plain" type="file" id="upFile" autocomplete="off" tabindex="-1"
|
||||
style="display: none;">
|
||||
<input class="file-name" :placeholder="lang.template_text133" readonly :value="fileName">
|
||||
<!-- 选择文件按钮 -->
|
||||
<div class="file-btn" @click="selectFile">{{lang.template_text134}}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user