Browse Source

feat(地址管理): 新增收货地址添加页面及相关功能

refactor(键盘组件): 优化键盘组件逻辑并添加与store的交互

fix(购物车): 修复购物车数量修改逻辑及结算流程

style: 调整多个页面的z-index值及样式细节

perf(验证工具): 优化validates函数返回布尔值的处理逻辑
master
wei 2 days ago
parent
commit
b3d1d587f9
  1. 205
      components/keyboard/keyboard copy.vue
  2. 13
      components/keyboard/keyboard.vue
  3. 31
      libs/api/index.js
  4. 16
      libs/utils/index.js
  5. 0
      md.md
  6. 6
      pages.json
  7. 106
      pages/allDish/allDish.vue
  8. 150
      pages/deliveryAddress/addDeliveryAddress.scss
  9. 264
      pages/deliveryAddress/addDeliveryAddress.vue
  10. 2
      pages/deliveryAddress/deliveryAddress.vue
  11. 10
      pages/home/home.scss
  12. 114
      pages/home/home.vue
  13. 4
      pages/login/login.vue
  14. 8
      pages/personalInformation/personallInformation.scss
  15. 2
      pages/shoppingCart/shoppingCart.scss
  16. 122
      pages/shoppingCart/shoppingCart.vue
  17. 5
      store/index.js
  18. 1
      uni.scss

205
components/keyboard/keyboard copy.vue

@ -0,0 +1,205 @@
<script setup>
import { defineEmits, ref } from "vue";
const emit = defineEmits(["confirm", "cancel"]);
const inputValue = ref("");
function onTap(key) {
if (key === "confirm") {
//
if (inputValue.value === "") {
uni.showToast({
title: "请输入数量",
icon: "none",
// duration: 99999999,
});
return;
}
emit("confirm", Number(inputValue.value));
}
else if (key === "cancel") {
//
emit("cancel");
}
else if (key === "clear") {
//
inputValue.value = "";
}
else if (key === "delete") {
//
inputValue.value = inputValue.value.slice(0, -1);
}
else {
//
const nextValue = inputValue.value + key;
if (nextValue > 999) {
uni.showToast({
title: "数量不能超过999",
icon: "none",
});
return;
}
inputValue.value = `${Number(nextValue)}`;
}
}
</script>
<template>
<view class="keyboard">
<view class="keyboard-body">
<input class="select-num-top" placeholder="限0~999" disabled :value="inputValue">
<view class="key" @tap="() => onTap('1')">
1
</view>
<view class="key" @tap="() => onTap('2')">
2
</view>
<view class="key" @tap="() => onTap('3')">
3
</view>
<view class="key action delete" @tap="() => onTap('delete')">
</view>
<view class="key" @tap="() => onTap('4')">
4
</view>
<view class="key" @tap="() => onTap('5')">
5
</view>
<view class="key" @tap="() => onTap('6')">
6
</view>
<view class="key action clear" @tap="() => onTap('clear')">
清空
</view>
<view class="key" @tap="() => onTap('7')">
7
</view>
<view class="key" @tap="() => onTap('8')">
8
</view>
<view class="key" @tap="() => onTap('9')">
9
</view>
<view class="key action confirm" @tap="() => onTap('confirm')">
确定
</view>
<view class="key zero span-2" @tap="() => onTap('0')">
0
</view>
<view class="key cancel" @tap="() => onTap('cancel')">
取消
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.keyboard {
width: 100vw;
height: 100%;
position: fixed;
left: 0;
bottom: 0;
z-index: $z-index-popup;
background: rgba(0, 0, 0, 0.03);
}
/* Grid 容器:3列数字 + 1列操作 */
.keyboard-body {
box-sizing: border-box;
background: #f2f3f5;
padding: 20rpx 20rpx env(safe-area-inset-bottom) 20rpx;
left: 0;
bottom: 0;
display: grid;
position: fixed;
width: 100%;
grid-template-columns: repeat(3, 1fr) 1fr; /* 四列 */
/* 顶部输入占一整行 + 下方4行按键 */
grid-template-rows: 100rpx repeat(4, 84rpx);
gap: 12rpx;
}
/* 键通用样式 */
.key {
background-color: #fff;
border-radius: 12rpx;
// border: 1px solid #d8d8d8;
display: flex;
align-items: center;
justify-content: center;
font-size: $text-4xl;
font-weight: 430;
&:active {
background-color: #e0e2e7;
}
}
/* 0 跨两列:第4行的第1-2列 */
.span-2 {
grid-column: 1 / span 2;
}
/* 取消:第4行第3列 */
.cancel {
grid-column: 3;
grid-row: 4;
background-color: #e0e2e7;
&:active {
background-color: #fff;
}
}
/* 右侧操作列(第4列) */
.action {
background-color: #e0e2e7;
&:active {
background-color: #fff;
}
}
/* 删除:第1行第4列 */
.action.delete {
grid-column: 4;
grid-row: 2;
}
/* 清空:第2行第4列 */
.action.clear {
grid-column: 4;
grid-row: 3;
}
/* 确定:第3行开始,跨两行占第3-4行第4列 */
.action.confirm {
grid-column: 4;
grid-row: 4 / span 2;
}
/* 取消:第5行第3列 */
.cancel {
grid-column: 3;
grid-row: 5;
}
/* 顶部输入:跨4列、位于第1行 */
.keyboard .select-num-top {
height: 100rpx;
border: none;
font-size: 32rpx;
font-weight: bold;
color: #000;
padding: 0rpx 10rpx;
text-align: center;
border-radius: 12rpx;
background: #fff;
/* 关键定位 */
grid-column: 1 / -1;
grid-row: 1;
}
</style>

