Browse Source

Merge branch 'master' of http://123.60.98.226:3000/chenkainan/cgc_WeChat

# Conflicts:
#	pages.json
#	static/js/request.js
master
chenkainan 5 months ago
parent
commit
2273af05fd
  1. 398
      components/addressAdd.vue
  2. 455
      components/cartData.vue
  3. 265
      components/contactAdd.vue
  4. 19
      package.json
  5. 19
      pages.json
  6. 36
      static/css/base.css
  7. 28
      static/js/CommonFunction.js
  8. 7
      static/js/request.js
  9. 792
      subPackages/techan/detail.vue
  10. 789
      subPackages/techan/index.vue
  11. 1281
      subPackages/techan/order.vue
  12. 253
      subPackages/techan/selfPickUpPoint.vue

398
components/addressAdd.vue

@ -0,0 +1,398 @@
<template>
<view class="bg">
<view class="list-forms">
<view class="list-item">
<view class="list-item-title">姓名</view>
<view class="list-item-input"><input type="text" v-model="username" placeholder="请输入姓名" /></view>
</view>
<view class="list-item">
<view class="list-item-title">手机号</view>
<view class="list-item-input"><input type="number" v-model="mobile" placeholder="请输入手机号" maxlength="11"
/></view>
</view>
<view class="list-item" style="position: relative;">
<view class="list-item-title">选择地区</view>
<view class="list-item-input3" style="flex: 1;">
<picker mode="multiSelector" :range="newProvinceDataList" range-key="name" @change="changeArea" @columnchange="pickerColumnchange"
style="position: relative;z-index: 2;">
<input type="text" readonly style="font-size: 35rpx;position: relative;z-index: -1;"
v-model="citySeld" disabled="true" placeholder="请选择地区"/>
</picker>
</view>
</view>
<view class="list-item">
<view class="list-item-title">详细地址</view>
<view class="list-item-input"><input type="text" v-model="detailAddr" placeholder="请输入详细地址" /></view>
</view>
<view class="list-item" style="border-bottom: 0;">
<view class="list-item-title">设为默认</view>
<view class="list-item-switch">
<switch :checked="idDefault" @change="switchChange" color="#74A5AA"/>
</view>
</view>
<!-- <view class="list-item-btn">
<view class="list-item-post" @click="postSave()">保存</view>
</view> -->
</view>
</view>
</template>
<script>
import District from 'ydui-district/dist/jd_province_city_area_id';
export default {
data() {
return {
username: '',
mobile: '',
citySeld: '',
detailAddr: '',
idDefault: false,
title: '新增收货地址',
show: false,
district: District, //
ready: false,
province: null,
city: null,
area: '',
provinceId: null,
cityId: null,
areaId: null,
columns: [],
id: '',
newProvinceDataList:[
[],[],[]
],
multiIndex: [0, 0, 0],
}
},
onLoad(option){
},
methods: {
init(option) {
this.id = null
this.username = ''
this.mobile = ''
this.citySeld = ''
this.detailAddr = ''
this.idDefault = false
this.province = null
this.city = null
this.area = ''
this.provinceId = null
this.cityId = null
this.areaId = null
this.multiIndex = [0, 0, 0]
this.id = option.id
if (option.id > 0) {
this.title = '编辑收货地址'
this.getDetail()
}
else {
this.getSeldCityList()
}
},
switchChange(e){
this.idDefault = e.detail.value
},
changeArea(e){
//
this.multiIndex = e.detail.value;
this.citySeld = this.newProvinceDataList[0][this.multiIndex[0]].name + this.newProvinceDataList[1][this.multiIndex[1]].name + this.newProvinceDataList[2][this.multiIndex[2]].name
this.provinceId = this.newProvinceDataList[0][this.multiIndex[0]].id
this.cityId = this.newProvinceDataList[1][this.multiIndex[1]].id
this.areaId = this.newProvinceDataList[2][this.multiIndex[2]].id
},
getSeldCityList() {
if (this.columns.length>0) {
return
}
let that = this
that.Post({}, '/api/areas/getAll').then(res => {
if (res.code === 1) {
var data = res.data;
var result = {};
for (var i = 0; i < data.length; i++) {
var item = data[i];
if (item.parent_id == 0) {
continue;
}
//
if (item.parent_id == "1") {
result[item.id.toString()] = {};
result[item.id.toString()].children = []
result[item.id.toString()].name = item.name;
result[item.id.toString()].id = item.id;
} else if (result[item.parent_id.toString()]) {
//
var t = {
id: item.id,
name: item.name,
children: []
}
result[item.parent_id.toString()].children.push(t)
} else {
//
var k = {
id: item.id,
name: item.name
}
for (var j = 0; j < result[item.parent_id.toString().substr(0, 2) + "0000"].children
.length; j++) {
if (result[item.parent_id.toString().substr(0, 2) + "0000"].children[j].id == item
.parent_id) {
result[item.parent_id.toString().substr(0, 2) + "0000"].children[j].children.push(k)
}
}
}
}
var r = [];
//ObjectArray
for (var i in result) {
r.push(result[i]);
}
//
that.district = r;
let arr = []
let arr1 = []
let arr2 = []
that.district.forEach(item => {
arr.push(item)
})
that.district[0].children.forEach(item => {
arr1.push(item)
})
that.district[0].children[0].children.forEach(item => {
arr2.push(item)
})
that.columns = arr
//
that.ready = true;
console.log(this.columns)
for(let i=0; i<this.columns.length; i++){
this.newProvinceDataList[0].push({name:this.columns[i].name,id:this.columns[i].id});
}
console.log(this.columns[0].children)
for(let i=0; i<this.columns[0].children.length; i++){
this.newProvinceDataList[1].push({name:this.columns[0].children[i].name,id:this.columns[0].children[i].id});
}
for(let i=0; i<this.columns[0].children[0].children.length; i++){
this.newProvinceDataList[2].push({name:this.columns[0].children[0].children[i].name,id:this.columns[0].children[0].children[i].id});
}
}
})
},
//
pickerColumnchange(e){
//
// console.log(e.detail.column);
//
// console.log(e.detail.value)
//
if(e.detail.column === 0){
this.multiIndex[0] = e.detail.value
// console.log('');
// this.newProvinceDataList[1] = [];
this.newProvinceDataList[1] = this.columns[this.multiIndex[0]].children.map((item,index)=>{
// console.log(item)
return item
})
// console.log(this.multiIndex)
if(this.columns[this.multiIndex[0]].children.length === 1){
this.newProvinceDataList[2] = this.columns[this.multiIndex[0]].children[0].children.map((item,index)=>{
// console.log(item)
return item
})
}else{
this.newProvinceDataList[2] = this.columns[this.multiIndex[0]].children[this.multiIndex[1]].children.map((item,index)=>{
// console.log(item)
return item
})
}
//
this.multiIndex.splice(1, 1, 0)
this.multiIndex.splice(2, 1, 0)
}
//
if(e.detail.column === 1){
this.multiIndex[1] = e.detail.value
// console.log('');
// console.log(this.multiIndex)
this.newProvinceDataList[2] = this.columns[this.multiIndex[0]].children[this.multiIndex[1]].children.map((item,index)=>{
// console.log(item)
return item
})
//
this.multiIndex.splice(2, 1, 0)
}
//
if(e.detail.column === 2){
this.multiIndex[2] = e.detail.value
// console.log('')
// console.log(this.multiIndex)
}
},
getDetail() {
this.Post({
id: this.id
}, "/api/user/contactDetail").then(res => {
res = res.data;
if (res && res.id > 0) {
this.username = res.name
this.mobile = res.tel
this.idDefault = res.is_default == 1 ? true : false
this.provinceId = res.province_id
this.cityId = res.city_id
this.areaId = res.district_id
this.citySeld = res.province_text + '' + res.city_text + '' + res.district_text
this.detailAddr = res.detail_addr;
this.getSeldCityList();
}
})
},
async postSave() {
this.username = this.username.trim()
this.mobile = this.mobile.trim()
this.detailAddr = this.detailAddr.trim()
if (this.username.length < 1) {
uni.showToast({
title: '请输入姓名',
icon: 'none'
})
return
}
if (this.username.length > 6) {
uni.showToast({
title: '姓名最多6个字',
icon: 'none'
})
return
}
if (!this.IsTel(this.mobile)) {
uni.showToast({
title: '请输入正确的手机号',
icon: 'none'
})
return
}
if (this.citySeld.length < 1) {
uni.showToast({
title: '请选择地区',
icon: 'none'
})
return
}
if (this.detailAddr.length < 2) {
uni.showToast({
title: '请输入具体地址',
icon: 'none'
})
return
}
let res = await this.Post({
name: this.username,
tel: this.mobile,
is_default: this.idDefault ? '1' : '0',
province_id: this.provinceId,
city_id: this.cityId,
district_id: this.areaId,
detail_addr: this.detailAddr,
id: this.id || null
},'/api/user/' + (this.id > 0 ? 'edit' : 'add') + 'Consignee')
if(res.code == '1'){
// uni.setStorageSync('addressNow',JSON.stringify(res.data))
uni.showModal({
title: '提示',
content: this.id>0?'编辑成功':'添加成功',
showCancel: false,
})
}else{
uni.showModal({
title: '提示',
content: res.msg,
showCancel: false,
})
}
return {...res,data: {id: this.id}}
}
}
}
</script>
<style scoped>
.bg {
width: 100%;
height: 100%;
}
.list-forms {
display: flex;
flex-direction: column;
box-sizing: content-box
}
.list-item {
display: flex;
border-bottom: 1rpx solid #D8D8D8;
padding: 30rpx 0;
height: 60rpx;
align-items: center;
box-sizing: content-box
}
.list-item-title {
width: 150rpx;
font-size: 31rpx;
margin-right: 20rpx;
}
.list-item-input {
flex: 1;
}
.list-item-input input {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
border: 0;
background-color: transparent;
line-height: 31rpx;
font-size: 31rpx;
}
.list-item-input input::placeholder {
font-size: 26rpx;
}
.list-item-switch {
display: flex;
flex: 1;
justify-content: flex-end;
}
.list-item-btn {
display: flex;
justify-content: center;
margin-top: 20rpx;
}
.list-item-post {
display: flex;
color: #FFFFFF;
font-size: 36rpx;
width: 697rpx;
height: 73rpx;
background: linear-gradient(90deg, #F84A56, #FF9834);
border-radius: 37rpx;
justify-content: center;
align-items: center;
margin-top: 725rpx;
}
</style>

455
components/cartData.vue

@ -0,0 +1,455 @@
<template>
<view class="bg">
<uni-popup ref="popup" type="bottom" border-radius="10px 10px 0 0"
:safe-area="true" @change="popChange">
<view class="cart-container" v-if="showCart">
<view class="header-container">
<view class="select-area flex flex-items-center" @click.stop="selectAllGoods">
<view class="select-cycle" v-show="!selectAll"></view>
<view class="select-cycle selected" v-show="selectAll">
<image :src="showImg('/uploads/20241104/3d903e0c2788104b57b4ce5e07ea1de1.png')">
</view>
<view style="padding-left: 26rpx;" >全选</view>
</view>
<view class="delete-area flex flex-items-center" @click.stop="clearAllGoods">
<image :src="showImg('/uploads/20241104/50900c9a5fa5fbdbdee526abc9af4a40.png')"></image>
<view style="padding-left: 8rpx;" >清空</view>
</view>
</view>
<view class="content-container">
<view class="content-item" v-for="(item,i) in cartData" :key="i" :model="cartData">
<view class="flex flex-items-center" @tap.stop="setItemSelect(item)">
<view class="select-cycle" v-show="!item.isSelected"></view>
<view class="select-cycle selected" v-show="item.isSelected">
<image :src="showImg('/uploads/20241104/3d903e0c2788104b57b4ce5e07ea1de1.png')">
</view>
<view style="padding-left: 26rpx;flex:1">
<view class="commodity box" >
<image class="img" :src="showImg(item.Specifications_image)" mode="aspectFill"></image>
<view class="title goods-text-area">
<view class="commodity-info">
<view class="text-overflowRows" style="font-weight: bold;">{{ item.good_name }}</view>
<view class="text-overflowRows" style="font-size: 27rpx;color: #999999;padding-top: 10rpx;">{{ item.Specifications_name }}</view>
</view>
<view class="flex flex-between">
<view class="commodity-price">
<view style="font-size: 40rpx;">{{item.Specifications_money/100}}</view>
</view>
<view class="add-num-area">
<view :class="['ctrl',item.num>1?'':'disabled']" @click.stop="addBuyNum(item,-1,i)" >-</view>
<view>{{item.num}}</view>
<view :class="['ctrl']" @click.stop="addBuyNum(item,1,i)">+</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</uni-popup>
<slot name="content"></slot>
</view>
</template>
<script>
export default {
name: "cartData",
data() {
return {
cartData: [],
showCart: false,
selectAll: false,
canOpenpop: true,
allPrice: {allPrice:0, iNum:0, fNum:'00'},
}
},
props:{
paramData: {
type: Object,
},
},
mounted() {
this.canOpenpop = true
this.refreshData()
uni.$on("updateDataByConnect",this.getDataByConnect)
},
beforeUnmount () {
console.log('触发off')
uni.$off("updateDataByConnect",this.getDataByConnect)
},
beforeDestroy () {
console.log('触发off')
uni.$off("updateDataByConnect",this.getDataByConnect)
},
methods: {
calNum () {
let res = 0
this.cartData.forEach(v=>{
res += v.num
})
return res
},
closePopup() {
this.$refs.popup.close()
this.paramData.showCart = this.showCart
this.$emit('changeParamData', this.paramData)
},
openPop(){
this.$refs.popup.open()
this.paramData.showCart = this.showCart
this.$emit('changeParamData', this.paramData)
},
popChange (e) {
this.showCart = e.show
this.paramData.showCart = this.showCart
this.$emit('changeParamData', this.paramData)
},
getDataByConnect(data) {
if (data.msgType == "updateCartDataInfo") {
this.refreshData(data)
}
},
refreshData (data) {
let selectedData = []
try {
selectedData = JSON.parse(uni.getStorageSync('cartDataInfo'));
} catch(e) {
selectedData = []
}
if (Array.isArray(data) && data.length>0) {
this.cartData = data
this.setAllSelect()
} else {
this.Post({noForceLogin: true},'/api/shopping/getShoppingList').then(res => {
if (res) {
this.cartData = (res.data || []).map(v=>{return {...v, isSelected:selectedData.includes(v.specifications_id)}})
this.setAllSelect()
}
})
}
},
//
setItemSelect(item) {
item.isSelected = !item.isSelected
// uni.setStorageSync('cartDataInfo', JSON.stringify(this.cartData));
this.setAllSelect()
},
selectAllGoods(){
let goods = this.cartData
if (this.selectAll) {
goods.forEach(v => v.isSelected = false)
this.selectAll = false
} else {
goods.forEach(v => v.isSelected = true)
this.selectAll = true
}
this.setAllSelect()
},
clearAllGoods(){
let _this = this
Promise.all(this.cartData.map(v=>{
return _this.Post({s_id: v.id},'/api/shopping/delShopping')
})).finally(res =>{
this.cartData = []
this.setAllSelect()
})
},
setAllSelect() {
let goods = this.cartData
if(goods.length>0&& goods.every(v => v.isSelected)){
this.selectAll = true
} else {
this.selectAll = false
}
let selectedData = goods.filter(v=>v.isSelected).map(v=>v.specifications_id)
uni.setStorageSync('cartDataInfo', JSON.stringify(selectedData));
this.calAllPrice()
},
addBuyNum(item, num,index){
if (num == -1 && item.num == 1) {
this.Post({s_id: item.id},'/api/shopping/delShopping').then(res =>{
this.cartData.splice(index,1)
this.setAllSelect()
})
} else {
let numData = item.num + num
this.Post({s_id: item.id, num: numData},'/api/shopping/updateShopping').then(res =>{
item.num += num
this.setAllSelect()
})
}
},
calAllPrice () {
let selectedGoods = this.cartData.filter(v=>v.isSelected)
let totalPrice = 0
selectedGoods.forEach(v=>{
totalPrice += v.Specifications_money/100 * v.num
})
totalPrice = totalPrice.toFixed(2)
console.log(totalPrice)
this.allPrice = {allPrice: totalPrice, iNum: totalPrice.split('.')[0], fNum: totalPrice.split('.')[1]}
this.paramData.allPrice = totalPrice
this.paramData.iNum = this.allPrice.iNum
this.paramData.fNum = this.allPrice.fNum
this.paramData.num = this.calNum()
this.$emit('changeParamData', this.paramData)
},
goCartOrder () {
if(this.cartData.every(v => !v.isSelected)){
uni.showToast({
title:'请先选中要购买的商品',
icon:'none',
})
return
}
let orderData = this.cartData.filter(v=>v.isSelected).map(v=>{
return {
goodsInfo: {
image: v.Specifications_image,
title:v.good_name,
merchant_name: v.merchant_name,
},
skuInfo: {
title:v.Specifications_name,
buyNum:v.num,
money: v.Specifications_money,
id: v.specifications_id,
},
}
})
let orderInfo = {
is_post: 1, //
goods: orderData,
post: 0
}
uni.setStorageSync('teChanOrder', JSON.stringify(orderInfo)); //
// uni.setStorageSync('teChanInfo', JSON.stringify(this.info)); //
uni.navigateTo({
url: '/subPackages/techan/order'
});
},
},
}
</script>
<style scoped lang="scss">
*{
box-sizing: border-box;
}
.bg{
width: 100%;
height: 100%;
}
.cart-container{
display: flex;
flex-direction: column;
background-color: white;
height: 933rpx;
padding-bottom: 184rpx;
border-radius: 20rpx 20rpx 0rpx 0rpx;
display: flex;
flex-direction: column;
position: absolute;
width: 100%;
bottom: 0;
z-index: 20;
.header-container{
display: flex;
align-items: center;
justify-content: space-between;
padding: 40rpx 26rpx;
.select-area{
font-family: PingFang SC;
font-weight: bold;
font-size: 37rpx;
color: #000000;
}
.delete-area{
font-family: PingFang SC;
font-weight: bold;
font-size: 27rpx;
color: #999999;
image{
width: 26rpx;
height: 26rpx;
}
}
}
}
.content-container{
flex: 1;
height: 10rpx;
overflow-y: auto;
padding:0 26rpx 26rpx;
.content-item{
margin-bottom: 48rpx;
}
.commodity {
display: flex;
.add-num-area{
display: flex;
justify-content: space-between;
align-items: center;
width: 160rpx;
image{
width: 49rpx;
height: 49rpx;
}
}
.goods-text-area{
display: flex;
flex-direction: column;
justify-content: space-between;
}
.commodity-price{
font-weight: 500;
font-size: 24rpx;
color: #F84A56;
display: flex;
align-items: baseline;
}
.commodity-info{
font-family: PingFangSC;
font-weight: 500;
font-size: 32rpx;
color: #2C2C2C;
}
// align-items: center;
.img {
width: 217rpx;
height: 179rpx;
border-radius: 13rpx;
flex-shrink: 0;
}
.title {
flex: 1;
margin-left: 20rpx;
font-size: 32rpx;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #000000;
.price-list {
display: flex;
margin-top: 18rpx;
align-items: center;
.price-r {
font-size: 32rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #fc5109;
&:before {
content: '¥';
display: inline-block;
color: #fc5109;
font-size: 24rpx;
}
}
.price-g {
font-size: 24rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #b5bcc9;
text-decoration: line-through;
margin-left: 10rpx;
}
}
}
.num-box {
display: flex;
align-items: center;
margin-left: 20rpx;
width: 160rpx;
justify-content: space-between;
.num {
text-align: center;
width: 50rpx;
}
.ctrl {
width: 46rpx;
height: 46rpx;
}
}
}
}
.select-cycle{
width: 40rpx;
height: 40rpx;
border-radius: 50%;
border: 1px solid #999999;
image{
width: 100%;
height: 100%;
}
}
.select-cycle.selected {
border: none;
image{
width: 40rpx;
height: 40rpx;
}
}
.ctrl {
width: 47rpx;
height: 47rpx;
background: #74A5AA;
border-radius: 50%;
font-family: PingFang SC;
font-weight: 400;
font-size: 34rpx;
color: #FFFFFF;
line-height: 47rpx;
text-align: center;
}
.ctrl.disabled{
background: #E8E8E8;
color: #999999;
}
</style>

265
components/contactAdd.vue

@ -0,0 +1,265 @@
<template>
<view class="bg">
<view class="list-forms">
<view class="list-item">
<view class="list-item-title">姓名</view>
<view class="list-item-input"><input type="text" v-model="username" placeholder="请输入姓名" /></view>
</view>
<view class="list-item">
<view class="list-item-title">证件类型</view>
<view class="list-item-input">
<picker mode="selector" :range="idcardTypeList" range-key="title" @change="changeIdType">
<input type="text" readonly style="font-size: 35rpx;position: relative;"
v-model="idcardTypeValue" disabled="true" placeholder="请选择"/>
</picker>
</view>
</view>
<view class="list-item">
<view class="list-item-title">证件号</view>
<view class="list-item-input"><input type="text" v-model="idNumber" placeholder="请输入正确的证件号" /></view>
</view>
<view class="list-item">
<view class="list-item-title">联系电话</view>
<view class="list-item-input"><input type="number" v-model="mobile" placeholder="请输入手机号" maxlength="11" /></view>
</view>
<view class="list-item">
<view class="list-item-title">设为默认</view>
<view class="list-item-switch">
<switch :checked="idDefault" @change="switchChange" color="#515150"/>
</view>
</view>
</view>
<!-- <view class="btn" @click="submit">保存</view> -->
</view>
</template>
<script>
export default {
data() {
return {
username: '',
mobile: '',
idNumber: '',
idcardTypeValue: '身份证',
show: false,
idcardTypeList: [],
document_type: 'DAM01001',
id: '',
type: '',
idDefault: false,
}
},
methods: {
init (data) {
this.username = ''
this.mobile= ''
this.idNumber= ''
this.idcardTypeValue= '身份证'
this.show= false
this.idcardTypeList= []
this.document_type= 'DAM01001'
this.id= ''
this.type=''
this.idDefault= false
this.type = 'add'
this.getIdcardTypeList()
if (data && data.id) {
this.id = data.id
this.type = 'edit'
this.getDetail()
}
},
switchChange(e){
this.idDefault = e.detail.value
},
getDetail() {
this.Post({
id: this.id
}, '/api/user/contactDetail').then(res => {
if (res.code === 1) {
res = res.data
if (res && res.id > 0) {
this.username = res.name
this.mobile = res.tel
this.idNumber = res.id_number
this.idDefault = res.is_default == 1 ? true : false
this.document_type = res.document_type
this.idcardTypeValue = res.document_type_text
}
}
})
},
//
getIdcardTypeList() {
this.Post({}, '/api/user/getIdcardTypeList').then(res => {
this.idcardTypeList = res.data
})
},
//
changeIdType(e) {
this.idcardTypeValue = this.idcardTypeList[e.detail.value].title
this.document_type = this.idcardTypeList[e.detail.value].document_type
},
//
async submit() {
this.username = this.username.trim()
this.mobile = this.mobile.trim()
this.idNumber = this.idNumber.trim()
if (this.username.length < 1) {
uni.showToast({
title: '请输入姓名',
icon: 'none'
})
return
}
if (!this.IsTel(this.mobile)) {
uni.showToast({
title: '请输入正确的手机号',
icon: 'none'
})
return
}
if (this.idcardTypeValue == '身份证') {
if (!this.idCardNumber(this.idNumber)) {
uni.showToast({
title: '请输入正确的身份证',
icon: 'none'
})
return
}
} else if (this.idcardTypeValue == '护照') {
if (!this.passportValid(this.idNumber)) {
uni.showToast({
title: '请输入正确的护照',
icon: 'none'
})
return
}
} else if (this.idcardTypeValue == '台胞证') {
if (!this.taiwanValid(this.idNumber)) {
uni.showToast({
title: '请输入正确的台胞证',
icon: 'none'
})
return
}
} else if (this.idcardTypeValue == '港澳通行证') {
if (!this.gangaoValid(this.idNumber)) {
uni.showToast({
title: '请输入正确的港澳通行证',
icon: 'none'
})
return
}
} else if (this.idcardTypeValue == '外国人永久居留证') {
if (!this.foreignerValid(this.idNumber)) {
uni.showToast({
title: '请输入正确的外国人永久居留证',
icon: 'none'
})
return
}
} else if (this.idcardTypeValue == '军官证') {
if (!this.officerValid(this.idNumber)) {
uni.showToast({
title: '请输入正确的军官证',
icon: 'none'
})
return
}
}
let res = await this.Post({
id: this.type == 'edit'?this.id:'',
id_number: this.idNumber,
name: this.username,
tel: this.mobile,
document_type: this.document_type,
is_default: this.idDefault ? '1' : '0',
}, this.type=='edit'?'/api/user/editContact':'/api/user/addContact')
if (res.code == 1) {
uni.showModal({
title: '提示',
content: '操作成功',
showCancel: false,
})
}else{
uni.showModal({
title: '提示',
content: res.msg,
showCancel: false,
})
}
return {...res,data: {id: this.id}}
}
}
}
</script>
<style scoped lang="scss">
.bg {
width: 100%;
height: 100%;
position: relative;
}
.list-forms {
padding: 0 33rpx;
.list-item {
display: flex;
border-bottom: 1rpx solid #D8D8D8;
padding: 30rpx 0;
height: 60rpx;
box-sizing: content-box;
align-items: center;
.list-item-title {
font-size: 34rpx;
margin-right: 20rpx;
width: 200rpx;
}
.list-item-input {
flex: 1;
input {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
border: 0;
background-color: transparent;
line-height: 34rpx;
font-size: 34rpx;
text-align: left;
}
input::placeholder {
font-size: 26rpx;
}
}
}
}
.btn {
width: 697rpx;
height: 80rpx;
background: #515150;
border-radius: 40rpx;
text-align: center;
line-height: 80rpx;
font-size: 36rpx;
font-family: PingFang SC;
font-weight: 500;
color: #FFFFFF;
position: absolute;
bottom: 53rpx;
left: 27rpx;
}
</style>

19
package.json

@ -0,0 +1,19 @@
{
"name": "cgc_wechat",
"version": "1.0.0",
"description": "",
"main": "main.js",
"dependencies": {
"ydui-district": "^1.1.0"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "http://123.60.98.226:3000/chenkainan/cgc_WeChat.git"
},
"author": "",
"license": "ISC"
}

19
pages.json

@ -71,6 +71,25 @@
"style" : {
"navigationBarTitleText" : "下单"
}
},
{
"path": "techan/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "techan/detail",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "techan/order",
"style": {
"navigationBarTitleText": "确认订单"
}
}
]
}],

