.NET经销商实战(十二)——优化用户体验,完善产品列表查询
2022/5/25 23:20:14
本文主要是介绍.NET经销商实战(十二)——优化用户体验,完善产品列表查询,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
商品列表查询时,查询条件显示在url后面
1.在商品列表页面中引入useRouter()
代码如下:
import { useRouter,useRoute } from 'vue-router'
var router = useRouter()
var route = useRoute()
2.前端查询方法代码如下:
点击查看代码
search: async () => { clearTimeout(productInfo.timer) productInfo.timer = setTimeout(async () => { router.push(`productList?keyword=${productInfo.searchText}`) // productInfo.products = await getProduct({ // searchText: productInfo.searchText, // systemNo: productInfo.systemIndex, // productType: productInfo.typeSelected, // sort: 'ProductName', // pageIndex: 1, // }) }, 1000) },
3.ProductList.vue完整代码如下:
点击查看代码
<template> <div> <div class="search-pad"> <input v-model="searchText" type="text" name="" id="" @focus="searchFocus()" @blur="searchBlur()" @input="search" /> <button v-show="isShowSearchBtn">搜索</button> <button v-show="!isShowSearchBtn" @click="showRight()">筛选</button> </div> <div class="system-pad"> <div v-for="belongType in belongTypes" :key="belongType.sysNo" :class="[ 'system-item', { 'system-select': systemIndex == belongType.sysNo }, ]" @click="getSystemProduct(belongType.sysNo)" > <span>{{ belongType.belongTypeName }}</span> </div> </div> <div class="product-list"> <ul> <li v-for="product in products" :key="product.id"> <img :src="product.productPhoto?.productPhotoUrl" alt="" /> <div> <p class="p-name">{{ product.productName }}</p> <p class="p-type">类别:{{ product.typeName }}</p> <p class="p-price"> ¥{{ tranPrice(product.productSale?.salePrice) }}/张 </p> </div> </li> </ul> <div :class="['left-menu', { 'left-menu-show': isShowLeft }]"> <div class="left-switch" @click="showLeft()"> <img src="/img/dealerImgs/up.png" alt="" /> </div> <ul> <li v-for="productType in productTypes" :key="productType.typeNo" @click="selectType(productType.typeNo)" :class="{ 'left-item-select': typeSelected == productType.typeNo }" > {{ productType.typeName }} </li> </ul> </div> </div> <div class="right-pad"> <div class="list-pad"> <ul class="f-type-list"> <template v-for="(values, key) in productProps"> <li v-if="values.length > 0" :key="key"> <p>{{ formatKey(key) }}</p> <ul class="f-item-list"> <li v-for="value in values" :key="value"> <span>{{ value }}</span> </li> <!-- <li><span class="prop-select">胡桃色</span></li> --> </ul> <div class="clear-tag"></div> </li> </template> </ul> </div> <div class="right-edit"> <button @click="confirmFilter()" style="background-color: rgb(188, 0, 0); color: #fff" > 确定 </button> <button @click="hideRight()">取消</button> </div> </div> <div class="cover" v-show="isShowCover" @click="hideRight()"></div> </div> </template> <script lang="ts"> import { ref, onMounted, reactive, toRefs } from 'vue' import { getProduct, getBelongType, getProductType, getProps, } from '@/httpRequests/ProductListRequest' import { IProductInfo } from '@/Interfaces/ProductList' import { useRouter, useRoute } from 'vue-router' import router from '@/router' export default { setup() { var router = useRouter() var route = useRoute() const pageController = reactive({ isShowLeft: ref(false), isShowCover: ref(false), isShowSearchBtn: ref(false), }) //IProductInfo const productInfo: IProductInfo = reactive({ systemIndex: '1', products: [], belongTypes: [], productTypes: [], typeSelected: '', searchText: '', productProps: {}, timer: 0, /** * 获取物品 */ getProducts: async ( systemIndex: string, productType: string | null = null, searchText: string | null ) => { productInfo.products = await getProduct({ searchText: searchText, systemNo: systemIndex, productType: productType, sort: 'ProductName', pageIndex: 1, }) console.log(productInfo.products) }, tranPrice: (price: number) => { if (price == null) { return '0.00' } else { return price.toFixed(2).toString() } }, getBelongType: async () => { productInfo.belongTypes = await getBelongType() console.log(productInfo.belongTypes) }, // getProductType: async (sysNo: string) => { productInfo.productTypes = await getProductType(sysNo) }, //增加注释 getSystemProduct: async (index: string) => { productInfo.typeSelected = null productInfo.systemIndex = index await productInfo.getProducts(index, null, null) await productInfo.getProductType(index) await productInfo.getProps(index, null) }, getProps: async (belongTypeNo: string, typeNo: string | null = null) => { console.log('belongTypeNo:' + belongTypeNo) var res = await getProps({ belongTypeNo, typeNo }) productInfo.productProps = res console.log(res) }, formatKey: (key: string) => { return key.split('|')[1] }, selectType: async (typeNo: string) => { if (productInfo.typeSelected == typeNo) { productInfo.typeSelected = '' } else { productInfo.typeSelected = typeNo } await productInfo.getProducts( productInfo.systemIndex, productInfo.typeSelected, null ) console.log('productInfo.typeSelected: ' + productInfo.typeSelected) }, search: async () => { clearTimeout(productInfo.timer) productInfo.timer = setTimeout(async () => { router.push(`productList?keyword=${productInfo.searchText}`) // productInfo.products = await getProduct({ // searchText: productInfo.searchText, // systemNo: productInfo.systemIndex, // productType: productInfo.typeSelected, // sort: 'ProductName', // pageIndex: 1, // }) }, 1000) }, }) const showLeft = () => { pageController.isShowLeft = !pageController.isShowLeft } const searchFocus = () => { pageController.isShowSearchBtn = true } const searchBlur = () => { pageController.isShowSearchBtn = false } const confirmFilter = () => {} const showRight = () => { pageController.isShowCover = true var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '0' } const hideRight = () => { pageController.isShowCover = false var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '-85%' } //解析地址 let keyword: string | null = '' const resoluationAddress = () => { keyword = route.query.keyword as string console.log(keyword) } onMounted(async () => { resoluationAddress() await productInfo.getProducts('bc', null, keyword) await productInfo.getBelongType() await productInfo.getProductType('1') await productInfo.getProps('1', null) }) return { ...toRefs(pageController), ...toRefs(productInfo), showLeft, searchFocus, searchBlur, confirmFilter, showRight, hideRight, } }, } </script> <style lang="scss" scoped> .i-search:after { background-color: #b70101 !important; } .search-pad { z-index: 10; position: fixed; width: 100%; padding: 6px 20px; background-color: #f0f0f0; display: flex; input { height: 28px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 3px; flex: 1; outline: none; } button { background-color: transparent; width: 56px; border: 0 none; font-size: 14px; font-weight: bold; color: #333; outline: none; } } .system-pad { z-index: 10; position: fixed; width: 100%; top: 40px; background-color: #fff; display: flex; .system-item { flex: 1; text-align: center; border-bottom: 1px #ddd solid; border-right: 1px transparent solid; border-left: 1px transparent solid; span { border: 0 none !important; background-color: #f0f2f5; margin: 6px 5px; font-size: 12px; font-weight: normal; text-align: center; border-radius: 4px; padding: 6px 0; display: block; height: 20px; line-height: 12px; } } .system-select { border-bottom: 1px transparent solid; border-right: 1px #ddd solid; border-left: 1px #ddd solid; span { background-color: transparent; } } } .product-list { padding-top: 75px; ul { background-color: #fff; li { list-style: none; height: 88px; padding-left: 108px; position: relative; img { height: 66px; width: 66px; background-color: #ccc; position: absolute; left: 28px; top: 11px; } div { padding: 10px 0; border-bottom: 1px solid #f0f0f0; padding-bottom: 12px; text-align-last: left; .p-name { font-size: 13px; } .p-type { font-size: 12px; color: #666; margin-top: 8px; } .p-price { font-size: 13px; color: #f23030; margin-top: 8px; } } } } .left-menu { position: fixed; height: calc(100% - 116px); left: -106px; width: 125px; background-color: #fff; top: 76px; border-radius: 0 18px 0 0; border: 1px solid #d7d7d7; overflow: hidden; transition: 0.5s; margin-bottom: 120px; .left-switch { width: 20px; background-color: #fff; position: absolute; right: 0; height: 100%; img { position: absolute; top: 42%; left: 2px; width: 20px; transform: rotate(90deg); transition: 0.5s; } } ul { position: absolute; height: 100%; width: 106px; background-color: #f0f0f0; overflow: auto; li { width: 106px; height: 50px; text-align: center; line-height: 50px; border-bottom: 1px solid #d7d7d7; padding: 0; font-size: 12px; color: #333; } li.left-item-select { background-color: #fff; } } } .left-menu-show { left: 0; .left-switch { img { transform: rotate(-90deg); } } } } .right-pad { position: fixed; /* right: -85%; */ right: -85%; top: 0; width: 85%; height: 100%; background-color: #f7f7f7; z-index: 103; transition: 580ms; z-index: 101; ul { list-style: none; overflow: hidden; } .list-pad { overflow: auto; height: 100%; padding-bottom: 40px; .f-type-list { overflow: hidden; > li { padding: 10px; background-color: #fff; margin-bottom: 10px; .f-item-list { overflow: auto; display: flex; flex-wrap: wrap; li { flex-basis: 33.3%; span { display: block; margin-top: 10px; margin-right: 10px; background: #eee; border: 1px solid #eee; padding: 5px 0; text-align: center; border-radius: 6px; font-size: 13px; overflow: hidden; height: 39px; } .prop-select { border: 1px solid red; background: #fff; color: red; } } } p { font-size: 14px; } } } } .right-edit { position: absolute; bottom: 0; left: 0; width: 100%; button { float: left; height: 40px; width: 50%; line-height: 40px; text-align: center; border: 0px none; } } } .cover { position: fixed; height: 100%; width: 100%; left: 0; top: 0; background-color: rgba(51, 51, 51, 0.36); z-index: 11; } </style>
4.修改Layout.vue代码如下:
埋种子
点击查看代码
<template> <div> <router-view :key="key" /> <div class="foot-menu-pad"> <div class="foot-menu"> <router-link to="/productList" v-slot="{ navigate }" custom> <div class="foot-item" @click="navigate"> <b :class="['i-search', 'f-menu-sel']"></b> </div> </router-link> <router-link to="/shoppingCart" v-slot="{ navigate }" custom> <div class="foot-item" @click="navigate"> <b :class="['i-cart', 'f-menu-sel']"> <i>58</i> </b> </div> </router-link> <router-link to="/main" v-slot="{ navigate }" custom> <div class="foot-item" @click="navigate"> <b :class="['i-user', 'f-menu-sel']"></b> </div> </router-link> </div> </div> </div> </template> <script> import { ref } from 'vue' export default { setup() { const key = ref(Date.now()) return key }, } </script> <style lang="scss" scoped> .foot-menu-pad { height: 40px; .foot-menu { position: fixed; height: 40px; background-color: #fff; width: 100%; left: 0; bottom: 0; display: flex; .foot-item { flex: 1; text-align: center; height: 40px; line-height: 40px; position: relative; b { background-color: #acacac; width: 26px; height: 26px; background-size: 16px; background-repeat: no-repeat; background-position: center; border-radius: 13px; margin-top: 6px; display: inline-block; position: relative; i { position: absolute; font-size: 12px; color: #fff; // background-color: red; padding: 1px 3px; text-align: center; font-style: normal; display: inline; top: -5px; right: -12px; border-radius: 12px; line-height: 12px; font-weight: normal; } } b.i-search { background-image: require('/img/icons-png/search-white.png'); } b.i-cart { background-image: require('/img/icons-png/shoppingCar-white.png'); } b.i-user { background-image: require('/img/icons-png/user-white.png'); } .f-menu-sel { background-color: #b70101; } } } } </style>
5.输入搜索框你要搜索的内容进行立刻刷新
商品列表代码如下:
点击查看代码
<template> <div> <div class="search-pad"> <input v-model="searchText" type="text" name="" id="" @focus="searchFocus()" @blur="searchBlur()" @input="search" /> <button v-show="isShowSearchBtn">搜索</button> <button v-show="!isShowSearchBtn" @click="showRight()">筛选</button> </div> <div class="system-pad"> <div v-for="belongType in belongTypes" :key="belongType.sysNo" :class="[ 'system-item', { 'system-select': systemIndex == belongType.sysNo }, ]" @click="getSystemProduct(belongType.sysNo)" > <span>{{ belongType.belongTypeName }}</span> </div> </div> <div class="product-list"> <ul> <li v-for="product in products" :key="product.id"> <img :src="product.productPhoto?.productPhotoUrl" alt="" /> <div> <p class="p-name">{{ product.productName }}</p> <p class="p-type">类别:{{ product.typeName }}</p> <p class="p-price"> ¥{{ tranPrice(product.productSale?.salePrice) }}/张 </p> </div> </li> </ul> <div :class="['left-menu', { 'left-menu-show': isShowLeft }]"> <div class="left-switch" @click="showLeft()"> <img src="/img/dealerImgs/up.png" alt="" /> </div> <ul> <li v-for="productType in productTypes" :key="productType.typeNo" @click="selectType(productType.typeNo)" :class="{ 'left-item-select': typeSelected == productType.typeNo }" > {{ productType.typeName }} </li> </ul> </div> </div> <div class="right-pad"> <div class="list-pad"> <ul class="f-type-list"> <template v-for="(values, key) in productProps"> <li v-if="values.length > 0" :key="key"> <p>{{ formatKey(key) }}</p> <ul class="f-item-list"> <li v-for="value in values" :key="value"> <span>{{ value }}</span> </li> <!-- <li><span class="prop-select">胡桃色</span></li> --> </ul> <div class="clear-tag"></div> </li> </template> </ul> </div> <div class="right-edit"> <button @click="confirmFilter()" style="background-color: rgb(188, 0, 0); color: #fff" > 确定 </button> <button @click="hideRight()">取消</button> </div> </div> <div class="cover" v-show="isShowCover" @click="hideRight()"></div> </div> </template> <script lang="ts"> import { ref, onMounted, reactive, toRefs } from 'vue' import { getProduct, getBelongType, getProductType, getProps, } from '@/httpRequests/ProductListRequest' import { IProductInfo } from '@/Interfaces/ProductList' import { useRouter, useRoute } from 'vue-router' import router from '@/router' export default { setup() { var router = useRouter() var route = useRoute() const pageController = reactive({ isShowLeft: ref(false), isShowCover: ref(false), isShowSearchBtn: ref(false), }) //IProductInfo const productInfo: IProductInfo = reactive({ systemIndex: '1', products: [], belongTypes: [], productTypes: [], typeSelected: '', searchText: '', productProps: {}, timer: 0, /** * 获取物品 */ getProducts: async ( systemIndex: string, productType: string | null = null, searchText: string | null ) => { productInfo.products = await getProduct({ searchText: searchText, systemNo: systemIndex, productType: productType, sort: 'ProductName', pageIndex: 1, }) console.log(productInfo.products) }, tranPrice: (price: number) => { if (price == null) { return '0.00' } else { return price.toFixed(2).toString() } }, getBelongType: async () => { productInfo.belongTypes = await getBelongType() console.log(productInfo.belongTypes) }, // getProductType: async (sysNo: string) => { productInfo.productTypes = await getProductType(sysNo) }, //增加注释 getSystemProduct: async (index: string) => { productInfo.typeSelected = null productInfo.systemIndex = index await productInfo.getProducts(index, null, null) await productInfo.getProductType(index) await productInfo.getProps(index, null) }, getProps: async (belongTypeNo: string, typeNo: string | null = null) => { console.log('belongTypeNo:' + belongTypeNo) var res = await getProps({ belongTypeNo, typeNo }) productInfo.productProps = res console.log(res) }, formatKey: (key: string) => { return key.split('|')[1] }, selectType: async (typeNo: string) => { if (productInfo.typeSelected == typeNo) { productInfo.typeSelected = '' } else { productInfo.typeSelected = typeNo } await productInfo.getProducts( productInfo.systemIndex, productInfo.typeSelected, null ) console.log('productInfo.typeSelected: ' + productInfo.typeSelected) }, search: async () => { clearTimeout(productInfo.timer) productInfo.timer = setTimeout(async () => { router.push(`/productList?keyword=${productInfo.searchText}`) // location.href = `/productList?keyword=${productInfo.searchText}` // productInfo.products = await getProduct({ // searchText: productInfo.searchText, // systemNo: productInfo.systemIndex, // productType: productInfo.typeSelected, // sort: 'ProductName', // pageIndex: 1, // }) }, 1000) }, }) const showLeft = () => { pageController.isShowLeft = !pageController.isShowLeft } const searchFocus = () => { pageController.isShowSearchBtn = true } const searchBlur = () => { pageController.isShowSearchBtn = false } const confirmFilter = () => {} const showRight = () => { pageController.isShowCover = true var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '0' } const hideRight = () => { pageController.isShowCover = false var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '-85%' } //解析地址 let keyword: string | null = '' const resoluationAddress = () => { keyword = route.query.keyword as string console.log(keyword) } onMounted(async () => { resoluationAddress() await productInfo.getProducts('1', null, keyword) await productInfo.getBelongType() await productInfo.getProductType('1') await productInfo.getProps('1', null) }) return { ...toRefs(pageController), ...toRefs(productInfo), showLeft, searchFocus, searchBlur, confirmFilter, showRight, hideRight, } }, } </script> <style lang="scss" scoped> .i-search:after { background-color: #b70101 !important; } .search-pad { z-index: 10; position: fixed; width: 100%; padding: 6px 20px; background-color: #f0f0f0; display: flex; input { height: 28px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 3px; flex: 1; outline: none; } button { background-color: transparent; width: 56px; border: 0 none; font-size: 14px; font-weight: bold; color: #333; outline: none; } } .system-pad { z-index: 10; position: fixed; width: 100%; top: 40px; background-color: #fff; display: flex; .system-item { flex: 1; text-align: center; border-bottom: 1px #ddd solid; border-right: 1px transparent solid; border-left: 1px transparent solid; span { border: 0 none !important; background-color: #f0f2f5; margin: 6px 5px; font-size: 12px; font-weight: normal; text-align: center; border-radius: 4px; padding: 6px 0; display: block; height: 20px; line-height: 12px; } } .system-select { border-bottom: 1px transparent solid; border-right: 1px #ddd solid; border-left: 1px #ddd solid; span { background-color: transparent; } } } .product-list { padding-top: 75px; ul { background-color: #fff; li { list-style: none; height: 88px; padding-left: 108px; position: relative; img { height: 66px; width: 66px; background-color: #ccc; position: absolute; left: 28px; top: 11px; } div { padding: 10px 0; border-bottom: 1px solid #f0f0f0; padding-bottom: 12px; text-align-last: left; .p-name { font-size: 13px; } .p-type { font-size: 12px; color: #666; margin-top: 8px; } .p-price { font-size: 13px; color: #f23030; margin-top: 8px; } } } } .left-menu { position: fixed; height: calc(100% - 116px); left: -106px; width: 125px; background-color: #fff; top: 76px; border-radius: 0 18px 0 0; border: 1px solid #d7d7d7; overflow: hidden; transition: 0.5s; margin-bottom: 120px; .left-switch { width: 20px; background-color: #fff; position: absolute; right: 0; height: 100%; img { position: absolute; top: 42%; left: 2px; width: 20px; transform: rotate(90deg); transition: 0.5s; } } ul { position: absolute; height: 100%; width: 106px; background-color: #f0f0f0; overflow: auto; li { width: 106px; height: 50px; text-align: center; line-height: 50px; border-bottom: 1px solid #d7d7d7; padding: 0; font-size: 12px; color: #333; } li.left-item-select { background-color: #fff; } } } .left-menu-show { left: 0; .left-switch { img { transform: rotate(-90deg); } } } } .right-pad { position: fixed; /* right: -85%; */ right: -85%; top: 0; width: 85%; height: 100%; background-color: #f7f7f7; z-index: 103; transition: 580ms; z-index: 101; ul { list-style: none; overflow: hidden; } .list-pad { overflow: auto; height: 100%; padding-bottom: 40px; .f-type-list { overflow: hidden; > li { padding: 10px; background-color: #fff; margin-bottom: 10px; .f-item-list { overflow: auto; display: flex; flex-wrap: wrap; li { flex-basis: 33.3%; span { display: block; margin-top: 10px; margin-right: 10px; background: #eee; border: 1px solid #eee; padding: 5px 0; text-align: center; border-radius: 6px; font-size: 13px; overflow: hidden; height: 39px; } .prop-select { border: 1px solid red; background: #fff; color: red; } } } p { font-size: 14px; } } } } .right-edit { position: absolute; bottom: 0; left: 0; width: 100%; button { float: left; height: 40px; width: 50%; line-height: 40px; text-align: center; border: 0px none; } } } .cover { position: fixed; height: 100%; width: 100%; left: 0; top: 0; background-color: rgba(51, 51, 51, 0.36); z-index: 11; } </style>
6.优化产品类型查询
商品列表代码如下:
点击查看代码
<template> <div> <div class="search-pad"> <input v-model="searchText" type="text" name="" id="" @focus="searchFocus()" @blur="searchBlur()" @input="search" /> <button v-show="isShowSearchBtn">搜索</button> <button v-show="!isShowSearchBtn" @click="showRight()">筛选</button> </div> <div class="system-pad"> <div v-for="belongType in belongTypes" :key="belongType.sysNo" :class="[ 'system-item', { 'system-select': systemIndex == belongType.sysNo }, ]" @click="getSystemProduct(belongType.sysNo)" > <span>{{ belongType.belongTypeName }}</span> </div> </div> <div class="product-list"> <ul> <li v-for="product in products" :key="product.id"> <img :src="product.productPhoto?.productPhotoUrl" alt="" /> <div> <p class="p-name">{{ product.productName }}</p> <p class="p-type">类别:{{ product.typeName }}</p> <p class="p-price"> ¥{{ tranPrice(product.productSale?.salePrice) }}/张 </p> </div> </li> </ul> <div :class="['left-menu', { 'left-menu-show': isShowLeft }]"> <div class="left-switch" @click="showLeft()"> <img src="/img/dealerImgs/up.png" alt="" /> </div> <ul> <li v-for="productType in productTypes" :key="productType.typeNo" @click="selectType(productType.typeNo)" :class="{ 'left-item-select': typeSelected == productType.typeNo }" > {{ productType.typeName }} </li> </ul> </div> </div> <div class="right-pad"> <div class="list-pad"> <ul class="f-type-list"> <template v-for="(values, key) in productProps"> <li v-if="values.length > 0" :key="key"> <p>{{ formatKey(key) }}</p> <ul class="f-item-list"> <li v-for="value in values" :key="value"> <span>{{ value }}</span> </li> <!-- <li><span class="prop-select">胡桃色</span></li> --> </ul> <div class="clear-tag"></div> </li> </template> </ul> </div> <div class="right-edit"> <button @click="confirmFilter()" style="background-color: rgb(188, 0, 0); color: #fff" > 确定 </button> <button @click="hideRight()">取消</button> </div> </div> <div class="cover" v-show="isShowCover" @click="hideRight()"></div> </div> </template> <script lang="ts"> import { ref, onMounted, reactive, toRefs } from 'vue' import { getProduct, getBelongType, getProductType, getProps, } from '@/httpRequests/ProductListRequest' import { IProductInfo } from '@/Interfaces/ProductList' import { useRouter, useRoute } from 'vue-router' import router from '@/router' export default { setup() { var router = useRouter() var route = useRoute() const pageController = reactive({ isShowLeft: ref(false), isShowCover: ref(false), isShowSearchBtn: ref(false), }) //IProductInfo const productInfo: IProductInfo = reactive({ systemIndex: '1', products: [], belongTypes: [], productTypes: [], typeSelected: '', searchText: '', productProps: {}, timer: 0, /** * 获取物品 */ getProducts: async ( systemIndex: string, productType: string | null = null, searchText: string | null ) => { productInfo.products = await getProduct({ searchText: searchText, systemNo: systemIndex, productType: productType, sort: 'ProductName', pageIndex: 1, }) console.log(productInfo.products) }, tranPrice: (price: number) => { if (price == null) { return '0.00' } else { return price.toFixed(2).toString() } }, getBelongType: async () => { productInfo.belongTypes = await getBelongType() console.log(productInfo.belongTypes) }, // getProductType: async (sysNo: string) => { productInfo.productTypes = await getProductType(sysNo) }, //增加注释 /** * 点击大类时我们不需要考虑搜索的内容,因为每次点击大类,都应该清空搜索框 * 但是搜索物品时,就应该考虑大类 * */ getSystemProduct: async (index: string) => { router.push(`/productList?belongType=${index}`) // productInfo.typeSelected = null // productInfo.systemIndex = index // await productInfo.getProducts(index, null, null) // await productInfo.getProductType(index) // await productInfo.getProps(index, null) }, getProps: async (belongTypeNo: string, typeNo: string | null = null) => { console.log('belongTypeNo:' + belongTypeNo) var res = await getProps({ belongTypeNo, typeNo }) productInfo.productProps = res console.log(res) }, formatKey: (key: string) => { return key.split('|')[1] }, selectType: async (typeNo: string) => { if (productInfo.typeSelected == typeNo) { productInfo.typeSelected = '' } else { productInfo.typeSelected = typeNo } await productInfo.getProducts( productInfo.systemIndex, productInfo.typeSelected, null ) console.log('productInfo.typeSelected: ' + productInfo.typeSelected) }, search: async () => { clearTimeout(productInfo.timer) productInfo.timer = setTimeout(async () => { router.push( `/productList?belongType=${productInfo.systemIndex}&keyword=${productInfo.searchText}` ) // location.href = `/productList?keyword=${productInfo.searchText}` // productInfo.products = await getProduct({ // searchText: productInfo.searchText, // systemNo: productInfo.systemIndex, // productType: productInfo.typeSelected, // sort: 'ProductName', // pageIndex: 1, // }) }, 1000) }, }) const showLeft = () => { pageController.isShowLeft = !pageController.isShowLeft } const searchFocus = () => { pageController.isShowSearchBtn = true } const searchBlur = () => { pageController.isShowSearchBtn = false } const confirmFilter = () => {} const showRight = () => { pageController.isShowCover = true var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '0' } const hideRight = () => { pageController.isShowCover = false var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '-85%' } //解析地址 let keyword: string | null = '' let systemIndex: string = '' const resoluationAddress = () => { keyword = route.query.keyword as string productInfo.systemIndex = systemIndex = (route.query.belongType as string) ?? '1' console.log(systemIndex) } onMounted(async () => { resoluationAddress() await productInfo.getProducts(systemIndex, null, keyword) await productInfo.getBelongType() await productInfo.getProductType(systemIndex) await productInfo.getProps(systemIndex, null) }) return { ...toRefs(pageController), ...toRefs(productInfo), showLeft, searchFocus, searchBlur, confirmFilter, showRight, hideRight, } }, } </script> <style lang="scss" scoped> .i-search:after { background-color: #b70101 !important; } .search-pad { z-index: 10; position: fixed; width: 100%; padding: 6px 20px; background-color: #f0f0f0; display: flex; input { height: 28px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 3px; flex: 1; outline: none; } button { background-color: transparent; width: 56px; border: 0 none; font-size: 14px; font-weight: bold; color: #333; outline: none; } } .system-pad { z-index: 10; position: fixed; width: 100%; top: 40px; background-color: #fff; display: flex; .system-item { flex: 1; text-align: center; border-bottom: 1px #ddd solid; border-right: 1px transparent solid; border-left: 1px transparent solid; span { border: 0 none !important; background-color: #f0f2f5; margin: 6px 5px; font-size: 12px; font-weight: normal; text-align: center; border-radius: 4px; padding: 6px 0; display: block; height: 20px; line-height: 12px; } } .system-select { border-bottom: 1px transparent solid; border-right: 1px #ddd solid; border-left: 1px #ddd solid; span { background-color: transparent; } } } .product-list { padding-top: 75px; ul { background-color: #fff; li { list-style: none; height: 88px; padding-left: 108px; position: relative; img { height: 66px; width: 66px; background-color: #ccc; position: absolute; left: 28px; top: 11px; } div { padding: 10px 0; border-bottom: 1px solid #f0f0f0; padding-bottom: 12px; text-align-last: left; .p-name { font-size: 13px; } .p-type { font-size: 12px; color: #666; margin-top: 8px; } .p-price { font-size: 13px; color: #f23030; margin-top: 8px; } } } } .left-menu { position: fixed; height: calc(100% - 116px); left: -106px; width: 125px; background-color: #fff; top: 76px; border-radius: 0 18px 0 0; border: 1px solid #d7d7d7; overflow: hidden; transition: 0.5s; margin-bottom: 120px; .left-switch { width: 20px; background-color: #fff; position: absolute; right: 0; height: 100%; img { position: absolute; top: 42%; left: 2px; width: 20px; transform: rotate(90deg); transition: 0.5s; } } ul { position: absolute; height: 100%; width: 106px; background-color: #f0f0f0; overflow: auto; li { width: 106px; height: 50px; text-align: center; line-height: 50px; border-bottom: 1px solid #d7d7d7; padding: 0; font-size: 12px; color: #333; } li.left-item-select { background-color: #fff; } } } .left-menu-show { left: 0; .left-switch { img { transform: rotate(-90deg); } } } } .right-pad { position: fixed; /* right: -85%; */ right: -85%; top: 0; width: 85%; height: 100%; background-color: #f7f7f7; z-index: 103; transition: 580ms; z-index: 101; ul { list-style: none; overflow: hidden; } .list-pad { overflow: auto; height: 100%; padding-bottom: 40px; .f-type-list { overflow: hidden; > li { padding: 10px; background-color: #fff; margin-bottom: 10px; .f-item-list { overflow: auto; display: flex; flex-wrap: wrap; li { flex-basis: 33.3%; span { display: block; margin-top: 10px; margin-right: 10px; background: #eee; border: 1px solid #eee; padding: 5px 0; text-align: center; border-radius: 6px; font-size: 13px; overflow: hidden; height: 39px; } .prop-select { border: 1px solid red; background: #fff; color: red; } } } p { font-size: 14px; } } } } .right-edit { position: absolute; bottom: 0; left: 0; width: 100%; button { float: left; height: 40px; width: 50%; line-height: 40px; text-align: center; border: 0px none; } } } .cover { position: fixed; height: 100%; width: 100%; left: 0; top: 0; background-color: rgba(51, 51, 51, 0.36); z-index: 11; } </style>
7.产品左侧菜单栏查询优化
代码如下:
点击查看代码
<template> <div> <div class="search-pad"> <input v-model="searchText" type="text" name="" id="" @focus="searchFocus()" @blur="searchBlur()" @input="search" /> <button v-show="isShowSearchBtn">搜索</button> <button v-show="!isShowSearchBtn" @click="showRight()">筛选</button> </div> <div class="system-pad"> <div v-for="belongType in belongTypes" :key="belongType.sysNo" :class="[ 'system-item', { 'system-select': systemIndex == belongType.sysNo }, ]" @click="getSystemProduct(belongType.sysNo)" > <span>{{ belongType.belongTypeName }}</span> </div> </div> <div class="product-list"> <ul> <li v-for="product in products" :key="product.id"> <img :src="product.productPhoto?.productPhotoUrl" alt="" /> <div> <p class="p-name">{{ product.productName }}</p> <p class="p-type">类别:{{ product.typeName }}</p> <p class="p-price"> ¥{{ tranPrice(product.productSale?.salePrice) }}/张 </p> </div> </li> </ul> <div :class="['left-menu', { 'left-menu-show': isShowLeft }]"> <div class="left-switch" @click="showLeft()"> <img src="/img/dealerImgs/up.png" alt="" /> </div> <ul> <li v-for="productType in productTypes" :key="productType.typeNo" @click="selectType(productType.typeNo)" :class="{ 'left-item-select': typeSelected == productType.typeNo }" > {{ productType.typeName }} </li> </ul> </div> </div> <div class="right-pad"> <div class="list-pad"> <ul class="f-type-list"> <template v-for="(values, key) in productProps"> <li v-if="values.length > 0" :key="key"> <p>{{ formatKey(key) }}</p> <ul class="f-item-list"> <li v-for="value in values" :key="value"> <span>{{ value }}</span> </li> <!-- <li><span class="prop-select">胡桃色</span></li> --> </ul> <div class="clear-tag"></div> </li> </template> </ul> </div> <div class="right-edit"> <button @click="confirmFilter()" style="background-color: rgb(188, 0, 0); color: #fff" > 确定 </button> <button @click="hideRight()">取消</button> </div> </div> <div class="cover" v-show="isShowCover" @click="hideRight()"></div> </div> </template> <script lang="ts"> import { ref, onMounted, reactive, toRefs } from 'vue' import { getProduct, getBelongType, getProductType, getProps, } from '@/httpRequests/ProductListRequest' import { IProductInfo } from '@/Interfaces/ProductList' import { useRouter, useRoute } from 'vue-router' import router from '@/router' export default { setup() { var router = useRouter() var route = useRoute() const pageController = reactive({ isShowLeft: ref(false), isShowCover: ref(false), isShowSearchBtn: ref(false), }) //IProductInfo const productInfo: IProductInfo = reactive({ systemIndex: '1', products: [], belongTypes: [], productTypes: [], typeSelected: '', searchText: '', productProps: {}, timer: 0, /** * 获取物品 */ getProducts: async ( systemIndex: string, productType: string | null = null, searchText: string | null ) => { productInfo.products = await getProduct({ searchText: searchText, systemNo: systemIndex, productType: productType, sort: 'ProductName', pageIndex: 1, }) console.log(productInfo.products) }, tranPrice: (price: number) => { if (price == null) { return '0.00' } else { return price.toFixed(2).toString() } }, getBelongType: async () => { productInfo.belongTypes = await getBelongType() console.log(productInfo.belongTypes) }, // getProductType: async (sysNo: string) => { productInfo.productTypes = await getProductType(sysNo) }, /** * 点击大类时我们不需要考虑搜索的内容,因为每次点击大类,都应该清空搜索框 * 但是搜索物品时,就应该考虑大类 * */ getSystemProduct: async (index: string) => { router.push(`/productList?belongType=${index}`) }, getProps: async (belongTypeNo: string, typeNo: string | null = null) => { console.log('belongTypeNo:' + belongTypeNo) var res = await getProps({ belongTypeNo, typeNo }) productInfo.productProps = res console.log(res) }, formatKey: (key: string) => { return key.split('|')[1] }, selectType: async (typeNo: string) => { var url = `/productList?belongType=${productInfo.systemIndex}` if (productInfo.typeSelected != typeNo) { url += `&type=${typeNo}` } router.push(url) // await productInfo.getProducts( // productInfo.systemIndex, // productInfo.typeSelected, // null // ) console.log('productInfo.typeSelected: ' + productInfo.typeSelected) }, search: async () => { clearTimeout(productInfo.timer) productInfo.timer = setTimeout(async () => { var url = `/productList?belongType=${productInfo.systemIndex}` if (productInfo.searchText?.trim() != '') { url += `&keyword=${productInfo.searchText}` } if (productInfo.typeSelected?.trim() != '') { url += `&type=${productInfo.typeSelected}` } router.push(url) }, 1000) }, }) const showLeft = () => { pageController.isShowLeft = !pageController.isShowLeft } const searchFocus = () => { pageController.isShowSearchBtn = true } const searchBlur = () => { pageController.isShowSearchBtn = false } const confirmFilter = () => {} const showRight = () => { pageController.isShowCover = true var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '0' } const hideRight = () => { pageController.isShowCover = false var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '-85%' } //解析地址 let keyword: string | null = '' let systemIndex: string = '' let typeSelected: string = '' const resoluationAddress = () => { keyword = (route.query.keyword as string) ?? '' productInfo.systemIndex = systemIndex = (route.query.belongType as string) ?? '1' productInfo.typeSelected = typeSelected = (route.query.type as string) ?? '' console.log(systemIndex) } onMounted(async () => { resoluationAddress() await productInfo.getProducts(systemIndex, typeSelected, keyword) await productInfo.getBelongType() await productInfo.getProductType(systemIndex) await productInfo.getProps(systemIndex, typeSelected) }) return { ...toRefs(pageController), ...toRefs(productInfo), showLeft, searchFocus, searchBlur, confirmFilter, showRight, hideRight, } }, } </script> <style lang="scss" scoped> .i-search:after { background-color: #b70101 !important; } .search-pad { z-index: 10; position: fixed; width: 100%; padding: 6px 20px; background-color: #f0f0f0; display: flex; input { height: 28px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 3px; flex: 1; outline: none; } button { background-color: transparent; width: 56px; border: 0 none; font-size: 14px; font-weight: bold; color: #333; outline: none; } } .system-pad { z-index: 10; position: fixed; width: 100%; top: 40px; background-color: #fff; display: flex; .system-item { flex: 1; text-align: center; border-bottom: 1px #ddd solid; border-right: 1px transparent solid; border-left: 1px transparent solid; span { border: 0 none !important; background-color: #f0f2f5; margin: 6px 5px; font-size: 12px; font-weight: normal; text-align: center; border-radius: 4px; padding: 6px 0; display: block; height: 20px; line-height: 12px; } } .system-select { border-bottom: 1px transparent solid; border-right: 1px #ddd solid; border-left: 1px #ddd solid; span { background-color: transparent; } } } .product-list { padding-top: 75px; ul { background-color: #fff; li { list-style: none; height: 88px; padding-left: 108px; position: relative; img { height: 66px; width: 66px; background-color: #ccc; position: absolute; left: 28px; top: 11px; } div { padding: 10px 0; border-bottom: 1px solid #f0f0f0; padding-bottom: 12px; text-align-last: left; .p-name { font-size: 13px; } .p-type { font-size: 12px; color: #666; margin-top: 8px; } .p-price { font-size: 13px; color: #f23030; margin-top: 8px; } } } } .left-menu { position: fixed; height: calc(100% - 116px); left: -106px; width: 125px; background-color: #fff; top: 76px; border-radius: 0 18px 0 0; border: 1px solid #d7d7d7; overflow: hidden; transition: 0.5s; margin-bottom: 120px; .left-switch { width: 20px; background-color: #fff; position: absolute; right: 0; height: 100%; img { position: absolute; top: 42%; left: 2px; width: 20px; transform: rotate(90deg); transition: 0.5s; } } ul { position: absolute; height: 100%; width: 106px; background-color: #f0f0f0; overflow: auto; li { width: 106px; height: 50px; text-align: center; line-height: 50px; border-bottom: 1px solid #d7d7d7; padding: 0; font-size: 12px; color: #333; } li.left-item-select { background-color: #fff; } } } .left-menu-show { left: 0; .left-switch { img { transform: rotate(-90deg); } } } } .right-pad { position: fixed; /* right: -85%; */ right: -85%; top: 0; width: 85%; height: 100%; background-color: #f7f7f7; z-index: 103; transition: 580ms; z-index: 101; ul { list-style: none; overflow: hidden; } .list-pad { overflow: auto; height: 100%; padding-bottom: 40px; .f-type-list { overflow: hidden; > li { padding: 10px; background-color: #fff; margin-bottom: 10px; .f-item-list { overflow: auto; display: flex; flex-wrap: wrap; li { flex-basis: 33.3%; span { display: block; margin-top: 10px; margin-right: 10px; background: #eee; border: 1px solid #eee; padding: 5px 0; text-align: center; border-radius: 6px; font-size: 13px; overflow: hidden; height: 39px; } .prop-select { border: 1px solid red; background: #fff; color: red; } } } p { font-size: 14px; } } } } .right-edit { position: absolute; bottom: 0; left: 0; width: 100%; button { float: left; height: 40px; width: 50%; line-height: 40px; text-align: center; border: 0px none; } } } .cover { position: fixed; height: 100%; width: 100%; left: 0; top: 0; background-color: rgba(51, 51, 51, 0.36); z-index: 11; } </style>
8.抽离search方法,抽离出setRouter方法:
点击查看代码
search: async () => { clearTimeout(productInfo.timer) productInfo.timer = setTimeout(async () => { setRouter() }, 1000) }, const setRouter = () => { var url = `/productList?belongType=${productInfo.systemIndex}` if (productInfo.searchText?.trim() != '') { url += `&keyword=${productInfo.searchText}` } if (productInfo.typeSelected?.trim() != '') { url += `&type=${productInfo.typeSelected}` } router.push(url) }
9.selectType方法更新如下:
productList.vue代码如下:
点击查看代码
selectType: async (typeNo: string) => { if (productInfo.typeSelected != typeNo) { productInfo.typeSelected = typeNo } setRouter() // await productInfo.getProducts( // productInfo.systemIndex, // productInfo.typeSelected, // null // ) console.log('productInfo.typeSelected: ' + productInfo.typeSelected) },
10.为左侧筛选框增加样式
点击查看代码
<template> <div> <!-- 搜索面板 --> <div class="search-pad"> <input v-model="searchText" type="text" name="" id="" @focus="searchFocus()" @blur="searchBlur()" @input="search" /> <button v-show="isShowSearchBtn">搜索</button> <button v-show="!isShowSearchBtn" @click="showRight()">筛选</button> </div> <!-- 物品大类面板 --> <div class="system-pad"> <div v-for="belongType in belongTypes" :key="belongType.sysNo" :class="[ 'system-item', { 'system-select': systemIndex == belongType.sysNo }, ]" @click="getSystemProduct(belongType.sysNo)" > <span>{{ belongType.belongTypeName }}</span> </div> </div> <!-- 物品展示列表 --> <div class="product-list"> <ul> <li v-for="product in products" :key="product.id"> <img :src="product.productPhoto?.productPhotoUrl" alt="" /> <div> <p class="p-name">{{ product.productName }}</p> <p class="p-type">类别:{{ product.typeName }}</p> <p class="p-price"> ¥{{ tranPrice(product.productSale?.salePrice) }}/张 </p> </div> </li> </ul> <!-- 左边物品类型面板 --> <div :class="['left-menu', { 'left-menu-show': isShowLeft }]"> <div class="left-switch" @click="showLeft()"> <img src="/img/dealerImgs/up.png" alt="" /> </div> <ul> <li v-for="productType in productTypes" :key="productType.typeNo" @click="selectType(productType.typeNo)" :class="{ 'left-item-select': typeSelected == productType.typeNo }" > {{ productType.typeName }} </li> </ul> </div> </div> <!-- 右边物品属性面板 --> <div class="right-pad"> <div class="list-pad"> <ul class="f-type-list"> <template v-for="(values, key) in productProps"> <li v-if="values.length > 0" :key="key"> <p>{{ getPropKey(key, 1) }}</p> <ul class="f-item-list"> <li v-for="value in values" :key="value" @click="selectProp(getPropKey(key, 0), value)" > <span :class="{ 'prop-select': propSelect[getPropKey(key, 0)] == value, }" >{{ value }}</span > </li> <!-- <li><span class="prop-select">胡桃色</span></li> --> </ul> <div class="clear-tag"></div> </li> </template> </ul> </div> <div class="right-edit"> <button @click="confirmFilter()" style="background-color: rgb(188, 0, 0); color: #fff" > 确定 </button> <button @click="hideRight()">取消</button> </div> </div> <div class="cover" v-show="isShowCover" @click="hideRight()"></div> </div> </template> <script lang="ts"> import { ref, onMounted, reactive, toRefs } from 'vue' import { getProduct, getBelongType, getProductType, getProps, } from '@/httpRequests/ProductListRequest' import { IProductInfo } from '@/Interfaces/ProductList' import { useRouter, useRoute } from 'vue-router' import router from '@/router' export default { setup() { var router = useRouter() var route = useRoute() const pageController = reactive({ isShowLeft: ref(false), isShowCover: ref(false), isShowSearchBtn: ref(false), }) //IProductInfo const productInfo: IProductInfo = reactive({ systemIndex: '1', products: [], belongTypes: [], productTypes: [], typeSelected: '', searchText: '', propSelect: {}, productProps: {}, timer: 0, /** * 获取物品 */ getProducts: async ( systemIndex: string, productType: string | null = null, searchText: string | null ) => { productInfo.products = await getProduct({ searchText: searchText, systemNo: systemIndex, productType: productType, sort: 'ProductName', pageIndex: 1, }) console.log(productInfo.products) }, /** *价格保留两位小数 */ tranPrice: (price: number) => { if (price == null) { return '0.00' } else { return price.toFixed(2).toString() } }, getBelongType: async () => { productInfo.belongTypes = await getBelongType() console.log(productInfo.belongTypes) }, /** * 从后端获取物品类型 */ getProductType: async (sysNo: string) => { productInfo.productTypes = await getProductType(sysNo) }, /** * 点击大类时我们不需要考虑搜索的内容,因为每次点击大类,都应该清空搜索框 * 但是搜索物品时,就应该考虑大类 */ getSystemProduct: async (index: string) => { router.push(`/productList?belongType=${index}`) }, /** *从后端获取物品属性 */ getProps: async (belongTypeNo: string, typeNo: string | null = null) => { console.log('belongTypeNo:' + belongTypeNo) var res = await getProps({ belongTypeNo, typeNo }) productInfo.productProps = res console.log(res) }, /** * 获取物品属性种类的名称 */ getPropKey: (key: string, index: number) => { return key.split('|')[index] }, /** * 选择物品类型 ,选择物品类型时可以清空搜索栏 */ selectType: async (typeNo: string) => { if (productInfo.typeSelected != typeNo) { productInfo.typeSelected = typeNo } setRouter() }, /** *搜索物品 */ search: async () => { clearTimeout(productInfo.timer) productInfo.timer = setTimeout(async () => { setRouter() }, 1000) }, selectProp: (propKey: string, propValue: string) => { if (productInfo.propSelect[propKey] == propValue) { productInfo.propSelect[propKey] = '' } else { productInfo.propSelect[propKey] = propValue } console.log(productInfo.propSelect) }, confirmFilter: () => { for (const key in productInfo.propSelect) { const value = productInfo.propSelect[key] productProps += `${key}_${value}%5E` } // console.log(productProps) productProps = productProps.substring(0, productProps.length - 3) console.log(productProps) // productInfo.propSelect.forEach((value: any, key: any) => { // console.log(value) // console.log(key) // }) }, }) const setRouter = () => { var url = `/productList?belongType=${productInfo.systemIndex}` if (productInfo.searchText?.trim() != '') { url += `&keyword=${productInfo.searchText}` } if (productInfo.typeSelected?.trim() != '') { url += `&type=${productInfo.typeSelected}` } router.push(url) } const showLeft = () => { pageController.isShowLeft = !pageController.isShowLeft } const searchFocus = () => { pageController.isShowSearchBtn = true } const searchBlur = () => { pageController.isShowSearchBtn = false } const showRight = () => { pageController.isShowCover = true var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '0' } const hideRight = () => { pageController.isShowCover = false var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '-85%' } //解析地址 let keyword: string | null = '' let systemIndex: string = '' let typeSelected: string = '' let productProps: string = '' const resoluationAddress = () => { keyword = (route.query.keyword as string) ?? '' productInfo.systemIndex = systemIndex = (route.query.belongType as string) ?? '1' productInfo.typeSelected = typeSelected = (route.query.type as string) ?? '' productProps = (route.query.prop as string) ?? '' if (productProps != '') { var arrayProductProps = productProps.split('%5E') for (let i = 0; i < arrayProductProps.length; i++) { const value: any = arrayProductProps[i] productInfo.propSelect[value.split('_')[0]] = value.split('_')[1] } } //格式大约是 &prop=xxx_xxx%5Eyyy_yy console.log(systemIndex) } onMounted(async () => { resoluationAddress() await productInfo.getProducts(systemIndex, typeSelected, keyword) await productInfo.getBelongType() await productInfo.getProductType(systemIndex) await productInfo.getProps(systemIndex, typeSelected) }) return { ...toRefs(pageController), ...toRefs(productInfo), showLeft, searchFocus, searchBlur, showRight, hideRight, } }, } </script> <style lang="scss" scoped> .i-search:after { background-color: #b70101 !important; } .search-pad { z-index: 10; position: fixed; width: 100%; padding: 6px 20px; background-color: #f0f0f0; display: flex; input { height: 28px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 3px; flex: 1; outline: none; } button { background-color: transparent; width: 56px; border: 0 none; font-size: 14px; font-weight: bold; color: #333; outline: none; } } .system-pad { z-index: 10; position: fixed; width: 100%; top: 40px; background-color: #fff; display: flex; .system-item { flex: 1; text-align: center; border-bottom: 1px #ddd solid; border-right: 1px transparent solid; border-left: 1px transparent solid; span { border: 0 none !important; background-color: #f0f2f5; margin: 6px 5px; font-size: 12px; font-weight: normal; text-align: center; border-radius: 4px; padding: 6px 0; display: block; height: 20px; line-height: 12px; } } .system-select { border-bottom: 1px transparent solid; border-right: 1px #ddd solid; border-left: 1px #ddd solid; span { background-color: transparent; } } } .product-list { padding-top: 75px; ul { background-color: #fff; li { list-style: none; height: 88px; padding-left: 108px; position: relative; img { height: 66px; width: 66px; background-color: #ccc; position: absolute; left: 28px; top: 11px; } div { padding: 10px 0; border-bottom: 1px solid #f0f0f0; padding-bottom: 12px; text-align-last: left; .p-name { font-size: 13px; } .p-type { font-size: 12px; color: #666; margin-top: 8px; } .p-price { font-size: 13px; color: #f23030; margin-top: 8px; } } } } .left-menu { position: fixed; height: calc(100% - 116px); left: -106px; width: 125px; background-color: #fff; top: 76px; border-radius: 0 18px 0 0; border: 1px solid #d7d7d7; overflow: hidden; transition: 0.5s; margin-bottom: 120px; .left-switch { width: 20px; background-color: #fff; position: absolute; right: 0; height: 100%; img { position: absolute; top: 42%; left: 2px; width: 20px; transform: rotate(90deg); transition: 0.5s; } } ul { position: absolute; height: 100%; width: 106px; background-color: #f0f0f0; overflow: auto; li { width: 106px; height: 50px; text-align: center; line-height: 50px; border-bottom: 1px solid #d7d7d7; padding: 0; font-size: 12px; color: #333; } li.left-item-select { background-color: #fff; } } } .left-menu-show { left: 0; .left-switch { img { transform: rotate(-90deg); } } } } .right-pad { position: fixed; /* right: -85%; */ right: -85%; top: 0; width: 85%; height: 100%; background-color: #f7f7f7; z-index: 103; transition: 580ms; z-index: 101; ul { list-style: none; overflow: hidden; } .list-pad { overflow: auto; height: 100%; padding-bottom: 40px; .f-type-list { overflow: hidden; > li { padding: 10px; background-color: #fff; margin-bottom: 10px; .f-item-list { overflow: auto; display: flex; flex-wrap: wrap; li { flex-basis: 33.3%; span { display: block; margin-top: 10px; margin-right: 10px; background: #eee; border: 1px solid #eee; padding: 5px 0; text-align: center; border-radius: 6px; font-size: 13px; overflow: hidden; height: 39px; } .prop-select { border: 1px solid red; background: #fff; color: red; } } } p { font-size: 14px; } } } } .right-edit { position: absolute; bottom: 0; left: 0; width: 100%; button { float: left; height: 40px; width: 50%; line-height: 40px; text-align: center; border: 0px none; } } } .cover { position: fixed; height: 100%; width: 100%; left: 0; top: 0; background-color: rgba(51, 51, 51, 0.36); z-index: 11; } </style>
11.修复前端bug,左侧筛选框,url地址拼接失败问题
点击查看代码
<template> <div> <!-- 搜索面板 --> <div class="search-pad"> <input v-model="searchText" type="text" name="" id="" @focus="searchFocus()" @blur="searchBlur()" @input="search" /> <button v-show="isShowSearchBtn">搜索</button> <button v-show="!isShowSearchBtn" @click="showRight()">筛选</button> </div> <!-- 物品大类面板 --> <div class="system-pad"> <div v-for="belongType in belongTypes" :key="belongType.sysNo" :class="[ 'system-item', { 'system-select': systemIndex == belongType.sysNo }, ]" @click="getSystemProduct(belongType.sysNo)" > <span>{{ belongType.belongTypeName }}</span> </div> </div> <!-- 物品展示列表 --> <div class="product-list"> <ul> <li v-for="product in products" :key="product.id"> <img :src="product.productPhoto?.productPhotoUrl" alt="" /> <div> <p class="p-name">{{ product.productName }}</p> <p class="p-type">类别:{{ product.typeName }}</p> <p class="p-price"> ¥{{ tranPrice(product.productSale?.salePrice) }}/张 </p> </div> </li> </ul> <!-- 左边物品类型面板 --> <div :class="['left-menu', { 'left-menu-show': isShowLeft }]"> <div class="left-switch" @click="showLeft()"> <img src="/img/dealerImgs/up.png" alt="" /> </div> <ul> <li v-for="productType in productTypes" :key="productType.typeNo" @click="selectType(productType.typeNo)" :class="{ 'left-item-select': typeSelected == productType.typeNo }" > {{ productType.typeName }} </li> </ul> </div> </div> <!-- 右边物品属性面板 --> <div class="right-pad"> <div class="list-pad"> <ul class="f-type-list"> <template v-for="(values, key) in productProps"> <li v-if="values.length > 0" :key="key"> <p>{{ getPropKey(key, 1) }}</p> <ul class="f-item-list"> <li v-for="value in values" :key="value" @click="selectProp(getPropKey(key, 0), value)" > <span :class="{ 'prop-select': propSelect[getPropKey(key, 0)] == value, }" >{{ value }}</span > </li> <!-- <li><span class="prop-select">胡桃色</span></li> --> </ul> <div class="clear-tag"></div> </li> </template> </ul> </div> <div class="right-edit"> <button @click="confirmFilter()" style="background-color: rgb(188, 0, 0); color: #fff" > 确定 </button> <button @click="hideRight()">取消</button> </div> </div> <div class="cover" v-show="isShowCover" @click="hideRight()"></div> </div> </template> <script lang="ts"> import { ref, onMounted, reactive, toRefs } from 'vue' import { getProduct, getBelongType, getProductType, getProps, } from '@/httpRequests/ProductListRequest' import { IProductInfo } from '@/Interfaces/ProductList' import { useRouter, useRoute } from 'vue-router' import router from '@/router' export default { setup() { var router = useRouter() var route = useRoute() const pageController = reactive({ isShowLeft: ref(false), isShowCover: ref(false), isShowSearchBtn: ref(false), }) //IProductInfo const productInfo: IProductInfo = reactive({ systemIndex: '1', products: [], belongTypes: [], productTypes: [], typeSelected: '', searchText: '', propSelect: {}, productProps: {}, timer: 0, /** * 获取物品 */ getProducts: async ( systemIndex: string, productType: string | null = null, searchText: string | null ) => { productInfo.products = await getProduct({ searchText: searchText, systemNo: systemIndex, productType: productType, sort: 'ProductName', pageIndex: 1, }) console.log(productInfo.products) }, /** *价格保留两位小数 */ tranPrice: (price: number) => { if (price == null) { return '0.00' } else { return price.toFixed(2).toString() } }, getBelongType: async () => { productInfo.belongTypes = await getBelongType() console.log(productInfo.belongTypes) }, /** * 从后端获取物品类型 */ getProductType: async (sysNo: string) => { productInfo.productTypes = await getProductType(sysNo) }, /** * 点击大类时我们不需要考虑搜索的内容,因为每次点击大类,都应该清空搜索框 * 但是搜索物品时,就应该考虑大类 */ getSystemProduct: async (index: string) => { router.push(`/productList?belongType=${index}`) }, /** *从后端获取物品属性 */ getProps: async (belongTypeNo: string, typeNo: string | null = null) => { console.log('belongTypeNo:' + belongTypeNo) var res = await getProps({ belongTypeNo, typeNo }) productInfo.productProps = res console.log(res) }, /** * 获取物品属性种类的名称 */ getPropKey: (key: string, index: number) => { return key.split('|')[index] }, /** * 选择物品类型 ,选择物品类型时可以清空搜索栏 */ selectType: async (typeNo: string) => { if (productInfo.typeSelected != typeNo) { productInfo.typeSelected = typeNo } setRouter() }, /** *搜索物品 */ search: async () => { clearTimeout(productInfo.timer) productInfo.timer = setTimeout(async () => { setRouter() }, 1000) }, selectProp: (propKey: string, propValue: string) => { if (productInfo.propSelect[propKey] == propValue) { productInfo.propSelect[propKey] = '' } else { productInfo.propSelect[propKey] = propValue } console.log(productInfo.propSelect) }, /** * 确认筛选 */ confirmFilter: () => { productProps = '' for (const key in productInfo.propSelect) { const value = productInfo.propSelect[key] productProps += `${key}_${value}^` } productProps = productProps.substring(0, productProps.length - 1) console.log(productProps) setRouter() }, }) /** * 设置路由 */ const setRouter = () => { // 根地址 包含根路由以及物品大类信息 var url = `/productList?belongType=${productInfo.systemIndex}` // 拼接物品搜索信息 if (productInfo.searchText?.trim() != '') { url += `&keyword=${productInfo.searchText}` } // 拼接物品类型 if (productInfo.typeSelected?.trim() != '') { url += `&type=${productInfo.typeSelected}` } if (productProps != '') { url += `&prop=${productProps}` } // 拼接属性 router.push(url) } const showLeft = () => { pageController.isShowLeft = !pageController.isShowLeft } const searchFocus = () => { pageController.isShowSearchBtn = true } const searchBlur = () => { pageController.isShowSearchBtn = false } const showRight = () => { pageController.isShowCover = true var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '0' } const hideRight = () => { pageController.isShowCover = false var dom = document.querySelector('.right-pad') as HTMLElement dom.style.right = '-85%' } //解析地址 let keyword: string | null = '' let systemIndex: string = '' let typeSelected: string = '' let productProps: string = '' const resoluationAddress = () => { keyword = (route.query.keyword as string) ?? '' productInfo.systemIndex = systemIndex = (route.query.belongType as string) ?? '1' productInfo.typeSelected = typeSelected = (route.query.type as string) ?? '' productProps = (route.query.prop as string) ?? '' if (productProps != '') { var arrayProductProps = productProps.split('^') for (let i = 0; i < arrayProductProps.length; i++) { const value: any = arrayProductProps[i] productInfo.propSelect[value.split('_')[0]] = value.split('_')[1] } } //格式大约是 &prop=xxx_xxx^yyy_yy console.log(systemIndex) } onMounted(async () => { resoluationAddress() await productInfo.getProducts(systemIndex, typeSelected, keyword) await productInfo.getBelongType() await productInfo.getProductType(systemIndex) await productInfo.getProps(systemIndex, typeSelected) }) return { ...toRefs(pageController), ...toRefs(productInfo), showLeft, searchFocus, searchBlur, showRight, hideRight, } }, } </script> <style lang="scss" scoped> .i-search:after { background-color: #b70101 !important; } .search-pad { z-index: 10; position: fixed; width: 100%; padding: 6px 20px; background-color: #f0f0f0; display: flex; input { height: 28px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 3px; flex: 1; outline: none; } button { background-color: transparent; width: 56px; border: 0 none; font-size: 14px; font-weight: bold; color: #333; outline: none; } } .system-pad { z-index: 10; position: fixed; width: 100%; top: 40px; background-color: #fff; display: flex; .system-item { flex: 1; text-align: center; border-bottom: 1px #ddd solid; border-right: 1px transparent solid; border-left: 1px transparent solid; span { border: 0 none !important; background-color: #f0f2f5; margin: 6px 5px; font-size: 12px; font-weight: normal; text-align: center; border-radius: 4px; padding: 6px 0; display: block; height: 20px; line-height: 12px; } } .system-select { border-bottom: 1px transparent solid; border-right: 1px #ddd solid; border-left: 1px #ddd solid; span { background-color: transparent; } } } .product-list { padding-top: 75px; ul { background-color: #fff; li { list-style: none; height: 88px; padding-left: 108px; position: relative; img { height: 66px; width: 66px; background-color: #ccc; position: absolute; left: 28px; top: 11px; } div { padding: 10px 0; border-bottom: 1px solid #f0f0f0; padding-bottom: 12px; text-align-last: left; .p-name { font-size: 13px; } .p-type { font-size: 12px; color: #666; margin-top: 8px; } .p-price { font-size: 13px; color: #f23030; margin-top: 8px; } } } } .left-menu { position: fixed; height: calc(100% - 116px); left: -106px; width: 125px; background-color: #fff; top: 76px; border-radius: 0 18px 0 0; border: 1px solid #d7d7d7; overflow: hidden; transition: 0.5s; margin-bottom: 120px; .left-switch { width: 20px; background-color: #fff; position: absolute; right: 0; height: 100%; img { position: absolute; top: 42%; left: 2px; width: 20px; transform: rotate(90deg); transition: 0.5s; } } ul { position: absolute; height: 100%; width: 106px; background-color: #f0f0f0; overflow: auto; li { width: 106px; height: 50px; text-align: center; line-height: 50px; border-bottom: 1px solid #d7d7d7; padding: 0; font-size: 12px; color: #333; } li.left-item-select { background-color: #fff; } } } .left-menu-show { left: 0; .left-switch { img { transform: rotate(-90deg); } } } } .right-pad { position: fixed; /* right: -85%; */ right: -85%; top: 0; width: 85%; height: 100%; background-color: #f7f7f7; z-index: 103; transition: 580ms; z-index: 101; ul { list-style: none; overflow: hidden; } .list-pad { overflow: auto; height: 100%; padding-bottom: 40px; .f-type-list { overflow: hidden; > li { padding: 10px; background-color: #fff; margin-bottom: 10px; .f-item-list { overflow: auto; display: flex; flex-wrap: wrap; li { flex-basis: 33.3%; span { display: block; margin-top: 10px; margin-right: 10px; background: #eee; border: 1px solid #eee; padding: 5px 0; text-align: center; border-radius: 6px; font-size: 13px; overflow: hidden; height: 39px; } .prop-select { border: 1px solid red; background: #fff; color: red; } } } p { font-size: 14px; } } } } .right-edit { position: absolute; bottom: 0; left: 0; width: 100%; button { float: left; height: 40px; width: 50%; line-height: 40px; text-align: center; border: 0px none; } } } .cover { position: fixed; height: 100%; width: 100%; left: 0; top: 0; background-color: rgba(51, 51, 51, 0.36); z-index: 11; } </style>
12.后端改造
这篇关于.NET经销商实战(十二)——优化用户体验,完善产品列表查询的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-03-01沐雪多租宝商城源码从.NetCore3.1升级到.Net6的步骤
- 2024-05-08首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!
- 2024-03-30C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
- 2024-03-29c# datetime tryparse
- 2024-02-21list find index c#
- 2024-01-24convert toint32 c#
- 2024-01-24Advanced .Net Debugging 1:你必须知道的调试工具
- 2024-01-24.NET集成IdGenerator生成分布式全局唯一ID
- 2024-01-23用CI/CD工具Vela部署Elasticsearch + C# 如何使用
- 2024-01-23.NET开源的简单、快速、强大的前后端分离后台权限管理系统