hookehuyr

完善申领物资页面,选择逻辑,加入购物车逻辑,填写数量逻辑

<!--
* @Date: 2024-07-23 12:53:15
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2024-07-24 11:05:03
* @LastEditTime: 2024-07-24 14:44:31
* @FilePath: /temple_material_request/src/views/material_request.vue
* @Description: 申领物资页面
-->
<template>
<div class="material-request-page">
<van-tabs v-model:active="active" @change="onChange" sticky :color="styleColor.baseColor">
<van-tab v-for="index in 8" :title="'标签 ' + index">
<div class="list-wrapper">
<van-sticky :offset-top="44">
<van-row justify="space-between" class="select-all-item">
<van-col span="8"><van-icon name="passed" size="1.25rem" />&nbsp;&nbsp;<span :style="{ color: styleColor.baseColor }">全选</span></van-col>
<van-col span="8">
<van-icon v-if="is_all_checked" @click="onCheckAll()" name="checked" size="1.25rem" :color="styleColor.baseColor" />
<van-icon v-else name="passed" @click="onCheckAll()" size="1.25rem" />
<span @click="onCheckAll()" :style="{ color: styleColor.baseColor }">&nbsp;&nbsp;全选</span>
</van-col>
<van-col span="16" style="text-align: right; font-size: 0.85rem; color: #666666;">参考上次同类活动的领用情况</van-col>
</van-row>
</van-sticky>
......@@ -22,17 +27,31 @@
finished-text="没有更多了"
@load="onLoad"
>
<div v-for="item in list" :key="item" class="list-boxer">
<div v-for="item in list" :id="item.id" :key="item.id" class="list-boxer">
<van-row align="center" justify="space-between">
<van-col span="16" style="display: flex;">
<van-icon name="passed" size="1.25rem" />&nbsp;&nbsp;<div class="van-ellipsis" :style="{ color: styleColor.baseColor, textDecoration: 'underline' }" @click="onClickTitle(item)">床垫 1.2m*2m</div>
<van-icon v-if="item.checked" @click="onCheck(item)" name="checked" size="1.25rem" :color="styleColor.baseColor" />
<van-icon v-else name="passed" @click="onCheck(item)" size="1.25rem" />&nbsp;&nbsp;
<div class="van-ellipsis" :style="{ color: styleColor.baseColor, textDecoration: 'underline' }" @click="onClickTitle(item)">
{{ item.name }}
</div>
</van-col>
<van-col span="8" style="display: flex; align-items: center;">
<van-field v-model="num_value" style="border: 1px solid #f0f0f0; padding: 0; border-radius: 5px;" label="" label-width="0" input-align="center" placeholder="数量" type="number" >
<van-field
v-model="item.num"
style="border: 1px solid #f0f0f0; padding: 0; border-radius: 5px;"
label=""
label-width="0"
input-align="center"
placeholder="数量"
type="number"
@blur="onBlur(item)"
>
<template #left-icon></template>
</van-field>&nbsp;&nbsp;<span style="font-size: 0.9rem; color: #666;">个</span>
</van-col>
</van-row>
<div v-if="item.error" style="padding: 0.5rem 2rem 0 0; font-size: 0.85rem; color: red; text-align: right;">输入值有误</div>
</div>
</van-list>
<div style="height: 6rem;"></div>
......@@ -46,11 +65,12 @@
<div style="display: flex; align-items: center;">
<van-button plain type="primary" :color="styleColor.baseColor" @click="addShoppingCart">加入购物车</van-button>
&nbsp;&nbsp;
<van-badge :content="5">
<van-badge :content="cart_count">
<van-icon name="shopping-cart-o" size="2.5rem" :color="styleColor.baseColor" @click="goShoppingCart" />
</van-badge>
</div>
</div>
</div>
<choose-material :show="show_choose_material" @close="onCloseChoose"></choose-material>
......@@ -74,11 +94,58 @@ const $route = useRoute();
const $router = useRouter();
useTitle($route.meta.title);
const is_all_checked = ref(false);
const num_value = ref('');
const onCheckAll = () => {
is_all_checked.value = !is_all_checked.value;
if (is_all_checked.value) {
list.value.forEach(item => {
item.checked = true;
})
} else {
list.value.forEach(item => {
item.checked = false;
item.error = false;
})
}
}
const onCheck = (item) => {
item.checked = !item.checked;
// 全部为选中
let all_checked = list.value.every((item) => item.checked === true);
if (all_checked) {
is_all_checked.value = true;
} else {
is_all_checked.value = false;
}
// 如果取消选中,隐藏错误提示
if (!item.checked) {
item.error = false;
}
}
const onBlur = (item) => { // 输入框失去焦点回调
if (item.checked) {
if (item.num === null || item.num === '') {
item.error = true;
} else {
item.error = false;
}
}
}
const active = ref(0);
const onChange = (index) => {
const onChange = (index) => { // 切换标签回调
console.warn(index);
// 取消全选
is_all_checked.value = false;
// TODO:重新查询列表数据, 取消选中
list.value.forEach(item => {
item.checked = false;
item.error = false;
});
}
const list = ref([]);
......@@ -90,7 +157,7 @@ const onLoad = () => {
// setTimeout 仅做示例,真实场景中一般为 ajax 请求
setTimeout(() => {
for (let i = 0; i < 10; i++) {
list.value.push(list.value.length + 1);
list.value.push({ id: list.value.length + 1, name: '标题 床垫 1.2m*2m', num: null, checked: false, error: false });
}
// 加载状态结束
......@@ -101,6 +168,8 @@ const onLoad = () => {
finished.value = true;
}
}, 1000);
// TODO: 如果查询到的数据大于0,需要取消全选
is_all_checked.value = false;
};
const onClickTitle = (item) => { // 点击物资标题回调
......@@ -113,8 +182,29 @@ const addMore = () => { // 添加更多
show_choose_material.value = true;
}
const cart_count = ref(0);
const shop_cart_list = ref([]); // 购物车列表
const addShoppingCart = () => { // 加入购物车
console.warn('addShoppingCart');
shop_cart_list.value = [];
// 把选中的值集合
list.value
.filter(item => item.checked)
.forEach(item => {
shop_cart_list.value = shop_cart_list.value.concat(item);
});
// 校验购物车值
let error_list = shop_cart_list.value.filter((item) => { if (item.num === null || item.num === '') { return item;} })
if (error_list.length) {
// 跳到第一个错误框
scrollToSection(error_list[0].id);
// 标记所有错误
error_list.forEach(item => {
item.error = true;
})
return;
}
// 购物车数量
cart_count.value = shop_cart_list.value.length;
}
const goShoppingCart = () => { // 跳转购物车
......@@ -131,6 +221,20 @@ const show_material_detail = ref(false);
const onCloseDetail = () => {
show_material_detail.value = false;
}
const scrollToSection = (id) => { // 滚动到指定位置
const current_index = list.value.findIndex((item) => item.id === id);
// 因为布局问题,需要滚动到上一个节点 查询上一个节点ID
const previous_index = current_index - 2 >= 0 ? current_index - 2 : 0;
nextTick(() => {
let element = $('.list-wrapper').find(`#${list.value[previous_index]['id']}`);
if (element[0]) {
element[0].scrollIntoView({ behavior: 'smooth' });
} else {
console.log('Element with ID ' + id + ' not found.');
}
})
}
</script>
<style lang="less" scoped>
......