This commit is contained in:
wtq
2025-11-28 10:19:58 +08:00
commit 3e6f452aa5
275 changed files with 47800 additions and 0 deletions

21
.gitignore vendored Normal file
View File

@@ -0,0 +1,21 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
*.local
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

36
.hbuilderx/launch.json Normal file
View File

@@ -0,0 +1,36 @@
{
// launch.json 配置了启动调试时相关设置configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtype项可配置值为local或remote, local代表前端连本地云函数remote代表前端连云端云函数
"version" : "0.0",
"configurations" : [
{
"app-plus" : {
"launchtype" : "local"
},
"default" : {
"launchtype" : "local"
},
"mp-alipay" : {
"launchtype" : "local"
},
"mp-kuaishou" : {
"launchtype" : "local"
},
"mp-toutiao" : {
"launchtype" : "local"
},
"mp-weixin" : {
"launchtype" : "local"
},
"type" : "uniCloud"
},
{
"playground" : "custom",
"type" : "uni-app:app-android"
},
{
"playground" : "custom",
"type" : "uni-app:app-ios"
}
]
}

11
README.md Normal file
View File

@@ -0,0 +1,11 @@
# 京西菜市/京西到家
- 小程序(微信、抖音、快手、支付宝)
- app(Android 、 Ios)
## 项目安装
- node版本 19.6.0
- npm install / cnpm i
### 项目仓库
- 名字jxc4_app_and_mini
- 项目地址https://e.coding.net/rosydev/jxc4_app_and_mini/jxc4_app_and_mini.git

23
index.html Normal file
View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

19547
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

68
package.json Normal file
View File

@@ -0,0 +1,68 @@
{
"name": "uni-preset-vue",
"version": "0.0.0",
"scripts": {
"dev:app": "uni -p app",
"dev:app-android": "uni -p app-android",
"dev:app-ios": "uni -p app-ios",
"dev:custom": "uni -p",
"dev:h5": "uni",
"dev:h5:ssr": "uni --ssr",
"dev:mp-alipay": "uni -p mp-alipay",
"dev:mp-baidu": "uni -p mp-baidu",
"dev:mp-jd": "uni -p mp-jd",
"dev:mp-kuaishou": "uni -p mp-kuaishou",
"dev:mp-lark": "uni -p mp-lark",
"dev:mp-qq": "uni -p mp-qq",
"dev:mp-toutiao": "uni -p mp-toutiao",
"dev:mp-weixin": "uni -p mp-weixin",
"dev:quickapp-webview": "uni -p quickapp-webview",
"dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
"dev:quickapp-webview-union": "uni -p quickapp-webview-union",
"build:app": "uni build -p app",
"build:app-android": "uni build -p app-android",
"build:app-ios": "uni build -p app-ios",
"build:custom": "uni build -p",
"build:h5": "uni build",
"build:h5:ssr": "uni build --ssr",
"build:mp-alipay": "uni build -p mp-alipay",
"build:mp-baidu": "uni build -p mp-baidu",
"build:mp-jd": "uni build -p mp-jd",
"build:mp-kuaishou": "uni build -p mp-kuaishou",
"build:mp-lark": "uni build -p mp-lark",
"build:mp-qq": "uni build -p mp-qq",
"build:mp-toutiao": "uni build -p mp-toutiao",
"build:mp-weixin": "uni build -p mp-weixin",
"build:quickapp-webview": "uni build -p quickapp-webview",
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
"build:quickapp-webview-union": "uni build -p quickapp-webview-union"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-3081220230817001",
"@dcloudio/uni-app-plus": "3.0.0-3081220230817001",
"@dcloudio/uni-components": "3.0.0-3081220230817001",
"@dcloudio/uni-h5": "3.0.0-3081220230817001",
"@dcloudio/uni-mp-alipay": "3.0.0-3081220230817001",
"@dcloudio/uni-mp-baidu": "3.0.0-3081220230817001",
"@dcloudio/uni-mp-jd": "3.0.0-3081220230817001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-3081220230817001",
"@dcloudio/uni-mp-lark": "3.0.0-3081220230817001",
"@dcloudio/uni-mp-qq": "3.0.0-3081220230817001",
"@dcloudio/uni-mp-toutiao": "3.0.0-3081220230817001",
"@dcloudio/uni-mp-weixin": "3.0.0-3081220230817001",
"@dcloudio/uni-quickapp-webview": "3.0.0-3081220230817001",
"sass": "^1.67.0",
"vue": "^3.2.45",
"vue-i18n": "^9.1.9",
"vuex": "^4.1.0"
},
"devDependencies": {
"@dcloudio/types": "^3.3.2",
"@dcloudio/uni-automator": "3.0.0-3081220230817001",
"@dcloudio/uni-cli-shared": "3.0.0-3081220230817001",
"@dcloudio/uni-stacktracey": "3.0.0-3081220230817001",
"@dcloudio/vite-plugin-uni": "3.0.0-3081220230817001",
"@vue/runtime-core": "^3.2.45",
"vite": "4.1.4"
}
}

10
shims-uni.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
/// <reference types='@dcloudio/types' />
import 'vue'
declare module '@vue/runtime-core' {
type Hooks = App.AppInstance & Page.PageInstance;
interface ComponentCustomOptions extends Hooks {
}
}

124
src/App.vue Normal file
View File

@@ -0,0 +1,124 @@
<script>
import { checkProgramUpdate } from '@/utils/uniapi'
import { errToast } from '@/utils/uniapi.js'
import { store } from '@/store'
import loginApi from '@/apis/login'
export default {
// 全局参数
globalData: {
catID: null
},
onLaunch: async function ({query}) {
// store.commit('indexPage/changeStoreType',false) // 更换域名
store.commit('indexPage/changeDNS','wxC4') // 更换域名 默认为菜市
store.commit('login/setTmpData', {})
store.commit('indexPage/saveBrandID', 1)
// #ifdef APP-PLUS || APP
let iSExistWeixinApp = plus.runtime.isApplicationExist({ pname: 'com.tencent.mm', action: 'weixin://' })
store.commit('login/setISExistWeixinApp',iSExistWeixinApp)
store.commit('setIsShowShop',iSExistWeixinApp)
// #endif
uni.removeStorageSync('waybillAddress')
// #ifdef MP-TOUTIAO
// tta6a1d01c399f264201 京西菜市(抖音小程序)
await store.dispatch('isHiddenCart','ks680887971696897880') // 是否隐藏与购物车相关的一切信息
// #endif
// await this.globalLogin()
// #ifdef MP-WEIXIN
if (query !== undefined) {
// await this.sceneValue(query)
// 是否进行支付
if(query.scene ){
if (query.scene.includes('JXpay')) {
let orderID = ''
let dns = 'wxC4'
if(query.scene.includes('id')){
let decodedString = decodeURIComponent(query.scene)
orderID = decodedString.split('-')[0].substring(3)
dns = decodedString.split('-')[1].substring(6)
}
await this.globalLogin('',true)
// 京西支付
uni.reLaunch({
url: `/pagesPay/JX-pay/JX-pay?orderID=${orderID}&dns=${dns}`
});
}else{
// 扫码进入的
// uni.removeStorageSync('fromStoreID')
// uni.removeStorageSync('storeType')
}
}
// 公众号进入
if (query.brandID) {
// uni.removeStorageSync('queryStoreID')
// uni.removeStorageSync('fromStoreID')
// uni.removeStorageSync('storeType')
}
}
// #endif
uni.getSystemInfo({
success: info => {
store.commit('setIosOrAndroid', info)
}
})
try {
// 先隐藏底部tabBar
uni.hideTabBar()
// 检查是否有更新
// #ifdef MP-WEIXIN || MP-KUAISHOU || MP-ALIPAY || MP-TOUTIAO || MP-ALIPAY
await checkProgramUpdate()
// #endif
// #ifdef APP-PLUS || APP
// uni['globalAlert'] = globalAlert // 挂载全局可覆盖tabar弹窗
// let res = await loginApi.getVersionController('wxf3657c94aa01a3f0')
// let appVersion = JSON.parse(res[0].value).update.version.replace(/[^0-9]/g, '')
// console.log(Number(appVersion), 'STORE999999', store.getters.iosOrAndroid.appVersionCode)
// if (Number(appVersion) > store.getters.iosOrAndroid.appVersionCode) {
// if (Number(appVersion) < store.getters.iosOrAndroid.appVersionCode) {
// console.log('app有新版本啦啦啦', Number(appVersion))
// // uni.globalAlert({
// // data: {
// // type: 3,
// // },
// // })
// uni.navigateTo({
// url: `/components/globalAlert/globalAlert?data=${JSON.stringify(options.data)}`,
// success(e) {
// console.log('11111',e)
// }
// })
// }
// #endif
// if (store.getters['login/isLogin']) {
// // 查询信息
// await getSelfInfo()
// }
} catch (e) {
errToast(e)
}
},
onShow: function () {
console.log('App Show')
},
onHide: function () {
console.log('App Hide')
}
}
</script>
<style>
/*每个页面公共css */
page {
background-color: #f4f4f4;
}
</style>

14
src/androidPrivacy.json Normal file
View File

@@ -0,0 +1,14 @@
{
"version" : "2",
"prompt" : "template",
"title" : "服务协议和隐私政策",
"message" : "  请您务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向您提供服务,我们需要收集您的设备标识、操作日志等信息用于分析、优化应用性能。<br/>  您可阅读<a href=\"https://www.jxc4.com/managerApp/service.html\">《服务协议》</a>和<a href=\"https://www.jxc4.com/managerApp/privacy.html\">《隐私政策》</a>了解详细信息。如果您同意,请点击下面按钮开始接受我们的服务。",
"buttonAccept" : "同意并接受",
"buttonRefuse" : "暂不同意",
"second" : {
"title" : "确认提示",
"message" : "  进入应用前,您需先同意<a href=\"https://www.jxc4.com/managerApp/service.html\">《用户协议》</a>和<a href=\"https://www.jxc4.com/managerApp/privacy.html\">《隐私政策》</a>,否则将退出应用。",
"buttonAccept" : "同意并继续",
"buttonRefuse" : "退出应用"
}
}

171
src/apis/address/index.js Normal file
View File

@@ -0,0 +1,171 @@
import api from '../request'
import { gdMapKey } from "@/apis/config"
import { json2query } from '@/utils'
export default {
/**
* 高德坐标解析
*/
posToCity: async (data) => {
try {
let res = await api('v3/geocode/regeo', {
data: {
key: gdMapKey,
location: `${data.longitude},${data.latitude}`,
extensions: data.extensions ? 'all' : 'base'
}
}, 'gdMap')
return res
} catch (e) {
console.error('posToCity', e)
throw (e)
}
},
/**
* 获取建议地址
*/
getSuggestion: async (keywords, city) => {
try {
let res = await api('v3/place/text', {
data: {
key: gdMapKey,
keywords,
city,
citylimit: true
}
}, 'gdMap')
return res
} catch (e) {
console.error('getSuggestion', e)
throw (e)
}
},
/**
* 按当前位置匹配门店
*/
storeListByLocation: async (data) => {
try {
// #ifdef MP-KUAISHOU
// data.lat = 30.69015
// data.lng = 104.05293
// #endif
let res = await api('v2/store/GetStoreListByLocation', {
data
})
return res
} catch (e) {
console.error('storeListByLocation', e)
throw (e)
}
},
/**
* 关键字检索城市
*/
getCity: async (params) => {
try {
let res = await api('v2/cms/GetPlaces', {
data: {
level: params.level,
includeDisabled: true,
keyword: params.keyword
}
})
return mapCity(res || [])
} catch (e) {
console.error('getCity', e)
throw (e)
}
},
/**
* 查询地址管理
* @param {*} params 暂无
*/
getMyDeliveryAddress: async (params = {}) => {
try {
let res = await api('v2/user2/QueryMyDeliveryAddress', {
data: params
})
return res
} catch (e) {
console.error('getMyDeliveryAddress', e)
throw (e)
}
},
/**
* 添加地址
* @param {Object} form 参数对象
* consigneeName 收货人
* consigneeMobile 收货人手机
* address 详细地址
* detailAddress
* lng 经度 Number
* lat 纬度 Number
*
* 非必须
* tag 标签(家、公司、学校)
* remark 备注
* isDefault 是否是默认 true false
*/
addAddressList: async (form = {}) => {
try {
let res = await api('v2/user2/AddMyDeliveryAddress', {
method: 'POST',
data: json2query(form)
})
return res
} catch (e) {
console.error('addMyDeliveryAddress', e)
throw (e)
}
},
/**
* 修改地址
* @param {Object} form
*/
updateMyDeliveryAddress: async (form = {}) => {
try {
let res = await api('v2/user2/UpdateMyDeliveryAddress', {
method: 'PUT',
data: json2query(form)
})
return res
} catch (e) {
console.error('updateMyDeliveryAddress', e)
throw (e)
}
},
/**
* 删除地址
* @param {Number} addressID 地址ID
*/
delMyDeliveryAddress: async (addressID) => {
try {
let res = await api('v2/user2/DeleteMyDeliveryAddress?id=' + addressID, {
method: 'DELETE'
})
return res
} catch (e) {
console.error('delMyDeliveryAddress', e)
throw (e)
}
}
}
const mapCity = (arr) => {
if (arr.length === 0) return []
return arr.map(item => ({
id: item.id,
code: item.code,
name: item.name
}))
}

173
src/apis/apiStore/index.js Normal file
View File

@@ -0,0 +1,173 @@
import api from '../request'
import { store } from '@/store'
export default {
/**
* 获取配置文件
* @param {string} keyword // 1.banner时 shopBanner 2.vip时 DiscountCard 3.materialDesc时 materialDesc
* @param {string} type // 1.banner 和 materialDesc 时 JxStore 2.Vip时 DiscountCard
*/
getConfigInfo: async (type) => {
try {
let res = await api('v2/cms/QueryConfigs', {
data: {
keyword: type === 'banner' ? 'shopBanner' : (type === 'vip' ? 'DiscountCard' : (type === 'materialDesc' ? 'materialDesc' : '')),
type: (type === 'banner' || type === 'materialDesc') ? 'JxStore' : 'DiscountCard'
}
})
if (res && res.length > 0) {
return JSON.parse(res[0].value)
} else {
return []
}
} catch (e) {
throw (e)
}
},
/**
* 推荐商家
*/
getNearlyStore: async (data,dns = 'wxC4') => {
try {
// if (!data.lat) return []
if (!(data && data.lat)) return []
// #ifdef MP-KUAISHOU
// data.lat = 30.69015
// data.lng = 104.05293
// #endif
if(data.brandID && data.brandID.length) data.brandID = JSON.stringify(data.brandID)
let res = await api('v2/store/GetHomePageByLocation', {
data
},
dns)
// 过滤重复项
let array = []
let storeIDsArr = []
if (res && res.length > 0) {
res.map((item) => {
let findIndex = storeIDsArr.findIndex(i => i === item.storeInfo.storeID)
if (findIndex === -1) {
storeIDsArr.push(item.storeInfo.storeID)
array.push(item)
}
})
}
return array
} catch (e) {
console.error('getNearlyStore', e)
throw (e)
}
},
/**
* 获取门店信息
*/
getStoreInfo: async (data) => {
try {
let res = await api('v2/store/GetStores', {
data
})
return res
} catch (e) {
console.error('getStoreInfo', e)
throw (e)
}
},
/**
* 获取门店减运策略
*/
getWayBillFeeMinus: async (storeID) => {
try {
let res = await api('v2/store/GetStoreVendorMaps', {
data: {
storeID,
vendorID: 9
}
})
if (res && res.length > 0) {
store.commit('indexPage/saveWaybillSLG', {
satisfy: res[0].deliveryFeeDeductionSill / 100,
reduce: res[0].deliveryFeeDeductionFee / 100
})
} else {
store.commit('indexPage/saveWaybillSLG', {
satisfy: 0,
reduce: 0
})
}
return res
} catch (e) {
console.error('getWayBillFeeMinus', e)
throw (e)
}
},
/**
* 获取品牌
* @param {*} brandID
* @param {*} storeID
* brandID
*/
getBrand: async (data) => {
try {
let res = await api('v2/store/GetBrands', {
data
})
return res
} catch (e) {
console.error('getBrand', e)
throw (e)
}
},
/**
* 获取配送时间
*/
getDeliverTime: async (storeID) => {
try {
let res = await api('v2/jxorder/GetAvailableDeliverTime', {
data: {
storeID
}
})
return res
} catch (e) {
console.error('getDeliverTime', e)
throw (e)
}
},
/**
* 物料篇-----------
* 刷新物料库存
*/
refreshStock: async () => {
try {
let res = await api('v2/store/sku/RefreshMatterStock', {
method: 'POST'
})
return res
} catch (e) {
console.error('', e)
throw (e)
}
},
/**
* 物料是否能够购买,以及销量
*/
getMatterStoreOrderStatus: async (storeID) => {
try {
let res = await api(`v2/order/GetMatterStoreOrderCount?storeID=${storeID}`)
return res
} catch (e) {
console.error('', e)
throw (e)
}
}
}

View File

@@ -0,0 +1,71 @@
import api from '../request'
import { json2query } from '@/utils'
export default {
/**
* 获取购物车列表
*/
getMyCart: async (storeIDs) => {
try {
if (!(storeIDs && storeIDs.length !== 0)) return
let res = await api('v2/user2/LoadMyCart', {
data: {
storeIDs: JSON.stringify(storeIDs)
}
})
return res
} catch (e) {
console.error('getMyCart', e)
throw (e)
}
},
/**
* 存储购物车信息
* @params {Number} StoreID
* @params {String} payload 购物车商品列表
* payload []
* {
* skuID, count, price, storeID, isChecked
* }
*/
saveToCart: async (storeID, list) => {
try {
let payload = list.filter(item => item.storeID === storeID).map(item => ({
skuID: item.id,
count: item.count,
price: item.curPrice,
storeID: item.storeID,
isChecked: item.checked ? 1 : 0
}))
let res = await api('v2/user2/SaveMyCart', {
method: 'POST',
data: json2query({
storeID,
payload: JSON.stringify(payload)
})
})
return res
} catch (e) {
console.error('saveToCart', e)
throw (e)
}
},
/**
* 批量采购****************************
*/
getSupplySupportStoreSkus: async (json) => {
try {
let res = await api('v2/jxorder/GetSupplySupportStoreSkus', {
data: {
...json
}
})
return res
} catch (e) {
console.error('getSupplySupportStoreSkus', e)
throw (e)
}
}
}

459
src/apis/config.js Normal file

File diff suppressed because one or more lines are too long

155
src/apis/goodPage/index.js Normal file
View File

@@ -0,0 +1,155 @@
import api from '../request'
// import config from "@/apis/config"
import { store } from "@/store"
import { mapSkuNames } from '@/utils'
export default {
/**
* 获取门店分类
*/
getCat: async (storeID) => {
try {
let res = await api('v2/store/GetStoreCategoryMap', {
data: {
storeID,
parentID: -1
}
})
// #ifdef MP-KUAISHOU || MP-ALIPAY || MP-TOUTIAO
// if (GetStoreCategoryMap === null) {
// data = config.JXCateroy
// }
// #endif
return {
catL1: mapCats(res, 1),
catL2: mapCats(res, 2),
}
} catch (e) {
console.error('getCat', e)
throw (e)
}
},
/**
* 获取推荐分类
*/
getTopCats: async (data) => {
try {
let res = await api('v2/store/sku/GetTopCategoriesByStoreIDs', {
data
})
// let res = config.topCats
if (res !== null) {
return res.map(item => ({
id: item.id,
level: item.level,
name: item.name.substring(0, 4),
parentID: item.parentID,
// img: item.img.includes('https') ? item.img : item.img.substring(0, 4) + 's' + item.img.substring(4)
img: item.img
}))
} else {
return []
}
} catch (e) {
console.error('getTopCats', e)
throw (e)
}
},
/**
* 获取分类商品
*/
getStoresSkus: async (params = { pageSize: -1, offset: 0 }) => {
let json = {
storeIDs: params.storeID ? JSON.stringify([params.storeID]) : JSON.stringify(store.getters['indexPage/storeID']),
isBySku:true,
pageSize: params.pageSize ? params.pageSize : -1,
offset: params.offset ? params.offset : 0
}
if (params.categoryID) {
if (params.categoryID === 'act') {
json.isAct = true
} else if (params.categoryID === 'one') {
json.skuIDs = JSON.stringify([Number(params.skuID)])
json.pageSize = 1
} else {
json.categoryID = params.categoryID
}
}
if (params.keyword) json.keyword = params.keyword
if (params.skuIDs) json.skuIDs = JSON.stringify(params.skuIDs)
if(!params.isBySku) json.isBySku = false
try {
let res = await api('v2/store/sku/GetStoresSkus', {
data: {
isFocus: true,
actVendorID: 9,
// isBySku: true,
fromStatus: 1,
toStatus: 1,
...json
}
})
return {
totalCount: res.totalCount,
skuNames: mapSkuNames(res.skuNames || [])
}
} catch (e) {
console.error('getStoresSkus', e)
throw (e)
}
},
/**
* GetCategories
*/
getCategories: async (storeID) => {
try {
let res = await api('v2/store/sku/GetStoreCategories', {
storeID
})
return res
} catch (e) {
console.error('getCategories', e)
throw (e)
}
},
/**
* 获取热销商品
*/
getTopGoods: async (storeID) => {
try {
let res = await api('v2/store/sku/GetTopSkusByStoreIDs', {
data: {
storeIDs: JSON.stringify(storeID)
}
})
return res
} catch (e) {
console.error('getTopGoods', e)
throw (e)
}
},
}
// 过滤分类
const mapCats = (arr, level) => {
return arr.filter(item => item.level === level && (item.isHidden === 1 || item.isHidden === 0)).map((item, index) => ({
id: item.categoryID,
level: item.level,
name: item.name.substring(0, 4),
parentID: item.parentID,
index: index + 1
}))
}

249
src/apis/login/index.js Normal file
View File

@@ -0,0 +1,249 @@
import api from '../request'
import { getCode } from "@/utils/uniapi.js";
import { authType } from "@/apis/config"
import { json2query } from '@/utils'
export default {
/**
* 登录
*/
wLogin: async (json) => {
try {
let data = json
// 获取code
if (!data) data = await loginData(data)
let res = await api('v2/auth2/Login', {
method: 'POST',
data
})
return res
} catch (e) {
console.error('wLogin', e)
throw (e)
}
},
/**
* 解析手机号 微信
*/
getUserByMiniInfo: async (data) => {
try {
let res = await api('v2/auth2/GetUserByMiniInfo', {
method: 'POST',
data: {
data: data.encryptedData,
iv: data.iv,
jsCode: await getCode('oauth'),
appID: 'wx4b5930c13f8b1170'
},
header: {
'content-type': 'application/x-www-form-urlencoded'
},
})
return res
} catch (e) {
console.error('getUserByMiniInfo', e)
throw (e)
}
},
/**
* 解析手机号 快手和抖音
* @param {*} sessionKey // 用户 login 返回的 sessionKey
* @param {*} msg // 密文 encryptedData
* @param {*} iv // 密钥 iv
* @param {*} loginType // 类型 authType()
*/
analyzeMobile: async (data) => {
try {
let res = await api('v2/auth2/TiktokDecrypt', {
method: 'POST',
data: {
sessionKey: data.sessionKey,
msg: data.phone.encryptedData,
iv: data.phone.iv,
loginType: await authType()
}
})
return res
} catch (e) {
console.error('analyzeMobile', e)
throw (e)
}
},
/**
* 绑定手机号
*/
addAuthBindWithMobile: async (data) => {
try {
let res = await api('v2/auth2/AddAuthBindWithMobile', {
method: 'POST',
data
})
return res
} catch (e) {
console.error('addAuthBindWithMobile', e)
throw (e)
}
},
/**
* 注册
* @param {String} authToken // login返回的临时token
* @param {Object} payload
* @param {String} payload.userID2
* @param {String} payload.name
* @param {String} payload.mobile
* @param {String} payload.avatar
*/
registerUser: async (data) => {
try {
let res = await api('v2/user2/RegisterUser', {
method: 'POST',
data
})
return res
} catch (e) {
console.error('registerUser', e)
throw (e)
}
},
/**
* 获取用户信息
*/
getSelfInfo: async () => {
try {
let res = await api('v2/user2/GetSelfInfo')
return res
} catch (e) {
console.error('getSelfInfo', e)
throw (e)
}
},
/**
* 更新用户信息
*/
updateUserLastInfo: async (storeID, brandID) => {
try {
let res = await api('v2/user2/UpdateUserLastInfo', {
method: 'POST',
data: json2query({
brandID,
storeID
})
})
return res
} catch (e) {
console.error('updateUserLastInfo', e)
throw (e)
}
},
/**
* 获取服务信息
*/
getServiceInfo: async () => {
try {
let res = await api('v2/cms/GetServiceInfo')
return res
} catch (e) {
console.error('', e)
throw (e)
}
},
/**
* 获取个人推荐码
* data:{scene: json}
*/
getTiktokOrWxCode: async (json) => {
try {
let res = await api('v2/event/GetWeixinUnlimited', {
method: 'POST',
data: json
})
return res
} catch (e) {
console.error('getTiktokCode', e)
throw (e)
}
},
/**
* 通过商家电话号码或者商家信息
*/
getUsers: async (mobile) => {
try {
let res = await api(`v2/user2/GetUsers?userType=0&mobile=${mobile}`)
return res
} catch (e) {
console.error('getUsers', e)
throw (e)
}
},
/**
* 聊天记录
*/
getImMessageRecord: async (vendorOrderID) => {
try {
let res = await api('v2/event/GetImMessageRecord', {
data: {
vendorOrderID
}
})
return res
} catch (e) {
console.error('getImMessageRecord', e)
throw (e)
}
},
// /**
// * 获取临时token
// */
// getTemToken: async () => {
// try {
// let res =await api('v2/app_need/getToken4Jxc4', {
// method: 'POST',
// }, 'print')
// return res
// }catch(e){
// console.error('', e)
// throw(e)
// }
// },
/**
* 获取版本信息
*/
getVersionController: async (appId) => {
try {
let res = await api('v2/version/GetVersionController', {
data: {
appId
}
})
return res
} catch (e) {
console.error('getVersionController', e)
throw (e)
}
}
}
/**
* 组合登录的参数
*/
const loginData = async (code) => {
let data = {
authType: authType(),
authSecret: code ? code : await getCode('oauth')
}
return data
}

406
src/apis/orderPage/index.js Normal file
View File