36
static/css/base.css

@ -69,3 +69,39 @@ view {
color: #999999;
}
.flex{
display: flex;
}
.flex-shrink-0{
flex-shrink: 0;
}
.flex-1{
flex: 1;
}
.flex-wrap{
flex-wrap: wrap;
}
.w-full{
width: 100%;
}
.w-1rpx{
width: 1rpx;
}
.h-1rpx{
height: 1rpx;
}
.relative{
position: relative;
}
.absolute{
position: absolute;
}
.flex-items-center{
align-items: center;
}
.no-scrollbar::-webkit-scrollbar{
display: none;
}
.font-bold{
font-weight: bold;
}

28
static/js/CommonFunction.js

@ -222,4 +222,32 @@ Vue.prototype.getHeadImg = type => {
).then(res => {
return res.data[0].image
});
}
// 判断是否去外部链接
Vue.prototype.goOtherDetail = (item,type) => {
if(item.link_type == 1) {
// 外部小程序
uni.navigateToMiniProgram({
shortLink: item.ext_link
})
return true
}else if(item.link_type == 2){
// 外部H5
uni.navigateTo({
url: '/subPackages/webPage/webPage?url=' + item.ext_link
});
return true
}
}
// 根据类型判断详情页
Vue.prototype.goDetailByType= function(item){
let res = this.goOtherDetail(item)
if (res) {
return
}
uni.navigateTo({
url: `/subPackages/techan/detail?id=?${item.id}`
})
}

