.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.后端改造
标签:实战,color,列表,productInfo,background,NET,height,border,left 来源: https://www.cnblogs.com/humblexwang/p/16303533.html