@@ -0,0 +1,406 @@
import api from '../request'
import { json2query, mapData } from '@/utils'
import { formatDate } from '@/utils/assist.js'
import { store } from '@/store'
export default {
/**
* 创建订单
*/
createOrder: async (json = {}) => {
try {
let res = await api('v2/jxorder/CreateOrder', {
method: 'POST',
data: json2query(json)
})
return res
} catch (e) {
console.error('createOrder', e)
throw (e)
}
},
/**
* 查询订单 通过vendorOrderID
*/
getOrderInfo:async (json,dns = 'wxC4') => {
try {
let res = await api('v2/order/GetOrders', {
data: json,
},dns)
return res
} catch (e) {
throw e
}
},
/**
* 查询订单数量
* @param {String} fromDate 开始日期 2019-12-12
* @param {String} toDate 结束日期
* @param {String} statuss 订单状态列表 [1,2,3]
*/
getOrderCount: async () => {
try {
let res = await api('v2/jxorder/GetMyOrderCountInfo', {
data: {
fromDate: formatDate(new Date() - 6 * 24 * 3600 * 1000, 'YYYY-MM-DD'),
toDate: formatDate(null, 'YYYY-MM-DD'),
statuss: JSON.stringify([2, 5, 10, 15, 17, 18, 20])
}
})
let orderInfo = res || []
let waitCount = orderInfo.find(item => item.status === 2) // 计算数量
let deliverCount = orderInfo.reduce((prev, next) => {
if (next.status >= 5 && next.status <= 20) {
return prev + next.count
} else {
return prev
}
}, 0)
return {
waitCount: waitCount ? waitCount.count : 0,
deliverCount
}
} catch (e) {
console.error('getMyOrderCountInfo', e)
throw (e)
}
},
/**
* 获取支付信息 Pay4Order
* @param {String} vendorOrderID 订单号
* @param {Number} payType 支付类型 PayTypeWX = 1 // 微信支付
* @param {String} vendorPayType 平台支付类型
*/
pay4Order: async (json,dns="wxC4") => {
try {
let res = await api('v2/jxorder/Pay4Order', {
method: 'POST',
data: json
},dns ? dns : 'wxC4')
return res
} catch (e) {
console.error('pay4Order', e)
throw {
errKey: 'pay4Order',
err: e
}
// throw (e)
}
},
/**
* @param {String} id 会员折扣id
* @param {Number} payType 支付类型 PayTypeWX = 1 // 微信支付
* @param {String} vendorPayType 平台支付类型
*/
pay4User: async (json) => {
try {
let res = await api('v2/jxorder/Pay4User', {
method: 'POST',
data: json
})
return res
} catch (e) {
console.error('pay4User', e)
throw (e)
}
// orderPage.pay4User
},
/**
* 获取我的订单
* @param {String} vendorOrderID 订单号
* @param {String} keyword 关键字
* @param {String} fromDate 开始日期 2006-01-02
* @param {String} fromDate 结束日期 2006-01-02
* @param {String} statuss 状态,缺省不限制
* @param {Number} offset 序号
* @param {Number} pageSize 页大小
*/
getMyOrders: async (json) => {
try {
let res = await api('v2/jxorder/GetMyOrders', {
data: {
...json,
fromDate: formatDate(new Date() - 364 * 24 * 3600 * 1000, 'YYYY-MM-DD'),
toDate: formatDate(null, 'YYYY-MM-DD'),
offset: 0,
pageSize: 10,
}
})
return {
totalCount: res.totalCount,
data: mapData(res.data)
}
} catch (e) {
console.error('getMyOrders', e)
throw (e)
}
},
/**
* 获取订单商品信息
* @param {String} vendorOrderID 订单号
* @param {Number} vendorID 厂商
*/
getOrderSkuInfo: async (vendorOrderID, vendorID) => {
try {
let res = await api('v2/order/GetOrderSkuInfo', {
data: {
vendorOrderID,
vendorID
}
})
return res
} catch (e) {
console.error('getOrderSkuInfo', e)
throw (e)
}
},
/**
* 获取订单状态
* @param {String} vendorOrderID 订单号
* @param {Number} vendorID 厂商
* @param {Number} orderType 订单1运单2订单+运单:-1
*/
getOrderStatus: async (vendorOrderID, vendorID) => {
try {
let res = await api('v2/order/GetOrderStatusList', {
data: {
vendorOrderID,
vendorID,
orderType: 1
}
})
if (res) {
return res.map(item => ({
id: item.id,
statusText: store.getters['login/cms'].orderStatus[item.status],
statusTime: formatDate(item.statusTime, 'YYYY-MM-DD hh:mm:ss'),
remark: item.remark
})).sort((n1, n2) => (new Date(n2.statusTime) - new Date(n1.statusTime)))
} else {
return []
}
// return res
} catch (e) {
console.error('getOrderStatus', e)
throw (e)
}
},
/**
* 查询物料订单状态
* @param {*} json
*/
getMatterOrderStatus: async (json) => {
try {
let res = await api('v2/jxorder/GetMatterOrderStatus', {
data: json
})
if (res) {
return res.map(item => ({
id: parseInt(Math.random() * 2000) + 1,
statusText: item.status,
statusTime: formatDate(item.time, 'YYYY-MM-DD hh:mm:ss'),
remark: item.name
})).sort((n1, n2) => (new Date(n2.statusTime) - new Date(n1.statusTime)))
} else {
return []
}
} catch (e) {
console.error('getMatterOrderStatus', e)
throw (e)
}
},
/**
* 买家取消订单
* @param {*} vendorOrderID 订单号
* @param {*} reason 原因
*/
buyerCancelOrder: async (json) => {
// try {
// await api('v2/jxorder/BuyerCancelOrder', {
// method: 'POST',
// data: json
// })
// } catch (e) {
// console.error('BuyerCancelOrder', e)
// throw e
// }
try {
let res = await api('v2/order/CancelOrder', {
method: 'PUT',
data: json
})
return res
} catch (e) {
console.error('buyerCancelOrder', e)
throw (e)
}
},
/**
* 获取售后单
* @param {*} afsOrderID 售后单号
* @param {*} vendorOrderID 订单号
* @param {*} fromTime 开始时间
* @param {*} toTime 结束时间
* @param {*} offset 起始序号
* @param {*} pageSize 页大小
*/
getAfsOrders: async (json) => {
try {
let res = await api('v2/jxorder/GetMyAfsOrders', {
data: json
})
return res
} catch (e) {
console.error('getAfsOrders', e)
throw (e)
}
},
/**
* 获取售后单商品
* @param {*} afsOrderID 售后单号
* @param {*} vendorID 厂商ID
*/
getAfsOrderSkuInfo: async (json) => {
try {
let data = {}
if (json.afsOrderID) data.afsOrderID = json.afsOrderID
if (json.vendorOrderID) data.vendorOrderID = json.vendorOrderID
data.vendorID = json.vendorID
data.isNotFaild = json.isNotFaild ? true : false
let res = await api('v2/order/GetAfsOrderSkuInfo', {
data
})
return res
} catch (e) {
console.error('getAfsOrderSkuInfo', e)
throw (e)
}
},
// /**
// * 发起售后退款 该接口直接退款并没有审核这一步故取消使用该接口发起售后修改为v2/jxshop/JxMsg
// * @param {*} vendorOrderID 订单号
// * @param {*} vendorID 厂商ID
// * @param {*} refundSkuList [{skuID, count, storeSubID}]
// * @param {*} reason 原因
// */
// partRefundOrder: async (vendorOrderID, vendorID, refundSkuList, reason) => {
// try {
// let res = await api('v2/order/PartRefundOrder', {
// method: 'PUT',
// data: {
// vendorOrderID,
// vendorID,
// refundSkuList,
// reason
// }
// })
// return res
// } catch (e) {
// console.error('partRefundOrder', e)
// throw (e)
// }
// }
/**
* 申请售后
* 该接口存在问题,需后端优化
* 目前只能进行部分商品售后退款申请
* 问题1全部商品申请退款失败
* 问题2每次只申请退款一个商品直至退到最后一个运费退不回来
*/
applyAfterSale: async (data) => {
try {
let res = await api('v2/jxshop/JxMsg', {
method: 'POST',
data
})
return res
} catch (e) {
console.error('applyAfterSale', e)
throw (e)
}
},
/**
* 自定义金额支付(接口已经调通,后端待优化)京西支付
*/
pay4StoreMyselfDeliverOrder: async (json) => {
try {
if (!store.getters['login/isLogin']) return
let res = await api('v2/jxorder/Pay4StoreMyselfDeliverOrder', {
method: 'POST',
data: json
})
return res
} catch (e) {
console.error('pay4StoreMyselfDeliverOrder', e)
throw (e)
}
},
/**
* 订单拣货完成 扫码支付 到店消费
*/
finishedPickup:async (json,dns='wxC4') => {
try {
let res = await api('v2/order/FinishedPickup', {
method: 'POST',
data: json
},dns)
return res
} catch (error) {
console.error('finishedPickup', error)
throw (error)
}
},
/**
* 订单送达
*/
selfDelivered:async (json,dns='wxC4') => {
try {
let res = await api('v2/order/SelfDelivered', {
method: 'POST',
data: json
},dns)
return res
} catch (error) {
console.error('selfDelivered', error)
throw (error)
}
},
/**
* 修改订单信息
*/
updateOrderInfo:async (json,dns='wxC4') => {
try {
let res = await api('v2/order/UpdateOrderInfo', {
method: 'POST',
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded'
// },
data: json
},dns)
return res
} catch (error) {
console.error('updateOrderInfo', error)
throw (error)
}
}
}

166
src/apis/request.js Normal file
View File

@@ -0,0 +1,166 @@
import { rootUrl,whiteListUrl } from "@/apis/config" //根路径
// #ifdef MP-WEIXIN
import { logInfo } from '@/utils/log'
// #endif
import { jumpPage } from "@/utils/uniapi.js";
import { store } from '@/store'
/**
* 根路径的类型
*/
const rootType = (type) => {
let rootType = type ? type : 'wxC4' // 默认为wxC4
// if (rootType === 'wxC4' && store.getters['indexPage/isGy']) rootType = 'wxGy'
if (rootType === 'wxC4' && store.getters['indexPage/dns']) {
rootType = store.getters['indexPage/dns']
}
return rootType
}
/**
* header
*/
const headerType = (options) => {
if (options) {
if (options.method === 'POST' || options.method === 'PUT') {
return {
'content-type': 'application/x-www-form-urlencoded'
}
}
} else {
return ''
}
}
/**
* 请求日志
*/
const logInfoItem = (url, options, startTime, endTime, token, data,rootUrl) => {
// #ifdef MP-WEIXIN
let logJson = {
rootUrl:rootUrl,
url: url,
params: options.data,
time: endTime - startTime,
token,
data: JSON.stringify(data)
}
logInfo(logJson)
// #endif
}
const request = (url, options = {}, root) => {
return new Promise((resolve, reject) => {
let type = rootType(root) // 根路径类型
let apiUrl = rootUrl[type] + url
// #ifdef H5
apiUrl = url
// #endif
// header
options.header = headerType(options)
// token
let token = uni.getStorageSync('token') ? uni.getStorageSync('token') : ''
if(whiteListUrl.includes(url) && !store.getters['indexPage/isMaterial']) token = ''
let startTime = +new Date() // 开始时间
// store.commit('showLoad')
uni.request({
url: apiUrl,
method: options.method || 'GET',
data: options.data,
// timeout: 15000, // 15s
header: {
token: token || '',
...options.header
},
success: ({ data, statusCode }) => {
const endTime = +new Date() // 结束时间
// console.log(apiUrl, '花费时间', endTime - startTime)
if (statusCode !== 200 && statusCode !== 304) {
console.log(statusCode)
let msg = '请求出错'
reject(msg)
}
let errMessage = ''
let code, res, desc
if (root === 'gdMap') {
code = data.status === '1' ? '0' : data.status
res = data.regeocode ? JSON.stringify(data.regeocode) : JSON.stringify(data)
if (data.info !== 'ok') errMessage = data.info
} else {
code = data.code
res = data.data
desc = data.desc
}
if (code !== '-104') logInfoItem(url, options, startTime, endTime, token, data,rootUrl[type]) // 请求日志 微信
if (code === '0') {
resolve(JSON.parse(res))
} else if (code === '-1') {
// 注册
if (url.includes('RegisterUser') && desc === '用户标识已经存在' || desc === '要登录类型已经存在') {
resolve(desc)
} else if (url.includes('CreateOrder') && desc.includes('配送范围')) {
resolve(desc)
} else {
errMessage = desc
}
// 校验地址范围
} else if (code === '-104') {
resolve({
...data
})
} else {
if (code === '-2') {
// 清空登录信息
store.commit('login/changeLoginStatus', '')
// 清空购物车
store.commit('cartPage/saveCartList', [])
errMessage = '身份验证过期,请重新登录'
jumpPage('switchTab', '/pages/mine/index', 800)
} else if (code === '-3') {
errMessage = code
} else {
if (desc === '需要正式TOKEN' || desc === "token过期或无效请重新登录") {
errMessage = '登录过期,请重新登录'
jumpPage('switchTab', '/pages/mine/index', 800)
} else {
errMessage = desc
}
}
}
if (errMessage) reject(new Error(errMessage))
// store.commit('hideLoad')
},
fail: (err) => {
console.log('请求错误', err)
const endTime = +new Date()
logInfoItem(url, options, startTime, endTime, token, err,rootUrl[type]) // 请求日志 微信
// store.commit('hideLoad')
reject(err)
}
})
})
}
export default request

115
src/assets/_animate.scss Normal file
View File

@@ -0,0 +1,115 @@
%ani-bounceIn {
animation: bounceIn 2s infinite;
animation-direction: alternate;
}
@keyframes bounceIn {
from,
20%,
40%,
60%,
80%,
to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
0% {
opacity: .4;
transform: scale3d(0.3, 0.3, 0.3);
}
20% {
transform: scale3d(1.1, 1.1, 1.1);
}
40% {
transform: scale3d(0.9, 0.9, 0.9);
}
60% {
opacity: 1;
transform: scale3d(1.03, 1.03, 1.03);
}
80% {
transform: scale3d(0.97, 0.97, 0.97);
}
to {
opacity: 1;
transform: scale3d(1, 1, 1);
}
}
%ani-rubberBand {
animation: rubberBand 1s infinite;
// animation-direction: alternate;
}
@keyframes rubberBand {
from {
transform: scale3d(1, 1, 1);
}
30% {
transform: scale3d(1.25, 0.75, 1);
}
40% {
transform: scale3d(0.75, 1.25, 1);
}
50% {
transform: scale3d(1.15, 0.85, 1);
}
65% {
transform: scale3d(0.95, 1.05, 1);
}
75% {
transform: scale3d(1.05, 0.95, 1);
}
to {
transform: scale3d(1, 1, 1);
}
}
@keyframes bounceInUp {
from,
60%,
75%,
90%,
to {
-webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
}
from {
opacity: 0;
-webkit-transform: translate3d(0, 3000px, 0);
transform: translate3d(0, 3000px, 0);
}
60% {
opacity: 1;
-webkit-transform: translate3d(0, -20px, 0);
transform: translate3d(0, -20px, 0);
}
75% {
-webkit-transform: translate3d(0, 10px, 0);
transform: translate3d(0, 10px, 0);
}
90% {
-webkit-transform: translate3d(0, -5px, 0);
transform: translate3d(0, -5px, 0);
}
to {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}

34
src/assets/_color.scss Normal file
View File

@@ -0,0 +1,34 @@
/*
配色
引入: @import '@/assets/_color.scss';
*/
$maincolor: #4EB331;
$maincolor2: #72b92c;
$primary: #409EFF;
$success: #67C23A;
$warning: #E6A23C;
$danger: #F56C6C;
$info: #909399;
$text1: #333;
$text2: #606266;
$text3: #909399;
$text4: #C0C4CC;
$border1: #DCDFE6;
$border2: #E4E7ED;
$border3: #EBEEF5;
$border4: #F2F6FC;
$strong: #fe6263;
$gray: #b2b2b2;
$noGoods: #dcdcdc;
$bggray: #fafafa;
$inputplaceholder: #666;
$inputtext: $text1;
$bginput: #efefef;
$inputremove: #c5c5c5;
$inputsearch: #999;

309
src/assets/_extend.scss Normal file
View File

@@ -0,0 +1,309 @@
// @import '@/assets/bundle.scss';
%flex-center {
display: flex;
align-items: center;
justify-content: center;
}
%flex-between {
display: flex;
align-items: center;
justify-content: space-between;
}
%flex-around {
display: flex;
align-items: center;
justify-content: space-around;
}
%flex-left {
display: flex;
align-items: center;
}
%flex-right {
display: flex;
align-items: center;
justify-content: flex-end;
}
%flex-bottom {
display: flex;
align-items: flex-end;
justify-content: center;
}
%flex-none {
flex: none;
}
%flex-auto {
flex: auto;
}
%bg-no-repeat-center {
background-repeat: no-repeat;
background-position: center center;
}
%bg-size-100 {
background-size: 100%;
}
%pd20 {
padding: 20rpx;
}
%pd30 {
padding: 30rpx;
}
%pd3020 {
padding: 30rpx 20rpx;
}
%pdtb20 {
padding: 20rpx 0;
}
%pdtb {
padding: 20rpx 0;
}
%pdlr {
padding: 0 20rpx;
}
// @extend %bgwhite;
%bgwhite {
background-color: white;
}
// @extend %colorwhite;
%colorwhite {
color: white !important;
}
// 文字一行
%oneline {
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
%h100bs {
height: 100rpx;
box-sizing: border-box;
}
// 渐变按钮
%btn-linearGradient {
background: linear-gradient(to left, $maincolor, $maincolor2);
font-size: 32rpx;
@extend %colorwhite;
height: 80rpx;
width: 280rpx;
border-radius: 140rpx;
@extend %flex-center;
}
// 直降秒杀badge
%act-type-text {
font-size: 16rpx;
border-radius: 20rpx;
color: $maincolor;
border: 1rpx solid $maincolor;
width: 40rpx;
height: 20rpx;
line-height: 0;
@extend %flex-center;
box-sizing: border-box;
}
// 全屏
%fullScreen {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
// 小盒子pd20 底部描边
%boxpd20bb {
@extend %pdtb20;
border-bottom: 1rpx solid $border1;
box-sizing: border-box;
margin: 0 20rpx;
}
// 下拉刷新遮罩样式
%mask {
width: 100vw;
height: 100vh;
position: fixed;
left: 0;
top: 0;
background: black;
opacity: 0;
z-index: 999;
}
%btn-base {
@extend %flex-center;
flex: 1;
height: 80rpx;
background: linear-gradient(to bottom, #4eb331 0%,#67c23a 100%);
@extend %colorwhite;
border-radius: 10rpx;
font-size: 32rpx;
box-sizing: border-box;
border-bottom: 6rpx solid $maincolor;
}
%vendor-0-color {
color: #47B34F;
}
%vendor-1-color {
color: #FAD300;
}
%vendor-2-color {
color: #008DE1;
}
%vendor-3-color {
color: #008DE1;
}
%vendor-4-color {
color: $text2;
}
%vendor-5-color {
color: $text2;
}
%vendor-6-color {
color: $text2;
}
%vendor-7-color {
color: $text2;
}
%vendor-8-color {
color: $text2;
}
%vendor-9-color {
color: $maincolor;
}
%vendor-10-color {
color: $maincolor;
}
%vendor-11-color {
color: #0065fa;
}
@for $vendorID from 0 to 10 {
%vendor-#{$vendorID}-icon {
.icon-vendor {
width: 40rpx;
height: 40rpx;
background-image: url(../../assets/images/icon-vendor.png);
background-repeat: no-repeat;
background-position: (-$vendorID * 40rpx) 0;
background-size: cover;
}
.order-seq {
@extend %vendor-#{$vendorID}-color;
font-size: 32rpx;
font-weight: 500;
margin-left: 10rpx;
@extend %text-shadow;
}
}
}
%text-shadow {
text-shadow: 0 0 1rpx rgba(black, .2);
}
%ft24 {
font-size: 24rpx;
}
%ft28 {
font-size: 28rpx;
}
%ft32 {
font-size: 32rpx;
}
%ft34 {
font-size: 34rpx;
}
%ft36 {
font-size: 36rpx;
}
%ft30 {
font-size: 30rpx;
}
// %vendor-0-icon {
// .icon-vendor {
// @extend %icon-vendor;
// }
// .order-seq {
// }
// }
%table-layout {
@extend %flex-left;
.left, .center, .right {
flex: none;
text-align: center;
}
.left {
width: 46%;
}
.center {
width: 30%;
}
.right {
width: 24%;
}
}
%borderbottom {
border-bottom: 1rpx solid $border3;
}
%devider {
border-top: 1rpx solid $warning;
height: 6rpx;
border-bottom: 1rpx dashed $warning;
opacity: .5;
}
%mt20 {
margin-top: 20rpx;
}
%mb20 {
margin-bottom: 20rpx;
}
%mb200 {
margin-bottom: 200rpx;
}
%icon-base {
@extend %bg-no-repeat-center;
@extend %bg-size-100;
}
%pd4020 {
padding: 40rpx 20rpx;
}
%boxShadow {
box-shadow: 0 0 4rpx rgba($border1, .4);
}
%btn-group-bottom {
position: fixed;
left: 0;
bottom: 0;
height: 120rpx;
@extend %bgwhite;
@extend %flex-left;
@extend %boxShadow;
border-top: 1rpx solid $border2;
width: 100%;
}

211
src/assets/_icon.scss Normal file
View File

@@ -0,0 +1,211 @@
// @import '@/assets/mixins/mixin_svg.scss';
// @import './mixins/mixin_svg.scss';
%icon-shopcar {
// @include svg_icon(shopcar, 909399);
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAhFJREFUWEfVl19SGkEQxr9eKCtvwROIJwjegNxAT2D54kKldmvnBJITDGHK0vEFbhBuoDlBuAHkBPCYIrhtzW6WIrp/lBnFzCvT0z+6+5tvlrDjRTvOj/cDIAf6jogZTBO+j78J0Z29RXXWFTAASUJCk4B5FPhHbwqQJZPyqkl1b8qIP4ugm0K94sqdgb7SzMCJCPyxVHpBwEdXDAx8FYHfy87LBZBKm/6PzEZ5edNCfN9wA+C1CbiIAn+dNx/AzAPxRASdyE3i9BSprtoE75ZXe/tCnC3SkctZUukRGE0R+m2nAAMdEUFWV0DpHjGfRmHn0CmA0j0w2pt/rKgCxwR83yR1AZJKnRci7BxXDGHWq/jQ5YUk1fUEoHG1CuSwQfXl3PVdkMib4zMRdkelFTA/ppshROj3nZS/4IIrNKOkX4S7zXLZgORJsFCGiWZzBsYKIEeC5QA5krECKDivrAVPLg0rgIKKFgP8vTZd3AXSqKq2nCZG9GioiwEub1oU889MirauyMAvrPZamQdUynAtxcyWbV1x9WHyOHnpEKbuZWyZx65dcXOWSh+lUl33ienUWLPNAGax7HlCfDn/56zKV7EcaPMmWJuHFUiNohcDWCV8RnB1BeSwUav9+RSG5z+ecd6TLUaCZfHVAErPCDjY1pjMIJfF/wcActhA/Xdr228E04Ky+MoKbNP3l8TsHOABxb4dMAyd9oUAAAAASUVORK5CYII=")
}
%icon-shopcar-white {
// @include svg_icon(shopcar, fff);
background-image: url("https://image.jxc4.com/image/b626ec15d8025aa088f697e4f1305c74.png")
}
%icon-share {
@include svg_icon(share, 909399);
}
%img-noGoods {
@include svg_icon(noGoods, DCDCDC);
}
%img-noOrders {
@include svg_icon(noOrders, DCDCDC);
}
%icon-plus {
@include svg_icon(plus, 4EB331);
}
%icon-minus {
@include svg_icon(minus, 858585);
}
%icon-plus-fff {
@include svg_icon(plus, fff);
}
%icon-minus-fff {
@include svg_icon(minus, fff);
}
%icon-store {
@include svg_icon(goodDetailStore, 909399);
}
%icon-search {
@include svg_icon(search, 666);
}
%icon-delete {
@include svg_icon(delete, c5c5c5);
}
%icon-position {
@include svg_icon(position, 4EB331);
}
%icon-aw-right {
@include svg_icon(arraw-right, DCDFE6);
}
%icon-aw-right-slim {
// @include svg_icon(arraw-right-slim, DCDFE6);
// background-image: url("https://image.jxc4.com/image/0d67887b81058d2ffdc66f9b2915e04b.png");
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAARdJREFUWEfF1j1uwkAQBeC3MimSBtGkgGqlpA83gBtwBN8McRJ8gzi9hU3jSFTuMZrISI5SxTO7bxO3Hvl9ftL+OPzz4zT5Vf2ZZ8hK759LzbxlRgc4tQ2czDM8bNkIFaCuL2836Qs4ETZCBRgqTYVQA1IhTIAUCDOAjQgCMBHBABYiCsBARANiERRADIIGCEVQASEIOuAbgf5dIOWrX61/Ox2TAIbjG5A9gMOLX+Z/CrCEDzBqA9ZwKmAMF8jHDE8b7xed5mZEaSA0nNJATHg0IDY8CsAIDwawwoMAzHAzgB1uAtyv5bgeBThb1vnUXqDaB1KFqxuoTm0nThrmn4/NqBqo6naX4bHQbq9Ttf98rwJYPmid/QIWswUw7I8vVgAAAABJRU5ErkJggg==");
}
%icon-aw-right-slim-text1 {
// @include svg_icon(arraw-right-slim, 333);
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAQNJREFUWEfF1tENgjAQBuArDOAqlS6gGzgCmxknkQUa6wa4AQtwZ/pA4pPctX+1rzT8H3/CtY7+vJwmfxiGkZlTXpr9lj1awExEB2Y+oxEqgPfe930/iYigESpArrQVQg1ohTABWiDMADSiCIBEFANQiCoAAlENqEVAADUIGKAUAQWUIOCAD8SDiFKM8fjtdGwCyMe3c+5KRLcY4/hTgCU8w6ANWMOhgC1cRJ7MfEopLZqbEaSB0nBIAzXh1YDa8CoAIrwYgAovAiDDzQB0uAmQr+Vd192J6GX5z/dmgWoOtApXNxBCWERkRn751oyqgRDCZV3XSTte92r/fK4CWF5o3fsG5pk6MBm6BhMAAAAASUVORK5CYII=")
}
%icon-aw-bottom {
@include svg_icon(arraw-bottom, 606266);
}
%icon-address-border {
@include svg_icon(addressBorder, DCDFE6);
}
%icon-checked {
@include svg_icon(check, fff);
}
%icon-checked-main {
@include svg_icon(check, 4EB331);
}
%img-noShopCar {
@include svg_icon(noShopCar, DCDCDC);
}
%icon-clearAll {
@include svg_icon(clearAll, 909399)
}
%icon-position-small {
@include svg_icon(position-small, DCDCDC)
}
%icon-position-small-text2 {
@include svg_icon(position-small, 606266)
}
%icon-editor {
@include svg_icon(editor, 909399)
}
%icon-indexPosition-text1 {
@include svg_icon(index-position, 333);
}
%icon-home {
@include svg_icon(home, DCDCDC)
}
%icon-collect-text3 {
@include svg_icon(collect, 909399)
}
// 我的页面图标
// 订单
%mine-order {
@include svg_icon(mine-order, 4EB331)
}
%mine-order-text3 {
@include svg_icon(mine-order, 4EB331)
}
// 待支付
%mine-waitpay-text3 {
@include svg_icon(mine-waitpay, 909399)
}
// 待收货
%mine-waitreceiving-text3 {
@include svg_icon(mine-waitreceiving, 909399)
}
// 待评价
%mine-waitcomment-text3 {
@include svg_icon(mine-waitcomment, 909399)
}
// 售后退款
%mine-aftersale-text3 {
@include svg_icon(mine-aftersale, 909399)
}
// 优惠券
%mine-coupons {
@include svg_icon(mine-coupons, bfbfbf)
}
// 地址
%mine-address {
@include svg_icon(mine-address, bfbfbf)
}
// 联系客服
%mine-service {
@include svg_icon(mine-service, 4EB331)
}
// 下载app
%icon-downloadApp {
@include svg_icon(mine-download, 000)
}
// 检查更新
%icon-checkUpdate {
@include svg_icon(mine-checkUpdate, 000)
}
// 配送员图标
%icon-courier-border1 {
@include svg_icon(icon-courier, DCDFE6)
}
// 电话图标
%icon-mobile-text2 {
@include svg_icon(icon-mobile, 606266)
}
%icon-mobile-primary {
// @include svg_icon(icon-mobile, 409EFF)
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAYhJREFUWEftltFVwkAQRe/QgFCBWIFYgduB0gEh/lOC2oENhEAFYgVuCViBlIANMJ5NQsghkgQJ4Sf7vTnv5s3MmxUufOTC+rQArQOVHTChdoGu9WRVZ+OWAphQB2yYIDwCH3Yso0YATKh9lHdgkBFc27H0mgT4zokpnvVlVhdEYQlMoEuE2z2xlR3LTVMAI4QwJ7ZhaJ9kUQdEsQOu8zesEK5SMeXL+pLti5M4yqcg0J0Lyg8d+taT9UmqmY9LAdxdE6hz4RoiN+6aBwjVoHxG4MrC+jJs1IHIham+AZMEYmZ98eqAqFSCrZCZqgXuE4ha8uA4gHgqbJoNSs4JF93Wk2VVd44CiEqRh1jQIS5HHN0GIshX64lzrPAcDZBCKC6I4nK46YBoW+6nJoLrnfmhyfkXQNoTgb4gPJf9JULvLACJG25dz/7YGVuuedEKP8mB7J8bl5jgHHGBtTtxcB1sytoAMmVx0e0eLw9U2Bu1A6Qg7kHjxqHkCXc2gNLGTC60AK0DF3fgF4D0giGcX5joAAAAAElFTkSuQmCC")
}
// 无定位
%icon-no-position {
@include svg_icon(no-position, 409EFF)
}
// 我的推广码
%icon-my-promote {
@include svg_icon(icon-erweicode, 4EB331)
}
%no-sale {
@include svg_icon(no-sale, 72b92c)
}
%is-dev {
@include svg_icon(is-dev, 000)
}
/* -------------- 物流相关 ----------------- */
%icon-mywaybill {
@include svg_icon(icon-mywaybill, 4EB331)
}
%icon-send-address {
@include svg_icon(icon-send-address, 409EFF)
}
%icon-receive-address {
@include svg_icon(icon-receive-address, F56C6C)
}
%icon-address-book {
@include svg_icon(icon-address-book, 409EFF)
}
%icon-address-update {
@include svg_icon(icon-address-update, 409EFF)
}

5
src/assets/bundle.scss Normal file
View File

@@ -0,0 +1,5 @@
@import '@/assets/_color.scss';
@import '@/assets/_extend.scss';
@import '@/assets/mixins/mixin_svg.scss';
@import '@/assets/_icon.scss';
@import '@/assets/_animate.scss';

48
src/assets/global.scss Normal file
View File

@@ -0,0 +1,48 @@
/*
公共样式
*/
// 引入颜色配置
@import './_color.scss';
.test {
width: 600rpx;
height: 600rpx;
background: orange;
}
* {
font-family: Helvetica Neue,
Helvetica,
Arial,
sans-serif,
Verdana,
Geneva,
Tahoma,
sans-serif;
}
/*隐藏滚动条*/
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
display: none;
}
scroll-view {
-webkit-overflow-scrolling: touch;
}
.no-border {
border: none !important;
}
button {
outline: none;
&:after {
border: none;
}
}
image{will-change: transform}

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
src/assets/images/error.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 B

BIN
src/assets/images/head.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

BIN
src/assets/images/time.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/assets/images/vip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,74 @@
<template>
<div class="my-bone">
<div class="top">
</div>
<div class="list">
<div class="list-item" v-for="item in arr" :key="item">
<div class="left"></div>
<div class="right">
<div class="right_div"></div>
<div class="right_div"></div>
<div class="right_div"></div>
<div class="right_div"></div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
arr: [1,2,3,4,5,6,7,8,9,10]
}
}
}
</script>
<style lang="scss">
.my-bone {
position: fixed;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 9999;
background: white;
padding: 20rpx;
overflow: hidden;
.top {
height: 260rpx;
background: #eee;
}
.list {
margin-top: 40rpx;
.list-item {
margin-top: 40rpx;
display: flex;
height: 260rpx;
}
.left {
flex: none;
width: 200rpx;
margin-right: 20rpx;
background: #eee;
}
.right {
flex: auto;
display: flex;
flex-flow: column;
justify-content: space-between;
.right_div{
height: 40rpx;
background: #eee;
}
// div {
// height: 40rpx;
// background: #eee;
// }
}
}
}
</style>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,48 @@
<template>
<div class="zy-loading" v-if="loadingShow" @touchmove.stop.prevent="moveHandle" :animation="animationData">
<div class="zy-loading-mask"></div>
<div class="zy-loading-border"></div>
<div class="zy-loading-img"></div>
</div>
</template>
<script>
export default {
name: 'ZYLoading',
data () {
return {
animationData: {}
}
},
computed: {
loadingShow() {
// console.log('this.$store',this.$store.getters.loading)
return this.$store.getters.loading
}
},
methods: {
show () {
const animation = uni.createAnimation({
duration: 500,
timingFunction: 'ease-in-out'
})
animation.opacity(0).step()
this.animationData = animation.export()
setTimeout(() => {
animation.opacity(1).step()
this.animationData = animation.export()
}, 50)
},
moveHandle () {}
},
watch: {
loadingShow (to) {
// if (to) this.show()
}
}
}
</script>
<style lang="scss">
@import './loading';
</style>