7
static/js/request.js

@ -18,8 +18,8 @@ const getToken = () => {
return store.state.user.userInfo.token;
};
// 定义错误处理函数
const handleError = (res, reject) => {
// 定义错误处理函数 noForceLogin 不强制登录
const handleError = (res, reject, noForceLogin) => {
setTimeout(() => {
uni.showToast({
title: res.data?.msg || res.msg,
@ -28,6 +28,7 @@ const handleError = (res, reject) => {
reject(res);
}, 0);
if (res.data?.code === 401) {
if (noForceLogin) { return }
store.commit('changeLoginPath');
}
};
@ -67,7 +68,7 @@ Vue.prototype.Post = (params = {}, apiurl) => {
fail: (err) => {
console.log('err', err);
uni.hideLoading()
handleError(err, reject);
handleError(err, reject, params.noForceLogin);
}
});
});

792
subPackages/techan/detail.vue

@ -0,0 +1,792 @@
<template>
<view class="bg" id="bg" v-if="info">
<view class="swipe-box">
<swiper class="swiper" :indicator-dots="false" :autoplay="false" :interval="3000" :duration="1000" circular>
<swiper-item v-if="info && info.videourl">
<video
:src="showImg(info.videourl)"
id="detailVideo"
:poster="showImg(info.image)"
@play="play"
@error="videoErrorCallback"
controls
style="width: 100%;height: 100%;"
object-fit="cover"
></video>
</swiper-item>
<swiper-item v-for="(item, index) in info.list_images.split(',')" :key="item.id">
<view class="swiper-item">
<image class="item-img" :src="showImg(item)" mode="aspectFill"></image>
</view>
</swiper-item>
</swiper>
<view class="swiper-item-num">{{ info.list_images.split(',').length }}</view>
</view>
<view class="w-full relative" style="padding: 26rpx 0;top: -52rpx;">
<view class="price-box ">
<view class="price-zan">
<view class="price">
<view class="present-price">{{ info.money / 100 }}</view>
</view>
</view>
<view class="tag no-scrollbar" v-if="info.goods_new_tag">
<view class="tag-item" v-for="(item, index) in info.goods_new_tag.split(',')" :key="index">
{{ item }}
</view>
</view>
<view class="title">{{ info.title }}</view>
</view>
<view class="sku-box" v-if="sku.length>0">
<view class="sku-item" v-for="(item,i) in sku" :key="i">
<image :src="showImg(item.image)"></image>
<view class="sku-content">
<view class="flex-1">{{item.title}}</view>
<view class="present-price">{{item.money/100}}</view>
</view>
</view>
</view>
<view class="notice" >
<view class="title">购买须知</view>
<view class="rich-text" v-html="formateRichText(info.special_content)"></view>
</view>
<view class="notice" >
<view class="title">商品须知</view>
<view class="rich-text" v-html="formateRichText(info.special_content)"></view>
</view>
</view>
<template v-if="!popShow">
<view class="btn-list" v-if="!paramData.showCart">
<view class="left-box">
<view class="img-box" slot="content">
<uni-badge class="uni-badge-left-margin" :text="paramData.num" absolute="rightTop" :offset="[5, 5]" size="small"
:custom-style="{background:'#D90F01',color:'#ffffff',border:'1px solid #ffffff'}">
<image @click.stop="showCartClick" :src="showImg('/uploads/20241104/88b88bf627a63dd000afe769d1392fb4.png')" mode="aspectFill"
style="width: 60rpx;height: 50rpx;"></image>
</uni-badge>
<text class="text">购物车</text>
</view>
</view>
<view class="btn-post">
<view class="left-btn-buy" @click="openPop(true)">加入购物车</view>
<view class="right-btn-buy" @click="openPop(false)">立即购买</view>
</view>
</view>
<view class="btn-list" v-else>
<view class="left-box">
<view class="img-box" slot="content">
<uni-badge class="uni-badge-left-margin" :text="paramData.num" absolute="rightTop" :offset="[5, 5]" size="small"
:custom-style="{background:'#D90F01',color:'#ffffff',border:'1px solid #ffffff'}">
<image @click.stop="showCartClick" :src="showImg('/uploads/20241104/88b88bf627a63dd000afe769d1392fb4.png')" mode="aspectFill"
style="width: 60rpx;height: 50rpx;"></image>
</uni-badge>
<text class="text">购物车</text>
</view>
<view class="bottom-price">
<text style="color: #000000;">总计</text>
<view class="bottom-price-yuan">{{paramData.iNum}}</view>
<view>.{{paramData.fNum}}</view>
</view>
</view>
<view class="btn-buy" @click="goCartOrder">
去结算
</view>
</view>
</template>
<cartDataVue ref="cartDataVueRef" :paramData="paramData" @changeParamData="changeParamData" :key="new Date().getTime()"></cartDataVue>
<uni-popup ref="popup" type="bottom" @change="changPopShow"
:safe-area="false" style="position: relative;z-index: 50;">
<view class="popup-content" v-if="sku.length>0">
<view @click="closePopup" style="padding: 31rpx 0 0 639rpx;width: 50rpx;height: 80rpx;">
<uni-icons type="closeempty" size="24"></uni-icons>
</view>
<view class="bottom-productImg">
<img :src="showImg(sku[productIndex].image)" alt="">
<view class="right-content">
<view class="bottom-productPrice com-price">{{(sku[productIndex].money||0)/100}}</view>
<view class="bottom-content text-overflow">已选择{{sku[productIndex].title}}</view>
</view>
</view>
<view>
<view class="sp">
规格
</view>
<view style="display: flex;align-items: center;justify-content: space-between;flex-wrap: wrap;">
<view style="position:relative;" v-for="(botItem,botIndex) in sku" :key="botIndex">
<view :class="['botProduct','text-overflow',{'noStore':botItem.store==0},{'botProducts':productIndex==botIndex}]"
@click="changeProduct(botItem,botIndex)">
{{botItem.title}}
</view>
<view class="noStore-text" v-if="botItem.store==0">
不可购买
</view>
<!-- <view class="noStore-text" v-else-if="is_post==1&&botItem.is_post!=1">不可加购</view> -->
</view>
</view>
</view>
<view class="buy-num com-flex-tao">
数量
<view class="number-btn">
<view>
<text @click="delNumber">-</text>
</view>
<view style="width: 96rpx;height: 69rpx;margin: 0 14rpx;">{{ buyNum }}</view>
<view>
<text @click="addNumber">+</text>
</view>
</view>
</view>
</view>
<!-- <view style="height: 100rpx;"></view> -->
<view class="btn-box">
<view class="buy-btn" @click="openPop(addCartOrOrder)">
{{addCartOrOrder?'加入购物车':'立即购买'}}
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import cartDataVue from '../../components/cartData.vue'
export default {
components: {cartDataVue},
data() {
return {
id: null,
info: null,
sku: [],
productIndex: 0,
is_post: "1",
isCollect: false,
showLength: 0,
buyNum: 1,
popShow: false,
paramData: {allPrice: 0,iNum:0, fNum:'00', showCart: false, num: 0},
addCartOrOrder: null, //true false
};
},
onLoad(option) {
this.id = option.id;
this.getInfo();
this.getSpecificationsByGoodsId();
},
methods: {
changPopShow (e) {
this.popShow = e.show
},
getInfo() {
this.Post({
goods_id: this.id
},
'/api/goods/getGoodDetail'
).then(res => {
if (res.data.flag == 0) {
setTimeout(() => {
uni.showToast({
title: '商品不存在或已下架',
icon: 'none'
})
}, 0)
setTimeout(() => {
this.goBack()
}, 2000)
}
this.info = res.data;
// this.isCollect = this.info.is_collect;
if (this.info.title) {
uni.setNavigationBarTitle({
title: this.info.title
})
}
});
},
getSpecificationsByGoodsId() {
this.Post({
goods_id: this.id
},
'/api/goods/getSpecificationsByGoodsId'
).then(res => {
if (res) {
this.sku = res.data || [];
// todo
// this.is_post = "2"
// if (this.sku.length>0 && this.sku.some(v=>v.is_post == 1)) {
// this.is_post = "1"
// }
}
});
},
//
collect() {
this.Post({
type: 5,
id: this.id
},
'/api/scenic/collect'
).then(res => {
if (res) {
uni.showToast({
title: res.msg,
icon: 'none'
});
this.isCollect = !this.isCollect
}
});
},
//
addNumber() {
this.buyNum += 1;
},
delNumber() {
if (this.buyNum <= 1) {
return;
}
this.buyNum -= 1;
},
closePopup() {
this.$refs.popup.close()
},
// false true
openPop(flag) {
if (!this.sku||this.sku.length<=0) {
uni.showToast({
title:'暂无可选规格',
icon:'none'
})
return
}
if (!this.popShow) {
this.$refs.popup.open()
this.addCartOrOrder = flag
} else {
if (flag) {
this.addToCart()
} else {
this.order()
}
}
},
order(item) {
let goods = this.sku[this.productIndex]
goods.buyNum = this.buyNum
let orderInfo = {
// is_post: goods.is_post || "2",
is_post: 1,
goods: [{goodsInfo: this.info, skuInfo: goods }],
post: 0,
}
uni.setStorageSync('teChanOrder', JSON.stringify(orderInfo)); //
// uni.setStorageSync('teChanInfo', JSON.stringify(this.info)); //
uni.navigateTo({
url: '/subPackages/techan/order'
});
},
addToCart () {
let goods = this.sku[this.productIndex]
goods.buyNum = this.buyNum
let goodsInfo = {goodsInfo:this.info, skuInfo: goods, isSelected: true}
this.Post({good_id: this.info.id, specifications_id: goods.id,num: this.buyNum },
'/api/shopping/addShopping').then(res => {
if (res) {
let selectedData = []
try {
selectedData = JSON.parse(uni.getStorageSync('cartDataInfo'));
} catch(e) {
selectedData = []
}
let currentGoods = selectedData.find(v =>v==goods.id)
if (!currentGoods) {
selectedData.push(goods.id)
}
uni.setStorageSync('cartDataInfo', JSON.stringify(selectedData));
uni.$emit("updateDataByConnect", {msgType:'updateCartDataInfo',data:null})
this.closePopup()
// this.$refs.cartDataVueRef.openPop()
}
});
},
goUser() {
uni.switchTab({
url: '/pages/index/user'
})
},
changeProduct(item,index) {
if (item.store==0) {
uni.showToast({
title:"库存不足!",
icon:'none'
})
return
}
this.productIndex = index
},
//
changeParamData (data) {
for(let key in this.paramData) {
this.paramData[key] = data[key]
}
},
showCartClick () {
if (this.paramData.showCart) {
this.$refs.cartDataVueRef.closePopup()
} else {
this.$refs.cartDataVueRef.openPop()
}
},
goCartOrder () {
this.$refs.cartDataVueRef.goCartOrder()
},
},
onReachBottom() {
}
};
</script>
<style lang="scss" scoped>
.bg {
min-height: 100vh;
overflow-x: hidden;
background: #f2f4f7;
padding-bottom: 210rpx;
}
view {
box-sizing: border-box;
}
.swipe-box {
height: 750rpx;
position: relative;
.swiper-item-num {
width: 90rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 20rpx;
font-size: 24rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
text-align: center;
line-height: 40rpx;
position: absolute;
right: 30rpx;
bottom: 50rpx;
}
}
.swiper {
height: 750rpx;
position: relative;
.swiper-item {
width: 100%;
height: 750rpx;
.item-img {
width: 750rpx;
height: 750rpx;
}
}
}
.price-box {
width: 100%;
background: #ffffff;
border-radius: 20rpx 20rpx 0 0;
padding: 24rpx 30rpx;
.price-zan {
display: flex;
align-items: center;
justify-content: space-between;
.price {
display: flex;
}
}
.tag {
margin:24rpx 0 15rpx 0;
display: flex;
align-items: center;
flex-wrap: nowrap;
overflow-x: auto;
.tag-item {
margin-right: 10rpx;
padding: 0rpx 15rpx;
flex-shrink: 0;
font-weight: 500;
font-size: 23rpx;
color: #60989E;
height: 37rpx;
line-height: 37rpx;
background: rgba(96, 152, 158, 0.2);
border-radius: 4rpx;
}
}
.title {
margin-top: 22rpx;
font-family: PingFang;
font-weight: bold;
font-size: 31rpx;
color: #000000;
}
}
.present-price {
font-size: 42rpx;
font-family: PingFang SC;
font-weight: 500;
color: #FC5109;
&:before {
content: '¥';
display: inline-block;
font-size: 26rpx;
}
&:after {
content: '起';
display: inline-block;
font-size: 24rpx;
font-family: PingFangSC;
color: #B5BCC9;
}
}
.notice {
width: 700rpx;
margin: 25rpx auto 0;
background: #ffffff;
border-radius: 20rpx;
padding: 40rpx 25rpx;
.title{
font-weight: bold;
font-size: 36rpx;
color: #000000;
margin-bottom: 30rpx;
}
}
.btn-list {
position: fixed;
z-index: 9999;
bottom: 0;
width: 750rpx;
height: 180rpx;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 16rpx 0rpx rgba(6, 0, 1, 0.1);
display: flex;
justify-content: space-between;
padding: 30rpx 25rpx 0 50rpx;
.left-box {
display: flex;
align-items: flex-start;
.bottom-price{
display: flex;
align-items: baseline;
font-family: PingFang SC;
font-weight: bold;
font-size: 27rpx;
color: #D70000;
padding-top: 20rpx;
.bottom-price-yuan{
font-size: 40rpx;
}
}
.bottom-detail-icon{
font-size: 24rpx;
display: flex;
align-items: center;
}
.img-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-right: 50rpx;
image {
width: 48rpx;
height: 48rpx;
}
.text {
font-weight: 500;
font-size: 22rpx;
color: #4D526C;
}
}
}
.btn-buy {
width: 240rpx;
height: 78rpx;
background: #74A5AA;
border-radius: 40rpx;
text-align: center;
line-height: 78rpx;
font-size: 32rpx;
font-family: PingFangSC;
font-weight: 500;
color: #FFFFFF;
}
}
.popup-content {
background-color: white;
padding: 0rpx 39rpx 51rpx 39rpx;
height: auto;
border-radius: 20rpx 20rpx 0 0;
.bottom-productImg {
display: flex;
margin-bottom: 23rpx;
img {
width: 218rpx;
height: 179rpx;
background: #666666;
border-radius: 13rpx;
}
}
.right-content {
margin: 10rpx 0 0 41rpx;
}
.bottom-productPrice {
font-size: 40rpx;
color: #FC524B;
&:before {
content: "¥";
font-size: 26rpx;
}
}
.bottom-content {
width: 331rpx;
font-size: 27rpx;
font-family: PingFang SC;
font-weight: 400;
color: #666666;
}
}
.botProduct {
width: 320rpx;
// height: 78rpx;
border-radius: 13rpx;
background-color: #EFEFEF;
font-size: 29rpx;
font-family: PingFang SC;
font-weight: 400;
color: #333333;
line-height: 78rpx;
text-align: center;
margin-bottom: 25rpx;
display: inline-block;
position: relative;
padding: 0 40rpx;
}
.noStore{
background-color: rgba(239, 239, 239, 1);
color: rgba(153, 153, 153, 1);
}
.noStore-text{
width: 113rpx;
height: 43rpx;
background: #C0C0C0;
border-radius: 7rpx 0rpx 7rpx 0rpx;
text-align: center;
line-height: 43rpx;
position: absolute;
right: -14rpx;
top: -20rpx;
font-size: 23rpx;
font-family: PingFangSC;
font-weight: 400;
color: #FFFFFF;
}
.botProducts {
// border: 1rpx solid #00AAFF;
// background-color: rgba(254, 180, 25, 1);
background: #74A5AA;
color: #FFFFFF;
}
.buy-num {
font-size: 29rpx;
font-family: PingFang SC;
font-weight: 400;
color: #333333;
// border-top: 1rpx solid #CCCCCC;
padding: 39rpx 0;
display: flex;
align-items: center;
justify-content: space-between;
.number-btn {
display: flex;
}
}
.buy-num .number-btn view {
display: flex;
justify-content: center;
align-items: center;
width: 69rpx;
height: 69rpx;
border: 1rpx solid #CCCCCC;
border-radius: 7rpx;
}
.buy-num .number-btn>view text {
font-size: 46rpx;
}
.buy-btn {
width: 670rpx;
height: 78rpx;
text-align: center;
line-height: 78rpx;
background: #74A5AA;
border-radius: 40rpx;
font-size: 34rpx;
font-family: PingFangSC;
font-weight: 500;
color: #FFFFFF;
}
.btn-box {
width: 750rpx;
height: 151rpx;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 16rpx 0rpx rgba(6, 0, 1, 0.1);
display: flex;
align-items: center;
justify-content: center;
}
.sp {
width: 100%;
height: 30rpx;
font-size: 32rpx;
font-family: PingFangSC;
font-weight: 400;
color: #060001;
line-height: 30rpx;
border-top: solid 2rpx #ccc;
margin: 60rpx 0;
padding-top: 30rpx;
}
.btn-post{
font-weight: 500;
font-size: 32rpx;
color: #60989E;
line-height: 77rpx;
text-align: center;
display: flex;
.left-btn-buy{
width: 186rpx;
height: 77rpx;
color: #60989E;
border-radius: 39rpx 0rpx 0rpx 39rpx;
background: rgba(116, 165, 170, 0.3);
}
.right-btn-buy{
width: 187rpx;
height: 77rpx;
background: #74A5AA;
border-radius: 0rpx 39rpx 39rpx 0rpx;
color: white;
}
}
.sku-box{
width: 700rpx;
margin: 25rpx auto 0;
background: #FFFFFF;
border-radius: 20rpx;
.sku-item{
border-radius: 20rpx;
width: 100%;
padding: 14rpx;
display: flex;
border-bottom: 1px solid #D8D8D8;
.sku-content{
display: flex;
padding-left: 16rpx;
flex: 1;
width: 1rpx;
}
image{
width: 160rpx;
height: 160rpx;
border-radius: 13rpx;
flex-shrink: 0;
}
.flex-1{
font-weight: 500;
font-size: 29rpx;
color: #000000;
height: 160rpx;
padding-right: 75rpx;
overflow: hidden;
}
.present-price{
display: flex;
align-items: center;
}
.present-price::after{
content: '';
}
}
.sku-item:last-of-type{
border: none;
}
}
</style>

