基于Node+Vue.js高质量商城系统的开发
Copyright ©2024 www.javaclimb.com 版权所有 5/26/2023
程序员根本不会有35岁危机!!!
周末,我没有出去,又接了个单子,一个网友让我用Node+vue做一个商城系统。
其实web开发,好多语言的后台逻辑处理都是千篇一律,学好一门语言可以横扫其他语言。所以学好啥语言都有前途。
这一个单子就是我原来一个月的工资!
程序行业是一个备受争议的行业:
高薪、996、秃顶、格子衫……
这都是外界给程序员的帽子。
我是一名多年开发的程序员,从本科到硕士一直重试计算机相关的工作,基本也是见证了这个行业的起起落落。
其实外界的声音不重要的,关键是做自己吧!今年和同行聊一下:
35岁有没有职业危机!
从我的职场经验来看,35岁没有危机,反而也是越来越吃香,薪资越来越高!
那什么样的程序员容易淘汰???
停滞不前,一直不学习,35岁的时候还是一顿CRUD(增删改查)!你说不辞退你辞退谁?
当然到了35岁,在学习能力和加班方面,我们比不上应届生。
但是你可以在技术、管理方面建立优势,当然也可以开发兼职,兼职可以做哪些??
咨询、接私活、自媒体等。
这些随便做起来一个都可以超过你上班的工资。我曾经做去企业做过一次咨询,给了五位数,Tob是真的香!上次和我对象的一个朋友吃饭,他是一个本科生,一直做NLP,上周去大学代课,一上午给了4500。
所以35岁还年轻,于程序员来说,有太多的转型的方向,我觉得程序员35岁失业就是P话!!!
下面看一下开发的这个系统。
# 一,系统界面
# 二,系统核心代码展示
// 小孟v:jishulearn
<template>
<view class="cart">
<!--<view class="header" :style="{ position: headerPosition, top: headerTop }">-->
<!--<view class="title">购物车</view>-->
<!--</view>-->
<!--<!– 占位 –>-->
<!--<view class="place"></view>-->
<!-- 购物车为空 -->
<view v-if="cartList.length === 0" class="empty">
<text class="iconfont icongouwuche" :class="'text-'+themeColor.name"></text>
<view v-if="hasLogin" class="empty-tips">
空空如也
<navigator
class="navigator"
:class="'text-'+themeColor.name"
v-if="hasLogin"
url="../category/category"
open-type="switchTab"
>随便逛逛></navigator
>
</view>
<view v-else class="empty-tips">
空空如也
<view class="navigator" :class="'text-'+themeColor.name" @tap="navTo('/pages/public/logintype')"
>登录/注册 ></view
>
</view>
</view>
<!-- 购物车列表 -->
<view class="goods-list" v-else>
<view class="rf-cart-row" v-for="(row, index) in cartList" :key="index">
<!-- 删除按钮 -->
<view class="menu" @tap.stop="deleteCartItem(row.id, 'one')" :class="'bg-'+themeColor.name">
<text class="iconfont icon iconiconfontshanchu1"></text>
</view>
<!-- 商品 -->
<view
class="carrier"
:class="[
theIndex === index ? 'open' : oldIndex === index ? 'close' : ''
]"
@touchstart="touchStart(index, $event)"
@touchmove="touchMove(index, $event)"
@touchend="touchEnd(index, $event)"
>
<!-- checkbox -->
<view class="checkbox-box" @tap="selected(index, row)">
<view
class="checkbox"
:class="[
parseInt(row.status, 10) === 0 ? `checkbox-disabled ${'text-'+themeColor.name}` : 'text-'+themeColor.name
]"
>
<view :class="[row.selected ? `on ${'bg-'+themeColor.name}` : '']"></view>
</view>
</view>
<!-- 商品信息 -->
<view class="goods-info">
<view class="img">
<image :src="row.productPic"></image>
</view>
<view class="info">
<view
class="title in2line"
@tap="navTo(`/pages/product/product?id=${row.product.id}`)"
>
{{ row.productName }}
</view>
<view class="state-wrapper">
<view class="spec" @tap.stop="toggleSpec(row)">{{ row.productAttr|attrFilter}}</view>
<view class="state" v-if="parseInt(row.status, 10) === 0">
已失效
</view>
</view>
<view class="price-number">
<view class="price">{{ moneySymbol }}{{
row.price
}}</view>
<view class="remark" >{{ row.remark }}</view>
<view class="number" >
<view class="sub" @tap.stop="sub(row, index)">
<text class="iconfont icon icon-jianhao"></text>
</view>
<view class="input" @tap.stop="discard">
<input
type="number"
:class="'text-'+themeColor.name"
v-model="row.quantity"
@input.stop="numberChange(row, $event, index)"
/>
</view>
<view class="add" @tap.stop="add(row, index)">
<text class="iconfont icon iconjia1"></text>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 脚部菜单 -->
<view
class="footer"
:style="{ bottom: footerbottom }"
v-if="cartList.length !== 0"
>
<view class="checkbox-box" @tap="allSelect">
<view class="checkbox" :class="'text-'+themeColor.name">
<view :class="[isAllselected ? `on ${'bg-'+themeColor.name}` : '']"></view>
</view>
<view class="text">全选</view>
</view>
<view
class="delBtn"
:class="'text-'+themeColor.name"
@tap="deleteCartItem"
v-if="selectedList.length > 0"
>删除</view
>
<view class="settlement">
<view class="sum"
>合计:
<view class="money">{{ moneySymbol }}{{ sumPrice }}</view>
</view>
<view class="btn" :class="'bg-'+themeColor.name" @tap="createOrder"
>结算({{ selectedList.length }})</view
>
</view>
</view>
<!-- 规格-模态层弹窗 -->
<view
class="popup spec show"
v-if="specClass === 'show'"
@touchmove.stop.prevent="stopPrevent"
@tap="hideSpec"
>
<!-- 遮罩层 -->
<view class="mask" @tap="hideSpec"></view>
<view class="layer" @tap.stop="stopPrevent">
<rf-attr-content
:isSelectedNum="false"
:product="productDetail"
@toggle="toggleSpec"
></rf-attr-content>
</view>
</view>
<!--页面加载动画-->
<rfLoading isFullScreen :active="loading"></rfLoading>
</view>
</template>
<script>
import {
cartItemClear,
cartItemDel,
cartItemList,
cartItemUpdateNum,
cartItemUpdateSku,
productDetail
} from '@/api/product';
import rfAttrContent from '@/components/rf-attr-content';
import { mapMutations } from 'vuex';
export default {
components: { rfAttrContent },
filters:{
attrFilter(val){
if(!val) return ;
val = JSON.parse(val);
let res = [];
val.map(v=>{
res.push(v.value);
})
return res.join(',');
}
},
data() {
return {
sumPrice: '0.00',
headerPosition: 'fixed',
headerTop: null,
statusTop: null,
showHeader: true,
selectedList: [],
isAllselected: false,
// 控制滑动效果
theIndex: null,
oldIndex: null,
isStop: false,
cartList: [],
hasLogin: null,
footerbottom: 0,
specClass: 'none',
productDetail: {
base_attribute_format: [],
sku: []
},
specSelected: [],
specChildList: [],
specList: [],
currentSkuId: '',
moneySymbol: this.moneySymbol,
loading: true,
singleSkuText: this.singleSkuText
};
},
onPageScroll(e) {
// 兼容iOS端下拉时顶部漂移
this.headerPosition = e.scrollTop >= 0 ? 'fixed' : 'absolute';
this.headerTop = e.scrollTop >= 0 ? null : 0;
this.statusTop = e.scrollTop >= 0 ? null : -this.statusHeight + 'px';
},
// 下拉刷新,需要自己在page.json文件中配置开启页面下拉刷新 "enablePullDownRefresh": true
onPullDownRefresh() {
this.selectedList.length = 0;
this.isAllselected = false;
this.sumPrice = 0;
this.getCartItemList('refresh');
},
onShow() {
// 兼容H5下结算条位置
// #ifdef H5
this.footerbottom =
document.getElementsByTagName('uni-tabbar')[0].offsetHeight + 'px';
// #endif
// #ifdef APP-PLUS
this.showHeader = false;
// eslint-disable-next-line
this.statusHeight = plus.navigator.getStatusbarHeight();
// #endif
this.initData();
},
methods: {
...mapMutations(['setCartNum']),
// 规格弹窗开关
toggleSpec(row) {
if (parseInt(row.status, 10) === 0) return;
if (this.specClass === 'show') {
if (!this.hasLogin) {
this.specClass = 'none';
this.$mHelper.toast('请先登录!');
return;
}
this.handleCartItemUpdateSku(this.currentSkuId, row.skuId);
this.specClass = 'hide';
setTimeout(() => {
this.specClass = 'none';
}, 250);
} else if (this.specClass === 'none') {
if (row) {
this.getProductDetail(row);
}
}
},
// 获取产品详情
async getProductDetail(row) {
this.currentSkuId = row.sku_id;
await this.$http
.get(`${productDetail}`, {
id: row.product_id
})
.then(async r => {
this.productDetail = r.data;
this.productDetail.sku_name = row.sku_name;
this.specClass = 'show';
});
},
hideSpec() {
this.specClass = 'hide';
setTimeout(() => {
this.specClass = 'none';
}, 250);
},
stopPrevent() {},
// 删除选中购物车商品
async deleteCartItem(id, type) {
let ids = [];
for (let i = 0; i < this.cartList.length; i++) {
if (this.cartList[i].selected) {
ids.push(parseInt(this.cartList[i].id, 10));
}
}
await this.$http2.post("cart/delete",{ids},{
header:{
'content-type':'application/x-www-form-urlencoded'
}
});
this.selectedList.length = 0;
this.isAllselected = false;
this.sumPrice = 0;
this.getCartItemList();
this.oldIndex = null;
this.theIndex = null;
// await this.$http
// .post(`${cartItemDel}`, {
// sku_ids: JSON.stringify(skuIds)
// })
// .then(() => {
// this.selectedList.length = 0;
// this.isAllselected = false;
// this.sumPrice = 0;
// this.getCartItemList();
// this.oldIndex = null;
// this.theIndex = null;
// });
},
// 修改购物车商品sku
async handleCartItemUpdateSku(skuId, newSkuId) {
await this.$http
.post(`${cartItemUpdateSku}`, {
sku_id: skuId,
new_sku_id: newSkuId
})
.then(() => {
this.selectedList.length = 0;
this.isAllselected = false;
this.sumPrice = 0;
this.getCartItemList();
});
},
// 数据初始化
initData() {
this.hasLogin = this.$mStore.getters.hasLogin;
if (this.hasLogin) {
this.theIndex = null;
this.oldIndex = null;
this.selectedList.length = 0;
this.isAllselected = false;
this.sumPrice = 0;
this.getCartItemList();
} else {
this.cartList = [];
this.selectedList.length = 0;
this.loading = false;
}
},
// 通用跳转
navTo(route) {
if (!this.$mStore.getters.hasLogin) {
uni.setStorageSync('backToPage', JSON.stringify({ route: '/pages/cart/cart' }));
}
this.$mRouter.push({ route });
},
// 获取购物车列表
async getCartItemList(type) {
let r = await this.$http2.get('cart/list').catch(() => {
this.cartList = [];
this.loading = false;
if (type === 'refresh') {
uni.stopPullDownRefresh();
}
});
this.loading = false;
this.cartList = r.data;
this.$set(this,'cartList',[...r.data]);
// 清空购物车
clearCart(params) {
const content = params ? '清空失效商品?' : '清空购物车?';
uni.showModal({
content,
success: async e => {
if (e.confirm) {
await this.$http.post(`${cartItemClear}`, params).then(() => {
this.selectedList.length = 0;
this.isAllselected = false;
this.sumPrice = 0;
this.getCartItemList();
});
}
}
});
},
// 控制左滑删除效果
touchStart(index, event) {
// 多点触控不触发
if (event.touches.length > 1) {
this.isStop = true;
return;
}
this.oldIndex = this.theIndex;
this.theIndex = null;
// 初始坐标
this.initXY = [event.touches[0].pageX, event.touches[0].pageY];
},
# 三,欢迎关注我
如果你想学习更多的技术,关注下方公众号,回复:项目大全,干货不断!