View File

@@ -0,0 +1,113 @@
@import '@/assets/bundle.scss';
.y-modal {
position: fixed;
z-index: 900;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background: rgba(black, .6);
animation: bounceInUp .8s ease-in-out;
.y-modal-wrapper {
@extend %flex-center;
height: 80vh;
}
}
.y-promopt {
@extend %bgwhite;
width: 600rpx;
padding: 40rpx;
border-radius: 10rpx;
box-shadow: 0 2rpx 4rpx rgba(black, .3);
border: 1rpx solid $maincolor;
@extend %ft30;
color: $text1;
box-sizing: border-box;
// .title {
// }
.textarea {
border: 1rpx solid $border1;
@extend %pd20;
@extend %ft30;
height: 150rpx;
border-radius: 10rpx;
margin: 40rpx 0 80rpx;
width: 100%;
box-sizing: border-box;
}
.btn-group {
@extend %flex-between;
}
.btn-cancel, .btn-confirm {
@extend %btn-base;
}
.btn-cancel {
margin-right: 20rpx;
background: $danger;
}
}
.y-confirm-check {
@extend %ft32;
@extend %bgwhite;
border-radius: 6rpx;
width: 600rpx;
.title {
@extend %ft36;
padding: 32rpx 0 20rpx;
text-align: center;
}
.icon-text {
color: $text3;
@extend %flex-center;
// line-height: 0;
margin-top: 20rpx;
.ipt{
margin-bottom: 5rpx;
border: 1rpx solid #cdcdcd;
border-radius: 10rpx;
}
}
.icon-check {
@extend %bg-no-repeat-center;
background-size: 60%;
width: 30rpx;
height: 30rpx;
border: 1rpx solid $border1;
border-radius: 50%;
margin-right: 10rpx;
}
.checked {
@extend %icon-checked-main;
border-color: $maincolor;
}
.body {
padding-bottom: 48rpx;
}
.text {
@extend %ft30;
color: $text3;
text-align: center;
}
.btn-group {
box-sizing: border-box;
border-top: 1rpx solid #eee;
@extend %flex-left;
}
.btn-cancel, .btn-confirm {
flex: 1;
@extend %ft36;
height: 100rpx;
@extend %flex-center;
}
.btn-cancel {
color: $text3;
border-right: 1rpx solid #eee;
}
.btn-confirm {
color: $maincolor;
}
}

View File

@@ -0,0 +1,18 @@
<template>
<div class="y-modal" @click.stop @touchmove.stop.prevent>
<!-- <div class="h5-placeholder"></div> -->
<div class="y-modal-wrapper">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
methods: {},
};
</script>
<style lang="scss">
@import "./modal.scss";
</style>

View File

@@ -0,0 +1,53 @@
<template>
<Modal>
<div class="y-promopt">
<!-- <div class="title">{{title}}:</div> -->
<textarea v-model.trim="text" class="textarea" :placeholder="title" auto-focus></textarea>
<div class="btn-group">
<div @click="cancel" class="btn-cancel">取消</div>
<div @click="confirm" class="btn-confirm">确定</div>
</div>
</div>
</Modal>
</template>
<script>
import Modal from './modal'
export default {
components: {
Modal
},
props: {
title: {
type: String,
default: ''
},
type: {
type: String,
default: 'textarea'
}
},
data () {
return {
text: ''
}
},
methods: {
cancel () {
this.$emit('close')
},
confirm () {
if (!this.text) {
this.$toast(this.title)
return false
}
this.$emit('confirm', this.text)
this.$emit('close')
}
}
}
</script>
<style lang="scss">
@import "./modal.scss";
</style>

View File

@@ -0,0 +1,17 @@
@import '@/assets/bundle.scss';
.y-badge {
position: relative;
.y-badge-dot {
position: absolute;
border-radius: 30rpx;
background-color: $danger;
right: 5rpx;
top: 5rpx;
font-size: 20rpx;
color: white;
padding: 6rpx;
min-width: 26rpx;
@extend %flex-center;
}
}

View File

@@ -0,0 +1,21 @@
<template>
<div class="y-badge">
<div class="y-badge-dot" v-if="count>0">{{count}}</div>
<slot></slot>
</div>
</template>
<script>
export default {
props: {
count: {
type: Number,
default: 0
}
}
}
</script>
<style lang="scss">
@import './badge.scss';
</style>

View File

@@ -0,0 +1,91 @@
@import '@/assets/bundle.scss';
.car-group {
overflow-y: auto;
margin: 20rpx auto;
background: #eee;
// width: 750rpx;
// box-sizing: border-box;
@extend %pdlr;
.car-item{
background:#fff;
padding:0 20rpx;
overflow: hidden;
border-radius: 20rpx;
}
.store-info {
@extend %flex-between;
font-size: 28rpx;
color: $text1;
height: 100rpx;
border-bottom: 1rpx solid $border2;
// padding-left: 100rpx;
// border: 1rpx solid greenyellow;
background-color: #fff;
}
.circle{
width: 30rpx;
height: 30rpx;
border-radius: 50%;
margin-right: 20rpx;
background-color:#eee;
}
// .waybillSLG{
// border: 1rpx solid red;
// width: 150rpx;
// padding: 10rpx;
// white-space: nowrap;
// color: $maincolor;
// }
.icon-right-aw {
flex: none;
@extend %icon-aw-right-slim;
width: 30rpx;
background-position: right center;
background-repeat: no-repeat;
background-size: 30rpx;
}
.store-name {
flex: 1;
@extend %oneline;
}
.store-mobile {
flex: none;
}
.skuName-item{
display:flex;
// width: 90vw;
// border:1rpx solid red;
}
.skuName-cell {
@extend %flex-left;
// border-bottom: 1rpx solid $border2;
border: 1rpx solid #e2dfdf;
margin-bottom: 20rpx;
margin-top: 20rpx;
border-radius: 20rpx;
background-color: #fff;
padding: 10rpx;
// display: flex;
// width: 100vw;
}
.delButton{
// height: 240rpx;
line-height: 140rpx;
background: #ff0000;
// border: 1rpx solid green;
color: #fff;
margin-top: 10rpx;
margin-left:30rpx;
font-size: 30rpx;
// width: 100rpx;
padding:10rpx 20rpx;
}
.flex-auto {
@extend %flex-auto;
}
// .skuName-item:last-child{
// // margin-bottom: 194rpx;
// }
}

View File

@@ -0,0 +1,241 @@
<template>
<div class="car-group">
<div class="car-item">
<div class="store-info">
<div style="display:flex">
<div class="circle"></div>
<!-- isMaterial -->
<div class="store-name" v-if="isMaterial">物料店</div>
<!-- v-if="storeID!=='666666' && storeMap" -->
<div class="store-name" v-else >{{storeMap[storeID].name}}</div>
<!-- <div class="store-name" v-else="storeID!=='666666'">物料店</div> -->
</div>
<!-- <div class="waybillSLG">
<span >购满{{ waybillSLG.satisfy }}{{waybillSLG.reduce}}运费</span>
</div>
<div style="display:flex">
<div>去凑单</div>
<div class="icon-right-aw"></div>
</div> -->
<!-- <div class="store-mobile" @click="call(storeMap[storeID].mobile)">{{storeMap[storeID].mobile}}</div> -->
</div>
<!-- style="border:1rpx solid red;" -->
<div
v-for="(skuName, index) in skuNamesNew"
:key="index"
class="skuName-item"
:style="{'transform': 'translateX(' + skuName.offset + 'px)'}"
@touchmove="touchmove_cart"
@touchstart="touchstart_cart($event,index)"
@touchend="touchend_cart"
>
<div class="skuName-cell">
<check-item
v-if="!isMaterial"
@on-click="checkSkuName(skuName, index)"
:checked="skuName.checked"
></check-item>
<good-cell
:titleWidth="isMaterial?'482rpx':'412rpx'"
ref="goodCell"
class="flex-auto"
:index="index"
:skuName="skuName"
:noBorder="true"
:waitShow="false"
type="cart"
@handleSkuNamePlus="handleSkuNamePlus"
@handleSkuNameMinus="handleSkuNameMinus($event, skuName)"
@handleSkuNameChange="handleSkuNameChange"
></good-cell>
</div>
<div class="delButton" @click.stop="del(index)" :style="delBtnHenght">删除</div>
</div>
</div>
</div>
</template>
<script>
import GoodCell from "@/components/goodCmp/good-cell/good-cell.vue";
import CheckItem from "@/components/checkItem/check-item.vue";
import { errToast, modal } from "@/utils/uniapi.js";
import { mapGetters } from "vuex";
// import { msgData } from "@/config";
export default {
components: {
GoodCell,
CheckItem,
},
provide() {
return {
shopCar: true,
};
},
props: {
storeID: {
type: String,
},
skuNames: {
type: Array,
}
},
data() {
return {
checked: true,
currentIndex: -1,
skuNamesNew: [],
moveX: 0,
offsetDistance: 50,
delBtnHenght:'height: 260rpx;' // 140rpx
};
},
created() {
// console.log('打印手机系统信息', this.iosOrAndroid, '宽度', this.iosOrAndroid.screenWidth)
if (this.iosOrAndroid && this.iosOrAndroid.screenWidth) {
this.offsetDistance = (this.iosOrAndroid.screenWidth * 50) / 375
// console.log('查看偏移的宽度',this.offsetDistance)
}
// 750 260*2
// 1080 x
// x = (this.iosOrAndroid.screenHeight *260*2 )/ (750 * 2)
},
watch: {
skuNames: {
handler(val) {
this.skuNamesNew = []
val.forEach((item,index) => {
// #ifdef MP-WEIXIN
if (item.checked === false && item.storeID === 666666 ) {
this.checkSkuName(item,index)
}
// #endif
this.skuNamesNew.push({
...item,
offset:0
})
});
},
immediate: true,
deep:true
}
},
computed: {
...mapGetters({
storeMap:"indexPage/storeMap",
isMaterial: "indexPage/isMaterial",
iosOrAndroid: "iosOrAndroid"
})
},
methods: {
// 删除商品
async del(index) {
this.handleSkuNameChange({index,count:0})
},
touchstart_cart(e, index) {
// console.log('打印移动开始时的信息',e)
if (this.currentIndex !== -1 && this.currentIndex !== index) {
if (this.skuNamesNew[this.currentIndex]) {
this.skuNamesNew[this.currentIndex].offset = 0
}
}
this.moveX = e.changedTouches[0].pageX
// this.skuNamesNew[index].offset = -50
this.currentIndex = index
},
touchmove_cart(e) {
let distance = 0
// 向右滑动
if (e.changedTouches[0].pageX - this.moveX >= 0) {
distance = 0
// if (e.changedTouches[0].pageX - this.moveX >= 50) {
// distance = 50
// } else {
// distance = e.changedTouches[0].pageX - this.moveX
// }
}
// 向左滑动
if (e.changedTouches[0].pageX - this.moveX < 0) {
if (Math.abs(e.changedTouches[0].pageX - this.moveX) >= this.offsetDistance) {
// distance = -50
distance = - this.offsetDistance
} else {
distance = 0 - Math.abs(e.changedTouches[0].pageX - this.moveX)
}
}
// 偏移
this.skuNamesNew[this.currentIndex].offset = distance
},
// 手指松开后
touchend_cart(e) {
let distance = e.changedTouches[0].pageX - this.moveX
if (distance >0) {
// this.skuNamesNew[this.currentIndex].offset = distance >= 50?50: 0
this.skuNamesNew[this.currentIndex].offset = 0
}
if(distance<0) {
this.skuNamesNew[this.currentIndex].offset = Math.abs(distance) >= this.offsetDistance?0-this.offsetDistance: 0
}
},
// 商品 +
handleSkuNamePlus(index) {
this.$emit("handleSkuNamePlus", {
index,
key: this.storeID,
});
},
// 商品 -
handleSkuNameMinus(index, skuName, count = 2) {
// console.log('商品减少--------')
this.$emit("handleSkuNameMinus", {
index,
key: this.storeID,
countNew:count
});
},
handleSkuNameChange({ index, count }) {
this.$emit("handleSkuNameChange", {
index,
count,
key: this.storeID,
});
},
// check商品
async checkSkuName(skuName, index) {
try {
// 修改store里面
await this.$store.dispatch("cartPage/checkSkuName", {
skuName,
checkStatus: !skuName.checked,
});
// 通知父级修改
this.$emit("handleSkuNameCheck", {
index,
key: this.storeID,
checkStatus: !skuName.checked,
});
} catch (e) {
console.error(e);
errToast(e);
}
},
// 打电话
async call(phoneNumber) {
if (phoneNumber) {
let confirm = await modal("拨打电话", "是否拨打门店电话");
if (confirm) uni.makePhoneCall({ phoneNumber });
}
},
},
};
</script>
<style lang="scss">
@import "./car-group.scss";
</style>

View File

@@ -0,0 +1,24 @@
@import '@/assets/bundle.scss';
.y-check-box {
flex: none;
@extend %flex-left;
.check-cirle {
width: 50rpx;
height: 50rpx;
border-radius: 50%;
box-sizing: border-box;
border: 1rpx solid $border1;
margin-right: 20rpx;
}
.checked {
@extend %icon-checked;
background-color: $maincolor;
@extend %bg-no-repeat-center;
background-size: 52%;
}
.y-checkbox-text {
font-size: 32rpx;
color: $text1;
}
}

View File

@@ -0,0 +1,53 @@
<template>
<div class="y-check-box" @click="handleClick">
<div
:class="{
'check-cirle': true,
'checked': checked
}"
:style="{
width: width + 'rpx',
height: height + 'rpx'
}"
>
</div>
<div class="y-checkbox-text" :style="{'font-size': fontSize + 'rpx'}" v-if="text">{{text}}</div>
</div>
</template>
<script>
export default {
name: 'checkItem',
props: {
checked: {
type: Boolean,
default: false
},
text: {
type: String,
default: ''
},
width: {
type: Number,
default: 50
},
height: {
type: Number,
default: 50
},
fontSize: {
type: Number,
default: 32
}
},
methods: {
handleClick () {
this.$emit('on-click')
}
}
}
</script>
<style lang="scss">
@import './check-item.scss'
</style>

View File

@@ -0,0 +1,31 @@
@import '@/assets/bundle.scss';
.img-lazy-load {
position: relative;
width: 100%;
height: 100%;
.img-thumb, .img-origin {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
filter: blur(1vw);
object-fit: fill;
}
.img-origin {
animation: fadeIn .2s;
animation-fill-mode: both;
}
}
@keyframes fadeIn {
from {
filter: blur(1vw);
// transform: scale(1.05);
}
to {
filter: blur(0);
// transform: scale(1);
}
}

View File

@@ -0,0 +1,52 @@
<template>
<div class="img-lazy-load">
<!-- | img150type2 -->
<image class="img-thumb" :mode="mode" :src="src" @load="imgOnload" @error="errorImg"></image>
<image v-if="originSrc" class="img-origin" :mode="mode" :src="url"></image>
</div>
</template>
<script>
export default {
props: {
mode: {
type: String,
default: 'aspectFill'
},
src: {
type: String,
required: true
},
clip: {
type: String
}
},
data () {
return {
originSrc: '',
url:''
}
},
methods: {
errorImg(e) {
console.log('图片加载错误',e)
},
// 图片加载完成
imgOnload () {
this.url = this.src.includes('https') ? this.src : this.src.replace('http','https')
uni.getImageInfo({
// src: this.src.replace('http://', 'https://') + `?` + this.clip,
src: this.url,
success: ({path}) => {
// console.log('path',path)
this.originSrc = path
}
})
}
}
}
</script>
<style lang="scss">
@import './img-lazy.scss';
</style>

View File

@@ -0,0 +1,29 @@
@import '@/assets/bundle.scss';
.cmp-list-none {
@extend %flex-center;
flex-flow: column;
.list-none-img {
width: 300rpx;
height: 300rpx;
@extend %bg-no-repeat-center;
@extend %bg-size-100;
}
.img-noGoods {
@extend %img-noGoods;
}
.img-noOrders {
@extend %img-noOrders;
}
.img-noShopCar {
@extend %img-noShopCar;
}
.img-noPosition {
@extend %icon-no-position;
}
.list-none-msg {
font-size: 32rpx;
color: $text3;
padding-top: 30rpx;
}
}

View File

@@ -0,0 +1,32 @@
<template>
<div class="cmp-list-none">
<div :class="{
'list-none-img': true,
'img-noGoods': img === 'img-noGoods',
'img-noShopCar': img === 'img-noShopCar',
'img-noOrders': img === 'img-noOrders',
'img-noPosition': img === 'img-noPosition'
}"></div>
<div class="list-none-msg">{{msg}}</div>
</div>
</template>
<script>
export default {
props: {
img: {
type: String,
required: true,
default: 'img-noGoods'
},
msg: {
type: String,
default: '没有查询到东西'
}
}
}
</script>
<style lang="scss">
@import './list-none.scss';
</style>

View File

@@ -0,0 +1,53 @@
@import '@/assets/bundle.scss';
.cmp-search-input {
@extend %flex-center;
.input-wrapper {
// position: relative;
flex: 1;
background-color: $bginput;
// padding: 10rpx;
box-sizing: border-box;
border-radius: 50rpx;
@extend %flex-center;
height: 60rpx;
}
.input {
flex: auto;
color: $inputtext;
width: 100%;
font-size: 30rpx;
padding: 10rpx;
}
.input-placeholder {
color: $inputplaceholder;
}
.icon-search, .icon-delete {
flex: none;
// position: absolute;
top: 50%;
// transform: translateY(-50%);
width: 50rpx;
height: 50rpx;
@extend %bg-no-repeat-center;
background-size: 30rpx;
z-index: 10;
}
.icon-search {
left: 10rpx;
@extend %icon-search;
}
.icon-delete {
right: 10rpx;
@extend %icon-delete;
}
.btn-search {
font-size: 30rpx;
margin-left:20rpx;
color: #fff;
border-radius: 70rpx;
padding: 10rpx 20rpx;
background-color: rgb(129, 190, 78);
text-align: center;
}
}

View File

@@ -0,0 +1,67 @@
<template>
<div class="cmp-search-input">
<div class="input-wrapper">
<div class="icon-search"></div>
<input
v-model.trim="text"
class="input"
type="text"
:placeholder="placeholder"
placeholder-class="input-placeholder"
confirm-type="search"
@input="handleInput"
@confirm="handleConfirm"
:focus="focus"
>
<div v-if="text" class="icon-delete" @click="handleDelete"></div>
</div>
<div v-if="searchBtnShow" class="btn-search" @click="handleConfirm">搜索</div>
</div>
</template>
<script>
import {debounce} from '@/utils'
export default {
props: {
searchBtnShow: {
type: Boolean,
default: true
},
placeholder: {
type: String,
default: '请输入商品名称'
},
focus: {
type: Boolean,
default: true
}
},
data () {
return {
text: ''
}
},
methods: {
handleInput: debounce(function (e) {
// console.log(e.detail.value)
let value = e.detail.value
// console.log(value)
this.$emit('on-change', value)
}, 500),
handleConfirm (e) {
// console.log(e.detail.value)
let value = e.detail.value || this.text
// console.log(value)
this.$emit('on-change', value)
},
handleDelete () {
this.text = ''
this.$emit('on-change', '')
}
}
}
</script>
<style lang="scss">
@import './search-input.scss';
</style>

View File

@@ -0,0 +1,38 @@
<template>
<div class="zy-search-btn" :class="{'showBtn':isShowBtn===true}" @click="handleClick" :style="{background: background, color: color}">
<div class="zy-search-btn" >
<div class="icon"></div>
<div class="placeholder" >{{name}}</div>
</div>
<div v-if="isShowBtn" class="searchBtn" >搜索</div>
</div>
</template>
<script>
export default {
name: 'ZySearchBtn',
props: {
name: {
default: '请输入商品名称'
},
background: {
default: '#f5f5f5'
},
color: {
default: '#cccccc'
},
isShowBtn: {
default:false
}
},
methods: {
handleClick () {
this.$emit('click')
}
}
}
</script>
<style lang="scss">
@import "./search.scss";
</style>

View File

@@ -0,0 +1,30 @@
@import '@/assets/bundle.scss';
.zy-search-btn {
height: 70rpx;
@extend %flex-center;
font-size: 30rpx;
border-radius: 70rpx;
.icon {
// 放大镜
@include svg_icon(search, a8a8a8);
@extend %bg-no-repeat-center;
@extend %bg-size-100;
width: 36rpx;
height: 36rpx;
margin-right: 10rpx;
margin-left:10rpx;
}
}
.showBtn{
display: flex;
justify-content: space-between;
}
.searchBtn{
// 搜索按钮
padding:10rpx 20rpx;
border-radius: 25rpx;
margin-right: 10rpx;
background: rgb(129, 190, 78);
color:#fff;
}

View File

@@ -0,0 +1,120 @@
@import '@/assets/bundle.scss';
.good-cell-big {
@extend %pd20;
@extend %bgwhite;
box-sizing: border-box;
box-shadow: 0 0 4rpx rgba($border1, 1);
border-radius: 10rpx;
.good-img {
width: 300rpx;
height: 300rpx;
.good-img-size{
width: 100%;
height: 100%;
}
}
.good-name {
font-size: 28rpx;
margin-top: 20rpx;
color: $text1;
height: 4em;
overflow: hidden;
text-align: justify;
line-height: 1.2;
}
.good-price {
display: flex;
align-items: center;
justify-content: space-between;
}
.btn-wait{
flex: 1;
text-align: right;
}
.btn-self{
color: #fff;
background-color: rgba(78, 179, 49, 0.6);
}
.countTime-wrap{
height: 17rpx;
width: 100%;
margin-bottom: 5rpx;
}
.countTime{
color: #E6A23C;
font-size: 26rpx;
}
.stock-and-waitPirce{
display: flex;
}
.price {
display: flex;
align-items: baseline;
.unit{
font-size:28rpx;
color:$strong;
}
}
.ori-price {
font-size: 20rpx;
color: $gray;
margin-left: 10rpx;
text-decoration: line-through;
&:before {
content: "";
}
}
.act-type-wrapper {
height: 20rpx;
overflow: hidden;
}
.act-type {
@extend %act-type-text;
}
.check-detail{
font-size:28rpx;
color:rgba(78, 179, 49, 0.6);
}
.handle-shopcar {
margin-top: 20rpx;
height: 50rpx;
}
.add-cart{
height: 60rpx;
line-height: 60rpx;
font-size:30rpx;
background:#81be4e;
color:#fff;
text-align:center;
border-radius:20rpx;
margin-top:10rpx;
}
}
// #ifdef MP-KUAISHOU
.viewDetail{
// border:1px solid red;
text-align: center;
background: rgba(78, 179, 49, 0.8);
border-radius: 20rpx;
height: 50rpx;
line-height: 50rpx;
color:#fff;
}
// #endif
// .good-cell-big{
// box-sizing: border-box;
// box-shadow: 0 0 4rpx rgba($border1, 1);
// border-radius: 10rpx;
// .good-img {
// width: 300rpx;
// height: 300rpx;
// img {
// width: 100%;
// height: 100%;
// }
// }
// }

View File

@@ -0,0 +1,221 @@
<template>
<div class="good-cell-big" ref="" @click="toGoodDetail" >
<div class="good-img" v-if="skuName.img">
<img class="good-img-size" :src="skuName.img" alt="加载中..." />
</div>
<div class="good-name" v-if="skuName.name">{{skuName.name}}</div>
<div class="countTime-wrap">
<div class="countTime" v-if="skuName.actType===5 && skuName.actPrice!==0 && skuName.trendType !==0 && timeTen">{{skuName.trendType===2 ? '降价' :'升价'}}还剩 {{msg}}</div>
</div>
<div class="priceStyle" v-if="skuName.unit">
<span></span>
<!-- <span v-if="isB2B"></span> -->
<span v-if="!isB2B || isMaterial">{{skuName.unit}}</span>
<span v-else></span>
<span>约为</span>
<!-- <span class="priceColor" v-if="isMaterial || isB2B">{{$filters.toFixed2(price*100)}}</span> -->
<span class="priceColor" v-if="isMaterial">{{$filters.toFixed2(skuName.curPrice)}}</span>
<span class="priceColor" v-else-if="isB2B">{{$filters.toFixed2(skuName.price*100)}}</span>
<span class="priceColor" v-else>{{$filters.toFixed2(skuName.curPrice)}}</span>
<span>(以实际价格为准)</span>
</div>
<div class="good-price" v-if="newPrice">
<div class="price">
<div class="good-price" >
<span></span>
<span class="good-price-font" >{{newPrice }}</span>
</div>
<span class="unit" v-if="isMaterial || isB2B">/{{skuName.unit}}</span>
<!-- <span class="unit" v-if="isB2B">/{{skuName.unit}}</span> -->
<span class="unit" v-else>/</span>
<div class="ori-price" v-if="skuName.oriPrice && !isMaterial" >{{$filters.toFixed2(skuName.oriPrice)}}</div>
</div>
<div class="act-type-wrapper">
<div class="act-type" v-if="skuName.actType">{{actTypeArr[skuName.actType]}}</div>
</div>
</div>
<div class="add-cart" @click.stop="addCart" v-if="skuName.count===0 && isShowShop">加入购物车</div>
<template v-if="skuName.count!==0 && isShowShop">
<div class="handle-shopcar" @click.stop="clickStop" v-if="skuName.id !== 6031118">
<plus-minus :skuName="skuName" :count="skuName.count" type="input" @clickPlus="handlePlus" @clickMinus="handleMinus" @countChange="countChange"></plus-minus>
</div>
</template>
</div>
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import { toast, modal, errToast,jumpPage } from "@/utils/uniapi.js";
import PlusMinus from "@/components/goodCmp/plus-minus/plus-minus";
import { msgData, actTypeArr } from "@/config";
// import orderPage from '@/apis/orderPage'
// import { handleCreatePay } from '@/utils/uniapi.js'
export default {
components: {
PlusMinus
},
props: {
skuName: Object,
index: {
type: Number,
}
},
data() {
return {
actTypeArr,
fromTime: null,
toTime: null,
modalShow: false,
msg: "",
num: null,
// price: null,
price: 0,
checked: false,
preCreateData: {},
highPrice: null,
lowPrice: null
// imgUrl:'https://image.jxc4.com/image/8a98a93946f9f70dd84960c06725f4fb.jpg'
};
},
computed: {
...mapGetters({
storeID:"indexPage/storeID",
defaultAddress: "addressVue/defaultAddress",
isB2B:'indexPage/isB2B',
isLogin: "login/isLogin",
isShowShop: "isShowShop",
isMaterial: "indexPage/isMaterial",
materialInfo:"indexPage/materialInfo"
}),
newPrice(){
let priceStr = ''
// let curPrice = this.isB2B ? this.skuName.curPrice : this.price * 100
let curPrice = this.isMaterial ? this.skuName.curPrice : this.isB2B ? this.skuName.curPrice : this.price * 100
// let curPrice = this.isB2B ? this.skuName.curPrice : this.price
// console.log(this.isB2B,'打印当前的价格',curPrice,'skuName',this.skuName.curPrice,'this.price',this.price)
if (curPrice !== 0) {
priceStr = ((curPrice/100).toFixed(2)).split('.')[0] + '.' + ((curPrice/100).toFixed(2)).split('.')[1]
}
return priceStr
}
},
created() {
let weight = this.skuName.weight?this.skuName.weight : 1
this.price = ((this.skuName.curPrice / 100) / weight) * 500;
// if (this.skuName.id === 6041958 ) {
// console.log(this.skuName.curPrice / 100,'this.price',this.price,'weight')
// }
},
methods: {
// // 设置图片信息
// setImgInfo() { // val
// this.imgUrl = this.skuName.img
// },
// 加入购物车
addCart(){
// console.log('添加购物车')
if(!this.isLogin){
toast('请登录')
jumpPage('switchTab','/pages/mine/index',800)
return
}
this.handlePlus()
},
// 阻止点击事传播
clickStop(){
// console.log('阻止点击事件传播')
},
//守家
waitPriceDown(x) {
this.modalShow = true;
console.log(x);
},
close() {
this.modalShow = false;
},
async handlePlus() {
// #ifdef MP-WEIXIN
// if (this.isMaterial && this.skuName.id === 6039382 && this.materialInfo && this.materialInfo.fromStoreInfo && this.materialInfo.fromStoreInfo.packageSwitch === 1) {
// toast('禁止购买物料袋,请联系运营')
// return
// }
// #endif
this.$emit("handleSkuNamePlus", this.index);
},
async handleMinus() {
if (this.skuName.count === 1) {
let confirm = await modal("温馨提示", msgData.delGoods);
if (!confirm) return
}
this.$emit("handleSkuNameMinus", this.index);
},
async countChange(count) {
try {
// await this.changeCar({
// skuName: this.skuName,
// count,
// });
this.$emit("handleSkuNameChange", {
index: this.index,
count,
});
} catch (e) {
console.error(e);
errToast(e);
}
},
// 跳转到商品详情页
toGoodDetail() {
if (this.shopCar) return false;
jumpPage('navigateTo',`/pagesGoods/good-detail/index?skuID=${this.skuName.id}&storeID=${this.skuName.storeID}`)
},
},
};
</script>
<style lang="scss">
@import "./good-cell-big.scss";
.red {
flex: 1;
color: #fe6263;
margin: 10rpx 0;
font-size: 28rpx;
}
.gray {
flex: 1;
color: #999;
margin: 10rpx 0;
font-size: 28rpx;
}
.priceStyle{
color: rgb(149, 209,131);
font-size: 25rpx;
margin-bottom:10rpx;
}
.priceColor{
color:$strong;
}
.good-price {
font-size: 32rpx;
color: $strong;
font-weight: 500;
// &:before {
// content: "¥";
// font-size: 28rpx;
// }
&-font{
font-size: 38rpx;
&:after{
// content: ".";
font-size: 28rpx;
padding:0 5rpx;
}
}
}
</style>