789
subPackages/techan/index.vue

@ -0,0 +1,789 @@
<template>
<view class="bg">
<view class="search-header" :style="{'height': height+'px','padding-top':statusBarHeight+'px'}">
<uni-icons type="left" size="20" @click="goBack" style="flex-shrink: 0;"></uni-icons>
<view class="input-model">
<uni-icons style="height: 1.4rem;line-height: 1.4rem;" type="search" size="15" color="#ABAAAD" ></uni-icons>
<input class="input-text" placeholder="请输入商品名称" v-model="searchText" @confirm="search()" @keyup.enter="search()"></text>
</view>
</view>
<div :style="{'height':height+'px','flex-shrink':0}"></div>
<!-- 正常产品 -->
<template v-if="searchText.trim().length<=0">
<img :src="showImg(headImg)" class="topImg" />
<view class="goods-container">
<scroll-view class="left-container no-scrollbar" :scroll-y="true">
<view :class="['type-item',typeIndex==i?'active':'']"
v-for="(item,i) in typeParam" :key="i" @click="changeType(item,i)">
| WEI
<view class="active-type-bar" v-if="typeIndex==i"></view>
</view>
<view style="height: 148rpx;width: 1rpx;"></view>
</scroll-view>
<scroll-view class="right-container no-scrollbar" :scroll-y="true" @scrolltolower="scrollLow()">
<view class="item" v-for="item in list" :key="item.goods.id" @click="viewDetail(item.goods)">
<image class="item-img" :src="showImg(item.goods.image)" mode=""></image>
<view class="content">
<view class="title text-overflowRows">{{item.goods.title}}</view>
<view class="bottom">
<view class="price">
{{item.goods.money/100}}
</view>
<view class="buy-cart" @click.stop="showOrderCart(item.goods)">+</view>
</view>
</view>
</view>
<view style="height: 148rpx;width: 1rpx;"></view>
</scroll-view>
</view>
</template>
<!-- 搜索 -->
<view v-else>
<view v-if="searchList.length<=0" class="flex-center" style="width: 100%;height: 100%;flex-direction: column;">
<!-- <image style="width: 328rpx;height: 450.67rpx;"></image> -->
<view style="font-weight: 500;font-size: 28rpx;color: #666666;
text-align: center;margin-top: 67rpx;">暂无搜索结果</view>
</view>
<view style="padding:0 26rpx;background: #FFFFFF;" v-else>
<view class="flex" style="justify-content: space-between;">
<view class="search-result" >
<view v-for="(item,i) in searchList" >
<view v-if="i%2==1" class="search-item" :key="i" @click="viewDetail(item.goods)">
<image :src="showImg(item.goods.image)" mode="widthFix"></image>
<view class="search-container">
<view class="title text-overflowRows">{{item.goods.title}}</view>
<view class="flex-between" style="padding-top: 20rpx;">
<view>
<text class="price">{{item.goods.money/100}}</text>
<text class="oldPrice">{{item.goods.price/100}}</text>
</view>
<view class="buy-cart" @click.stop="showOrderCart(item.goods)">+</view>
</view>
</view>
</view>
</view>
</view>
<view class="search-result" >
<view v-for="(item,i) in searchList">
<view class="search-item" v-if="i%2==0" :key="i" @click="viewDetail(item.goods)">
<image :src="showImg(item.goods.image)" mode="widthFix"></image>
<view class="search-container">
<view class="title text-overflowRows">{{item.goods.title}}</view>
<view class="flex-between" style="padding-top: 20rpx;">
<view>
<text class="price">{{item.goods.money/100}}</text>
<text class="oldPrice">{{item.goods.price/100}}</text>
</view>
<view class="buy-cart" @click.stop="showOrderCart(item.goods)">+</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
<view style="height: 148rpx;width: 1rpx;"></view>
</view>
<!-- 购物车 -->
<view class="btn-bottom" >
<cartDataVue ref="cartDataVueRef" :paramData="paramData" @changeParamData="changeParamData" style="width: 100%;height: 100%;">
<template class="btn-list" slot="content">
<view class="left-box">
<uni-badge class="uni-badge-left-margin" :text="paramData.num" absolute="rightTop" :offset="[5, 5]" size="small"
:custom-style="{background:'#D90F01',color:'#ffffff',border:'1px solid #ffffff'}">
<view class="img-box" @click.stop="showCartClick">
<image :src="showImg('/uploads/20241104/88b88bf627a63dd000afe769d1392fb4.png')" mode="aspectFill"></image>
</view>
</uni-badge>
<view class="bottom-price">
<text style="color: #000000;">总计</text>
<view class="bottom-price-yuan">{{paramData.iNum}}</view>
<view>.{{paramData.fNum}}</view>
</view>
<view class="bottom-detail-icon" @click.stop="showCartClick">
明细
<view v-if="!paramData.showCart" style="transform: rotate(-90deg);"><uni-icons color="#0B898E" type="left" size="15"></uni-icons></view>
<view v-else style="transform: rotate(90deg);"><uni-icons color="#0B898E" type="left" size="15"></uni-icons></view>
</view>
</view>
<view class="btn-buy" @click="goCartOrder">
去结算
</view>
</template>
</cartDataVue>
</view>
<uni-popup ref="popup" type="bottom" :safe-area="true">
<view class="popup-content" v-if="sku.length>0">
<view @click="closePopup" style="padding: 31rpx 0 0 639rpx;width: 50rpx;height: 80rpx;">
<uni-icons type="closeempty" size="24"></uni-icons>
</view>
<view class="bottom-productImg">
<img :src="showImg(sku[productIndex].image)" alt="">
<view class="right-content">
<view class="bottom-productPrice com-price">{{(sku[productIndex].money||0)/100}}</view>
<view class="bottom-content text-overflow">已选择{{sku[productIndex].title}}</view>
</view>
</view>
<view>
<view style="display: flex;align-items: center;justify-content: space-between;flex-wrap: wrap;">
<view style="position:relative;" v-for="(botItem,botIndex) in sku" :key="botIndex">
<view :class="['botProduct','text-overflow',{'noStore':botItem.store==0},{'botProducts':productIndex==botIndex}]"
@click="changeProduct(botItem,botIndex)">
{{botItem.title}}
</view>
<view class="noStore-text" v-if="botItem.store==0">
不可购买
</view>
<!-- <view class="noStore-text" v-else-if="botItem.is_post!=1">不可加购</view> -->
</view>
</view>
</view>
<view class="buy-num com-flex-tao">
数量
<view class="number-btn">
<view>
<text @click="delNumber">-</text>
</view>
<view style="width: 96rpx;height: 69rpx;margin: 0 14rpx;">{{ buyNum }}</view>
<view>
<text @click="addNumber">+</text>
</view>
</view>
</view>
</view>
<view class="placeholder-content">
<view style="height: 100rpx;"></view>
<view class="btn-cover">
<view class="btn" @click.stop="order">加入购物车</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import cartDataVue from '../../components/cartData.vue'
export default {
components: {cartDataVue},
data() {
return {
//
height: 0,
statusBarHeight: 0,
headImg: null,
typeParam: [
{id: 60, title: ''},{id: 59, title: ''},{id: 60, title: ''},
{id: 1, title: ''},{id: 1, title: ''},{id: 1, title: ''},
{id: 1, title: ''},{id: 1, title: ''},{id: 1, title: ''},
{id: 1, title: ''},{id: 1, title: ''},{id: 1, title: ''},
{id: 1, title: ''},{id: 1, title: ''},{id: 1, title: ''},
],
typeIndex: 0,
list:[],
finished: false,
paramData: {allPrice: 0,iNum:0, fNum:'00', showCart: false, num: 0},
currentGoods: {},
sku: [],
productIndex: 0,
buyNum: 1,
cartDataVueShow: false,
searchText: '',
searchList: [],
searchFinish: false,
}
},
onLoad(options) {
this.getHeadImg("techan").then(res => {this.headImg = res})
},
onReady() {
this.initRectInfo()
this.getList()
},
methods: {
initRectInfo () {
const sysInfo = uni.getSystemInfoSync()
this.statusBarHeight = sysInfo.statusBarHeight
//
this.height = sysInfo.statusBarHeight + 40
},
changeType (item, i) {
if (this.typeIndex!== i) {
this.typeIndex=i
this.finished = false
this.list = []
this.getList()
}
},
//
getList(){
this.Post({
tag_id: this.typeParam[this.typeIndex].id,
offset: this.list.length,
limit: 10,
},'/api/tag/getGoodsByTagId').then(res => {
this.list = [...this.list, ...res.data];
if (res.data.length < 10) {
this.finished = true
}
})
},
scrollLow () {
if (!this.finished) {
this.getList()
}
},
viewDetail(item) {
// this.goOtherDetail(item)
if(!item.link_type) {
uni.navigateTo({
url: '/subPackages/techan/detail?id=' + item.id
})
}
},
showCartClick () {
if (this.paramData.showCart) {
this.$refs.cartDataVueRef.closePopup()
} else {
this.$refs.cartDataVueRef.openPop()
}
},
changeParamData (data) {
for(let key in this.paramData) {
this.paramData[key] = data[key]
}
},
//
showOrderCart (item) {
console.log(item)
this.sku = []
this.productIndex = 0
this.buyNum = 1
this.currentGoods = JSON.parse(JSON.stringify(item))
this.getSpecificationsByGoodsId(item.id)
},
changeProduct(item,index) {
if (item.store==0) {
uni.showToast({
title:"库存不足!",
icon:'none'
})
return
}
this.productIndex = index
},
getSpecificationsByGoodsId(goods_id) {
this.Post({goods_id: goods_id},'/api/goods/getSpecificationsByGoodsId'
).then(res => {
if (res) {
this.sku = res.data;
if (!this.sku||this.sku.length<=0) {
uni.showToast({
title:'暂无可选规格',
icon:'none'
})
return
}
this.openPop()
}
});
},
//
addNumber() {
this.buyNum += 1;
},
delNumber() {
if (this.buyNum <= 1) {
return;
}
this.buyNum -= 1;
},
closePopup() {
this.$refs.popup.close()
},
openPop(){
this.$refs.popup.open()
},
order() {
let goods = this.sku[this.productIndex]
if(goods.is_post!=1) {
uni.showToast({
title: '此规格不支持加入购物车',
icon: 'none'
})
return
}
goods.buyNum = this.buyNum
let goodsInfo = {goodsInfo:this.currentGoods, skuInfo: goods, isSelected: true}
this.Post({good_id: this.currentGoods.id, specifications_id: goods.id,num: this.buyNum },
'/api/shopping/addShopping').then(res => {
if (res) {
let selectedData = []
try {
selectedData = JSON.parse(uni.getStorageSync('cartDataInfo'));
} catch(e) {
selectedData = []
}
let currentGoods = selectedData.find(v =>v==goods.id)
if (!currentGoods) {
selectedData.push(goods.id)
}
uni.setStorageSync('cartDataInfo', JSON.stringify(selectedData));
uni.$emit("updateDataByConnect", {msgType:'updateCartDataInfo',data:null})
this.closePopup()
// this.$refs.cartDataVueRef.openPop()
}
});
},
goCartOrder () {
this.$refs.cartDataVueRef.goCartOrder()
},
//
search () {
this.searchFinish = false
this.searchList = []
// todo
this.searchList = [...this.list,...this.list,...this.list,...this.list]
},
},
onReachBottom() {
if (!this.searchFinish) {
this.search()
}
console.log(1)
}
}
</script>
<style lang="scss" scoped>
view {
box-sizing: border-box;
}
.search-header{
width: 100%;
position: fixed;
top: 0;
left: 0;
right: 0;
background: white;
display: flex;
align-items: center;
padding-left: 10rpx;
padding-right: 120px;
.input-model{
flex: 1;
width: 1rpx;
height: 64rpx;
background: #FFFFFF;
border-radius: 55rpx;
border: 1rpx solid #20898D;
margin-left: 12rpx;
display: flex;
align-items: center;
font-weight: 400;
font-size: 24rpx;
color: #ABAAAD;
padding-left: 24rpx;
}
.input-text{
height:19px;
padding-left: 14rpx;
font-weight: 400;
font-size: 24rpx;
color: #030000;
}
}
.bg {
height: 100vh;
padding-bottom: 26rpx;
display: flex;
flex-direction: column;
background: #F8FAFB;
}
.topImg {
width: 750rpx;
height: 344rpx;
flex-shrink: 0;
}
.goods-container{
height: 1rpx;
flex: 1;
display: flex;
}
.left-container{
width: 214rpx;
flex-shrink: 0;
.type-item{
font-weight: 400;
font-size: 24rpx;
color: #000000;
text-align: center;
width: 216rpx;
height: 120rpx;
line-height: 120rpx;
position: relative;
.active-type-bar{
position: absolute;
left: 0;
top: 0;
bottom: 0;
height: 100%;
width: 12rpx;
background: #74A5AA;
}
}
.type-item.active{
background: linear-gradient( 90deg, rgba(32,137,141,0.4) 0%, rgba(32,137,141,0) 100%);
font-weight: 600;
font-size: 28rpx;
}
}
.right-container{
flex: 1;
width: 1rpx;
background: white;
padding-top: 32rpx;
.item {
width: 100%;
padding:0 32rpx 32rpx 32rpx;
display: flex;
.item-img {
width: 148rpx;
height: 148rpx;
border-radius: 15rpx;
flex-shrink: 0;
}
.content {
height: 148rpx;
padding-left: 24rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
flex: 1;
}
.title {
font-weight: 500;
font-size: 28rpx;
color: #000000;
width: 100%;
}
.bottom {
display: flex;
justify-content: space-between;
align-items: center;
.price {
font-size: 40rpx;
color: #FA0000;
font-weight: 400;
}
.price::before {
content: '¥';
font-size: 24rpx;
}
}
}
}
.buy-cart{
width: 44rpx;
height: 44rpx;
color: #FFFFFF;
background: #74A5AA;
line-height: 44rpx;
font-size: 30rpx;
text-align: center;
border-radius: 50%;
}
.btn-list {
z-index: 99;
position: fixed;
bottom: 0;
width: 750rpx;
height: 148rpx;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 16rpx 0rpx rgba(6, 0, 1, 0.1);
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 26rpx;
.left-box {
display: flex;
align-items: center;
.bottom-price{
display: flex;
align-items: baseline;
font-family: PingFang SC;
font-weight: bold;
font-size: 27rpx;
color: #D70000;
padding: 0 12rpx;
.bottom-price-yuan{
font-size: 40rpx;
}
}
.bottom-detail-icon{
font-size: 24rpx;
display: flex;
align-items: center;
color: #0B898E;
}
.img-box {
image {
width: 78rpx;
height: 78rpx;
}
}
}
.btn-buy {
width: 240rpx;
height: 78rpx;
background: #74A5AA;
border-radius: 40rpx;
text-align: center;
line-height: 78rpx;
font-size: 32rpx;
font-family: PingFangSC;
font-weight: 500;
color: #FFFFFF;
}
}
//
.popup-content {
background-color: white;
padding: 0rpx 39rpx 51rpx 39rpx;
height: auto;
border-radius: 20rpx 20rpx 0 0;
.bottom-productImg {
display: flex;
margin-bottom: 48rpx;
}
.bottom-productImg img {
width: 218rpx;
height: 179rpx;
background: #666666;
border-radius: 13rpx;
}
.right-content {
margin: 10rpx 0 0 41rpx;
}
.bottom-productPrice {
font-size: 40rpx;
color: #C3282E;
&:before {
content: "¥";
font-size: 26rpx;
}
}
.bottom-content {
width: 331rpx;
font-size: 27rpx;
font-family: PingFang SC;
font-weight: 400;
color: #666666;
}
.botProduct {
width: 320rpx;
// height: 78rpx;
border-radius: 13rpx;
background-color: #EFEFEF;
font-size: 29rpx;
font-family: PingFang SC;
font-weight: 400;
color: #333333;
line-height: 78rpx;
text-align: center;
margin-bottom: 25rpx;
display: inline-block;
position: relative;
padding: 0 40rpx;
}
.noStore{
background-color: rgba(239, 239, 239, 1);
color: rgba(153, 153, 153, 1);
}
.noStore-text{
width: 113rpx;
height: 43rpx;
background: #C0C0C0;
border-radius: 7rpx 0rpx 7rpx 0rpx;
text-align: center;
line-height: 43rpx;
position: absolute;
right: -14rpx;
top: -20rpx;
font-size: 23rpx;
font-family: PingFangSC;
font-weight: 400;
color: #FFFFFF;
}
.botProducts {
background: #74A5AA;
color: #FFFFFF;
}
.buy-num {
font-size: 29rpx;
font-family: PingFang SC;
font-weight: 400;
color: #333333;
// border-top: 1rpx solid #CCCCCC;
padding: 39rpx 0;
display: flex;
align-items: center;
justify-content: space-between;
border-top: 1px solid #CCCCCC;
}
.buy-num .number-btn {
display: flex;
}
.buy-num .number-btn view {
display: flex;
justify-content: center;
align-items: center;
width: 69rpx;
height: 69rpx;
border: 1rpx solid #CCCCCC;
border-radius: 7rpx;
}
.buy-num .number-btn>view text {
font-size: 46rpx;
}
.btn-box {
width: 750rpx;
height: 151rpx;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 16rpx 0rpx rgba(6, 0, 1, 0.1);
display: flex;
align-items: center;
justify-content: center;
}
}
.placeholder-content{
background: white;
position: relative;
.btn-cover{
z-index: 200;
position: fixed;
bottom: 0;
width: 750rpx;
height: 148rpx;
background: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0rpx 0rpx 16rpx 0rpx rgba(6,0,1,0.1);
.btn{
width: 670rpx;
height: 78rpx;
text-align: center;
line-height: 78rpx;
background: #74A5AA;
border-radius: 40rpx;
font-size: 34rpx;
font-family: PingFangSC;
font-weight: 500;
color: #FFFFFF;
}
}
}
.search-result{
display: flex;
flex-direction: column;
width: 100%;
flex: 1;
flex-shrink: 0;
.search-item{
width: 337rpx;
box-shadow: 0rpx 0rpx 9rpx 0rpx rgba(153,153,153,0.33);
border-radius: 13rpx;
flex-shrink: 0;
margin-bottom: 20rpx;
height: fit-content;
image{
width: 100%;
border-radius: 13rpx;
}
.search-container{
padding: 20rpx;
.title{
font-weight: 500;
font-size: 27rpx;
color: #000000;
}
.price{
font-weight: 400;
font-size: 33rpx;
color: #D70000;
}
.price:before{
content: "¥";
font-size: 23rpx;
}
.oldPrice{
font-weight: 400;
font-size: 21rpx;
color: #999999;
text-decoration-line: line-through;
padding-left: 12rpx;
}
}
}
}
</style>