13
components/keyboard/keyboard.vue

@ -1,10 +1,13 @@
<script setup>
import { defineEmits, ref } from "vue";
import useStore from "@/store";
const emit = defineEmits(["confirm", "cancel"]);
const inputValue = ref("");
function onTap(key) {
const store = useStore();
async function onTap(key) {
if (key === "confirm") {
//
if (inputValue.value === "") {
@ -17,10 +20,14 @@ function onTap(key) {
}
emit("confirm", Number(inputValue.value));
store.cache.keyboardConfirm(Number(inputValue.value));
}
else if (key === "cancel") {
//
emit("cancel");
// const [, cancel] = keyboardEmit();
// cancel();
}
else if (key === "clear") {
//
@ -100,13 +107,13 @@ function onTap(key) {
<style lang="scss" scoped>
.keyboard {
width: 100%;
width: 100vw;
height: 100%;
position: fixed;
left: 0;
bottom: 0;
z-index: $z-index-popup;
background: rgba(0, 0, 0, .8);
background: rgba(0, 0, 0, 0.03);
}
/* Grid 容器:3列数字 + 1列操作 */

31
libs/api/index.js

@ -445,3 +445,34 @@ export function getNewsListApi(params = {}) {
// odule.exports.addCart = function (postData, success) {
// request('/cart/add.do', 'POST', postData, success);
// };
/**
* 获取地址选择数据列表
*/
export function getAreaInfoApi() {
return request({
errorMessage: "地址选择数据",
method: "GET",
url: "/addr/tree.do",
});
}
// //添加收货地址
// module.exports.addAddress = function (postData, success) {
// request('/receiverAddr/add.do', 'POST', postData, success)
// }
/**
* 添加收货地址
*/
export function addAddressApi(data = {}) {
return request({
errorMessage: "添加收货地址",
method: "POST",
data,
header: {
"content-type": "application/x-www-form-urlencoded;charset=UTF-8",
},
url: "/receiverAddr/add.do",
});
}

16
libs/utils/index.js

@ -146,7 +146,7 @@ export function gotoBack() {
* @typedef {object} toastConfig
* @property {string} title - toast标题
* @property {string} icon - toast图标默认none
* @property {boolean} returnBoolean - 是否返回字符串默认返回布尔值
* @property {boolean} returnBoolean - 是否返回布尔值默认返回布尔值
*/
/**
@ -168,10 +168,13 @@ export function validates(validators, toastConfig = { icon: "none", returnBoolea
for (const validator of validatorsFlat) {
const msg = validator();
if (msg) {
if (toastConfig.returnBoolean) {
uni.showToast({
...toastConfig,
title: msg,
});
}
return toastConfig.returnBoolean ? false : msg;
}
}
@ -202,3 +205,14 @@ export function increaseFontScale(incScale = 0.1) {
uni.setStorageSync("fontScale", store.fontScale);
// validates(() => true && `${store.fontScale} 倍数`);
}
/**
* 获取指定路由的页面实例
* @param {string} route 页面路由
* @returns {object|undefined} 页面实例或undefined
*/
export function getPage(route) {
const pages = getCurrentPages();
const page = pages.find(page => page.route == route);
return page;
}

0
md.md

6
pages.json

@ -67,6 +67,12 @@
"navigationBarTitleText": ""
}
},
{
"path": "pages/deliveryAddress/addDeliveryAddress",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "pages/joinEnterprise/joinEnterprise",
"style": {

106
pages/allDish/allDish.vue

@ -2,6 +2,7 @@
import { onHide, onShow } from "@dcloudio/uni-app";
import { nextTick, ref } from "vue";
import customTabBar from "@/components/custom-tab-bar/my-tab-bar.vue";
import keyboard from "@/components/keyboard/keyboard.vue";
// import navigation from "@/components/navigation/navigation.vue";
import navv from "@/components/nav/nav.vue";
import {
@ -205,9 +206,9 @@ const hasFetchedCart = ref(false);
*/
const inputValue = ref("");
/**
* 隐藏购买数量弹框
* 是否显示购买数量弹框
*/
// const hiddenModal = ref(true);
const isShowkeyboard = ref(false);
/**
* 搜索商品
*/
@ -709,8 +710,6 @@ async function toCart(item, diff) {
}
if (!data.warehouseId || !data.addrId) {
console.log(data.warehouseId, data.addrId);
uni.showModal({
title: "提示",
content: "请先选择收货地址,再添加商品",
@ -725,7 +724,8 @@ async function toCart(item, diff) {
if (res.code !== "0") {
return;
}
initCartInfo();
store.changeCartList(res.data.items);
// initCartInfo();
}
/**
@ -767,7 +767,64 @@ function onChooseNorm(item) {
// function onModelCancel() { }
function onShowKeyboard() { }
function openKeyBoard(item) {
isShowkeyboard.value = true;
store.cache.keyboardConfirm = (value) => {
determine(value, item);
};
}
/**
* 确定购买数量
* @param value 购买数量
* @param item 商品项
*/
async function determine(value, item) {
const isPass = validates([
() => item.stock != -1 && value > item.stock && "采购数量不能大于库存数量",
() => item.stock == 0 && "库存数量为0无法添加",
]);
if (!isPass) {
return;
}
item.sum = value;
isShowkeyboard.value = false;
const data = {
quantity: value,
specId: item.id,
Chuxiao: item.chuxiao,
warehouseId: uni.getStorageSync("warehousId"),
addrId: uni.getStorageSync("addressId"),
isUpdate: 1,
isChuxiao: false,
};
if (!data.specId) {
uni.showModal({
title: "提示",
content: "当前商品规格错误,请稍候再试",
showCancel: false,
confirmText: "确定",
});
}
if (!data.warehouseId || !data.addrId) {
uni.showModal({
title: "提示",
content: "请先选择收货地址,再添加商品",
showCancel: false,
confirmText: "确定",
});
}
const res = await addCartApi(data);
if (res.code !== "0") {
return;
}
// store.changeCartList(res.data);
await initCartInfo();
}
onShow(() => {
if (store.productTypeId) {
currentType.value = 0;
@ -1012,7 +1069,10 @@ onHide(() => {
<view class="minus" @tap.stop="() => onMinus(item.specs[0])">
<image class="icon" src="/static/home/minus.png" mode="" />
</view>
<text class="input" @tap="() => onShowKeyboard(item)">
<text
class="input"
@tap="() => openKeyBoard(item.specs[0])"
>
{{ item.specs[0].sum }}
</text>
</block>
@ -1065,11 +1125,17 @@ onHide(() => {
>
<image class="icon" src="/static/home/minus.png" mode="" />
</view>
<text
<!-- <text
class="input"
@tap="() => showKeyboard()"
>
{{ childs.sum }}
</text> -->
<text
class="input"
@tap="() => openKeyBoard(childs)"
>
{{ childs.sum }}
</text>
</block>
<view
@ -1165,24 +1231,6 @@ onHide(() => {
</view>
</view>
<!-- 输入购买数量弹框 -->
<!-- <modal
v-show="!hiddenModal"
title="修改购买数量"
confirm-text="确定"
cancel-text="取消"
@confirm="onModelConfirm"
@cancel="onModelCancel"
>
<input
placeholder="输入所需数量"
focus="{{focus}}"
:value="inputValue"
type="number"
@input="input"
>
</modal> -->
<!-- display: showBall ? '' : 'none' -->
<view
v-if="showBall"
@ -1196,6 +1244,12 @@ onHide(() => {
/>
</view>
<keyboard
v-if="isShowkeyboard"
@cancel="() => isShowkeyboard = false"
/>
<!-- @confirm="(val) => determine(val)" -->
<customTabBar tab-index="1" />
</template>
</navv>

150
pages/deliveryAddress/addDeliveryAddress.scss

@ -0,0 +1,150 @@
.section{
padding:20rpx 30rpx;
overflow: hidden;
font-size: 28rpx;
border-top: solid 1px #e7e7e7;
position: relative;
}
.section input{
float:left;
}
.section_title{
width:130rpx;
line-height:48rpx;
float: left;
}
.section_addressTxt{
float: left;
padding-left: 8rpx;
}
.section_right{
overflow: hidden;
position: relative;
width:110rpx;
margin-left:auto;
}
.section_right text{
float: left;
margin-right: 10rpx;
color: #737373
}
.arrow{
width: 20rpx;
height: 20rpx;
border-top: 4rpx solid #737373;
border-right: 4rpx solid #737373;
transform: rotate(45deg);
float: right;
position: absolute;
right: 5rpx;
margin-top: 10rpx;
}
.section textarea{
margin-top:10rpx;
line-height: 40rpx;
height: 120rpx;
}
.section switch{
flex: 1;
text-align: right;
}
.btn-area{
padding-top: 40rpx;
width:96%;
margin: 0 2%;
}
.primary{
line-height: 80rpx;
font-size: 28rpx;
background-color: #3aa24b !important;
}
switch{
margin-top: 4rpx;
}
.wx-switch-input{width:88rpx !important;height:52rpx !important;}
.wx-switch-input::before{width:86rpx !important;height: 52rpx !important;}
.wx-switch-input::after{width: 48rpx !important;height: 48rpx !important;}
.icon-dingwei{
position: absolute;
right: 20rpx;
top: 50rpx;
/* padding: 20rpx; */
z-index: 9999;
font-size: 50rpx;
}
.content {
background: #FFFFFF;
box-shadow: 0rpx 3rpx 14rpx 0rpx rgba(54,77,65,0.1);
border-radius: 14rpx;
// margin: 20rpx 14rpx 0;
box-sizing: border-box;
padding: 40rpx 28rpx;
}
.content .item {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 35rpx;
border-bottom: 1px solid #E6E6E6;
margin-bottom: 35rpx;
}
.content .item .left {
width: 30%;
font-weight: 400;
font-size: 29rpx;
color: #333333;
}
.content .item .right {
flex: 1;
margin-left: 20rpx;
}
.content .item .right .input {
font-size: 26rpx;
color: #333333;
text-align: left;
}
.content .item .right .select-box{
display: flex;
align-items: center;
}
.content .item .right .select-box .text{
font-weight: 400;
font-size: 26rpx;
color: #999999;
flex: 1;
margin-right: 15rpx;
}
.content .item .right .select-box .icon {
width: 13rpx;
height: 26rpx;
}
.content .item .right .select-box .icon-two {
width: 29rpx;
height: 28rpx;
}
.content .item .right .select-box .select-box-input{
flex: 1;
margin-right: 15rpx;
color: #333333;
}
.add-btn{
background: #06CA64;
border-radius: 60rpx;
margin: 60rpx 34rpx 0;
font-weight: bold;
font-size: 33rpx;
color: #FFFFFF;
}

264
pages/deliveryAddress/addDeliveryAddress.vue

@ -0,0 +1,264 @@
<script setup>
import { onLoad } from "@dcloudio/uni-app";
import { ref } from "vue";
import navv from "@/components/nav/nav.vue";
import topTitle from "@/components/topTitle/topTitle.vue";
import { addAddressApi, getAreaInfoApi } from "@/libs/api";
import { gotoBack, validates } from "@/libs/utils";
const cityLists = [];
const address = ref({
receiverName: "",
telephone: "",
region: "",
street: "",
defaultAddr: false,
});
/**
* 区域选择器索引
*/
const multiIndex = ref([0, 0, 0]);
/**
* 区域选择器数据
*/
const multiArray = ref([]);
/**
* 提交按钮文本
*/
const buttonTxt = ref("");
/**
* 多级选择器值改变事件
*/
function bindMultiPickerChange(e) {
const { value } = e.detail;
const info = multiArray.value;
// eslint-disable-next-line max-len
address.value.region = `${info[0][value[0]].address} ${info[1][value[1]].address} ${info[2][value[2]].address}`;
address.value.city = info[0][value[0]].address;
address.value.cityId = info[0][value[0]].id;
address.value.county = info[1][value[1]].address;
address.value.countyId = info[1][value[1]].id;
address.value.town = info[2][value[2]].address;
address.value.townId = info[2][value[2]].id;
}
/**
* 多级选择器列改变事件
*/
function bindMultiPickerColumnChange(e) {
const { column, value } = e.detail;
multiIndex.value[column] = value;
if (column == 0) {
multiArray.value[1] = cityLists[value].children;
multiArray.value[2] = cityLists[value].children[0].children;
multiIndex.value[1] = 0;
multiIndex.value[2] = 0;
}
else if (column == 1) {
multiArray.value = multiArray.value[1][value].children;
}
}
/**
* 选择地图位置事件
*/
function map() {
uni.chooseLocation({
success(res) {
console.log(res);
address.value.street = res.name;
address.value.map = `${res.longitude},${res.latitude}`;
},
fail() {
// fail
},
complete() {
// complete
},
});
}
//
// function switchChange() {}
/**
* 提交按钮点击事件
*/
async function submit() {
uni.showLoading({
title: "提交中....",
mask: true,
});
const msg = validates([
() => address.value.receiverName == "" && "收货人不能为空",
() => address.value.telephone == "" && "联系电话不能为空",
() => address.value.region == "" && "所在区域不能为空",
() => address.value.street == "" && "街道地址信息不能为空",
], { returnBoolean: false });
if (msg.length) {
uni.hideLoading();
uni.showToast({
title: msg,
icon: "none",
});
return;
}
if (buttonTxt.value == "确认添加") {
const res = await addAddressApi(address.value);
uni.hideLoading();
if (res.code !== "0") {
return;
}
gotoBack();
}
}
/**
* 获取城市列表
*/
async function getCityList() {
const res = await getAreaInfoApi();
if (res.code !== "0") {
return;
}
cityLists.push(...res.data);
multiArray.value = [cityLists, cityLists[0].children, cityLists[0].children[0].children];
}
onLoad((options) => {
getCityList();
if (options.key == "edit") {
uni.setNavigationBarTitle({
title: "修改收货地址",
});
buttonTxt.value = "确认修改";
address.value = JSON.parse(options.address);
}
else {
uni.setNavigationBarTitle({
title: "添加收货地址",
});
buttonTxt.value = "确认添加";
}
});
</script>
<template>
<navv>
<template #default="{ style, content }">
<topTitle title="添加收货地址" :style="style" />
<view
class="content"
:style="{
height: `${content}px`,
overflowY: 'auto',
}"
>
<view class="item">
<view class="left">
收货人
</view>
<view class="right">
<input
v-model="address.receiverName"
class="input"
type="text"
name="name"
placeholder-style="color:#999999"
placeholder="收货人姓名"
>
</view>
</view>
<view class="item">
<view class="left">
手机号
</view>
<view class="right">
<input
v-model="address.telephone"
class="input"
name="tel"
type="number"
data-item="telephone"
placeholder="收货人手机号"
placeholder-style="color:#999999"
>
</view>
</view>
<view class="item">
<view class="left">
所在地址
</view>
<view class="right">
<view class="select-box">
<picker
v-model="multiIndex"
style="flex: 1;"
mode="multiSelector"
:range="multiArray"
range-key="address"
@change="bindMultiPickerChange"
@columnchange="bindMultiPickerColumnChange"
>
<text v-if="!address.region" class="text">
请选择
</text>
<text v-else class="text" style="color: #333;">
{{ address.region }}
</text>
</picker>
<text class="iconfont icon-right" />
<!-- <image class="icon" src="../../../images/myinfo/arrow.png" mode="" /> -->
</view>
</view>
</view>
<view class="item">
<view class="left">
详细地址
</view>
<view class="right">
<view class="select-box">
<input
v-model="address.street"
class="select-box-input"
type="text"
placeholder="点击定位图标,选择详细地址"
placeholder-style="color:#999999"
data-item="street"
>
<text class="iconfont icon-right" @tap="map" />
<!-- <image
class="icon-two"
src="../../../images/nearby/addr.png"
mode=""
@tap="map"
/> -->
</view>
</view>
</view>
<view class="item">
<view class="left">
设为默认地址
</view>
<view class="right" style="text-align: right;">
<switch
:checked="address.defaultAddr"
style="font-size: 28rpx;"
color="#06CA64"
@change="(e) => address.defaultAddr = e.detail.value"
/>
</view>
</view>
<button form-type="submit" class="add-btn" @tap="submit">
{{ buttonTxt }}
</button>
</view>
</template>
</navv>
</template>
<style scoped lang="scss">
@import './addDeliveryAddress.scss';
</style>

2
pages/deliveryAddress/deliveryAddress.vue

@ -131,7 +131,7 @@ function optionTap(item) {
*/
function onGotoAdd() {
uni.navigateTo({
url: "/pages/addAddress/addAddress",
url: "/pages/deliveryAddress/addDeliveryAddress",
});
}

10
pages/home/home.scss

@ -293,7 +293,7 @@
opacity: 0.5;
position: absolute;
right: -8rpx;
z-index: $z-index-below;
z-index: -1;
}
.title {
font-size: 33rpx;
@ -433,7 +433,7 @@
width: 88%;
height: 1px;
background-color: #D6D6D6;
z-index: $z-index-below;
z-index: -1;
}
.line-two {
position: absolute;
@ -442,7 +442,7 @@
width: 88%;
height: 1px;
background-color: #D6D6D6;
z-index: $z-index-below;
z-index: -1;
}
.add {
width: 58rpx;
@ -534,7 +534,7 @@
width: 88%;
height: 1px;
background-color: #D6D6D6;
z-index: $z-index-below;
z-index: -1;
}
.line-two {
position: absolute;
@ -543,7 +543,7 @@
width: 88%;
height: 1px;
background-color: #D6D6D6;
z-index: $z-index-below;
z-index: -1;
}
.minus {
width: 58rpx;

114
pages/home/home.vue

@ -315,13 +315,57 @@ function changeSwiper(e) {
}
/**
* 点击确认按钮时将输入框的值赋值给商品项的sum属性
* @param e 事件对象
* 确定购买数量
* @param value 购买数量
* @param item 商品项
*/
function determine(value, item) {
console.log(value, 333);
async function determine(value, item) {
const isPass = validates([
() => item.stock != -1 && value > item.stock && "采购数量不能大于库存数量",
() => item.stock == 0 && "库存数量为0无法添加",
]);
if (!isPass) {
return;
}
item.sum = value;
isShowkeyboard.value = false;
const data = {
quantity: value,
specId: item.id,
Chuxiao: item.chuxiao,
warehouseId: uni.getStorageSync("warehousId"),
addrId: uni.getStorageSync("addressId"),
isUpdate: 1,
isChuxiao: false,
};
if (!data.specId) {
uni.showModal({
title: "提示",
content: "当前商品规格错误,请稍候再试",
showCancel: false,
confirmText: "确定",
});
}
if (!data.warehouseId || !data.addrId) {
uni.showModal({
title: "提示",
content: "请先选择收货地址,再添加商品",
showCancel: false,
confirmText: "确定",
});
}
const res = await addCartApi(data);
if (res.code !== "0") {
return;
}
// store.changeCartList(res.data);
initCartInfo();
}
/**
* 选择地址
*/
@ -468,10 +512,12 @@ async function toCart(item, diff) {
confirmText: "确定",
});
}
const res = addCartApi(data);
const res = await addCartApi(data);
if (res.code !== "0") {
initCartInfo();
return;
}
store.changeCartList(res.data.items);
// initCartInfo();
}
/**
@ -484,31 +530,32 @@ async function initCartInfo() {
};
const res = await getCartInfoApi(data);
if (res.code !== "0")
if (res.code !== "0") {
return;
}
store.changeCartList(res.data);
}
/**
*
* @param {InputEvent} e
* @param {{specs: {sum: number}[]}} item
*/
function onChangeGoods(e, item, index) {
const value = e.detail.value * 1;
if (Number.isNaN(value))
return;
if (value >= item.specs[index].stock) {
uni.showToast({
icon: "none",
title: "采购数量不能大于库存数量",
});
// item.specs[0].sum = item.specs[0].stock;
return;
}
item.specs[index].sum = value;
}
// /**
// *
// * @param {InputEvent} e
// * @param {{specs: {sum: number}[]}} item
// */
// function onChangeGoods(e, item, index) {
// const value = e.detail.value * 1;
// if (Number.isNaN(value))
// return;
// if (value >= item.specs[index].stock) {
// uni.showToast({
// icon: "none",
// title: "",
// });
// // item.specs[0].sum = item.specs[0].stock;
// return;
// }
// item.specs[index].sum = value;
// }
/**
* 创建购物车小球的动画
@ -810,7 +857,7 @@ onShow(async () => {
{{ item.specs[0].sum }}
</text>
<keyboard
v-if="isShowkeyboard"
v-show="isShowkeyboard"
@confirm="(val) => determine(val, item.specs[0])"
@cancel="() => isShowkeyboard = false"
/>
@ -859,12 +906,23 @@ onShow(async () => {
<view class="minus" @tap="() => onMinusGoods(item.specs[specsIndex])">
<image class="icon" src="/static/home/minus.png" mode="" />
</view>
<input
<!-- <input
:value="specsItem.sum"
class="input"
type="number"
@input="e => onChangeGoods(e, item, specsItem)"
> -->
<text
class="input"
@tap="() => isShowkeyboard = true"
>
{{ item.specs[specsIndex].sum }}
</text>
<keyboard
v-show="isShowkeyboard"
@confirm="(val) => determine(val, item.specs[specsIndex])"
@cancel="() => isShowkeyboard = false"
/>
</block>
<view class="add" @tap="(e) => onAddGoods(item.specs[specsIndex], e)">
<image class="icon" src="/static/home/add.png" mode="" />

4
pages/login/login.vue

@ -426,7 +426,7 @@ page {
input {
border-bottom:solid 1px #f6f6f6;
width:90%;
z-index: $z-index-low;
z-index: 1;
}
.header {
margin: 90rpx 0 90rpx 0rpx;
@ -543,7 +543,7 @@ input {
flex-direction: column;
.login-btn {
width: 100%;
z-index: $z-index-head !important;
z-index: 10 !important;
border-radius: 100px;
border: none;
background-color: #06CA64;

8
pages/personalInformation/personallInformation.scss

@ -393,7 +393,7 @@
position: absolute;
right: 10rpx;
bottom: 10rpx;
z-index: $z-index-max;
z-index: $z-index-toast;
}
}
@ -408,7 +408,7 @@
width: 60rpx;
height: 60rpx;
border-radius: 50%;
z-index: $z-index-max;
z-index: $z-index-toast;
}
/* 新版样式 */
@ -753,7 +753,7 @@
position: absolute;
right: 10rpx;
bottom: 10rpx;
z-index: $z-index-max;
z-index: $z-index-toast;
}
}
@ -768,7 +768,7 @@
width: 60rpx;
height: 60rpx;
border-radius: 50%;
z-index: $z-index-max;
z-index: $z-index-toast;
}
}

2
pages/shoppingCart/shoppingCart.scss

@ -226,7 +226,7 @@
width: 100%;
// bottom: 90rpx;
background: #fff;
z-index: $z-index-tab;
// z-index: $z-index-tab;
/* padding-bottom: 20rpx; */
padding: 0 14rpx 10rpx;
box-sizing: border-box;

122
pages/shoppingCart/shoppingCart.vue

@ -2,6 +2,7 @@
import { onLoad, onShow } from "@dcloudio/uni-app";
import { ref } from "vue";
import customTabBar from "@/components/custom-tab-bar/my-tab-bar.vue";
import keyboard from "@/components/keyboard/keyboard.vue";
import navv from "@/components/nav/nav.vue";
// import topTitle from "@/components/topTitle/topTitle.vue";
import {
@ -13,7 +14,7 @@ import {
getUserInfoApi,
previewApi,
} from "@/libs/api";
import { sleep } from "@/libs/utils";
import { sleep, validates } from "@/libs/utils";
import useStore from "@/store";
const store = useStore();
@ -49,7 +50,7 @@ const totalPrice = ref(0);
/**
* 选中的购物车项
*/
const checkedItems = ref([]);
// const checkedItems = ref([]);
/**
* 选中所有购物车项
*/
@ -67,6 +68,10 @@ const cartCount = ref(0);
* 是否显示购物车小球
*/
const showBall = ref(false);
/**
* 是否显示键盘
*/
const isShowkeyboard = ref(false);
/**
* 购物车小球的动画
*/
@ -160,17 +165,68 @@ function onTouchMove(e, index) {
}
/**
* 购物车项选择事件
* @param index 购物车项索引
* @param item 购物车项
*/
async function onCheckboxChange(index) {
cartLists.value[index].checked = !cartLists.value[index].checked;
async function onCheckboxChange(item) {
// cartLists.value[index].checked = !cartLists.value[index].checked;
item.checked = !item.checked;
store.changeCartList(cartLists.value.filter(item => item.checked));
checkedItems.value = store.cartList.map(item => item.id);
await preview(checkedItems.value);
const checkedItems = store.cartList.map(item => item.id);
await preview(checkedItems);
inspectCheck();
}
function onShowKeyboard() {}
/**
* 确定购买数量
* @param value 购买数量
* @param item 商品项
*/
async function determine(value, item) {
const isPass = validates([
() => item.stock != -1 && value > item.stock && "采购数量不能大于库存数量",
() => item.stock == 0 && "库存数量为0无法添加",
]);
if (!isPass) {
return;
}
item.sum = value;
isShowkeyboard.value = false;
const data = {
quantity: value,
specId: item.id,
Chuxiao: item.chuxiao,
warehouseId: uni.getStorageSync("warehousId"),
addrId: uni.getStorageSync("addressId"),
isUpdate: 1,
isChuxiao: false,
};
if (!data.specId) {
uni.showModal({
title: "提示",
content: "当前商品规格错误,请稍候再试",
showCancel: false,
confirmText: "确定",
});
}
if (!data.warehouseId || !data.addrId) {
uni.showModal({
title: "提示",
content: "请先选择收货地址,再添加商品",
showCancel: false,
confirmText: "确定",
});
}
const res = await addCartApi(data);
if (res.code !== "0") {
return;
}
// store.changeCartList(res.data);
initCartInfo();
}
/**
* 购物车项增加事件
@ -300,17 +356,14 @@ async function onSelectAllGoods() {
cartLists.value = cartLists.value.map(item => ({ ...item, checked: checkedAll.value }));
// cartLists.value[index].checked = !cartLists.value[index].checked;
store.changeCartList(cartLists.value.filter(item => item.checked));
checkedItems.value = store.cartList.map(item => item.id);
await preview(checkedItems.value);
const checkedItems = store.cartList.map(item => item.id);
await preview(checkedItems);
inspectCheck();
}
/**
* 结算
*/
function onGotoOrder() {
console.log(123);
if (store.cartList.length == 0) {
uni.showToast({
title: "下单商品不能为空",
@ -365,13 +418,15 @@ function onDeleteCart() {
if (res.cancel) {
return;
}
const checkedItems = store.cartList.filter(item => item.checked).map(item => item.id);
const res2 = await deleteFromCartApi({
ids: checkedItems.value.join(","),
ids: checkedItems.join(","),
});
if (res2.code !== "0") {
return;
}
cartLists.value = cartLists.value.filter(item => !checkedItems.value.includes(item.id));
cartLists.value = cartLists.value.filter(item => !checkedItems.includes(item.id));
initCartInfo();
},
});
@ -422,6 +477,7 @@ async function toCart(item, diff) {
if (res.code !== "0") {
return;
}
// store.changeCartList(res.data)
initCartInfo();
}
@ -536,7 +592,7 @@ async function getUserInfo() {
* 初始化购物车列表
*/
async function initCartInfo() {
checkedItems.value = [];
// checkedItems.value = [];
// isLoading.value = true;
const res = await getCartInfoApi({
warehouseId: uni.getStorageSync("warehousId"),
@ -544,21 +600,23 @@ async function initCartInfo() {
});
if (res.code === "0") {
checkedItems.value = res.data.map(each => each.id);
//
store.changeCartList(res.data);
let checkedItems = res.data.map(each => each.id);
// isLoading.value = false;
cartLists.value = res.data.map(each => ({
...each,
checked: true,
isTouchMove: false,
}));
totalPrice.value = res.data.reduce((acc, cur) => acc + cur.amount, 0);
if (checkedItems.value.length) {
await preview(checkedItems.value);
if (checkedItems.length) {
//
store.changeCartList(cartLists.value);
totalPrice.value = res.data.reduce((acc, cur) => acc + cur.amount, 0).toFixed(2);
await preview(checkedItems);
}
else {
checkedItems.value = [];
checkedItems = [];
// genOrder.value = false;
serviceFee.value = 0;
shippingFee.value = 0;
@ -614,6 +672,7 @@ onShow(() => {
// cartList.value = [];
// inShow.value = true;
getUserInfo();
// initCartInfo();
});
onLoad(() => {
@ -625,7 +684,7 @@ onLoad(() => {
<template>
<navv>
<template #default="{ menu, status, content, tabbar }">
<template #default="{ menu, status, content }">
<!-- 购物车标题 -->
<view
class="header-box"
@ -672,7 +731,7 @@ onLoad(() => {
:value="item.id"
:checked="item.checked"
color="#06CA64"
@tap="() => onCheckboxChange(index)"
@tap="() => onCheckboxChange(item)"
/>
<view
class="cart-list-item"
@ -708,12 +767,23 @@ onLoad(() => {
<view class="minus" @tap.stop="(e) => onMinus(e, item, index)">
<image class="icon" src="/static/home/minus.png" mode="" />
</view>
<!-- <text
class="input"
@tap="determine"
>
{{ item.quantity }}
</text> -->
<text
class="input"
@tap="onShowKeyboard"
@tap="() => isShowkeyboard = true"
>
{{ item.quantity }}
</text>
<keyboard
v-show="isShowkeyboard"
@confirm="(val) => determine(val, item)"
@cancel="() => isShowkeyboard = false"
/>
</block>
<view class="add" @tap.stop="(e) => onAdd(e, item, index)">

5
store/index.js

@ -68,6 +68,10 @@ export default defineStore("store",
*/
const fontScale = ref(1);
const cache = ref({
keyboardConfirm: () => {},
});
/**
* 修改购物车数量
* @param {*} info
@ -142,6 +146,7 @@ export default defineStore("store",
tabbarBottomHeight,
tabbarItemWidth,
fontScale,
cache,
increment,
changeSearchValue,
clearSearchValue,

1
uni.scss

@ -49,7 +49,6 @@ $z-index-modal: 3000;
$z-index-mask: 3001;
$z-index-toast: 4000;
:deep(uni-modal) {
z-index: $z-index-modal;
}

Loading…
Cancel
Save