View File

@@ -0,0 +1,129 @@
@import '@/assets/bundle.scss';
.good-cell {
// @extend %pd20;
padding: 30rpx 0;
display: flex;
// border-bottom: 1rpx solid $border4;
border-bottom: 1rpx solid #dadada;
.good-img {
flex: none;
width: 150rpx;
height: 150rpx;
.good-img-size{
width: 100%;
height: 100%;
}
// img {
// width: 100%;
// height: 100%;
// }
}
.good-info {
flex: auto;
margin-left: 20rpx;
}
.lookDetail{
height: 60rpx;
line-height: 60rpx;
font-size:30rpx;
background:#81be4e;
color:#fff;
text-align:center;
border-radius:20rpx;
margin-top:10rpx;
}
.good-name {
font-size: 30rpx;
font-weight: 400;
color: $text1;
min-height: 80rpx;
line-height: 1.1;
}
.btn-wait{
flex: 1;
}
.btn-self{
color: #fff;
background-color: rgba(78, 179, 49, 0.6);
}
.countTime-wrap{
height: 17px;
width: 100%;
margin-bottom: 5rpx;
}
.countTime{
color: #E6A23C;
font-size: 26rpx;
}
.stock-and-waitPirce{
display: flex;
}
.act-type-wrapper {
height: 20rpx;
overflow: hidden;
}
.act-type {
@extend %act-type-text;
}
.good-price {
@extend %flex-between;
flex-wrap: wrap;
}
.price {
display: flex;
align-items: baseline;
}
.cur-price {
font-size: 32rpx;
color: $strong;
font-weight: 700;;
&:before {
content: "";
font-size: 24rpx;
}
}
.ori-price {
font-size: 20rpx;
color: $gray;
margin-left: 10rpx;
text-decoration: line-through;
&:before {
content: "";
}
}
.handle-shopcar {
flex: none;
// background: red;
margin-left: auto;
height: 60rpx;
@extend %flex-center;
}
.cart-act-count {
font-size: 24rpx;
color: $text2;
display: flex;
flex-flow: column;
align-items: flex-end;
line-height: 1;
.act-count-show {
width: 220rpx;
@extend %flex-between;
}
}
.add-cart{
width: 200rpx;
height: 60rpx;
line-height: 60rpx;
font-size:30rpx;
background:#81be4e;
color:#fff;
text-align:center;
border-radius:20rpx;
// border:1rpx solid red;
}
}
.no-border{
border-bottom: 1rpx solid #fff !important;
}

View File

@@ -0,0 +1,334 @@
<template>
<div @click="toGoodDetail" :class="{
'good-cell': true,
'no-border': noBorder
}">
<div class="good-img" v-if="skuName && skuName.img">
<img :src="$filters.urlToHttps(skuName.img)" alt="加载中..." class="good-img-size"/>
</div>
<div class="good-info">
<!-- style="width: 412rpx;" 193px-->
<!-- width:fit-content -->
<div class="good-name" :style="{'width':titleWidth}">{{skuName.name}}</div>
<div class="countTime-wrap" v-if="skuName.actType===5 &&skuName.actPrice!==0 &&skuName.trendType !==0 && timeTen && waitShow">
<div class="countTime" >{{skuName.trendType===2 ? '降价' :'升价'}}还剩 {{msg}}</div>
</div>
<div class="act-type-wrapper">
<div class="act-type" v-if="skuName.actType">{{actTypeArr[skuName.actType]}}</div>
</div>
<!-- v-if="isShowShop" -->
<div class="good-price">
<div class="price">
<good-price :price="skuName.curPrice"></good-price>
<div class="ori-price" v-if="skuName && skuName.oriPrice && !isMaterial">{{$filters.toFixed2(skuName.oriPrice)}}</div>
</div>
<div class="add-cart" @click.stop="addCart" v-if="skuName.count===0 && isShowShop">加入购物车</div>
<!-- #ifdef MP-TOUTIAO || APP-PLUS -->
<!-- @click.stop="addCart" v-if="skuName.count===0" -->
<div class="add-cart" v-if="!isShowShop">查看详情</div>
<!-- #endif -->
<!-- v-if="skuName.count!==0 && isShowShop" -->
<template v-if="skuName.count!==0 && isShowShop">
<div class="handle-shopcar" @click.stop="clickStop" v-if="skuName.id !== 6031118" >
<plus-minus type="input" :skuName="skuName" :count="skuName.count" @clickPlus="handlePlus" @clickMinus="handleMinus" @countChange="countChange"></plus-minus>
</div>
</template>
<!-- <div v-if="!isShowShop" class="lookDetail" style="border:1rpx solid red">查看详情</div> -->
</div>
<!-- 购物车活动商品普通商品分层 -->
<div class="cart-act-count" v-if="type === 'cart' && skuName.actType && skuName.count > 1">
<div class="act-count-show">
<span>{{$filters.toFixed2(skuName.curPrice)}}</span>
<span>x1</span>
</div>
<div class="act-count-show">
<span>{{$filters.toFixed2(skuName.oriPrice)}}</span>
<span>x{{skuName.count - 1}}</span>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from "vuex";
import { toast, modal, errToast,jumpPage } from "@/utils/uniapi.js";
import PlusMinus from "@/components/goodCmp/plus-minus/plus-minus";
import { actTypeArr } from "@/config";
import GoodPrice from '@/components/goodCmp/good-price/good-price'
import orderPage from '@/apis/orderPage'
import { handleCreatePay } from '@/utils/uniapi.js'
export default {
name: "goodCell",
inject: {
shopCar: {
default: false,
},
},
components: {
PlusMinus,
GoodPrice
},
props: {
skuName: {
type: Object,
// default() {
// return {};
// },
},
index: {
type: Number,
},
noBorder: {
type: Boolean,
default: false,
},
type: {
type: String,
default: "",
},
waitShow: {
type: Boolean,
default: true,
},
titleWidth: {
type: String,
default:'390rpx'
}
},
computed: {
...mapGetters({
countTime: "countTime",
storeID:"indexPage/storeID",
defaultAddress: "addressVue/defaultAddress",
isLogin:"login/isLogin",
isShowShop: "isShowShop",
isMaterial: "indexPage/isMaterial"
}),
},
data() {
return {
actTypeArr,
msg: "",
modalShow: false,
fromTime: null,
toTime: null,
num: null,
price: null,
beforeCreateData: {},
timer: null,
highPrice: null,
lowPrice: null,
timeTen: true,
imgUrl:'https://image.jxc4.com/image/8a98a93946f9f70dd84960c06725f4fb.jpg'
};
},
created() {
// this.fromTime = new Date();
// this.fromTime.setHours(8);
// this.fromTime.setMinutes(0);
// this.fromTime.setSeconds(1);
// // console.log("8dian", this.fromTime);
// this.toTime = new Date();
// this.toTime.setHours(22);
// this.toTime.setMinutes(0);
// this.toTime.setSeconds(0);
// this.timer = setInterval(() => {
// this.countDown(this.toTime);
// }, 1000);
// if (new Date().getHours() < 10 || new Date().getHours() > 22) {
// this.timeTen = false;
// clearInterval(this.timer);
// }
// if (!(this.skuName.actType === 5 && this.skuName.actPrice !== 0)) {
// clearInterval(this.timer);
// }
// let sku = this.skuName;
// if (this.skuName.discountType == 1) {
// this.highPrice = (sku.oriPrice / 100).toFixed(2);
// this.lowPrice = (sku.discountValue2 / 100).toFixed(2);
// } else {
// this.highPrice = (sku.oriPrice / 100).toFixed(2);
// this.lowPrice = ((sku.discountValue2 * sku.actPrice) / 100).toFixed(2);
// }
},
beforeDestroy() {
clearInterval(this.timer);
},
methods: {
// 设置图片信息
// setImgInfo() { // val
// this.imgUrl = this.skuName.img.includes('https')?this.skuName.img:this.skuName.img.replace('http','https')
// },
// 加入购物车
addCart() {
if (!this.isLogin) {
errToast('请登录')
jumpPage('switchTab', '/pages/mine/index', 800)
return
}
this.handlePlus()
},
clickStop(){
// console.log('阻止点击事件传递')
},
// ...mapActions({
// changeCar: "cartPage/changeCar",
// }),
waitPriceDown(x) {
this.modalShow = true;
console.log(x);
},
//守家确定调支付三步
async comfirmWaitPrice(price, num, checked) {
this.price = Number(price).toFixed(2);
this.num = Number(num);
this.checked = checked;
console.log(this.price, this.num, this.checked);
console.log("skuname", this.skuName);
//预创建
if (
this.num > 0 &&
this.num < this.skuName.stock &&
Number(price) > this.lowPrice &&
Number(price) <= this.highPrice
) {
try {
let obj1 = {
jxOrder: JSON.stringify({
storeID: this.storeID[0],
expectedDeliveredTimestamp: null,
skus: [
{
skuID: this.skuName.id,
count: this.num,
defendPrice: Number(this.price * 100),
},
],
orderType: 3,
}),
addressID: this.defaultAddress[0].id,
createType: 0,
isDeliverySelf: false,
};
console.log(obj1)
let res = await orderPage.createOrder(obj1)
this.preCreateData = res;
} catch (e) {
if ("errKey" in e) {
errToast(e.err);
} else {
throw e;
}
}
try {
let obj2 = {
jxOrder: JSON.stringify({
...this.preCreateData,
// expectedDeliveredTimestamp: 0,
storeID: this.storeID[0],
orderType: 3,
isBuyNowPrice: this.checked ? 1 : 0,
defendPrice: (this.price * 100).toFixed(2),
}),
addressID: this.defaultAddress[0].id,
createType: 1,
isDeliverySelf: false,
};
//第二步
let orderInfo = await orderPage.createOrder(obj2)
console.log(orderInfo);
this.modalShow = false;
let payInfo = await orderPage.pay4Order({
vendorOrderID: orderInfo.orderID,
payType: 2,
vendorPayType: "W06",
subAppID:"wx4b5930c13f8b1170",
});
console.log(payInfo);
// return false
await handleCreatePay(
payInfo.vendorOrderID,
payInfo.prepayID,
JSON.parse(payInfo.codeURL)
);
toast("支付成功");
} catch (e) {
if ("errKey" in e) {
errToast(e.err);
} else {
throw e;
}
}
} else if (this.price < this.lowPrice || this.price > this.highPrice) {
errToast("请输入守家范围内的价格");
} else if (this.num === 0) {
errToast("份数最少为一份");
}
},
close() {
this.modalShow = false;
},
//倒计时
countDown(time1) {
if (this.toTime > new Date()) {
let res = ((new Date(time1) - new Date()) / (1000 * 60)) % 10;
let minutes = Math.floor(res);
let seconds = Math.floor((res * 60) % 60);
//console.log(seconds.toString().length);
if (seconds.toString().length < 2) {
seconds = "0" + seconds;
}
this.msg = "0" + minutes + "分 : " + seconds + "秒";
}
},
//销量
stock() {
let num = this.skuName.stock;
if (num >= 1000) {
return "库存:1000+";
} else if (num < 1000 && num > 0) {
return "库存:" + num;
} else if (num === 0) {
return "卖完了";
}
},
async handlePlus() {
this.$emit("handleSkuNamePlus", this.index)
},
async handleMinus() {
this.$emit("handleSkuNameMinus", this.index)
},
async countChange(count) {
this.$emit("handleSkuNameChange", {
index: this.index,
count,
});
},
// 跳转到商品详情页
toGoodDetail() {
jumpPage('navigateTo',`/pagesGoods/good-detail/index?skuID=${this.skuName.id}&storeID=${this.skuName.storeID}`)
},
},
};
</script>
<style lang="scss">
@import "./good-cell.scss";
.red {
flex: 1;
color: #fe6263;
margin: 10rpx 0;
}
.gray {
flex: 1;
color: #999;
margin: 10rpx 0;
}
</style>

View File

@@ -0,0 +1,20 @@
@import '@/assets/bundle.scss';
.good-price {
font-size: 32rpx;
color: $strong;
font-weight: 500;
// &:before {
// content: "¥";
// font-size: 28rpx;
// }
&-font{
font-size: 38rpx;
&:after{
// content: ".";
font-size: 28rpx;
padding:0 5rpx;
}
}
}

View File

@@ -0,0 +1,31 @@
<template>
<div class="good-price">
<span></span>
<span class="good-price-font" >{{newPrice }}</span>
</div>
</template>
<script>
export default {
// props: {
// price:{
// type:Number,
// default:0
// }
// },
props:['price'],
computed: {
newPrice(){
let str = ''
if(this.price!==0){
str = ((this.price/100).toFixed(2)).split('.')[0] + '.' + ((this.price/100).toFixed(2)).split('.')[1]
}
return str
}
}
}
</script>
<style lang="scss">
@import './good-price.scss';
</style>

View File

@@ -0,0 +1,33 @@
@import '@/assets/bundle.scss';
.left-cats {
// height: calc(100vh - 90rpx);
/* #ifndef H5 */
height: calc(100vh - 90rpx);
/* #endif */
/* #ifdef H5 */
height: calc(100vh - 270rpx);
/* #endif */
.cats-item {
height: 110rpx;
font-size: 28rpx;
color: #666;
@extend %flex-center;
box-sizing: border-box;
}
.cat-name {
border-left: 6rpx solid transparent;
flex: 1;
height: 60rpx;
@extend %flex-center;
}
.active {
background: white;
color: $maincolor;
.cat-name {
border-left-color: $maincolor;
}
}
}

View File

@@ -0,0 +1,52 @@
<template>
<scroll-view class="left-cats" scroll-y :scroll-into-view="intoID" scroll-with-animation>
<div
:class="{
'cats-item': true,
active: cat.id === current
}"
v-for="(cat, index) in catL1"
:key="cat.id"
:id="'l' + cat.id"
@click="handleClick(cat.id, index)"
>
<text class="cat-name">{{cat.name}}</text>
</div>
</scroll-view>
</template>
<script>
export default {
name: 'LeftCats',
props: {
catL1: {
default: []
},
current: {
default: null
}
},
data () {
return {
intoID: ''
}
},
methods: {
handleClick (id, index) {
this.$emit('catChange', {
id,
index
})
// this.intoID = 'l' + id
},
scrollInToID (id) {
this.intoID = 'l' + id
}
}
}
</script>
<style lang="scss">
@import './left-cats.scss';
</style>

View File

@@ -0,0 +1,70 @@
@import '@/assets/bundle.scss';
.cmp-minus-plus, .cmp-minus-plus2 {
@extend %flex-center;
.minus-plus-wrapper {
@extend %flex-center;
}
.btn-minus, .btn-plus {
flex: none;
@extend %bg-no-repeat-center;
@extend %bgwhite;
background-size: 24rpx;
width: 60rpx;
height: 60rpx;
border-radius: 50%;
border: 1rpx solid $border1;
position: relative;
z-index: 1;
padding: 0;
box-sizing: content-box;
}
.btn-minus {
@extend %icon-minus;
}
.btn-plus {
@extend %icon-plus;
}
.count {
flex: none;
color: $text1;
font-size: 34rpx;
width: 70rpx;
text-align: center;
margin: 0 10rpx;
color: $text2;
}
.input-count {
// background :red;
color: $text2;
font-size: 34rpx;
}
// .type-shopCar {
// background: $border1;
// border-radius: 10rpx;
// margin: 0 10rpx;
// }
.cannot-buy {
color: $text3;
font-size: 28rpx;
}
}
.cmp-minus-plus2 {
.disabled {
opacity: .2;
}
}
.add-cart{
// padding:0 20rpx;
// width: calc(100%-125px);
width: 100vw;
height: 64rpx;
line-height: 64rpx;
font-size:30rpx;
background:#81be4e;
color:#fff;
text-align:center;
border-radius:20rpx;
}

View File

@@ -0,0 +1,84 @@
<template>
<div class="cmp-minus-plus">
<div class="add-cart" v-if="!count" @click.stop="handlePlus">加入购物车</div>
<div class="minus-plus-wrapper" v-else>
<div class="btn-minus" @click.stop="handleMinus"></div>
<div :class="{count: true, 'type-shopCar': typeShopCar}">
<span v-if="type !== 'input'">{{count}}</span>
<input v-if="type === 'input'" type="number" class="input-count" @blur="countChange" v-model.number="inputCount">
</div>
<div class="btn-plus" @click.stop="handlePlus"></div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import { errToast,jumpPage } from '@/utils/uniapi.js'
import { msgData } from '@/config.js'
import {debounce} from '@/utils'
export default {
inject: {
shopCar: {
default: ''
}
},
props:['count','type','skuName'],
data() {
return {
typeShopCar: false,
inputCount: this.count
}
},
computed: {
...mapGetters({
isLogin: 'login/isLogin',
storeMap: "indexPage/storeMap",
storeID: "indexPage/storeID"
})
},
mounted() {
this.typeShopCar = this.shopCar
this.inputCount = this.count
},
watch: {
count(count) {
this.inputCount = +count
}
},
methods: {
// minus
handleMinus:debounce(function() {
if (this.storeMap[this.storeID[0]].status !== 1) return errToast(msgData.storeIsClose) // 判断当前门店是否营业
this.$emit('clickMinus')
},1000),
// plus
handlePlus:debounce(function() {
if (this.storeMap[this.storeID[0]].status !== 1) return errToast(msgData.storeIsClose) // 判断当前门店是否营业
// 判断用的登录状态
if (!this.isLogin) {
errToast('请登录')
jumpPage('switchTab', '/pages/mine/index', 800)
return
}
this.$emit('clickPlus')
},1000),
// count改变
countChange:debounce(function(e) {
if(+e.target.value > this.skuName.stock) {
this.inputCount = this.skuName.count
return errToast('暂时没有那么多商品喔~')
}
const count = +e.target.value
if (!count) this.inputCount = 0
if (count !== this.count) this.$emit('countChange', count ? count : 0)
},1000)
}
}
</script>
<style lang="scss">
@import "./plus-minus.scss";
</style>

View File

@@ -0,0 +1,58 @@
@import '@/assets/bundle.scss';
// 顶部二级菜单
.top-cats {
display: flex;
align-items: center;
position: relative;
// 遮罩
&:after {
content: "";
display: block;
position: absolute;
background: linear-gradient(to left, white, rgba(white, 0));
right: 15%;
width: 80rpx;
height: 100%;
}
.scroll-x {
// white-space: nowrap;
width: 85%;
// background: red;
.scroll-area {
display: flex;
align-items: center;
}
.scroll-item {
// display: inline-block;
flex: none;
font-size: 28rpx;
padding: 20rpx;
}
.scroll-item-placeholder {
flex: none;
width: 80rpx;
height: 50rpx;
}
.cat-active {
color: $maincolor;
border: 1rpx solid $maincolor;
padding: 4rpx 10rpx;
background: rgb(234, 240, 227);
border-radius: 10rpx;
}
}
.btn-up-down {
width: 15%;
height: 79rpx;
@include svg_icon(arraw-up, 9a9a9a);
background-size: 20rpx;
@extend %bg-no-repeat-center;
transform: rotateX(180deg);
transition: all .5s;
}
.arrow-active {
transform: rotateX(0);
}
}

View File

@@ -0,0 +1,77 @@
<template>
<div class="top-cats">
<scroll-view class="scroll-x" :scroll-left="scrollLeft" scroll-x="true" :scroll-into-view="intoID" @scroll="scroll">
<div class="scroll-area">
<div
:class="{
'scroll-item': true,
'cat-active': current === cat.id
}"
v-for="(cat, index) in cats"
:key="cat.id"
:id="'c' + cat.id"
@click="clickCat(cat.id, index)"
>
{{cat.name}}
</div>
<div class="scroll-item-placeholder"></div>
</div>
</scroll-view>
<div :class="{'btn-up-down': true, 'arrow-active': up}" @click="clickArrow"></div>
</div>
</template>
<script>
import {debounce} from '@/utils'
export default {
name: 'TopCats',
props: ['cats', 'current', 'wallShow', 'up'],
data () {
return {
intoID: 'c0',
scrollLeft: 0,
oldScroll: 0
}
},
methods: {
// 点击箭头
clickArrow () {
this.$emit('toggleCat2')
},
// 点击分类
clickCat (id, index) {
this.$emit('cat2Change', {
id,
index
})
},
scrollInToIndex (index) {
this.intoID = 'c' + this.cats[index - 1 >= 0 ? index - 1 : 0].id
},
// 设置位置
// setScroll (id) {
// let index = this.cats.findIndex(item => item.id === id)
// this.intoID = 'c' + this.cats[index - 1 >= 0 ? index - 1 : 0].id
// },
// 滚动防抖
scroll: debounce(function (e) {
this.oldScroll = e.detail.scrollLeft
}, 50)
},
watch: {
cats (to, from) {
if (from[1] && to[1] && to[1].id !== from[1].id) {
// 回到原点
this.scrollLeft = this.oldScroll
this.$nextTick(() => {
this.scrollLeft = 0
})
}
}
}
}
</script>
<style lang="scss">
@import "./top-cats.scss";
</style>

View File

@@ -0,0 +1,23 @@
@import '@/assets/bundle.scss';
.top-cats-wall {
background: white;
font-size: 28rpx;
display: flex;
flex-flow: row wrap;
padding: 20rpx 0 40rpx;
.wall-item {
width: 30%;
// margin-left: (10% / 5);
margin-top: 4%;
box-sizing: border-box;
border: 2rpx solid #ddd;
height: 50rpx;
@extend %flex-center;
border-radius: 30rpx;
}
.active {
border-color: $maincolor;
background: rgba($maincolor, .2);
}
}

View File

@@ -0,0 +1,35 @@
<template>
<div class="top-cats-wall">
<div
:class="{
'wall-item': true,
'active': current === cat.id
}"
v-for="(cat, index) in cats"
:key="cat.id"
@click="handleClick(cat.id, index)"
>
{{cat.name}}
</div>
</div>
</template>
<script>
export default {
name: 'TopCatsWall',
props: ['cats', 'current'],
methods: {
// 点击分类
handleClick (id, index) {
this.$emit('clickCat2', {
id,
index
})
}
}
}
</script>
<style lang="scss">
@import './top-cats-wall.scss';
</style>

View File

@@ -0,0 +1,65 @@
<template>
<view class="empty-root">
<image
class="img"
:src="src"
mode="scaleToFill"
/>
<text class="text">{{ title }}</text>
<slot></slot>
</view>
</template>
<script>
export default {
props:{
icon: {
type:String,
default:'kongzhuangtai',
},
size:{
type:Number,
default:150
},
title:{
type:String,
// default:'暂无数据'
default:'暂无门店列表'
},
color:{
type:String,
default:'#7fc86c'
},
src:{
type:String,
default:'https://image.jxc4.com/image/d0adecd3671e8a1c2294783b22a46426.png'
}
}
}
</script>
<style lang="scss" scoped>
.empty-root {
position: absolute;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 999999;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
.img {
width: 400rpx;
height: 400rpx;
}
.text {
color: v-bind(color);
text-decoration: none;
margin-top: -70rpx;
text-align: center;
}
}
</style>

View File

@@ -0,0 +1,32 @@
@import '@/assets/bundle.scss';
.left-right-cell {
// width: 100vw;
@extend %flex-between;
@extend %pdlr;
min-height: 100rpx;
box-sizing: border-box;
font-size: 32rpx;
@extend %bgwhite;
.left, .right {
color: $text1;
}
.left {
flex: none;
margin-right: 20rpx;
}
.right {
@extend %flex-right;
flex: auto;
@extend %oneline;
.icon-right-aw {
flex: none;
@extend %icon-aw-right-slim;
width: 50rpx;
height: 30rpx;
background-position: right center;
background-repeat: no-repeat;
background-size: 30rpx;
}
}
}

View File

@@ -0,0 +1,26 @@
<template>
<view class="left-right-cell">
<view class="left">
<slot name="left"></slot>
</view>
<view class="right">
<slot name="right"></slot>
<view v-if="!noClick" class="icon-right-aw"></view>
</view>
</view>
</template>
<script>
export default {
props: {
noClick: {
type: Boolean,
default: false
}
}
}
</script>
<style lang="scss">
@import './left-right-cell.scss';
</style>

View File

@@ -0,0 +1,23 @@
<template>
<div class="material-info">
<div>单量: {{preSaleCount}}已选袋子件数/数量: {{totalBag.unitCount}}/{{totalBag.totalCount}}</div>
<div :class="{danger: bagOverload !== '未超出购买限制'}">{{bagOverload}}</div>
</div>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
computed: {
...mapGetters({
preSaleCount: 'indexPage/preSaleCount',
totalBag: 'indexPage/totalBag',
bagOverload: 'indexPage/bagOverload',
})
}
}
</script>
<style lang="scss">
@import "./material-info.scss"
</style>

View File

@@ -0,0 +1,11 @@
@import '@/assets/bundle.scss';
.material-info {
font-size: 30rpx;
color: $text2;
text-align: center;
.danger {
color: $danger;
font-weight: 500;
}
}

View File

@@ -0,0 +1,188 @@
@import '@/assets/bundle.scss';
.nearlyStores{
margin-top:20rpx;
background:#fff;
border-radius:10rpx;
padding:10rpx;
// border: 1rpx solid red;
box-shadow: 0rpx 2rpx 10rpx rgb(207, 207, 207);
}
.storeInfo{
display:flex;
font-size:30rpx;
position:relative;
}
.storeImg{
width:120rpx;
height:120rpx;
}
.storeStatus{
position:absolute;
// top:80rpx;
bottom: 0;
left:0;
width:120rpx;
text-align:center;
background:rgba(0,0,0,0.5);
color:#fff;
}
.storeRight{
margin-left:20rpx;
}
.storeName{
display:flex;
font-weight:bold;
margin-bottom:4rpx;
}
.storeTime,.storeTime1,.storeTime2{
font-size: 24rpx;
}
.storeTime2{
margin-left:20rpx;
}
.storeRate{
display:flex !important;
font-size: 24rpx;
margin-top:6rpx
}
.fullReduce{
display:flex;
margin-bottom:20rpx;
justify-content:space-between;
font-size: 24rpx;
width:566rpx;
margin-top:6rpx;
&Fee{
border:1rpx solid #f16a6a;
text-align:center;
border-radius:10rpx;
padding:6rpx;
// background: #fff;
color: #f16a6a;
}
}
.storeGood{
// border: 1rpx solid red;
display:flex;
// margin-left:142rpx;
margin-left:20rpx;
overflow:hidden;
overflow-x:auto;
width:98%;
white-space:nowrap;
&Item:not(:last-child){
margin-right:20rpx;
// width: 100%;
}
// .storeGood:not(:last-child){
// // margin-left: 0;
// border: 1rpx solid red;
// }
&Img{
width:146rpx;
height:146rpx;
}
&Name{
width:120rpx;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
font-size:24rpx;
}
&Price{
color:#ff0000;
font-size:24rpx;
}
&Price::before{
content: '';
font-size:20rpx;
}
&More{
// border: 1rpx solid green;
// position: relative;
// right: 0;
position:sticky;
right:0;
writing-mode:vertical-lr;
text-align:center;
background:rgba(132, 132, 132, 0.5);
color:#fff;
padding:0 12rpx;
}
}
.top-title_near ,.top-title{
background: #fff;
padding: 20rpx 0;
border-radius: 10rpx;
line-height: 1;
box-shadow: 5rpx 5rpx 4rpx rgba(194, 193, 192, 0.2);
}
.top-title{
@extend %flex-left;
}
.top-title_near{
display: flex;
justify-content: space-between !important;
}
.icon-border {
width: 6rpx;
background-color: $maincolor;
height: 30rpx;
margin-right: 10rpx;
}
.title {
font-weight: bold;
color: $text1;
font-size: 36rpx;
}
.ranking_left,.ranking_right{
display:flex;
border:0
}
.operationRaking,.optimalScore,.nearlyDistance{
padding:4px 10px;
font-size:28rpx;
}
.active_status{
border-bottom:2rpx solid #4EB331;
color:#4EB331;
font-weight: bold;
}
.top-goods-list {
display: flex;
box-sizing: border-box;
flex-flow: row wrap;
justify-content: space-between;
.goods-item {
margin-top: 20rpx;
width: 345rpx;
flex: none ;
}
}

View File