1281
subPackages/techan/order.vue

File diff suppressed because it is too large

253
subPackages/techan/selfPickUpPoint.vue

@ -0,0 +1,253 @@
<template>
<view class="bg">
<view :class="['item-bg',selectItem.id==item.id?'active':'']" v-for="(item,index) in list" :key="index" @click="selectPoint(item)">
<view class="item">
<view class="item-point-title">
<view class="name text-overflow flex-shrink-0">{{item.extract_name}}</view>
<view class="addressStr">
<!-- <view class="flex-shrink-0"></view> -->
<view class="text-overflowRows">地址{{item.detail_addr}}</view>
</view>
</view>
<view class="item-point-guide" @click.stop="goMap(item)">
<view>
<image :src="showImg('/uploads/20241104/8ff7aa0225c9e4fb86df1a9cb229c932.png')" mode="aspectFill" class="mapPoint"></image>
</view>
<view>去这里</view>
</view>
</view>
</view>
<view class="no-data" v-if="list.length==0">
<image src="https://static.ticket.sz-trip.com/dongtai/images/user/noAddress.png" mode="aspectFill" class="no-address"></image>
<view class="">
暂无自提点地址
</view>
</view>
<!-- <view class="btn-bottom">
<view class="addBox" @click.stop="confirmPoint">
确定
</view>
</view> -->
</view>
</template>
<script>
export default {
data() {
return {
load: false,
pending: false,
list: [],
pickupId: null,
goodsId: null,
selectItem: {},
};
},
onLoad(options) {
this.pickupId = options.pickupId || null
this.goodsId = options.goodsId
},
onShow(options) {
this.getList()
},
methods: {
getList() {
if (this.pending) {
return
}
this.pending = true
// this.getLocation()
let param = {
goods_id: this.goodsId,
offset: this.list.length,
limit: 10,
lon: uni.getStorageSync('location').lon || '',
lat: uni.getStorageSync('location').lat || '',
}
this.Post(param, "/api/extract/getMerchantExtractListByGoodsIdNew").then(res => {
if (res) {
this.list = [...this.list, ...res.data];
if (res.data.length < 10) {
this.load = true;
}
if (this.pickupId && Array.isArray(this.list)) {
let selectItem = this.list.find(v=>v.id==this.pickupId)
if (selectItem) {
this.selectItem = selectItem
}
}
}
this.pending = false
})
},
selectPoint (item) {
this.selectItem = item
// selectItem
uni.$emit("updateDataByConnect", {msgType:'updatePickUpPoint',data:this.selectItem})
uni.navigateBack()
},
goMap (item) {
uni.openLocation({
latitude: Number(item.lat),
longitude: Number(item.lon),
name: item.extract_name,
address: item.detail_addr,
success: function () {
console.log('success');
}
});
},
confirmPoint () {
if(!this.selectItem.id) {
uni.showToast({icon: "none",title: "请先选择自提点"})
return;
}
// selectItem
uni.$emit("updateDataByConnect", {msgType:'updatePickUpPoint',data:this.selectItem})
uni.navigateBack()
}
},
onReachBottom() {
setTimeout(() => {
if (!this.load) {
this.getList()
}
}, 1000);
}
}
</script>
<style lang="scss" scoped>
view {
box-sizing: border-box;
font-family: PingFang SC;
}
.bg {
position: relative;
background: #F7F7F7;
min-height: 100vh;
padding-bottom: 170rpx;
}
.flex-shrink-0{
flex-shrink: 0;
}
.item-bg{
width: 697rpx;
height: 160rpx;
background: #FFFFFF;
border-radius: 13rpx;
margin: 0 auto;
margin-bottom: 28rpx;
padding: 2rpx;
}
.item {
padding: 24rpx;
padding-right: 0;
display: flex;
background: #FFFFFF;
border-radius: 13rpx;
width: 100%;
height: 100%;
.item-point-title{
flex: 1;
width: 10rpx;
padding-right: 78rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.item-point-guide{
width:140rpx;
flex-shrink: 0;
border-left: 1px solid #D8D8D8;
color: #515150;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 24rpx;
}
.mapPoint{
width: 33rpx;
height: 33rpx;
}
}
.item-bg.active{
background: #515150;
}
.name {
display: flex;
font-size: 31rpx;
font-weight: bold;
color: #333333;
height: 42rpx;
}
.addressStr{
display: flex;
font-size: 27rpx;
color: #999999;
padding-top: 10rpx;
}
.no-data {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
view:nth-child(2) {
font-size: 30rpx;
font-family: PingFang SC;
font-weight: 500;
color: #333333;
margin-top: 25rpx;
}
image {
width: 160rpx;
height: 160rpx;
}
padding-bottom: 400rpx;
}
.btn-bottom{
position: fixed;
bottom: 0;
width: 750rpx;
height: 150rpx;
background: #FFFFFF;
box-shadow: 0rpx 0rpx 16rpx 0rpx rgba(6, 0, 1, 0.1);
display: flex;
justify-content: space-between;
padding: 30rpx 50rpx 30rpx 50rpx;
.addBox{
margin: 0 auto;
width: 697rpx;
height: 80rpx;
background: linear-gradient(90deg, #F84A56, #FF9834);
border-radius: 40rpx;
font-size: 36rpx;
font-family: PingFang SC;
font-weight: 500;
color: #FFFFFF;
line-height: 80rpx;
text-align: center;
}
}
</style>
Loading…
Cancel
Save