@@ -0,0 +1,198 @@
<template>
<div class="top-title_near">
<div class="ranking_left">
<slot>
<div class="icon-border"></div>
<div class="title">附近商家</div>
</slot>
</div>
<div class="ranking_right">
<div class="operationRaking" :class="activeID === 1 ?'active_status' :''" @click="optionSort(1)">综合排序</div>
<div class="optimalScore" :class="activeID === 2 ?'active_status' :''" @click="optionSort(2)">评分最优</div>
<div class="nearlyDistance" :class="activeID === 3 ?'active_status' :''" @click="optionSort(3)">距离最近</div>
</div>
</div>
<div v-show="nearStatus === 'noMore'">
<div
class="nearlyStores"
v-for="(item, index) in nearlyStores"
:key="index"
@click="clickMore(item)"
>
<!-- 商家信息 -->
<div class="storeInfo">
<div style="display: flex;align-items: center;">
<image :src="item.storeInfo.brandLogo" class="storeImg" alt="加载中1111111" />
</div>
<div v-if="item.storeInfo.status===-1" class="storeStatus">休息中</div>
<div class="storeRight">
<div class="storeName" style="display: flex;">
<div>{{item.storeInfo.storeName }}</div>
<div v-if="item.storeInfo.brandName">--</div>
<div>{{ item.storeInfo.brandName }}</div>
</div>
<!-- 营业时间 -->
<div style="text-align: left;display: flex;">
<div class="storeTime">营业时间</div>
<div class="storeTime1" v-if="item.storeInfo.openTime1 && item.storeInfo.closeTime1">{{$filters.processingHours(item.storeInfo.openTime1)}}-{{$filters.processingHours(item.storeInfo.closeTime1)}}</div>
<div class="storeTime2" v-if="item.storeInfo.openTime2 && item.storeInfo.closeTime2">{{$filters.processingHours(item.storeInfo.openTime2)}}-{{$filters.processingHours(item.storeInfo.closeTime2)}}</div>
</div>
<!-- 评分 -->
<div class="storeRate">
<div>门店评分</div>
<div v-if="item.storeInfo && item.storeInfo.storeWeeklyScore">
<uni-rate :size="20" allow-half :value="(item.storeInfo.storeWeeklyScore *5) /100" />
</div>
<div v-else>暂无评分</div>
</div>
<!-- 满减 -->
<div class="fullReduce">
<div v-if="item.StoreDeductionInfo[0].deliveryFeeDeductionFee && item.StoreDeductionInfo[0].deliveryFeeDeductionSill" class="fullReduceFee">
{{item.StoreDeductionInfo[0].deliveryFeeDeductionSill/100}}{{item.StoreDeductionInfo[0].deliveryFeeDeductionFee/100}}
</div>
<!-- 距离 -->
<div v-if="String(item.storeInfo.distance).length<=3">距您{{item.storeInfo.distance}}m</div>
<div v-else>距您{{(item.storeInfo.distance/1000).toFixed(2)}}km</div>
</div>
</div>
</div>
<!-- 商品 -->
<div class="storeGood" v-if="item.StoreSkuInfo!==null && !isSearch" @click.stop="clickStop">
<div v-for="(ite,i) in item.StoreSkuInfo" :key="i" class="storeGoodItem" @click="toDetail(ite)">
<image :src="$filters.urlToHttps(ite.img)" class="storeGoodImg" alt="" />
<div class="storeGoodName" >{{ite.skuName}}</div>
<div class="storeGoodPrice" >{{(ite.price/100).toFixed(2)}}/{{ite.unit}}</div>
</div>
<div class="storeGoodMore" @click="clickMore(item)">查看更多</div>
</div>
<!-- 搜索商品 -->
<div class="storeGood" v-if="isSearch" @click.stop="clickStop">
<div v-for="(ite,i) in item.searchSku" :key="i" class="storeGoodItem" @click="toDetail(ite)">
<image :src="$filters.urlToHttps(ite.img)" class="storeGoodImg" alt="" />
<div class="storeGoodName" >{{ite.skuName}}</div>
<!-- <div class="storeGoodPrice" >{{(ite.price/100).toFixed(2)}}/{{ite.unit}}</div> -->
<div class="storeGoodPrice" >{{(ite.curPrice/100).toFixed(2)}}/{{ite.unit}}</div>
</div>
<div class="storeGoodMore" @click="clickMore(item)">查看更多</div>
</div>
<!-- <div class="enterStore" v-else >
<div style="padding:20rpx;background:rgba(78, 179, 49, 0.9);color:#fff;border-radius: 10rpx;border:1rpx solid red;"> </div>
</div> -->
</div>
</div>
<!-- 加载更多 -->
<div style="background:#fff;margin-top:20rpx" v-if="!isSearch">
<uni-load-more :status="nearStatus" ></uni-load-more>
</div>
</template>
<script>
// import apiStore from '@/apis/apiStore';
import { mapGetters, mapActions } from "vuex";
import {debounce} from '@/utils'
import {store} from "@/store";
import { jumpPage } from "@/utils/uniapi.js";
export default {
props:{
storeList:{
type:Array,
default:() => []
},
isSearch:{
type:Boolean,
default:false
}
},
data(){
return {
// nearlyStores:[],
nearStatus:'loading',
originalNearlyStores:[],
activeID: 1,
}
},
// watch:{
// storeList:{
// handleError(val){
// console.log('打印val的值',val)
// }
// }
// },
computed:{
...mapGetters({
myLocation:"indexPage/myLocation",
reLocation: "indexPage/reLocation",
storeID: "indexPage/storeID",
isLogin: "login/isLogin",
}),
nearlyStores(){
if(this.storeList && this.storeList.length>0) {
this.nearStatus = 'loading'
this.originalNearlyStores = [...this.storeList] // 原始数据
this.activeID = this.activeID !==1 ? this.activeID : 1 // 获取推荐商家时,为综合排序
this.nearStatus = 'noMore'
}
return this.storeList
}
},
methods:{
// 查看更多
async clickMore(item) {
if(item.dnsType) store.commit('indexPage/changeDNS',item.dnsType) // 更换域名
else store.commit('indexPage/changeDNS','wxC4') // 更换域名
// console.log('item.storeInfo.storeIDn,,,99999999',item.storeInfo.storeID)
store.commit("indexPage/changeStoreID", [+item.storeInfo.storeID])
// if(this.isLogin ) await store.dispatch('cartPage/getCarList', store.getters['indexPage/storeID'])
if(this.isLogin ) {
await store.dispatch('cartPage/getCarList', this.storeID) // 获取购物车列表
await store.dispatch('addressVue/getList') // 加载地址列表
}
if(!(this.storeMap && this.storeMap[this.storeID[0]])) await store.dispatch('indexPage/getStoreInfo', { storeID: this.storeID[0] }) // 获取当前门店的信息
jumpPage('navigateTo','/pagesGoods/good/index')
},
// 跳转到详情页
toDetail(ite) {
// if(ite.storeID !== this.storeID[0])
store.commit("indexPage/changeStoreID", [+ite.storeID])
jumpPage('navigateTo', `/pagesGoods/good-detail/index?skuID=${ite.skuID}&storeID=${ite.storeID}`)
},
clickStop(){
// console.log('阻止默认事件')
},
optionSort: debounce(function (e) {
this.activeID = e
this.nearStatus = 'loading'
switch (e) {
case 1:
this.nearlyStores = [...this.originalNearlyStores]
break
case 2:
this.nearlyStores.sort(this.ArraySort('storeWeeklyScore','L2S'))
break
case 3:
this.nearlyStores.sort(this.ArraySort('distance', 'S2L'))
break
}
this.nearStatus = 'noMore'
},500),
// 数组排序 type L2S 大 ——> 小 S2L 小 ——> 大
ArraySort(property,type){
return function (a,b){
let value1=a.storeInfo[property]
let value2 = b.storeInfo[property]
return type === 'L2S'? value2 - value1 : value1 - value2
}
},
}
}
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>

View File

@@ -0,0 +1,59 @@
@import '@/assets/bundle.scss';
.btn-toShopCar-new {
// position: fixed;
// left: 40rpx;
// bottom: 100rpx;
background-color: rgba(black, .6);
width: 120rpx;
height: 120rpx;
border-radius: 50%;
z-index: 10;
@extend %flex-center;
}
.icon-shopcar {
@extend %icon-shopcar-white;
@extend %bg-no-repeat-center;
width: 100rpx;
height: 100rpx;
background-size: 50rpx;
border-radius: 50%;
}
.fixed-box {
pointer-events: none; // 这里是重点,盒子可穿透操作
width: 100vw;
height: 90vh;
position: fixed;
top: 100rpx;
left: 0;
z-index: 100000;
}
.fixed-button {
opacity: 1;
// background: #ccc;
border-radius: 100%;
pointer-events: auto;
// width: max-content;
// height: auto;
width: 120rpx;
height: 120rpx;
overflow: hidden;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
left: 20rpx;
top: 85vh;
.imger{
width: 52px;
height: 52px;
overflow: none;
}
}
/* 适配iphonex 有底部横条的 */
@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
.fixed-box {
bottom: constant(safe-area-inset-bottom);
bottom: env(safe-area-inset-bottom);
}
}

View File

@@ -0,0 +1,33 @@
<template>
<movable-area class="fixed-box">
<movable-view @click="switchToShopCar" class="fixed-button" direction="all" :inertia="true">
<div class="btn-toShopCar-new" >
<badge :count="shopCount">
<div class="icon-shopcar"></div>
</badge>
</div>
</movable-view>
</movable-area>
</template>
<script>
import {mapGetters, mapActions} from 'vuex'
import { jumpPage,errToast } from "@/utils/uniapi.js";
export default {
computed: {
...mapGetters({
shopCount: 'cartPage/carCount',
isLogin: "login/isLogin",
})
},
methods: {
switchToShopCar() {
jumpPage('navigateTo','/pages/cart/index')
}
}
}
</script>
<style lang="scss">
@import "./index.scss";
</style>

View File

@@ -0,0 +1,121 @@
@import "@/assets/bundle.scss";
.waterfalls-flow {
overflow: hidden;
padding: 10rpx;
/* #ifdef MP-ALIPAY */
background-color: #f4f4f4;
/* #endif */
&-column {
float: left;
}
}
.column-value {
width: 100%;
font-size: 0;
overflow: hidden;
transition: opacity .4s;
opacity: 0;
border:1rpx solid #e6e1e1;
// box-shadow: 1rpx 1rpx 1rpx 1rpx #8c8c8c;
padding: 20rpx;
box-sizing: border-box;
&-show {
opacity: 1;
}
.inner {
font-size: 30rpx;
}
.img {
width: 100%;
&-hide {
display: none;
}
&-error {
background: #f2f2f2 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAiAQMAAAAatXkPAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAAIZJREFUCNdlzjEKwkAUBNAfEGyCuYBkLyLuxRYW2SKlV1JSeA2tUiZg4YrLjv9PGsHqNTPMSAQuyAJgRDHSyvBPwtZoSJXakeJI9iuRLGDygdl6V0yKDtyMAeMPZySj8yfD+UapvRPj2JOwkyAooSV5IwdDjPdCPspe8LyTl9IKJvDETKKRv6vnlUasgg0fAAAAAElFTkSuQmCC) no-repeat center center;
}
}
.good-name {
font-size: 28rpx;
margin-top: 20rpx;
color: #333;
overflow: hidden;
text-align: justify;
line-height: 1.2;
margin-bottom: 10rpx;
}
.good-price {
// border:1rpx solid red;
display: flex;
align-items: center;
justify-content: space-between;
margin:10rpx 0;
font-weight: 500;
color: $strong;
}
.price {
display: flex;
align-items: baseline;
.price-text{
font-size: 28rpx;
}
.price-text::before{
content: "";
font-size: 28rpx;
}
.unit{
font-size:28rpx;
}
}
.ori-price {
font-size: 20rpx;
color: $gray;
margin-left: 10rpx;
text-decoration: line-through;
&:before {
content: "";
}
}
.act-type-wrapper {
height: 20rpx;
overflow: hidden;
}
.act-type {
@extend %act-type-text;
}
.countTime-wrap{
height: 17rpx;
width: 100%;
margin-bottom: 5rpx;
}
.countTime{
color: #E6A23C;
font-size: 26rpx;
}
.priceStyle{
color: rgb(149, 209,131);
font-size: 25rpx;
margin-bottom:10rpx;
}
.priceColor{
color:$strong;
}
}

View File

@@ -0,0 +1,404 @@
<template>
<view class="waterfalls-flow">
<view v-for="(item, index) in data.column" :key="index" class="waterfalls-flow-column"
:id="`waterfalls_flow_column_${index + 1}`" :msg="msg" :style="{ 'width': w, 'margin-left': index == 0 ? 0 : m }">
<view :class="['column-value', { 'column-value-show': item2.o }]" v-for="(item2, index2) in columnValue(index)"
:key="index2" :style="[s1]" @click.stop="wapperClick(item2)">
<image
:class="['img', { 'img-hide': item2[hideImageKey] == true || item2[hideImageKey] == 1 }, { 'img-error': !item2[data.imageKey] }]"
:src="item2[data.imageKey]" mode="widthFix" @load="imgLoad(item2, index + 1)"
@error="imgError(item2, index + 1)" @click.stop="imageClick(item2)">
</image>
<view class="inner">
<view>
<view class="good-name">{{ item2.name }}</view>
<view class="countTime-wrap">
<view class="countTime"
v-if="item2.actType === 5 && item2.actPrice !== 0 && item2.trendType !== 0 && timeTen">
{{ item2.trendType === 2 ? '降价' : '升价' }}还剩 {{ skunameMsg }}</view>
</view>
<view class="priceStyle" v-if="item2.unit">
<text></text>
<text v-if="isB2B && storeID[0] !== 666666"></text>
<span v-else>{{ item2.unit }}</span>
<text>约为</text>
<span class="priceColor" >{{ $filters.toFixed2(item2.curPrice) }}</span>
<text>(以实际价格为准)</text>
</view>
<view class="good-price">
<view class="price">
<view class="price-text">
<span class="good-price-font" v-if="isB2B || storeID[0] === 666666">{{((item2.curPrice/100).toFixed(2)).split('.')[0] + '.' + ((item2.curPrice/100).toFixed(2)).split('.')[1] }}</span>
<span class="good-price-font" v-else-if="item2.weight">{{(((((item2.curPrice/100)/item2.weight)*500)/100).toFixed(2)).split('.')[0] + '.' + (((((item2.curPrice/100)/item2.weight)*500)/100).toFixed(2)).split('.')[1] }}</span>
<span class="good-price-font" v-else>{{(((((item2.curPrice/100))*500)/100).toFixed(2)).split('.')[0] + '.' + (((((item2.curPrice/100))*500)/100).toFixed(2)).split('.')[1] }}</span>
</view>
<span class="unit" v-if="storeID[0] === 666666 || isB2B">/{{item2.unit}}</span>
<text class="unit" v-else>/</text>
<view class="ori-price" v-if="item2.oriPrice && !isMaterial" >{{$filters.toFixed2(item2.oriPrice)}}</view>
</view>
<view class="act-type-wrapper">
<view class="act-type" v-if="item2.actType">{{actTypeArr[item2.actType]}}</view>
</view>
</view>
<view v-if="isShowShop">
<PlusMinus :type="'input'" :skuName="item2" :count="item2.count" @clickPlus="skuNamePlusRecommend(item2.index)" @clickMinus="skuNameMinusRecommend(item2.index)" @countChange="skuNameChangeRecommend($event,item2.index)" ></PlusMinus>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 加载更多 -->
<view v-if="!isMaterial" style="background:#fff;margin-top:20rpx" :style="{'background-color':topGoodsStatus === 'loading'?'#f4f4f4':'#fff'}">
<uni-load-more :status="topGoodsStatus" ></uni-load-more>
</view>
<!-- <div
class="nearlyStores"
v-for="(item, index) in nearlyStores"
:key="index"
@click="clickMore(item)"
>
商家信息
<div class="storeInfo">
<div style="display: flex;align-items: center;">
<image :src="$filters.urlToHttps(item.storeInfo.brandLogo)" class="storeImg" alt="" />
</div>
<div v-if="item.storeInfo.status===-1" class="storeStatus">休息中</div>
<div class="storeRight">
<div class="storeName" style="display: flex;">
<div >{{item.storeInfo.brandName}}</div>
<div>{{item.storeInfo.storeName }}</div>
<div>--</div>
<div>{{ item.storeInfo.brandName }}</div>
</div>
营业时间
<span class="storeTime">营业时间</span>
<span class="storeTime1" v-if="item.storeInfo.openTime1 && item.storeInfo.closeTime1">{{$filters.processingHours(item.storeInfo.openTime1)}}-{{$filters.processingHours(item.storeInfo.closeTime1)}}</span>
<span class="storeTime2" v-if="item.storeInfo.openTime2 && item.storeInfo.closeTime2">{{$filters.processingHours(item.storeInfo.openTime2)}}-{{$filters.processingHours(item.storeInfo.closeTime2)}}</span>
评分
<div class="storeRate">
<div>门店评分</div>
<div v-if="item.storeInfo && item.storeInfo.storeWeeklyScore">
<uni-rate :size="20" allow-half :value="(item.storeInfo.storeWeeklyScore *5) /100" />
</div>
<div v-else>暂无评分</div>
</div>
满减
<div class="fullReduce">
<div v-if="item.StoreDeductionInfo[0].deliveryFeeDeductionFee && item.StoreDeductionInfo[0].deliveryFeeDeductionSill" class="fullReduceFee">
{{item.StoreDeductionInfo[0].deliveryFeeDeductionSill/100}}{{item.StoreDeductionInfo[0].deliveryFeeDeductionFee/100}}
</div>
距离
<div v-if="String(item.storeInfo.distance).length<=3">距您{{item.storeInfo.distance}}m</div>
<div v-else>距您{{(item.storeInfo.distance/1000).toFixed(2)}}km</div>
</div>
</div>
</div>
商品
<div class="storeGood" v-if="item.StoreSkuInfo!==null" @click.stop="clickStop">
<div v-for="(ite,i) in item.StoreSkuInfo" :key="i" class="storeGoodItem" @click="toDetail(ite)">
<img :src="$filters.urlToHttps(ite.img,'img120')" class="storeGoodImg">
<image :src="$filters.urlToHttps(ite.img)" class="storeGoodImg" alt="" />
<div class="storeGoodName" >{{ite.skuName}}</div>
<div class="storeGoodPrice" >{{(ite.price/100).toFixed(2)}}/{{ite.unit}}</div>
</div>
<div class="storeGoodMore" @click="clickMore(item)">
查看更多
</div>
</div>
<div class="enterStore" v-else >
<div style="padding:20rpx;background:rgba(78, 179, 49, 0.9);color:#fff;border-radius: 10rpx;border:1rpx solid red;"> </div>
</div>
</div> -->
</template>
<script>
import PlusMinus from "@/components/goodCmp/plus-minus/plus-minus";
import { mapGetters } from "vuex";
import { jumpPage } from "@/utils/uniapi.js";
export default {
props: {
value: Array,
column: { // 列的数量
type: [String, Number],
default: 2
},
maxColumn: { // 最大列数
type: [String, Number],
default: 5
},
columnSpace: { // 列之间的间距 百分比
type: [String, Number],
default: 2
},
imageKey: { // 图片key
type: [String],
default: 'image'
},
hideImageKey: { // 隐藏图片key
type: [String],
default: 'hide'
},
seat: { // 文本的位置1图片之上 2图片之下
type: [String, Number],
default: 2
},
listStyle: { // 单个展示项的样式eg:{'background':'red'}
type: Object
}
},
components: {
PlusMinus
},
data() {
return {
data: {
list: this.value ? this.value : [],
column: this.column < 2 ? 2 : this.column,
columnSpace: this.columnSpace <= 5 ? this.columnSpace : 5,
imageKey: this.imageKey,
seat: this.seat
},
msg: 0,
listInitStyle: {
'border-radius': '12rpx',
'margin-bottom': '20rpx',
'background-color': '#fff'
},
adds: [], //预置数据
isLoaded: true,
curIndex: 0,
isRefresh: true,
flag: false,
refreshDatas: [],
skunameMsg: '',
topGoodsStatus:'loading',
actTypeArr:['','','','直降','秒杀','折扣']
}
},
computed: {
...mapGetters({
isB2B: 'indexPage/isB2B',
isMaterial: "indexPage/isMaterial",
storeID:"indexPage/storeID",
isShowShop: "isShowShop"
}),
// 计算列宽
w() {
const column_rate = `${100 / this.data.column - (+this.data.columnSpace)}%`;
return column_rate;
},
// 计算margin
m() {
const column_margin = `${(100 - (100 / this.data.column - (+this.data.columnSpace)).toFixed(5) * this.data.column) / (this.data.column - 1)}%`;
return column_margin;
},
// list样式
s1() {
return { ...this.listInitStyle, ...this.listStyle };
}
},
created() {
// 初始化
this.refresh();
},
methods: {
// 添加
skuNamePlusRecommend(index) {
this.$emit('clickPlus',index)
},
// 减少
skuNameMinusRecommend(index) {
this.$emit('clickMinus',index)
},
// 商品数量发生改变
skuNameChangeRecommend(e,index) {
this.$emit('countChange',e,index)
},
// 预加载图片
loadImages(idx = 0) {
let count = 0;
const newList = this.data.list.filter((item, index) => index >= idx);
for (let i = 0; i < newList.length; i++) {
// #ifndef APP-PLUS || APP
uni.getImageInfo({
src: `${newList[i][this.imageKey]}.jpg`,
complete: res => {
count++;
if (count == newList.length) this.initValue(idx);
}
})
// #endif
// #ifdef APP-PLUS || APP
plus.io.getImageInfo({
src: `${newList[i][this.imageKey]}.jpg`,
complete: res => {
count++;
if (count == newList.length) this.initValue(idx);
}
})
// #endif
}
},
// 刷新
refresh() {
if (!this.isLoaded) {
this.refreshDatas = this.value;
return false;
};
this.topGoodsStatus = 'loading'
this.refreshDatas = [];
this.isRefresh = true;
this.adds = [];
this.data.list = this.value ? this.value : [];
this.data.column = this.column < 2 ? 2 : this.column >= this.maxColumn ? this.maxColumn : this.column;
this.data.columnSpace = this.columnSpace <= 5 ? this.columnSpace : 5;
this.data.imageKey = this.imageKey;
this.data.seat = this.seat;
this.curIndex = 0;
// 每列的数据初始化
for (let i = 1; i <= this.data.column; i++) {
this.data[`column_${i}_values`] = [];
this.msg++;
}
this.$nextTick(() => {
this.initValue(this.curIndex, 'refresh==>');
})
},
columnValue(index) {
return this.data[`column_${index + 1}_values`]
},
change(newValue) {
console.log('this.data9999999999',this.data)
for (let i = 0; i < this.data.list.length; i++) {
console.log(i,'i',this.data.list[i],'属于哪一列',this.data.list[i].column)
const cv = this.data[`column_${this.data.list[i].column}_values`];
for (let j = 0; j < cv.length; j++) {
if (newValue[i] && i === cv[j].index) {
this.data[`column_${this.data.list[i].column}_values`][j] = Object.assign(cv[j], newValue[i]);
this.msg++;
break;
}
}
}
},
getMin(a, s) {
let m = a[0][s];
let mo = a[0];
for (var i = a.length - 1; i >= 0; i--) {
if (a[i][s] < m) {
m = a[i][s];
}
}
mo = a.filter(i => i[s] == m);
return mo[0];
},
// 计算每列的高度
getMinColumnHeight() {
return new Promise(resolve => {
const heightArr = [];
for (let i = 1; i <= this.data.column; i++) {
const query = uni.createSelectorQuery().in(this);
query.select(`#waterfalls_flow_column_${i}`).boundingClientRect(data => {
heightArr.push({ column: i, height: data.height });
}).exec(() => {
if (this.data.column <= heightArr.length) {
resolve(this.getMin(heightArr, 'height'));
}
});
}
})
},
async initValue(i, from) {
this.isLoaded = false;
if (i >= this.data.list.length || this.refreshDatas.length) {
this.msg++;
this.loaded();
return false;
}
const minHeightRes = await this.getMinColumnHeight();
const c = this.data[`column_${minHeightRes.column}_values`];
this.data.list[i].column = minHeightRes.column;
c.push({ ...this.data.list[i], cIndex: c.length, index: i, o: 0 });
this.msg++;
this.topGoodsStatus = 'noMore'
},
// 图片加载完成
imgLoad(item, c) {
const i = item.index;
item.o = 1;
this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)));
this.initValue(i + 1);
},
// 图片加载失败
imgError(item, c) {
const i = item.index;
item.o = 1;
item[this.data.imageKey] = null;
this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)));
this.initValue(i + 1);
},
// 渲染结束
loaded() {
if (this.refreshDatas.length) {
this.isLoaded = true;
this.refresh();
return false;
}
this.curIndex = this.data.list.length;
if (this.adds.length) {
this.data.list = this.adds[0];
this.adds.splice(0, 1);
this.initValue(this.curIndex);
} else {
if (this.data.list.length) this.$emit('loaded');
this.isLoaded = true;
this.isRefresh = false;
}
},
// 单项点击事件
wapperClick(item) {
jumpPage('navigateTo',`/pagesGoods/good-detail/index?skuID=${item.id}&storeID=${this.storeID[0]}`)
// this.$emit('wapperClick', item);
},
// 图片点击事件
imageClick(item) {
jumpPage('navigateTo',`/pagesGoods/good-detail/index?skuID=${item.id}&storeID=${this.storeID[0]}`)
// this.$emit('imageClick', item);
}
},
watch: {
value: {
deep: true,
handler(newValue, oldValue) {
setTimeout(() => {
this.$nextTick(() => {
if (this.isRefresh) return false;
if (this.isLoaded) {
// if (newValue.length <= this.curIndex) return this.refresh();
if (newValue.length <= this.curIndex) return this.change(newValue);
this.data.list = newValue;
this.$nextTick(() => {
this.initValue(this.curIndex, 'watch==>');
})
} else {
this.adds.push(newValue);
}
})
}, 1000)
}
},
column(newValue) {
this.refresh();
}
}
}
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>

66
src/config.js Normal file

File diff suppressed because one or more lines are too long

133
src/filters/index.js Normal file
View File

@@ -0,0 +1,133 @@
import { formatDate } from '@/utils/assist.js'
import { switchWeight as computedWeight } from '@/utils'
// 过滤
const img120 = (src) => {
return src + '?imageView2/1/w/120/h/120'
}
const img150 = (src) => {
return src + '?imageView2/1/w/150/h/150'
}
const img200 = (src) => {
return src + '?imageView2/1/w/200/h/200'
}
const img300 = (src) => {
return src + '?imageView2/1/w/300/h/300'
}
const img150type2 = (src) => {
return src + '?imageView2/2/w/150'
}
const img345type2 = (src) => {
return src + '?imageView2/2/w/345'
}
const imgLowQ = (src) => {
return src + '?imageView2/2/w/750/q/10'
}
const img750 = (src) => {
return src + '?imageView2/1/w/750/h/750'
}
const img50 = (src) => {
return src + '?imageView2/1/w/50/h/50'
}
const img750type2 = (src) => {
return src + '?imageView2/2/w/750'
}
const imgSlim = (src) => {
return src + '?imageSlim'
}
/**
* http 转 https
*/
const urlToHttps = (url, type) => {
if (!url) return ''
let src = url && url.includes('https') ? url : url.replace('http', 'https')
switch (type) {
case 'img50':
src = img50(src)
break
case 'img120':
src = img120(src)
break
case 'img150':
src = img150(src)
break
case 'img200':
src = img200(src)
break
case 'img300':
src = img300(src)
break
case 'img150type2':
src = img150type2(src)
break
case 'imgLowQ':
src = imgLowQ(src)
break
case 'img750':
src = img750(src)
break
case 'img750type2':
src = img750type2(src)
break
case 'imgSlim':
src = imgSlim(src)
break
case 'img345type2':
src = img345type2(src)
break
}
return src
}
/**
* 营业时间 前缀补0
*/
const processingHours = (num) => {
let n = 4
let str = (Array(n).join(0) + num).slice(-n)
return str.slice(0, 2) + ':' + str.slice(2)
}
/**
* 2023-08-16T14:30:34+08:00 日期转换 YYYY-MM-DD hh:mm:ss
*/
const dateToLLLL = (str) => {
return formatDate(str, 'YYYY-MM-DD hh:mm:ss')
}
/**
* 分 转 元 并保留两位数
*/
const toFixed2 = (num) => {
if (num || num == 0) {
return (num / 100).toFixed(2)
} else {
return '--'
}
}
/**
* 重量
*/
const switchWeight = (weight) => {
return computedWeight(weight)
}
export {
urlToHttps, // 图片转换
processingHours, // 营业时间 前缀补0
dateToLLLL, // 日期转换
toFixed2, // 分 转 元
switchWeight // 重量转换
}

22
src/main.js Normal file
View File

@@ -0,0 +1,22 @@
import {
createSSRApp
} from "vue";
import App from "./App.vue";
import { store } from './store'
import mixins from '@/mixins'
import { modal, alert, toast, errToast, alertBack } from '@/utils/uniapi'
import * as filters from '@/filters'
export function createApp() {
const app = createSSRApp(App);
app.mixin(mixins)
app.use(store)
app.config.globalProperties.$modal = modal // 挂载全局方法
app.config.globalProperties.$alert = alert // 挂载全局方法
app.config.globalProperties.$toast = toast // 挂载全局方法
app.config.globalProperties.$errToast = errToast // 挂载全局方法
app.config.globalProperties.$alertBack = alertBack // 挂载全局方法
app.config.globalProperties.$filters = filters // 挂载全局方法
return {
app,
};
}

218
src/manifest.json Normal file
View File

@@ -0,0 +1,218 @@
{
"name" : "京西菜市",
"appid" : "__UNI__6407906",
"description" : "买菜就上京西菜市",
"versionName" : "1.1.5",
"versionCode" : 115,
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "京西菜市",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {
"OAuth" : {},
"Share" : {},
"Payment" : {},
"Geolocation" : {
"description" : "您的位置信息将用于为您筛选附近优质门店"
}
},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
],
"minSdkVersion" : 23,
"targetSdkVersion" : 30
},
/* ios */
"ios" : {
"dSYMs" : false,
"capabilities" : {
"entitlements" : {
"com.apple.developer.associated-domains" : [ "applinks:wx.jxc4.com" ]
}
},
"idfa" : false,
"privacyDescription" : {
"NSLocationWhenInUseUsageDescription" : "您的位置信息将用于为您筛选附近优质门店", //可选,字符串类型,运行期访问位置权限描述
"NSLocationAlwaysUsageDescription" : "您的位置信息将用于为您筛选附近优质门店", //可选,字符串类型,后台运行访问位置权限描述
"NSLocationAlwaysAndWhenInUseUsageDescription" : "您的位置信息将用于为您筛选附近优质门店", //可选,字符串类型,运行期后后台访问位置权限描述
"NSPhotoLibraryAddUsageDescription" : "保存个人推广码" //可选,字符串类型,系统相册写入权限描述
}
},
/* SDK */
"sdkConfigs" : {
"oauth" : {
"weixin" : {
"appid" : "wxf3657c94aa01a3f0",
"UniversalLinks" : "https://wx.jxc4.com/jxc4Mini"
}
},
"geolocation" : {
"amap" : {
"__platform__" : [ "ios", "android" ],
"appkey_ios" : "d7814af0ae0898f14a905dd6e8803b51",
"appkey_android" : "70e4330d3b5b50540ebcf79c3ddc1420"
}
},
"share" : {
"weixin" : {
"appid" : "wxf3657c94aa01a3f0",
"UniversalLinks" : "https://wx.jxc4.com/jxc4Mini"
}
},
"payment" : {
"weixin" : {
"__platform__" : [ "android" ],
"appid" : "wxf3657c94aa01a3f0",
"UniversalLinks" : "https://wx.jxc4.com/jxc4Mini"
}
},
"maps" : {},
"ad" : {}
},
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png"
},
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png"
}
}
},
"splashscreen" : {
"androidStyle" : "common",
"android" : {
"hdpi" : "",
"xhdpi" : "",
"xxhdpi" : ""
},
"iosStyle" : "common",
"useOriginalMsgbox" : true
}
},
"compatible" : {
"ignoreVersion" : true //true表示忽略版本检查提示框HBuilderX1.9.0及以上版本支持
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
/* */
"appid" : "wx4b5930c13f8b1170",
"setting" : {
"urlCheck" : false,
"es6" : true,
"minified" : true
},
"usingComponents" : true,
"permission" : {
"scope.userLocation" : {
"desc" : "您的位置信息将用于为您筛选附近优质门店"
}
},
"requiredPrivateInfos" : [ "getLocation" ],
"lazyCodeLoading" : "requiredComponents"
},
"navigateToMiniProgramAppIdList" : [ "wx6be9ae15444fa83f" ],
"mp-alipay" : {
"usingComponents" : true,
"appid" : "2019110769024042",
"enableAppxNg" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true,
"appid" : "ttaceeda5333d7a7ab01",
"setting" : {
"postcss" : false,
"es6" : false,
"minified" : true
}
},
"h5" : {
"devServer" : {
"port" : 8000,
"disableHostCheck" : true,
"proxy" : {
"/v2/" : {
"target" : "https://wx.jxc4.com/beta/v2",
"changeOrigin" : true,
"pathRewrite" : {
"^/v2/" : "/"
}
},
"/place/" : {
"target" : "https://apis.map.qq.com/ws/place",
"changeOrigin" : true,
"pathRewrite" : {
"^/place/" : "/"
}
}
}
}
},
"mp-kuaishou" : {
"appid" : "ks680887971696897880",
"permission" : {
"scope.userLocation" : {
"desc" : "您的位置信息将用于为您筛选附近优质门店"
}
}
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "3"
}

67
src/mixins/index.js Normal file
View File

@@ -0,0 +1,67 @@
// 全局mixin
import { mapMutations } from 'vuex'
import { store } from '@/store'
export default {
methods: {
...mapMutations({
showLoad: 'showLoad',
hideLoad: 'hideLoad'
}),
// 物料计算
computedBagsPrice(skuList) {
const canBuy = store.getters['indexPage/canBuy']
const bagOverload = store.getters['indexPage/bagOverload']
const bagSkuIDs = store.getters['indexPage/bagSkuIDs']
if (canBuy) {
// 收费袋子
if (bagOverload !== '未超出购买限制') {
skuList.forEach(item => {
if (bagSkuIDs.includes(item.id)) {
item.curPrice = item.jxPrice
item.oriPrice = 0
}
})
} else {
// 免费袋子
skuList.forEach(item => {
if (bagSkuIDs.includes(item.id)) {
item.curPrice = 1
item.oriPrice = item.jxPrice
}
})
}
} else {
// 收费袋子
skuList.forEach(item => {
if (bagSkuIDs.includes(item.id)) {
item.curPrice = item.jxPrice
item.oriPrice = 0
}
})
}
},
computedBagsPriceObj(obj) {
const keys = Object.keys(obj)
keys.forEach(storeID => {
const list = obj[storeID]
this.computedBagsPrice(list)
})
},
/**
* 全局登录
* data 登录的参数
* notGetCart 是否获取购物车列表
*/
async globalLogin(data, notGetCart) {
// 登录
await store.dispatch('login/apiLogin', data ? data : '')
// 获取购物车
if (store.getters['login/isLogin'] && !notGetCart && store.getters['indexPage/isMaterial']) {
await store.dispatch('cartPage/getCarList', store.getters['indexPage/storeID']) // 加载购物车
await store.dispatch('addressVue/getList') // 加载地址列表
}
}
}
}

View File

@@ -0,0 +1,12 @@
// tab菜单onshow时重新计算购物车的小红点
import reComputedShopCar from '@/utils/reComputedShopCar.js'
export default {
data() {
return {
saveShopCarCount: 0
}
},
onShow() {
reComputedShopCar(this.$store.getters['cartPage/cartList'])
}
}

125
src/mixins/scroll.js Normal file
View File

@@ -0,0 +1,125 @@
import {throttle} from '@/utils'
export default {
data () {
return {
y: 0,
yLock: '',
startY: 0,
disY: 0,
dir: '',
transform: 'translateY(0)',
allowScroll: true,
topText: '',
bottomText: ''
}
},
methods: {
resetScroll () {
this.y = 0
this.yLock = ''
this.startY = 0
this.disY = 0
this.dir = ''
this.transform = 'translateY(0)'
this.top = 0
// this.allowScroll = false
this.topText = ''
this.bottomText = ''
// console.log(this.yLock)
},
touchstart (e) {
// console.log('开始', e.touches[0])
this.y = 0
let tc = e.touches[0]
// let startX = touch.clientX
this.startY = tc.clientY
this.disY = this.startY - this.y
},
// touchmove
touchmove: throttle(function (e) {
// if (!this.allowScroll) return false
// console.log('move', e.touches[0])
const tc = e.touches[0]
// 判断方向
if (this.dir === '') {
if (Math.abs(tc.clientY - this.startY) >= 5) {
this.dir = 'y'
}
} else {
// 确定方向后
let y = tc.clientY - this.disY
this.y = y
// console.log(y, this.yLock)
if (y > 0) {
if (this.yLock === 'up') {
this.transform = `translateY(${this.y}px)`
return false
}
this.yLock = 'down'
if (y < 100) {
this.topText = '下拉加载上一个'
} else {
this.topText = '释放加载上一个'
}
}
if (y < 0) {
if (this.yLock === 'down') {
this.transform = `translateY(${this.y}px)`
return false
}
this.yLock = 'up'
if (y > -100) {
this.bottomText = '上拉加载下一个'
} else {
this.bottomText = '释放加载下一个'
}
}
this.transform = `translateY(${this.y}px)`
}
}, 0, {
leading: true,
trailing: true
}),
touchend (e) {
const y = this.y
if (y > 0) {
if (this.yLock === 'up') {
this.resetScroll()
return false
}
if (y < 100) {
this.transform = `translateY(0)`
} else {
console.log('load prev')
this.searchGoods('prev')
}
}
if (y < 0) {
if (this.yLock === 'down') {
this.resetScroll()
return false
}
if (y > -100) {
this.transform = `translateY(0)`
} else {
// console.log('load next')
this.searchGoods('next')
}
}
this.resetScroll()
}
// scrolltoupper () {
// console.log('到顶了')
// // this.allowScroll = true
// },
// scrolltolower () {
// console.log('到底了')
// // this.allowScroll = true
// },
// scroll () {
// console.log('滚动')
// // if (this.allowScroll) this.allowScroll = false
// }
}
}

421
src/pages.json Normal file
View File

@@ -0,0 +1,421 @@
{
"pages": [ //pages数组中第一项表示应用启动页参考https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
// #ifdef MP-KUAISHOU || MP-TOUTIAO
"navigationBarTitleText": "京西到家",
// #endif
// #ifndef MP-KUAISHOU || MP-TOUTIAO
"navigationBarTitleText": "京西菜市",
// #endif
"enablePullDownRefresh": true
}
},
// #ifndef MP-TOUTIAO || APP-PLUS
{
"path": "pages/cart/index",
"style": {
"enablePullDownRefresh": true,
"navigationBarTitleText": "购物车"
}
},
// #endif
{
"path": "pages/mine/index",
"style": {
"enablePullDownRefresh": true,
"navigationBarTitleText": "我的",
"navigationBarBackgroundColor": "#4EB331",
"navigationBarTextStyle": "white"
}
}
],
"runtimes": {
"win10-x64": {}
},
"subPackages": [
{
"root": "pagesGoods",
"pages": [
{
"path": "good/index",
"style": {
"navigationBarTitleText": "分类"
}
},
{
"path": "good-detail/index",
"style": {
"navigationBarTitleText": "商品详情"
}
},
{
"path": "good-search/index",
"style": {
"navigationBarTitleText": "商品搜索",
"navigationBarBackgroundColor": "#fafafa"
}
}
]
},
{
"root": "pagesAddress",
"pages": [
{
"path": "mine-address/index",
"style": {
"navigationBarTitleText": "我的收货地址"
}
},
{
"path": "position-address/index",
"style": {
"navigationBarTitleText": "地址搜索"
}
},
{
"path": "create-address/index",
"style": {
"navigationBarTitleText": "新建地址"
}
},
{
"path": "pick-city/index",
"style": {
"navigationBarTitleText": "选择城市"
}
},
{
"path": "edit-address/index",
"style": {
"navigationBarTitleText": "编辑收货地址"
}
},
{
"path": "pick-store/index",
"style": {
"navigationBarTitleText": "选择门店"
}
}
]
},
{
"root": "pagesOrders",
"pages": [
{
"path": "create-order/index",
"style": {
"navigationBarTitleText": "提交订单"
}
},
{
"path": "add-note/index",
"style": {
"navigationBarTitleText": "添加备注"
}
},
{
"path": "help-purchase/index",
"style": {
"navigationBarTitleText": "辅助进货"
}
},
{
"path": "my-order/index",
"style": {
"enablePullDownRefresh": true,
"onReachBottomDistance": 50,
"navigationBarTitleText": "全部订单"
}
},
{
"path": "order-detail/index",
"style": {
"enablePullDownRefresh": true,
"navigationBarTitleText": "订单详情"
}
},
{
"path": "my-afsorder/index",
"style": {
"enablePullDownRefresh": true,
"onReachBottomDistance": 50,
"navigationBarTitleText": "我的售后"
}
},
{
"path": "afsorder-detail/index",
"style": {
"enablePullDownRefresh": true,
"navigationBarTitleText": "售后单详情"
}
},
{
"path": "create-afsorder/index",
"style": {
"navigationBarTitleText": "创建售后单"
}
},
{
"path": "order-status/index",
"style": {
"enablePullDownRefresh": true,
"navigationBarTitleText": "订单状态"
}
},
{
"path": "online-contact/index",
"style": {
"navigationBarTitleText": "在线联系"
}
}
]
},
{
"root": "pagesAuth",
"pages": [
{
"path": "auth-index/index",
"style": {
"navigationBarTitleText": "登录"
}
},
{
"path": "auth-argument/index",
"style": {
"navigationBarTitleText": "注册/登录协议"
}
}
]
},
{
"root": "pagesMine",
"pages": [
{
"path": "my-promote/index",
"style": {
"navigationBarTitleText": "我的推广码"
}
},
{
"path": "my-news/index",
"style": {
"navigationBarTitleText": "我的消息"
}
},
{
"path": "vip/index",
"style": {
"navigationBarTitleText": "会员中心"
}
}
]
},
{
"root": "pagesBanner",
"pages": [
{
"path": "banner-template1/index",
"style": {
"navigationBarTitleText": "特色商品"
}
}
]
},
{
"root": "pagesStore",
"pages": [
{
"path": "store/index",
"style": {
"navigationBarTitleText": "门店列表"
}
}
]
}
// #ifdef MP-WEIXIN
,
{
"root": "pagesPay",
"pages": [
{
"path": "JX-pay/JX-pay",
"style": {
"navigationBarTitleText": "京西支付"
}
}
]
}
// #endif
// #ifdef MP-TOUTIAO || APP-PLUS
,
{
"root": "pages/cart",
"pages": [
{
"path": "index",
"style": {
"navigationBarTitleText": "购物车"
}
}
]
}
// #endif
],
"globalStyle": {
"backgroundTextStyle": "dark",
"navigationBarBackgroundColor": "#fff",
// #ifdef MP-KUAISHOU
"navigationBarTitleText": "京西到家",
// #endif
// #ifndef MP-KUAISHOU
"navigationBarTitleText": "京西菜市",
// #endif
"navigationBarTextStyle": "black",
"onReachBottomDistance": 50
},
"tabBar": {
"borderStyle": "black",
"selectedColor": "#37D260",
"color": "#888888",
"backgroundColor": "#F5F5F5",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/images/bottom-bar/icon-home.png",
"selectedIconPath": "static/images/bottom-bar/icon-home-active.png"
},
// #ifndef MP-TOUTIAO || APP-PLUS
{
"pagePath": "pages/cart/index",
"text": "购物车",
"iconPath": "static/images/bottom-bar/icon-cart.png",
"selectedIconPath": "static/images/bottom-bar/icon-cart-active.png"
},
// #endif
{
"pagePath": "pages/mine/index",
"text": "我的",
"iconPath": "static/images/bottom-bar/icon-mine.png",
"selectedIconPath": "static/images/bottom-bar/icon-mine-active.png"
}
]
},
"condition": {
"current": 0,
"list": [
{
"name": "首页",
"path": "pages/index/index"
},
{
"name": "商品详情",
"path": "pagesGoods/good-detail/index",
"query": "skuID=22733"
},
{
"name": "商品搜索",
"path": "pagesGoods/good-search/index"
},
{
"name": "新建收货地址",
"path": "pagesAddress/create-address/index"
},
{
"name": "我的收货地址",
"path": "pagesAddress/mine-address/index"
},
{
"name": "地址搜索",
"path": "pagesAddress/position-address/index"
},
{
"name": "选择城市",
"path": "pagesAddress/pick-city/index"
},
{
"name": "编辑收货地址",
"path": "pagesAddress/edit-address/index",
"query": "address=%7B%22id%22%3A4%2C%22consigneeName%22%3A%22%E5%91%A8%E5%91%A8%22%2C%22consigneeMobile%22%3A%2213684045763%22%2C%22autoAddress%22%3A%22%E5%9B%9B%E5%B7%9D%E7%9C%81%E6%88%90%E9%83%BD%E5%B8%82%E9%87%91%E7%89%9B%E5%8C%BA%E6%8A%9A%E7%90%B4%E8%A1%97%E9%81%93%E4%BA%8C%E7%8E%AF%E9%AB%98%E6%9E%B6%E8%B7%AF%E6%9F%B3%E5%A0%A4%E8%8B%91%22%2C%22address%22%3A%22%E7%A7%91%E6%8A%80%E5%A4%A7%E5%8E%A61701%22%2C%22isDefault%22%3A1%7D"
},
{
"name": "京西支付",
"path": "pagesPay/JX-pay/JX-pay",
// jxParams={"origin":"weixinappcs","vendorOrderID":888888888,"storeID":668470,"name":"芬姐B2B","totalPrice":1500}
"query": "jxParams={'origin':'weixinappcs','vendorOrderID':888888888,'storeID':668470,'name':'芬姐B2B','totalPrice':1500}"
},
{
"name": "京西支付(自定义金额)",
"path": "pagesPay/JX-pay/JX-pay",
"query": ""
},
{
"name": "提交订单",
"path": "pagesOrders/create-order/index"
},
{
"name": "辅助进货",
"path": "pagesOrders/help-purchase/index"
},
{
"name": "登录",
"path": "pagesAuth/auth-index/index"
},
{
"name": "我的",
"path": "pages/mine/index"
},
{
"name": "全部订单",
"path": "pagesOrders/my-order/index"
},
{
"name": "订单详情",
"path": "pagesOrders/order-detail/index",
"query": "vendorOrderID=2014907693000521"
},
{
"name": "我的售后单",
"path": "pagesOrders/my-afsorder/index",
"query": "vendorOrderID=88325176991588"
},
{
"name": "售后单详情",
"path": "pagesOrders/afsorder-detail/index",
"query": "vendorOrderID=88429292726364&afsOrderID=69647522635&vendorID=1"
},
{
"name": "创建售后单",
"path": "pagesOrders/create-afsorder/index",
"query": "vendorOrderID=2014907693000521&vendorID=0"
},
{
"name": "订单状态",
"path": "pagesOrders/order-status/index",
"query": "vendorOrderID=88313234666629&vendorID=9"
},
{
"name": "申请物料测试-c4",
"path": "pages/index/index",
"query": "storeID=666666&fromStoreID=100118&storeType=c4"
},
{
"name": "会员中心",
"path": "pagesMine/vip/index",
"query": ""
},
{
"name": "公众号",
"path": "pages/index/index",
"query": "brandID=6"
},
{
"name": "二维码进入",
"path": "pages/index/index",
"query": "storeID=667551"
}
]
}
}

447
src/pages/cart/index.vue Normal file
View File

@@ -0,0 +1,447 @@
<template>
<view class="shop-car">
<!-- 辅助进货 -->
<view v-if="isPurchase" @click="goPurchase" ref="wwww">
<left-right-cell>
<text style="color: #6bb82d" slot="left">辅助进货</text>
<span slot="right"></span>
</left-right-cell>
</view>
<!-- 没有商品 -->
<view class="no-shopcar" v-if="!carCount">
<list-none img="img-noShopCar" msg="购物车中没有商品哦"></list-none>
<text @click="goGoods" class="btn-toGoods">去购物</text>
</view>
<!-- 商品 -->
<view v-else>
<view class="goods-content">
<car-group
ref="carGrounp"
v-for="(val, key) in shopCarByGroup"
:key="key"
:storeID="key"
:skuNames="val"
@handleSkuNamePlus="handleSkuNamePlus"
@handleSkuNameMinus="handleSkuNameMinus"
@handleSkuNameCheck="handleSkuNameCheck"
@handleSkuNameChange="handleSkuNameChange"
>
</car-group>
</view>
</view>
<!-- 推荐商品 -->
<!-- <div v-if="!isMaterial" class="recommend" >
<div class="recommend-top" :style="sizeStyle">
<div class="recommend-line">------------</div>
<div class="recommend-icon">
<div class="recommend-img">
<img src="https://image.jxc4.com/image/3a71aa1d0bf559abd803643905935485.png" alt="" :style="imgStyle"/>
</div>
<div style="margin-left:10rpx;">为您推荐</div>
</div>
<div class="recommend-line">------------</div>
</div> -->
<!-- 瀑布流 -->
<!-- <waterfall
:value="newTopGood"
:imageKey="'img'"
@clickPlus="skuNamePlusRecommend"
@clickMinus="skuNameMinusRecommend"
@countChange="skuNameChangeRecommend"
>
</waterfall> -->
<!-- <div class="good">
<div
class="good-item"
v-for="(skuName, index) in newTopGood"
:key="index"
@click.stop="toGoodDetail(skuName.id,skuName.storeID)"
>
<good-cell-big
:skuName="skuName"
:index="index"
@handleSkuNamePlus="skuNamePlusRecommend"
@handleSkuNameMinus="skuNameMinusRecommend"
@handleSkuNameChange="skuNameChangeRecommend"
></good-cell-big>
</div>
</div> -->
<!-- </div> -->
<!-- <div style="height: 188rpx;" v-if="JSON.stringify(shopCarByGroup) !== '{}'"></div> -->
<!-- 底部菜单 -->
<view class="shop-car-bottom-bar" v-if="carCount">
<text class="waybillSLG" v-if="!(waybillSLG.satisfy) && waybillSLG.reduce">免运费{{waybillSLG.reduce}}</text>
<text class="waybillSLG" v-if="waybillSLG.satisfy && waybillSLG.reduce">商品满{{ waybillSLG.satisfy }}{{waybillSLG.reduce}}运费</text>
<!-- #ifdef MP-WEIXIN -->
<MaterialInfo v-if="isMaterial && !isPurchase"></MaterialInfo>
<!-- #endif -->
<view class="all-pick" v-if="!isMaterial">
<view class="btn-all-pick">
<check-item @on-click="allCheck" :checked="allChecked" text="全选" :width="40" :height="40" :fontSize="30"></check-item>
</view>
<text class="pick-count">已选 {{ carCheckedCount }} </text>
</view>
<view class="total">
<view class="btn-clear-shopCar" @click="handleClearAll">
<span class="icon-delete"></span>
<text class="icon-text">清空购物车</text>
</view>
<view class="price">
<view v-if="!isMaterial && totalPrice">
<view class="total-price">
<span class="total-text">合计:</span>
<good-price :price="totalPrice"></good-price>
</view>
</view>
<view :class="{
'btn-payment': true,
'btn-disabled':!storeOpen || (!canBuy && storeID[0] ===666666),
}" @click="goSettlement">
<view>
<span v-if="!canBuy && storeID[0] ===666666">无法申请</span>
<span v-else-if="!storeOpen">门店休息中</span>
<span v-else>提交订单</span>
</view>
</view>
</view>
</view>
</view>
<!-- loading -->
<zy-loading></zy-loading>
</view>
</template>
<script>
import reComputedCarCount from "@/mixins/reComputedCarCount.js";
import { modal,errToast, toast,jumpPage,queryEleInfo,setTabBarBadge } from "@/utils/uniapi.js";
import ZyLoading from "@/components/Loading/loading";
// import CarGroup from "@/componentst/car-group/car-group.vue";
import { mapGetters, mapActions } from "vuex";
import ListNone from "@/components/commonCmp/list-none.vue";
import CheckItem from "@/components/checkItem/check-item.vue";
import { msgData } from "@/config.js";
import goodCellBig from "@/components/goodCmp/good-cell-index/good-cell-big.vue";
// #ifdef MP-WEIXIN
import MaterialInfo from "@/components/material-info/index.vue";
// #endif
import LeftRightCell from "@/components/layout/left-right-cell.vue";
import GoodPrice from '@/components/goodCmp/good-price/good-price';
import PlusMinus from "@/components/goodCmp/plus-minus/plus-minus";
import apiStore from '@/apis/apiStore';
// import waterfall from '@/components/waterfall/index.vue'
import {store} from "@/store";
export default {
name: "ShopCar",
mixins: [reComputedCarCount],
components: {
ZyLoading,
// CarGroup,
ListNone,
CheckItem,
// #ifdef MP-WEIXIN
MaterialInfo,
// #endif
LeftRightCell,
GoodPrice,
goodCellBig,
PlusMinus,
// waterfall
},
data() {
return {
shopCarByGroup: {},
allChecked: false,
storeOpen: true,
vipArr: [],
vipCount: 1,
msg: "",
imgStyle:'width:20px;height:20px',
sizeStyle:'',
};
},
async created() {
// 这一串不知道是干嘛用的------------
if(!this.isLogin) return
this.vipArr = await apiStore.getConfigInfo('vip')
if (this.selfInfo.userMembers) {
for (let item of this.vipArr) {
if (num === item.id) {
this.vipCount = Number(item.pricePercentage) / 100
}
}
console.log(this.vipCount);
let num = this.selfInfo.userMembers[0].memberTypeID
}
},
async onShow() {
if(!this.isLogin) return
this.pageInit()
if(this.carCount) setTabBarBadge('set',this.carCount)
},
computed: {
...mapGetters({
selfInfo: "login/selfInfo",
isLogin: "login/isLogin",
storeID: "indexPage/storeID",
storeMap: "indexPage/storeMap",
isMaterial: "indexPage/isMaterial",
fromStoreID: "indexPage/fromStoreID",
notBuyPackbag: "indexPage/notBuyPackbag",
newTopGood:'indexPage/topGoods',
isPurchase: "indexPage/isPurchase",
canBuy: "indexPage/canBuy",
waybillSLG: "indexPage/waybillSLG",
materialInfo:"indexPage/materialInfo",
validCarList: "cartPage/validCarList",
totalPrice: "cartPage/totalPrice",
carCount: "cartPage/carCount",
cartList: "cartPage/cartList",
carCheckedCount: "cartPage/carCheckedCount",
cartNeedReload:"cartPage/cartNeedReload",
addressList: "addressVue/addressList",
confirmCheckShow: "confirmCheckShow",
isShowShop: "isShowShop",
isB2B:'indexPage/isB2B',
iosOrAndroid: "iosOrAndroid",
storeList:"indexPage/storeList"
}),
},
watch: {
carCheckedCount(val) {
// console.log(val);
if (val === this.carCount) {
this.allChecked = true;
} else {
this.allChecked = false;
}
},
carCount: {
handler(val) {
if(val) setTabBarBadge('set',val)
},
immediate:true
}
},
methods: {
...mapActions({
checkAllOrCancel: "cartPage/checkAllOrCancel",
clearAllShopCar: "cartPage/clearAllShopCar",
changeCar: "cartPage/changeCar",
getCarListVuex:"cartPage/getCarList",
}),
// 初始化页面
async pageInit() {
// console.log("onShow,购物车中,你调用了几次",this.carCount);
try {
this.showLoad()
if (this.cartNeedReload) {
this.refreshData()
}
//
// 获取购物车
this.shopCarByGroup = {}; // 先清空再设置
if (this.isLogin) {
// 获取门店状态
await store.dispatch('indexPage/getStoreInfo', { storeID: this.storeID[0] }) // 获取当前门店的信息
// if(this.isMaterial && !isPurchase)
this.storeOpen = this.storeMap[this.storeID[0]].status === 1 ? true : false
this.shopCarByGroup = await this.getCarList()
// #ifdef APP-PLUS || APP
// if (this.storeID && this.shopCarByGroup[this.storeID]) {
// // this.shopCarByGroup[this.storeID].forEach(item => {
// // // this.reIndexGoodData(item.id, item.count)
// // })
// }
// #endif
}
} catch (e) {
console.error(e);
errToast(e);
} finally {
this.hideLoad();
}
},
// 获取购物车商品
async getCarList() {
try {
let shopCar = this.cartList
let json = {}
shopCar.forEach(item => {
let key = item.storeID
if (key in json) {
json[key].push(item)
} else {
json[key] = []
json[key].push(item)
}
})
if (this.carCheckedCount === this.carCount) {
this.allChecked = true;
} else {
this.allChecked = false;
}
return json;
} catch (e) {
throw e;
}
},
// 跳转到商品详情页
toGoodDetail(id,storeID) {
jumpPage('navigateTo',`/pagesGoods/good-detail/index?skuID=${id}&storeID=${storeID}`)
},
// 商品 +
async skuNamePlusRecommend(index,type) {
const skuName = type === 'cart' ? this.shopCarByGroup[this.storeID[0]][index] : this.newTopGood[index]
await this.changeCar({
skuName,
count:skuName.count + 1
})
this.shopCarByGroup = await this.getCarList();
},
// 商品 -
async skuNameMinusRecommend(index, type) {
let skuName = type === 'cart'?this.shopCarByGroup[this.storeID[0]][index]:this.newTopGood[index]
await this.changeCar({
skuName: skuName,
count:skuName.count - 1,
})
this.shopCarByGroup = await this.getCarList()
},
// 商品change
async skuNameChangeRecommend(count,index,type) {
const skuName = type ==='cart'?this.shopCarByGroup[this.storeID[0]][index]:this.newTopGood[index];
await this.changeCar({
skuName: skuName,
count,
});
this.shopCarByGroup = await this.getCarList()
},
//更新降价or 升价 重新获取`数据就行
async refreshData() {
await store.dispatch('indexPage/getTopGoods', this.storeID)
},
// 购物车商品相加
async handleSkuNamePlus({ index, key }) {
this.skuNamePlusRecommend(index,'cart')
},
handleSkuNameMinus({ index, key }) {
this.skuNameMinusRecommend(index, 'cart')
},
async handleSkuNameChange({ index, count, key }) {
this.skuNameChangeRecommend(count,index,'cart')
},
// 勾选
handleSkuNameCheck({ index, key, checkStatus }) {
let skuName = this.shopCarByGroup[key][index];
skuName.checked = checkStatus
},
// 跳转到商品页面
goGoods() {
uni.navigateTo({ url: "/pagesStore/store/index" })
},
// 全选
async allCheck() {
try {
if (this.allChecked) {
// 取消全选
await this.checkAllOrCancel(false);
} else {
// 全选
await this.checkAllOrCancel(true);
}
this.shopCarByGroup = await this.getCarList();
} catch (e) {
console.error(e);
errToast(e);
}
},
// 清空购物车
async handleClearAll() {
try {
let res = await modal("温馨提示", msgData.clearAllShopCar);
if (res) {
await this.clearAllShopCar();
}
} catch (e) {
console.error(e);
errToast(e);
}
},
// 去结算页面
async goSettlement() {
// #ifdef MP-WEIXIN
if (this.isMaterial && this.materialInfo && this.materialInfo.fromStoreInfo.packageSwitch === 1) return toast(`非常抱歉,无法购买物料,请联系运营${this.materialInfo.fromStoreInfo.marketManPhone}`)
// #endif
if ((!this.storeOpen || !this.canBuy && this.storeID[0] ===666666)) {
return false;
}
if (this.isLogin) {
if (this.validCarList.length === 0) {
toast(msgData.noCheckGoods);
return false;
}
jumpPage('navigateTo','/pagesOrders/create-order/index')
} else {
toast('请登录')
jumpPage('switchTab','/pages/mine/index')
}
},
//到辅助进货页面
goPurchase() {
jumpPage('navigateTo','/pagesOrders/help-purchase/index')
}
},
mounted() {
// 获取推荐分类在页面中的信息
// if (this.iosOrAndroid.platform === 'ios') {
// this.imgStyle = `width:40px;height:40px`
// this.sizeStyle = 'font-size:30px'
// }
},
// 下拉刷新
async onPullDownRefresh() {
try {
this.storeOpen = this.storeMap[this.storeID[0]].status === 1 ? true : false
if (this.isLogin) {
await this.getCarListVuex()
this.shopCarByGroup = await this.getCarList()
}
if(this.carCount) setTabBarBadge('set',this.carCount)
} catch (e) {
console.error(e);
errToast(e);
} finally {
uni.stopPullDownRefresh();
}
},
onHide() {
store.commit('cartPage/cartNeedReload',false) // 去掉重载标识
},
};
</script>
<style lang="scss" scoped>
@import "./shop-car.scss";
</style>

View File

@@ -0,0 +1,356 @@
@import "@/assets/bundle.scss";
.shop-car {
box-sizing: border-box;
width: 100vw;
height: 100vh;
/* #ifdef MP-ALIPAY */
// overflow: hidden;
border:1rpx solid #eee;
/* #endif */
.no-shopcar {
/* #ifndef MP-WEIXIN || MP-ALIPAY || APP */
margin-top: 20vh;
/* #endif */
@extend %flex-center;
flex-flow: column;
.btn-toGoods {
@extend %btn-linearGradient;
margin-top: 40rpx;
}
}
.shop-car-bottom-bar {
position: fixed;
/* #ifndef H5 */
bottom: 0;
/* #endif */
/* #ifdef H5 */
// bottom: 100rpx;
/* #endif */
left: 0;
right: 0;
box-sizing: border-box;
border-top: 1rpx solid $border1;
@extend %bgwhite;
z-index: 10;
.all-pick {
@extend %flex-between;
@extend %pdlr;
height: 70rpx;
.pick-count {
font-size: 30rpx;
color: $text1;
}
}
.total {
@extend %flex-between;
padding-left: 20rpx;
}
.price {
@extend %flex-center;
}
.btn-clear-shopCar {
@extend %flex-left;
.icon-delete {
@extend %bg-no-repeat-center;
@extend %icon-clearAll;
@extend %bg-size-100;
width: 30rpx;
height: 30rpx;
}
.icon-text {
font-size: 28rpx;
color: $text3;
}
}
.total-price {
font-size: 28rpx;
@extend %flex-center;
margin-right: 20rpx;
.total-text {
margin-right: 10rpx;
color: $text1;
}
.total-val {
font-size: 40rpx;
color: $danger;
font-weight: 600;
display: flex;
flex-direction: column;
}
}
.preferential {
color: #ccc;
font-size: 22rpx;
}
.btn-payment {
@extend %btn-linearGradient;
height: 80rpx;
font-size: 32rpx;
width: 240rpx;
border-radius: 0;
}
.btn-disabled {
opacity: 0.5;
}
.waybillSLG {
font-size: 26rpx;
@extend %flex-center;
color: $maincolor;
height: 40rpx;
}
}
.goods-content {
// @extend %bgwhite;
background-color: #eee;
}
// .note{
// width: 100vw !important;
// position: fixed;
// top:160rpx;
// left:0;
// z-index: 999;
// border-bottom: 2rpx solid rgba(207, 205, 205, 0.5);
// }
}
// 推荐商品
.recommend{
margin-top: 60rpx;
// border: 1rpx solid red;
&-line{
// border: 1rpx solid red;
color: #d4d4d4;
}
&-top{
padding:10rpx;
display: flex;
justify-content: center;
// border:1rpx solid red;
}
&-icon{
margin:0 20rpx;
display: flex;
}
&-img{
margin-top:4rpx;
// img{
// width:20px;
// height:20px;
// }
}
.good{
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding:10rpx;
margin-top:20rpx;
background-color: #f4f4f4;
// display: flex;
// flex-direction: column;
// flex-wrap:wrap;
// align-content: space-around;
// height:5026px;
// background-color: #f4f4f4;
}
.good-item {
width:340rpx;
margin-bottom: 10rpx;
border-radius: 40rpx;
}
}
.placeholder-box{
height: 154rpx;
background-color: #eee;
}
// .car-group {
// // margin-top:270rpx;
// // margin-top: 200rpx;
// margin-top: 160rpx;
// overflow-y: auto;
// // margin-bottom: 200rpx;
// // margin-bottom: 100rpx;
// @extend %pdlr;
// .store-info {
// @extend %flex-between;
// font-size: 28rpx;
// color: $text1;
// height: 100rpx;
// border-bottom: 1rpx solid $border2;
// // padding-left: 100rpx;
// }
// .store-name {
// flex: 1;
// @extend %oneline;
// }
// .store-mobile {
// flex: none;
// }
// .skuName-cell {
// @extend %flex-left;
// border-bottom: 1rpx solid $border2;
// }
// .flex-auto {
// @extend %flex-auto;
// }
// .skuName-cell:last-child{
// margin-bottom: 194rpx;
// }
// }
.good-cell-big {
@extend %pd20;
@extend %bgwhite;
box-sizing: border-box;
box-shadow: 0 0 4rpx rgba($border1, 1);
border-radius: 10rpx;
.good-img {
width: 300rpx;
height: 300rpx;
.good-img-size{
width: 100%;
height: 100%;
}
}
.good-name {
font-size: 28rpx;
margin-top: 20rpx;
color: $text1;
// height: 4em;
overflow: hidden;
text-align: justify;
line-height: 1.2;
}
.good-price {
display: flex;
align-items: center;
justify-content: space-between;
}
.btn-wait{
flex: 1;
text-align: right;
}
.btn-self{
color: #fff;
background-color: rgba(78, 179, 49, 0.6);
}
.countTime-wrap{
height: 17rpx;
width: 100%;
margin-bottom: 5rpx;
}
.countTime{
color: #E6A23C;
font-size: 26rpx;
}
.stock-and-waitPirce{
display: flex;
}
.price {
display: flex;
align-items: baseline;
.unit{
font-size:28rpx;
color:$strong;
}
}
.ori-price {
font-size: 20rpx;
color: $gray;
margin-left: 10rpx;
text-decoration: line-through;
&:before {
content: "";
}
}
.act-type-wrapper {
height: 20rpx;
overflow: hidden;
}
.act-type {
@extend %act-type-text;
}
.check-detail{
font-size:28rpx;
color:rgba(78, 179, 49, 0.6);
}
.handle-shopcar {
margin-top: 20rpx;
height: 50rpx;
}
.add-cart{
height: 60rpx;
line-height: 60rpx;
font-size:30rpx;
background:#81be4e;
color:#fff;
text-align:center;
border-radius:20rpx;
margin-top:10rpx;
}
}
// #ifdef MP-KUAISHOU
.viewDetail{
// border:1px solid red;
text-align: center;
background: rgba(78, 179, 49, 0.8);
border-radius: 20rpx;
height: 50rpx;
line-height: 50rpx;
color:#fff;
}
// #endif
.red {
flex: 1;
color: #fe6263;
margin: 10rpx 0;
font-size: 28rpx;
}
.gray {
flex: 1;
color: #999;
margin: 10rpx 0;
font-size: 28rpx;
}
.priceStyle{
color: rgb(149, 209,131);
font-size: 25rpx;
margin-bottom:10rpx;
}
.priceColor{
color:$strong;
}
// .good-price {
// font-size: 32rpx;
// color: $strong;
// font-weight: 500;
// // &:before {
// // content: "¥";
// // font-size: 28rpx;
// // }
// &-font{
// font-size: 38rpx;
// &:after{
// // content: ".";
// font-size: 28rpx;
// padding:0 5rpx;
// }
// }
// }

603
src/pages/index/index.vue Normal file
View File

@@ -0,0 +1,603 @@
<template>
<view class="shop-index" >
<!-- #ifdef APP-PLUS || APP -->
<!-- <wrap-version-update
id="wxf3657c94aa01a3f0"
btnBgColor="#66be4d"
></wrap-version-update> -->
<!-- #endif -->
<img src="https://image.jxc4.com/image/0ffc1e09eca6e88cdad5ac43427ce4c4.jpg?imageView2/1/w/750/h/750" class="shop-background" alt="">
<view class="top-address" @tap="toDressPick" v-if="!isMaterial " :style="{'background':rgba}">
<view class="position-address">
<view class="cur-address" v-if="!queryStoreID">
<span class="icon-position"></span>
<text class="address">{{address}}</text>
</view>
<!-- <div class="cur-shop" @click.stop="switchShop" v-if="storeMap && storeMap[storeID[0]]">{{storeMap[storeID[0]].name}}</div> -->
</view>
</view>
<!-- #ifdef MP-WEIXIN -->
<!-- 物料申请说明 -->
<view class="material-title" v-if="(isMaterial && !isPurchase)">
<text class="text">物料申请说明</text>
</view>
<!-- 物料申请说明 -->
<!-- #endif -->
<view class="index-content" :class="{'no-padding': isMaterial }">
<!-- 查询按钮 -->
<view class="top-search-btn" v-if="!isMaterial ">
<SearchBtn @click="handleClickSearch" :isShowBtn="true" ></SearchBtn>
</view>
<!-- 轮播图 -->
<!-- previous-margin -->
<swiper
class="index-swiper"
indicator-dots
indicator-color="rgba(0,0,0, .1)"
indicator-active-color="#4EB331"
autoplay
interval="4000"
circular
v-if="!isMaterial"
>
<swiper-item
v-for="item in bannerArr"
:key="item.id"
class="index-item"
@click="jumpToBanner(item)"
>
<img :src="$filters.urlToHttps(item.content.imgSrc)" alt="加载中..." class="index-item-img">
</swiper-item>
</swiper>
<!-- 介绍 -->
<view class="introduce" v-if="!isMaterial">
<text class="itc-item itc-first">最快29分钟送达</text>
<text class="itc-item itc-second">满免运费</text>
<text class="itc-item itc-last">优鲜赔</text>
</view>
<!-- 推荐分类 -->
<view id="RecommendCategory" class="top-cat" v-if="!isMaterial" style="align-items: center;">
<view class="cat-item" v-for="cat in topCats" :key="cat.id" @tap="toGoodsByID(cat)" style="text-align: center;">
<view class="cat-img">
<image :src="cat.img" alt="" class="cat-img_size" />
</view>
<text class="cat-name">{{cat.name}}</text>
</view>
</view>
<!-- 分类 -->
<!-- #ifdef MP-WEIXIN -->
<!-- 物料说明 -->
<view class="material-desc-status" v-if="(isMaterial && !isPurchase)">
<view class="material-border">
<view class="material-desc">
<view class="desc-item" v-for="(item, index) in materialDesc" :key="index">{{item}}</view>
</view>
<view class="material-status">
<view>
已完成订单的1.1
<span class="strong">{{preSaleCount}}</span>
</view>
<view>
当前袋子申请状态
<span class="strong">{{canBuy ? '可申请' : '无法申请'}}</span>
</view>
<view>已选袋子件数/数量: {{totalBag.unitCount}}/{{totalBag.totalCount}}</view>
<view :class="{danger: bagOverload !== '未超出购买限制'}">{{bagOverload}}</view>
</view>
</view>
</view>
<!-- 猜你喜欢 -->
<view class="top-goods" ref="top-goods" v-if="isMaterial || queryStoreID">
<view class="top-title">
<span class="icon-border"></span>
<text class="title">推荐商品</text>
</view>
<!-- <div > -->
<!-- 瀑布流 -->
<!-- <waterfall
:value="topGoods"
:imageKey="'img'"
@clickPlus="handleSkuNamePlus"
@clickMinus="handleSkuNameMinus"
@countChange="handleSkuNameChange"
></waterfall> -->
<!-- </div> -->
<view class="top-goods-list">
<view
class="goods-item"
v-for="(skuName, index) in topGoods"
:key="skuName.id"
>
<good-cell-big
ref="goodCellBig"
:skuName="skuName"
:index="index"
@handleSkuNamePlus="handleSkuNamePlus"
@handleSkuNameMinus="handleSkuNameMinus"
@handleSkuNameChange="handleSkuNameChange"
></good-cell-big>
</view>
</view>
</view>
<!-- #endif -->
<!-- 推荐商家 v-if="!(isMaterial || queryStoreID)" -->
<view class="top-goods" v-if="!isMaterial">
<nearStoreCom :storeList="nearlyStores"></nearStoreCom>
</view>
</view>
<!-- loading -->
<ZyLoading></ZyLoading>
<!-- 骨架屏 -->
<Bone v-if="showBone"></Bone>
<!-- #ifdef MP-TOUTIAO || APP-PLUS -->
<!-- 购物车图标 -->
<shopCarIcon v-if="isShowShop"></shopCarIcon>
<!-- #endif -->
</view>
</template>
<script>
import ZyLoading from "@/components/Loading/loading";
import Bone from "@/components/Loading/bone";
import reComputedCarCount from "@/mixins/reComputedCarCount.js";
import { errToast,jumpPage,queryEleInfo,setTabBarBadge } from "@/utils/uniapi.js";
import { mapGetters, mapActions } from "vuex";
import {store} from "@/store";
// import ImgLazyLoad from "@/components/commonCmp/img-lazy/img-lazy";
import goodCellBig from "@/components/goodCmp/good-cell-index/good-cell-big.vue";
// import waterfall from '@/components/waterfall/index.vue'
// import { msgData } from "@/config";
import SearchBtn from "@/components/goodCmp/Search/search-btn";
// #ifdef MP-TOUTIAO || APP-PLUS
import shopCarIcon from '@/components/shopCarIcon/index'
// #endif
import apiStore from '@/apis/apiStore';
import nearStoreCom from '@/components/nearlyStoreCom/index.vue'
// import goodPage from '@/apis/goodPage';
// import {debounce} from '@/utils'
export default {
name: "ShopIndex",
mixins: [reComputedCarCount],
components: {
ZyLoading,
Bone,
goodCellBig,
SearchBtn,
// #ifdef MP-TOUTIAO || APP-PLUS
shopCarIcon,
// #endif
nearStoreCom
// waterfall,
// waterfallNew,
// PlusMinus
},
data() {
return {
jxBanner: [], //京西banner数组
bannerID: null,
showBone: true,
// showBone: false,
address: "加载中...",
topCats: [],
isOnLoad: false,
bannerArr: [],
materialDesc: [],
brandList: [],
topToGoods:0,
rgba: 'rgba(255,255,255,0.5)',
nearlyStores: [], // 附近的门店信息 推荐附近的门店
}
},
mounted() {
// 获取推荐分类在页面中的信息
if (!this.isMaterial && !this.storeID.includes(666666)) {
queryEleInfo(this, '#RecommendCategory').then((res) => {
if (res !== undefined && res && res.top) {
this.topToGoods = res.top
}
})
}
},
// 监听页面滚动的距离
onPageScroll: function (Object) {
let opacity=0
opacity=Object.scrollTop/this.topToGoods+0.5
this.rgba=opacity?'rgba(255,255,255,'+opacity+')':"rgba(255,255,255,0.5)"
},
computed: {
...mapGetters({
loading: "loading",
confirmCheckShow: "confirmCheckShow",
isShowShop: 'isShowShop',
isLogin: "login/isLogin",
selfInfo: "login/selfInfo",
myLocation:"indexPage/myLocation",
reLocation: "indexPage/reLocation",
indexNeedReload: "indexPage/indexNeedReload",
pois:"indexPage/pois",
storeMap:"indexPage/storeMap",
storeID: "indexPage/storeID",
isMaterial: "indexPage/isMaterial",
isPurchase: 'indexPage/isPurchase',
preSaleCount: "indexPage/preSaleCount",
totalBag: "indexPage/totalBag",
canBuy: "indexPage/canBuy",
topGoods:"indexPage/topGoods",
storeType:'indexPage/storeType',
bagOverload: "indexPage/bagOverload",
brandID:'indexPage/brandID',
queryStoreID: "indexPage/queryStoreID",
materialInfo: "indexPage/materialInfo",
})
},
async onLoad(query) {
if(query.scene && query.scene.includes('orderID')) return
// 门店
this.showLoad()
// #ifdef MP
if (JSON.stringify(query) !== '{}') {
await this.sceneValue(query)
} else {
if (uni.getStorageSync('materialInfo')) store.commit('indexPage/saveMaterialInfo', uni.getStorageSync('materialInfo'))
else if (uni.getStorageSync('queryStoreID')) {
store.commit('indexPage/saveQueryStoreID', uni.getStorageSync('queryStoreID'))
store.commit('indexPage/changeStoreType',uni.getStorageSync('storeType') === 'gy')
}
else if(uni.getStorageSync('brandID')) await store.dispatch('indexPage/getBrandInfo',{brandID:uni.getStorageSync('brandID')}) // 公众号进入
}
// #endif
await this.pageInit(); // 初始化门店信息
store.commit('indexPage/indexNeedReload',false) // 去掉首页的重载标识
this.hideLoad()
},
async onShow() {
store.commit('indexPage/changeStoreType',false) // 更换域名
if (this.indexNeedReload && !this.isMaterial) {
this.showLoad()
if (this.reLocation) this.pageInit() // 切换坐标地址
if(this.isLogin) await store.dispatch('cartPage/getCarList')
store.commit('indexPage/indexNeedReload',false) // 去掉首页的重载标识
this.hideLoad()
}
// if(this.carCount) setTabBarBadge('set',this.carCount)
},
// 分享
onShareAppMessage (res) {
return {
withShareTicket: true,
path: '/pages/index/index?storeID=' + this.storeID,
}
},
// 下拉刷新
async onPullDownRefresh() {
try {
this.showLoad();
if (!this.isMaterial) {
store.commit('indexPage/saveReLocation',null) // 清除重定位信息
this.pageInit()
} else {
this.refreshStockAndGetMaterStore()
}
// this.showBone=this.showBone?false:this.showBone
} catch (e) {
console.error(e);
this.showBone= false
errToast(e);
} finally {
uni.stopPullDownRefresh();
this.showBone= false
this.hideLoad();
}
},
methods: {
...mapActions({
getAddressList: "addressVue/getList",
getCarList: "cartPage/getCarList",
getPosition: "indexPage/getPosition",
storeListByLocation: "indexPage/storeListByLocation",
changeCar: "cartPage/changeCar"
}),
jumpToBanner(row){
// console.log('点击轮播图返回的数据2',row)
},
// 切换门店
switchShop() {
if (this.queryStoreID) return false;
jumpPage('navigateTo','/pagesAddress/pick-store/index')
},
/**
* init
*/
async pageInit() {
try {
this.hideLoad()
this.showBone = true
if (!this.isMaterial) {
if (!this.queryStoreID) {
// 获取定位
if(!(this.reLocation && this.reLocation.lat && this.reLocation.lng)) await this.getPosition()
this.address = this.reLocation && this.reLocation.address ? this.reLocation.address : this.pois[0] ? this.pois[0].name : "加载中...";
// 按当前位置匹配门店
// await this.storeListByLocation({
// isMaterial: false,
// data: {
// lat: this.reLocation && this.reLocation.lat ? this.reLocation.lat : this.myLocation.lat,
// lng: this.reLocation && this.reLocation.lng? this.reLocation.lng : this.myLocation.lng,
// brandID: this.brandID
// }
// })
}
// 加载轮播图
const banner = await apiStore.getConfigInfo('banner')
this.bannerArr = banner;
this.jxBanner = banner;
store.commit('indexPage/saveBannerList',banner)
} else {
// 1.登录
await this.globalLogin()
// 2.热销商品
await store.dispatch('indexPage/getTopGoods', this.storeID)
// 3.物料信息
if(!this.isPurchase) this.materialDesc = await apiStore.getConfigInfo('materialDesc')
// 4.计算袋子是否是原价
// if(!this.isPurchase) this.computedBagsPrice(this.topGoods)
}
await this.loadTop(); // 加载商品推荐
uni.showTabBar()
} catch (e) {
this.showBone = false
throw e;
} finally {
this.showBone = false
this.hideLoad()
}
},
/**
* 场景值
*/
async sceneValue(query) {
// const { storeID, fromStoreID, toStoreID, brandID,storeType,scene } = query;
if (query.scene) {
const promoteStr = decodeURIComponent(query.scene);
let newPromoteStr = promoteStr.split('-')
const key = newPromoteStr[0].split("=")[0];
const val = newPromoteStr[0].split("=")[1];
// console.log(newPromoteStr,'promoteStr',promoteStr,'key',key,'val',val)
if (key === "brandID" && val) {
await store.dispatch('indexPage/getBrandInfo',{brandID:val}) // 公众号进入
}else if (key === "promote" && val) {
store.commit('indexPage/savePromote',val) // 推广码
} else if (key === "storeID" && val) {
store.commit('indexPage/saveQueryStoreID',val) // 扫码进入
if(newPromoteStr[1]){
let storeType = newPromoteStr[1].split('=')
console.log('storeType[1]',storeType[1])
store.commit('indexPage/changeStoreType',storeType[1] === 'gy')
}
}
} else {
if(query.brandID) await store.dispatch('indexPage/getBrandInfo',{brandID:query.brandID}) // 公众号进入
else if(query.storeID && !query.storeType) {
await store.commit('indexPage/saveQueryStoreID',query.storeID)
}
else store.commit('indexPage/saveMaterialInfo',query)
}
},
// 加载推荐分类和商品
async loadTop() {
try {
// 获取当前门店的信息storeMap
if (!this.storeMap) {
// await store.dispatch('indexPage/getStoreInfo', { storeID: this.storeID[0] }) // 获取当前门店的信息
} else if (!(this.storeMap && this.storeID && this.storeMap[this.storeID[0]])) await store.dispatch('indexPage/getStoreInfo', { storeID: this.storeID[0] }) // 获取当前门店的信息
if (this.isMaterial) {
// 加载来自哪个门店的的数据
await store.dispatch('indexPage/getStoreInfo',{storeID:this.materialInfo.fromStoreID,type:'fromStoreID'})
// this.showBone = false
uni.showTabBar() // 显示tabbar
this.refreshStockAndGetMaterStore() // 刷新物料库存
} else {
// 获取推荐分类
this.topCats = [
{
img:'https://image.jxc4.com/jxapp/jxc4.png',
name:'京西菜市',
id:[1]
},
{
img:'https://image.jxc4.com/jxapp/jxgy.png',
name:'京西果园',
dnsType:'wxGy'
},
{
img:'https://image.jxc4.com/jxapp/jxToHome.png',
name:'京西到家',
id:[7]
},
{
img:'https://image.jxc4.com/jxapp/starfish.png',
name:'海星超市',
id:[29]
},
{
img:'https://image.jxc4.com/jxapp/dogCat.png',
name:'狗不理猫',
dnsType:'wxJxpet'
},
{
img:'https://image.jxc4.com/jxapp/jadeButterfly.png',
name:'玉蝴蝶',
id:[35]
}
]
this.showBone = false // 关闭骨架屏
uni.showTabBar() // 显示tabbar
if(!this.queryStoreID){
// 获取推荐商家
// 菜市
let arrC4 = await apiStore.getNearlyStore({
lat: this.reLocation && this.reLocation.lat? this.reLocation.lat : this.myLocation.lat,
lng: this.reLocation && this.reLocation.lng? this.reLocation.lng : this.myLocation.lng,
needWalkDistance:false
})
// 果园
let arrGy = await apiStore.getNearlyStore({
lat: this.reLocation && this.reLocation.lat? this.reLocation.lat : this.myLocation.lat,
lng: this.reLocation && this.reLocation.lng? this.reLocation.lng : this.myLocation.lng,
needWalkDistance:false
},'wxGy')
// 宠物
let arrPet = await apiStore.getNearlyStore({
lat: this.reLocation && this.reLocation.lat? this.reLocation.lat : this.myLocation.lat,
lng: this.reLocation && this.reLocation.lng? this.reLocation.lng : this.myLocation.lng,
needWalkDistance:false
},'wxJxpet')
arrGy = arrGy.map(item => ({...item,dnsType:'wxGy'}))
arrPet = arrPet.map(item => ({...item,dnsType:'wwwJxpet'}))
this.nearlyStores = arrC4.concat(arrGy).concat(arrPet)
store.commit('indexPage/saveStoreList',this.nearlyStores)
}else{
await store.dispatch('indexPage/getTopGoods', this.storeID) // 热销商品(扫码进店)
}
// 获取品牌信息
await store.dispatch('indexPage/getBrandInfo', { brandID: this.brandID })
await apiStore.getWayBillFeeMinus(this.storeID[0]) // 获取当前门店的运营策略
}
} catch (e) {
console.error(e);
this.showBone = false
throw e;
}finally{
this.showBone = false
}
},
async refreshStockAndGetMaterStore() {
// 刷新物料库存
await apiStore.refreshStock()
// 获取购买限制
let res= await apiStore.getMatterStoreOrderStatus(this.materialInfo.fromStoreID)
store.commit('indexPage/savePreSaleCount',res.count)
store.commit('indexPage/changeCanBuy',res.flag)
},
// 重新选择地址
toDressPick() {
jumpPage('navigateTo','/pagesAddress/position-address/index?choisePosition=1')
},
// 跳转到分类页面
toGoods(banner, bannerID) {
switch (banner.type) {
case 3:
uni.navigateToMiniProgram({
appId: banner.toPath
});
break
case 2:
jumpPage('navigateTo','/pagesBanner/banner-template1/index?id=' + bannerID)
break
case 1:
App.catID = banner.toPath;
jumpPage('navigateTo','/pagesGoods/good/index')
break
}
},
toGoodsByID(cats) {
if(cats.dnsType){
// 跳转到果园,查询果园门店
// store.commit('indexPage/changeStoreType',true)
// dnsType wxGy果园 wwwJxpet宠物
store.commit('indexPage/changeDNS',cats.dnsType)
jumpPage('navigateTo',`/pagesStore/store/index?type=${cats.dnsType}`)
}
else{
store.commit('indexPage/changeDNS','wxC4')
// 跳转到门店列表
jumpPage('navigateTo','/pagesStore/store/index?brandID=' +JSON.stringify( cats.id))
}
},
// 商品 +
async handleSkuNamePlus(index) {
const skuName = this.topGoods[index];
await this.changeCar({
skuName,
count:skuName.count + 1
})
},
// 商品 -
async handleSkuNameMinus(index) {
let skuName = this.topGoods[index];
await this.changeCar({
skuName: skuName,
count:skuName.count - 1,
})
},
async handleSkuNameChange(count,index) {
let skuName = this.topGoods[index];
await this.changeCar({
skuName: skuName,
count,
})
},
// 点击检索
handleClickSearch() {
jumpPage('navigateTo','/pagesGoods/good-search/index')
}
},
}
</script>
<style lang="scss" scoped>
@import './shop-index.scss';
</style>

File diff suppressed because one or more lines are too long

540
src/pages/mine/index.vue Normal file
View File

@@ -0,0 +1,540 @@
<template>
<view class="shop-mine">
<!-- #ifdef APP-PLUS || APP -->
<!-- <wrap-version-update id="wxf3657c94aa01a3f0" btnBgColor="#66be4d" :auto="false" ref="wrapVersion" @check="handleCheck"></wrap-version-update> -->
<!-- #endif -->
<view class="mine-header">
<view class="avatar">
<img v-if="isLogin && selfInfo.avatar" class="avatar_img" :src="selfInfo.avatar" alt=""/>
<img v-else class="avatar_img" src="https://image.jxc4.com/image/9dc7d11b8e64049273dd1bc6ad938166.png?imageView2/1/w/120/h/120" alt=""/>
</view>
<view class="user-info">
<view class="info" v-if="isLogin">
<view>
<view class="nick-name" v-if="selfInfo.name!== undefined "> {{ selfInfo.name}}</view>
<!-- | hideMobile -->
<view class="mobile" v-if="selfInfo.mobile">{{ selfInfo.mobile}}</view>
</view>
<view v-if="selfInfo.userMembers" class="vip">
VIP{{ selfInfo.userMembers[0].memberTypeID }}
<span v-if="endAt">({{ endAt }}到期)</span>
</view>
</view>
<!-- #ifdef MP-WEIXIN || APP-PLUS -->
<button v-else class="btn-login" @click="login"> 立即登录/注册</button>
<!-- #endif -->
<!-- #ifdef MP-TOUTIAO -->
<button v-else class="btn-login" @tap="login" data-eventsync="true" > 立即登录/注册</button>
<!-- #endif -->
<!-- #ifdef MP-ALIPAY -->
<button v-else class="btn-login" open-type="getAuthorize" @getAuthorize="login" scope='phoneNumber'> 立即登录/注册</button>
<!-- #endif -->
<!-- #ifdef MP-KUAISHOU -->
<view v-else class="btn-login" @click="login">立即登录/注册</view>
<!-- #endif -->
</view>
</view>
<!-- 订单块 -->
<view v-if="isLogin && isShowShop" class="order-wall">
<!-- #ifndef APP || APP-PLUS -->
<left-right-cell>
<template #left>
<view class="left">
<view class="icon icon-order"></view>
<text>我的订单</text>
</view>
</template>
<template #right>
<!-- @click.native="goMyOrder('all')" -->
<text slot="" class="right" @click="goMyOrder('all')">查看全部订单</text>
</template>
</left-right-cell>
<!-- #endif -->
<!-- #ifdef APP || APP-PLUS -->
<left-right-cell @click.native="goMyOrder('all')">
<template #left>
<view class="left">
<view class="icon icon-order"></view>
<text>我的订单</text>
</view>
</template>
<template #right>
<text class="right">查看全部订单</text>
</template>
</left-right-cell>
<!-- #endif -->
<view class="order-status">
<badge class="status-item" :count="orderCount.waitCount">
<view class="status-item-wrapper" @click="goMyOrder('waitPay')">
<view class="icon icon-pay"></view>
<text class="text">待支付</text>
</view>
</badge>
<badge class="status-item" :count="orderCount.deliverCount">
<view class="status-item-wrapper" @click="goMyOrder('waitReceive')">
<view class="icon icon-waitreceiving"></view>
<text class="text">待收货</text>
</view>
</badge>
<badge class="status-item" :count="0">
<view class="status-item-wrapper" @click="goMyOrder('waitComment')">
<view class="icon icon-waitcomment"></view>
<text class="text">待评价</text>
</view>
</badge>
<badge class="status-item" :count="0">
<view class="status-item-wrapper" @click="goAfterSales">
<view class="icon icon-aftersale"></view>
<text class="text">售后/退款</text>
</view>
</badge>
</view>
</view>
<!-- 订单块 -->
<!-- 我的地址 -->
<!-- && isShowShop -->
<view class="my-cell mt20" @click="goAddressManager" v-if="isLogin && isShowShop">
<left-right-cell>
<template #left>
<view class="left">
<view class="icon icon-address"></view>
<view>我的地址</view>
</view>
</template>
</left-right-cell>
</view>
<!-- 我的地址 -->
<!-- #ifdef MP-WEIXIN || MP-ALIPAY -->
<!-- 会员中心 -->
<!-- && isShowShop -->
<view class="my-cell mt20" @click="goVip" v-if="isLogin">
<left-right-cell>
<template #left>
<view class="left">
<view class="icon-wsx icon-vip"></view>
<view>会员中心</view>
</view>
</template>
</left-right-cell>
</view>
<!-- 会员中心 -->
<!-- #endif -->
<!-- 联系客服 -->
<view class="my-cell service" @click="contactService">
<left-right-cell>
<template #left>
<view class="left">
<view class="icon icon-service"></view>
<view>联系客服</view>
</view>
</template>
</left-right-cell>
</view>
<!-- 联系客服 -->
<!-- #ifndef MP-KUAISHOU || MP-ALIPAY -->
<!-- 我的推广码 -->
<view class="my-cell promopte" @click="goPromote" v-if="isBindMobile && iosOrAndroid.platform!=='ios'">
<left-right-cell>
<template #left>
<view class="left">
<view class="icon icon-mypromote"></view>
<view>我的推广码</view>
</view>
</template>
</left-right-cell>
</view>
<!-- 我的推广码 -->
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<!-- 下载app -->
<!-- <div class="my-cell promopte" @click="downloadAPP">
<left-right-cell :noClick="true">
<div slot="left" class="left">
<div class="icon icon-downloadApp"></div>
<div>点击下载APP</div>
</div>
</left-right-cell>
</div> -->
<!-- 下载app -->
<!-- #endif -->
<!-- #ifdef APP-PLUS || APP -->
<view style="border-top: 1rpx solid #E4E7ED;" @click="updateAPP">
<!-- <left-right-cell>
<template #left>
<div class="left">
<div class="icon icon-checkUpdate"></div>
<div>检查更新</div>
</div>
</template>
<template #right>
<div class="right" >
<div class="rightImgBox" v-if="versionText!=='当前版本号'">
<img src="https://image.jxc4.com/image/229a8908c77ce7b489713ba4fdd6b996.png" alt="" clss="right-img" >
</div>
<div >
<span :style="{color:versionText=='当前版本号'?'':'red'}">{{version}}</span>
</div>
</div>
</template>
</left-right-cell> -->
<view style="display:flex;" class="checkUpdate">
<view class="left">
<view class="icon icon-checkUpdate"></view>
<view>检查更新</view>
</view>
<view class="right" >
<view class="rightImgBox" v-if="versionText!=='当前版本号'">
<img src="https://image.jxc4.com/image/229a8908c77ce7b489713ba4fdd6b996.png" alt="" clss="right-img" >
</view>
<view>
<span :style="{color:versionText=='当前版本号'?'':'red'}">{{version}}</span>
</view>
</view>
</view>
</view>
<!-- #endif -->
<!-- 退出登录 -->
<view class="login-out mt20" @click="handleLogout" v-if="isLogin">退出登录</view>
<!-- 退出登录 -->
<!-- loading -->
<zy-loading></zy-loading>
</view>
</template>
<script>
import reComputedCarCount from "@/mixins/reComputedCarCount.js";
import LeftRightCell from "@/components/layout/left-right-cell.vue";
import { mapGetters } from "vuex";
import Badge from "@/components/badge/badge.vue";
import { modal, errToast,jumpPage,setTabBarBadge } from "@/utils/uniapi.js";
import ZyLoading from "@/components/Loading/loading";
import { timeFormat3 } from '@/utils'
import {store} from '@/store'
import orderPage from '@/apis/orderPage';
import loginAPI from '@/apis/login'
export default {
name: "ShopMine",
mixins: [reComputedCarCount],
components: {
LeftRightCell,
Badge,
ZyLoading
},
data() {
return {
orderCount: {
waitCount: 0,
deliverCount: 0,
},
endAt: '',
version: '1.0.0',
versionText: "当前版本号",
isChech: true,
};
},
computed: {
...mapGetters({
selfInfo: "login/selfInfo",
isLogin: "login/isLogin",
isBindMobile: "login/isBindMobile",
isMaterial: "indexPage/isMaterial",
isShowShop: 'isShowShop',
iosOrAndroid: "iosOrAndroid",
tmpData:'login/tmpData',
carCount:"cartPage/carCount"
})
},
watch: {
carCount: {
handler(val) {
if(val) setTabBarBadge('set',val)
},
immediate:true
}
},
created() {
if (this.selfInfo.userMembers) {
this.endAt = timeFormat3(this.selfInfo.userMembers[0].endAt)
}
uni.showTabBar() // 显示tabbar
// #ifdef APP-PLUS || APP
// this.getUpdate()
// #endif
},
async onShow() {
try {
// await this.globalLogin()
this.showLoad();
if (this.isLogin) {
await this.handleGetOrderCount();
}
// if (this.isMaterial) {
// await getMatterStoreOrderStatus();
// }
if(this.carCount) setTabBarBadge('set',this.carCount)
} catch (e) {
console.error(e);
errToast(e);
} finally {
uni.showTabBar() // 显示tabbar
this.hideLoad();
}
},
async onPullDownRefresh() {
console.log("下拉刷新");
// uni.stopPullDownRefresh()
try {
this.showLoad();
if (this.isLogin) {
// 1.个人信息
let selfInfo = await loginAPI.getSelfInfo() // 获取用户信息
store.commit('login/saveSelfInfo', selfInfo)
// 请求订单数量
await this.handleGetOrderCount();
}
} catch (e) {
console.error(e);
errToast(e);
} finally {
uni.stopPullDownRefresh();
this.hideLoad();
}
},
filters: {
hideMobile(mobile) {
return mobile
? mobile.split("").map((item, index) => {
if (index >= 3 && index <= 6) return "*";
else return item;
}).join("")
: "";
},
},
methods: {
// 登录
async login() {
let that = this
// #ifdef MP-WEIXIN
let obj = {
avatarUrl: 'https://image.jxc4.com/image/9dc7d11b8e64049273dd1bc6ad938166.png',
nickName:String(new Date().getTime()).substring(0, 11) // 模拟手机号
}
uni.setStorageSync('aldstat_user_info', obj)
await this.globalLogin()
if (JSON.stringify(this.tmpData) !== '{}') jumpPage('navigateTo', `/pagesAuth/auth-index/index?type=weixinmini`)
// let obj = {
// avatarUrl: 'https://image.jxc4.com/image/9dc7d11b8e64049273dd1bc6ad938166.png',
// nickName:String(new Date().getTime()).substring(0, 11) // 模拟手机号
// }
// uni.setStorageSync('aldstat_user_info', obj)
// jumpPage('navigateTo', `/pagesAuth/auth-index/index?type=weixinmini`)
// #endif
// #ifdef MP-TOUTIAO
// 有手机号权限时的操作
// uni.getUserProfile({
// success(res) {
// uni.setStorageSync('aldstat_user_info',res.userInfo)
// uni.login({
// force: true,
// success(r) {
// jumpPage("navigateTo",`/pagesAuth/auth-index/index?ttCode=${r.code}`)
// }
// });
// },
// fail(err) {
// console.log("getUserProfile 调用失败", err);
// uni.login({
// force: true,
// success(r) {
// jumpPage("navigateTo",`/pagesAuth/auth-index/index?ttCode=${r.code}`)
// },
// });
// },
// });
// 无手机号权限时
tt.getUserProfile({
async complete(res) {
if (res.errMsg === "getUserProfile:ok") uni.setStorageSync('aldstat_user_info', res.userInfo)
await that.globalLogin()
if(JSON.stringify(that.tmpData) !== '{}') await store.dispatch('login/analyzePhone')
jumpPage('switchTab','/pages/index/index') // 跳转
}
})
// #endif
// #ifdef MP-KUAISHOU
ks.getUserInfo({
complete(res) {
if(res.userInfo) uni.setStorageSync('aldstat_user_info',res.userInfo)
uni.login({
success(r) {
jumpPage('navigateTo',`/pagesAuth/auth-index/index?type=ksMini&ksCode=${r.code}`)
},
})
}
});
// #endif
// #ifdef APP-PLUS || APP
jumpPage('navigateTo',`/pagesAuth/auth-index/index?type=wxApp`)
// #endif
// #ifdef MP-ALIPAY
my.getPhoneNumber({
success: async (res) => {
let encryptedData = JSON.parse(res.response);
await that.globalLogin()
if (JSON.stringify(this.tmpData) !== '{}') await store.dispatch('login/analyzePhone', encryptedData.response)
},
fail: (res) => {
console.log("获取失败", res);
},
})
// #endif
},
// 获取订单数量
async handleGetOrderCount() {
try {
this.orderCount = await orderPage.getOrderCount();
} catch (e) {
throw e;
}
},
// 退出登录
async handleLogout() {
let res = await modal(
"确定退出?",
"退出登录后将无法查看订单,重新登录即可查看"
);
if (res) {
uni.clearStorageSync() // 清除缓存
store.commit("cartPage/saveCartList",[]) // 清除本地购物车
store.commit("login/changeLoginStatus",false) // 改变登录状态
store.commit("indexPage/saveMaterialInfo",{}) // 清除物料信息
store.commit('indexPage/savePromote','') // 推广码
store.commit('indexPage/saveQueryStoreID', '') // 清除扫码进入的参数
await store.dispatch('indexPage/getBrandInfo',{brandID:1}) // 将品牌更改为1
setTabBarBadge('',0)
}
},
// 下载app
// downloadAPP() {
// wx.showModal({
// title: "提示",
// content: "点击确认复制地址到浏览器直接下载",
// showCancel: false,
// success() {
// copyData("http://www.jxc4.com/jxc4app/app.apk");
// },
// });
// },
// #ifdef APP-PLUS || APP
updateAPP() {
console.log('this.$refs',this.$refs.wrapVersion)
return
this.$refs.wrapVersion.check()
if (!this.isChech) {
uni.showToast({
title: "当前版本为最新版",
icon: "none",
position: "bottom",
});
}
},
handleCheck(res) {
if (this.iosOrAndroid) {
let info = this.iosOrAndroid
let version = Number(res.version.split('.').join(''))
let appWgtVersion = Number(info.appWgtVersion.split('.').join(''))
if (version > appWgtVersion) {
this.version = res.version;
this.versionText = "发现新版本";
this.isChech = true;
} else {
this.version = info.appWgtVersion;
this.versionText = "当前版本号";
this.isChech = false;
}
} else {
let that = this
uni.getSystemInfo({
success: info => {
store.commit('setIosOrAndroid', info)
that.handleCheck(res)
}
})
}
},
// #endif
//联系客服
contactService() {
uni.makePhoneCall({
phoneNumber: "18048531223", //石老板电话
});
},
// 跳转到所有订单
goMyOrder(name) {
jumpPage('navigateTo',`/pagesOrders/my-order/index?name=${name}`)
},
// 跳转到售后/退款
goAfterSales() {
jumpPage('navigateTo',`/pagesOrders/my-afsorder/index`)
},
// 跳转到地址管理页面
goAddressManager() {
jumpPage('navigateTo',`/pagesAddress/mine-address/index?isManager=true`)
},
//会员中心
goVip() {
jumpPage('navigateTo','/pagesMine/vip/index')
},
// 跳转到我的推广码
goPromote() {
jumpPage('navigateTo',"/pagesMine/my-promote/index")
}
}
};
</script>
<style lang="scss">
@import "./mine.scss";
page {
background: #f4f4f4;
}
</style>

256
src/pages/mine/mine.scss Normal file
View File

@@ -0,0 +1,256 @@
@import '@/assets/bundle.scss';
// .shop-mine {
// box-sizing: border-box;
// width: 100%;
// overflow: hidden;
.mine-header {
@extend %flex-left;
@extend %pd30;
box-sizing: border-box;
background-color: $maincolor;
height: 200rpx;
.avatar {
flex: none;
width: 120rpx;
height: 120rpx;
border-radius: 50%;
background: white;
overflow: hidden;
@extend %flex-center;
.avatar_img{
width: 100%;
height: 100%;
}
// img {
// width: 100%;
// height: 100%;
// }
}
.user-info {
margin-left: 30rpx;
flex: 1;
color: white;
.btn-login {
width: 100%;
text-align: left;
font-size: 36rpx;
background: none;
font-weight: 500;
color: white;
padding: 0;
margin: 0;
border: none;
outline: none;
box-sizing: content-box;
&:after {
border: none;
}
}
.info {
font-size: 34rpx;
.nick-name {
font-weight: 500;
}
.mobile {
font-size: 32rpx;
}
.vip{
color: #fbc200;
}
.bind-mobile {
background: $success;
font-size: 28rpx;
padding: 4rpx 20rpx;
display: inline-block;
border-radius: 10rpx;
box-shadow: 0 2rpx 4rpx rgba(black, .4);
}
}
}
}
.icon {
@extend %bg-no-repeat-center;
background-size: 100%;
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
.left {
font-weight: 500;
color: $text1;
@extend %flex-center;
}
.order-wall {
// @extend %pd30;
padding-top: 10rpx;
padding-bottom: 30rpx;
@extend %bgwhite;
.icon-order {
@extend %mine-order;
}
.right {
font-size: 28rpx;
color: $text3;
}
.order-status {
border-top: 1rpx solid $border3;
margin: 0 20rpx;
padding-top: 10rpx;
@extend %flex-around;
.status-item {
flex: 1;
margin: 0 10rpx;
}
.status-item-wrapper {
@extend %flex-center;
flex-flow: column;
padding-top: 20rpx;
}
.icon {
@extend %bg-no-repeat-center;
background-size: 100%;
width: 50rpx;
height: 50rpx;
margin-right: 0;
}
.icon-pay {
@extend %mine-waitpay-text3;
}
.icon-waitreceiving {
@extend %mine-waitreceiving-text3;
}
.icon-waitcomment {
@extend %mine-waitcomment-text3;
}
.icon-aftersale {
@extend %mine-aftersale-text3;
}
.text {
margin-top: 20rpx;
font-size: 24rpx;
color: $text2;
}
}
}
// .invated {
// margin-top: 20rpx;
// @extend %pd30;
// @extend %bgwhite;
// }
.checkUpdate{
display: flex;
justify-content: space-between;
min-height: 100rpx;
box-sizing: border-box;
font-size: 32rpx;
background-color: #fff;
padding: 0 20rpx;
.left{
display:flex;
.icon-checkUpdate {
@extend %icon-checkUpdate;
}
}
.right{
width:fit-content;
display: flex;
color: #333;
align-items: center;
// border:1rpx solid red;
.rightImgBox{
display:flex;
justify-content: center;
align-items: center;
}
.right-img{
width: 50rpx;
height: 50rpx;
}
}
}
.mt20 {
margin-top: 20rpx;
}
.my-cell {
.icon-coupons {
@extend %mine-coupons;
}
.icon-address {
@extend %mine-address;
}
.icon-service {
@extend %mine-service;
}
.icon-mypromote {
@extend %icon-my-promote;
}
.icon-downloadApp {
@extend %icon-downloadApp;
}
.icon-waybill {
@extend %icon-mywaybill;
}
.icon-wsx {
background-size: 100%;
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
.icon-vip{
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAJVklEQVRoQ+1Ze4wdVR3+zpwz7/vYZ7vtLqTQVnkUSmHbVURFg/EP3cQGoomhpd3aVjG+jUqIiLF/iFE0BGi7fZEWTHzUYKqE1BBZTMTaLg1CG5SgYG2b0u3u3ntn77zOzDFn7s7de9ftvish6Uk2NzNz5ne+7/xe35kleJcP8i7Hj8sE3mkPXvbAZQ/McQdmHUItR3tfJQRX+QGs2WMgABERU+mpEObqUudnB2Zqa8YE2o733uu65NGsFRJDi5HXA1gsmHLdUmggjBkUEidzBQhGQh0BV+D5ApxDKIw8M7T6c5+c0ljNhBkRWHS8d3MQYGdzJiRZQwL3wYWS1GKNhtAIh0Y5gpghjCm8SEMcK8m9dIxwA340RkSScjlDGClwnBhMpwcHb9l013RJTJtA+8u71rt+vK8pEyntdgl3527D/tILyKvlKddyuAGX69CUMSLDvi3Dp+qNom+AR8BIGWCMPnlhdc+6KQ0D02tki0/u+ozvxD9vy/pKu81xf3M3PmQtwxcv7MDr3nlQJYKuRLBUH0FU2Xm5s7EgMOhYeBUCuw5TLYlIKJBhxkNJIgZjbPfgmp7NU5GY0gMdx3d8xePk4QVZT1mWIfhuczc6jSXYX+zDIf9ZGCxM1pCgIUT1Ol142K/PcSc0IcGmY9C3oYx6gscKpLckibIbQ9G0J4du2TCpJyYlcMUru77getGjjSZXbmqk+F5zN67X23Gg2IfD0aEkzkEIcqwMnVaIyMR0QgM6GwuXUDCMBFoV9Dm3AcbofB5TFLkJBZXk9rgKL1JlUqNcjkE0tnu48+KeuCiBxa/s+5jvBc802ZytylrYtuATWK614kCpD4f5IYyEBtrtC3UeXqK/H1m6EJSoF/X8GW8AJ0pv4E1HhUajZF6y6/GYV4YDS5YphKGA6xMhFH1bcc26ByYyOiGBjpf2frjM+XN5M6S2EeHrrauwMX8bnir9EQfd52SkoCNTD36lfRfI9FIKJT6Cvguv44Jf8ZocQ54FMsqhHGpJJZNDTvE8CKjsgWLnhm3jSfwPgZbjB7bEofeYrgl2Y4OGO3PLsWf4RXw034Rj7ikstIoIIoYFZqFqa4XVDUaMqfKt7rkkcfjcW3CikeS+BFzmlTCTPaLgm9X5IwED9yNBFO2+Qte6h2oN1RHQj/96uR0On2BMqK0ZDz9YeAfW5q7BvWd/gVPkRLJDsmyazIc+WhKvMT8OQ8nNCHw1wUMXfQNvYDh0k1u1CS3zKA0r2WscXwXhvgDVvlFcvf6nqY06Atkje12TRYZhEOS1MlboLVhuWuhzTyKrushpHsKYYKFZTN5fZtyODG2dFfiJSNSGUZrM6TzZAMMwBuGBiBX1y07XPY/KZ1UCuSNP/ElRcFvW5KAkRlbzYNIwqS46DUCISIBLw23WMK4yPoA8XTwn8ONJvFWWlbgCSVYnJ9Sr9mUj9GMGEgUQcXSu1NXTVk/gz71CtcxEHqhKDFv1kFF9MBIhq7mIBNBqOInBpeZSXGG8d17Ap0ZeLpzGC+cHEaOmGtX0ECk/3KhCiHglFG/dkjCteiB75InfqDRaaxsi0S5SoMl4JwSjpDhUJYKt+vA5Q1fjdWhgHfNCQuaAzIXTblzpLaOjEJhVj4SCJqWb8ACIo7eK7+tZUkdAXjQf3VMQiHMtWZ6Ejox7SgSYwmFL4RZTtJilxHyjVsYS49Y5h1EKXv4miVvTpUuBUe3aUpYUy9I7wi2t2ZgBqcjauiS2Th5cZDhDr1IlamrL+7BokHgjEgRNupPIBRn/csjF2q0SlpprkKOLZuWJQljG8wP/rFahYmAiroEktVE02uA8T8Dn1Cuy1mZ0dlcV5ISNrO2lHSUCkWnPuzBZkNT91tG6L0NKVig5ZFxSUKxuuAF5tmBGJGQf+MPbb6LEx9RsrbiTxtIQcj2BKII/ROMOdG6tO/RcVEos7N9ZUEicW9ZcQBDTxAOyOsnRoNdLaJWouNa+BU1q07RISPB/HT6BNx0GplTkhBy1fUBeSyEodz6METKhrRjouucf4xeYVMy1HdsxYmuBtThfhkyiFr1S/6XYkl4wR5WovKcpOlbYNyPHGiclkYL/d1mBIgXP6EiVaHodCwXnSzqCEFzPsQ+eu27jXyYyPKWcbu9/3DU1bizKlavJnBpyuImOGkGnKwauT0g0TEgiBX/eD+GEFtSaA04hHKs48uUBR4cXKJxS9VMDnRt+f7FdmZLA7eJB9vf+BcWcEZgtGR+NeqUXVHcOCqKYgkCA0RgaLNzadC2a1PrDSwpexvzbXgN0ZUzIydIpEzY9FxTLDCWPxYqG9QOrtjw1mUunJCBf7ji1uyk6H57J676es6IklNLD+UTGbWqiq3EFcqxCIgVf4B4KvlUFmr475NtJp0/mehI8jXVD/faZG3p+PGk8TvdIKY1c3//YsgGhnGyyPDVnRNBYOOl5OMssrMy9B34c4jXnXzjtCkSCVQ8uKbBCYFUzoeRSFF1VmAZ5+PTKzd+cCrx8Pi0PpIaufm1Hp1OKX2yxA9ZsS2FHkziWuik9UY1ftBDaCCNWF+9jiUvh8Io8SHbepULT8dWzK7c+Mh3wMyYgX7jy5ON3eA55tiXj0Wbbr6xDCEKuJL8EcXKYl/1CxnRaescDqtX/jkdRKKvCMNl3ztzY86Ppgp8VAfnS1a9uv7Pk4ZetlqdUScxg1VrJ4LgUBVeFpYnv/2fV1gdnYKaydzN9IZ1/5d+2b3U9sr0165Jma9QTUxgb/1FL7vzwCINpKT88c+Pm+2aDZdYE5GKN/XvvJpzvz9ucNJteEi6KIhIJLhuf1DFSAMpckcfE2srl+BTDDoNhsp+dXbnpa7MBPycPpAu2Huv9EufikQabI2OMyYLJAMmdH3IYdBM7z9209fOzBT8vBKSR1v5d9/NQbGu0A9hGRS9dbIx4CgYdDbaFA6dXblk/F/DzRkAaau7f/VAUxN9qygaw9YlJyGQdHqHImuT50zdt/shcwc8rgcQTx3p3+wE25TMC8tO7zAFZUuVfwAnccgzVYL8auLnn0/MBft4JSIMNR/ftjoNwk2URqGqlRsgvbGVPQFXp0xc6N62dL/CXhEASTkf3/DaK4m5F/utAALFIPpn/bqCzp3s+wV8yAgmJY3u7IMTDMoKg4OnBmzf9ZL7BX1IClwLsRDbn1Mj+XyAnW+cygXfaC+96D/wX+aErbdPLuMYAAAAASUVORK5CYII=') center no-repeat;
background-size: 100% 100%;
}
.icon-creStore{
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAE9klEQVRoQ+2ZW2wUVRjH/99suRm1aWJC9EFEIkQR2NkSI/pSEuKF7plpQYiJJgbTlGh4E4NgE2q88FB8MlEpUUiUGEEue2YKKjH0RQVpdxYiIZKo8UaDgSglahu685mz3e6twM6ZziZtwkk2m875Lv/fzJyz3/lKmOKDprh+3AQofYKtPUvmZ0cMwQaSBNwF0J2j8zzAwHmDeY8P/yvHOv1zVE8+kifQ4iYafd9vB1F7IGHM3YZhdB9KpvsD2d/AaMIAlhtfA6a9FTmGGfgegEfACIB4/jOz3I63SJHZNhGICQFYTnwrQJ1FAbSHyH93+r+zvH1rv/2vVFjTsaaZ9Zf/TiBmbGXwY8U57pQi81pYiNAAlhPfDNBbhcREq2UyfSCIEMsxld/moi+vlcnMviC+lTahAHLvPHPfWDAp1JuiPyzH5DEvg2hpmDURLrGM7yhZsNuk8LboywcsN7EKzPtHNyrullZmvW4cbQAhF88liv2kEhHoy5RIP66btNTechIfA/yMuhYz/AUHm0+d04mnDWDLeBsT7cwBZPnRVEvmG52Elba2G3+Emb7OXfexUdre2zrxtAGEYx4joAnA0OCt9Q29y3uHdBJW2q7Zu2zW8KyhvwDMYKDXEd5ynXjaAJZj/gBgPoDjUnjLdJJdz1Y4Zh8BjQDOSeEt0IkZAiAxCPBtAN6XwntBJ9kNAHYS0AbQFSnSt+vEDAFgXgagktQAAINSePW1BlAlwsIavUJnpPAerDXAJwCersUiJmB/SnhP1RRASHM1ET6rxTbKzOscK7O7pgDN7qKGGNedBTA74h+yC7Gr0xYeXPXdpZoCqOC2m+hi5o35RJGUEkS0PZVMv6wjfrQaCDGsVGIxDD415hpFMQeflkg7fVpXTigAlWRKl9Njd2lKH2gKENc4UhLhqs8YIOACAHXunZxHytyrlDKXUozWMXMLcp2IAGMyHOpt11zB4OfA9GyZZHXGKltZdGVStVVaDjbO8+uyXQC1FoXzFYBOEtHxLPtHmfyLTDMuXvjdv9S/vv9qgGdSMFnZY8453Oz9EtRHaxeynUQrE3eBMS+f4DzA3XXTYt0HnugfCJr0ulWpG3+DmF5l8C5HZJ4PEi8wwPgdhzujEq6ENruL7o1x3Y8F0T49Ke3059UgAgGUiSf0EagjlUx/US24znzSid9ngArnYWYSjpV2q8WoClAqnoGPRmLTNxxZeWKwWmDd+ZoACDfRTsw7lBgGPnWEp8romozIAfLNq6MAGgCclMJ7qCbK80EjB7AcU4lfAeBPKbzZUYpXZwrD4LnlMekOZmwqXCN8SGBVtpfs1sallEjvKr10zTVgOYkNAL8D1Vn2uUXamZ6oAGxpvsKECXSkaacU6UIbfxzAmqON9cNDfALgBcTUkbLSb0YlXsUpebJhw/4mhXf3mPM4AMsxOwC8zsDZkdj0h6PeceyexkXs++pIqnpLaqj/H6hdgkCIFakoqxqm+b/r8t9/ELg9JTKHbwQw2nXw8aK0vffC3iZdv0gWsX3YfICzOJO7LQbu0alJdAVX2kcDUGzcZqTwzImK0vGPBMCS5n4QVgHlK11HSFjbaABS5kswsJ0JbU7S+yCsmDB+kQCESRylj+WY/wC4RcX02ZjjWv2/VotftZirFiDK+VY3cX+WeZMB3n1IZHqDxJ5UAEEEV9rcBAhz16L0+R8olFJPfxP/vgAAAABJRU5ErkJggg==') center no-repeat;
background-size: 100% 100%;
}
}
.my-cell + .my-cell {
border-top: 1rpx solid $border2;
}
.login-out {
@extend %bgwhite;
font-size: 28rpx;
height: 90rpx;
@extend %flex-center;
color: #fff;
border-radius: 20rpx;
width: 96vw;
margin:20rpx auto;
background-color: #4EB331;
font-size: 32rpx;
}
.update{
border:1rpx solid green;
position: relative;
&-icon{
width:20px;
height:20px;
position: absolute;
right: 35px;
}
// }
// 更新提示框
// .maskLayer{
// width: 100%;
// height: 100%;
// position: fixed;
// top: 0;
// left: 0;
// background-color: rgba($color: #4b4b4b, $alpha: .5);
// z-index: 999;
// display: flex;
// justify-content: center;
// align-items: center;
// .center{
// width:491rpx;
// height: 653rpx;
// // background-image: url("https://image.jxc4.com/image/22cc4d0adfab0998514fb6af53a3cd0a.jpg");
// }
// }
}

View File

@@ -0,0 +1,34 @@
@import '@/assets/_color.scss';
.zy-switch {
width: 2em;
height: 1em;
display: inline-block;
background: white;
border: 1rpx solid $border2;
border-radius: 1em;
font-size: 50rpx;
position: relative;
align-items: center;
transition: all .3s;
.zy-switch-item {
position: absolute;
width: 1em;
height: 1em;
border-radius: 100%;
box-shadow: 0 6rpx 2rpx 0 rgba(0, 0, 0, 0.05), 0 4rpx 4rpx 0 rgba(0, 0, 0, 0.1), 0 6rpx 6rpx 0 rgba(0, 0, 0, 0.05);
transition: .3s;
background: white;
left: 0;
}
}
.switch-on {
flex-direction: row-reverse;
background: $maincolor;
.zy-switch-item {
left: 1em;
}
}
.switch-disabled {
opacity: .5;
}

View File

@@ -0,0 +1,77 @@
/*
滑块组件
*/
<template>
<div
class="zy-switch"
@click="onChange"
:class="{
'switch-on': currentValue,
'switch-disabled': disabled
}"
:style="{'font-size': size + 'rpx'}"
>
<div class="zy-switch-item"></div>
</div>
</template>
<script>
export default {
name: 'ZySwitch',
props: {
disabled: {
type: Boolean,
default: false
},
value: {
type: [Boolean, Number, String],
default: false
},
size: {
type: String,
default: '50'
},
trueValue: {
type: [Boolean, Number, String],
default: true
},
falseValue: {
type: [Boolean, Number, String],
default: false
}
},
watch: {
value (val) {
if (val === this.trueValue || val === this.falseValue) {
this.updateModel()
} else {
throw 'Value should be trueValue or falseValue'
}
}
},
data () {
return {
currentValue: this.value
}
},
methods: {
onChange () {
console.log('onchange')
if (this.disabled) return false
let checked = !this.currentValue
this.currentValue = checked
let value = checked ? this.trueValue : this.falseValue
this.$emit('input:value', value)
// this.$emit('on-change', value)
},
updateModel () {
this.currentValue = this.value === this.trueValue
}
}
}
</script>
<style lang="scss">
@import './switch';
</style>

View File

@@ -0,0 +1,29 @@
@import '@/assets/bundle.scss';
.address-item {
@extend %pdtb;
border-bottom: 1rpx solid $border3;
margin: 0 50rpx;
position: relative;
#{&}-title {
color: $text1;
font-size: 34rpx;
@extend %oneline;
width: 500rpx;
}
#{&}-address {
color: $text3;
font-size: 28rpx;
padding-top: 10rpx;
@extend %oneline;
// border: 1px solid red;
}
.title{
display: flex;
justify-content: space-between;
}
&-distance{
color:$text3;
font-size: 28rpx;
}
}

Some files were not shown because too many files have changed in this diff Show More