Compare commits

...

22 Commits

Author SHA1 Message Date
wwl 3566cca5f0 张园活动报名&核销 2024-04-26 18:11:24 +08:00
wwl 6d4ab29b2e 首页轮播图跳转公众号 2024-04-26 09:44:14 +08:00
wwl f1be6694c0 活动页面和1774 2024-04-23 19:01:43 +08:00
wwl 113bd5f979 新增商品1774详情页 2024-04-18 11:46:10 +08:00
wwl ebdcaad967 首页去掉活动 2024-04-10 16:13:27 +08:00
wwl 929ccc429e 首页去掉活动 2024-04-09 15:00:03 +08:00
wwl 4efbfcca65 fix bug 2024-04-08 19:35:11 +08:00
wwl 6e18cc6b4f fix bug 2024-04-03 10:53:24 +08:00
wwl 067e9892be add cancel fix bug 2024-03-29 20:12:32 +08:00
wwl 9e1051e2f2 fix bug 2024-03-29 17:26:13 +08:00
wwl 54804b6546 fix bug 2024-03-28 19:19:22 +08:00
wwl b7d4ac0428 fix bug 2024-03-27 19:37:36 +08:00
wwl 820b1ea5cf fix bug 2024-03-27 11:36:29 +08:00
wwl 2f7c194a98 update 2024-03-21 17:54:30 +08:00
wwl 0206b16e3b update 1.4.2 2024-03-20 15:32:23 +08:00
wwl 3cf19165a4 update 1.4.2 2024-03-20 15:24:17 +08:00
wwl 846b34afe1 update 1.4.1 2024-03-20 14:49:54 +08:00
wwl a2778f0a24 update 2024-03-19 15:55:23 +08:00
wwl 7c106ff3bc update 优惠券修改 2024-03-18 18:52:29 +08:00
wwl dc55deda6f update 活动移至首页 2024-03-15 18:21:22 +08:00
wwl 2b0a5953ce update 2024-03-15 14:39:36 +08:00
wwl 77fc731426 update 2024-03-15 10:18:40 +08:00
87 changed files with 3468 additions and 574 deletions

15
.env copy.production Executable file
View File

@ -0,0 +1,15 @@
APP_BASE_URL=https://test.birkenstock.net.cn/api/h5app/wxapp
APP_WEBSOCKET=wss://test.birkenstock.net.cn/ws
APP_COMPANY_ID=1
APP_PLATFORM=standard
APP_CUSTOM_SERVER=https://test.birkenstock.net.cn/
APP_HOME_PAGE=/pages/index
APP_TRACK=youshu
APP_YOUSHU_TOKEN=bi281e87ab2424481a
# APP_ID=wx3e1c17c88abf3e45
APP_ID=wx72e9e1a93420862c
APP_MAP_KEY=1ccc1ebc947719886f0cd766d70241fe
APP_MAP_NAME=BIRKENSTOCK门店定位
APP_IMAGE_CDN=https://b-img-cdn.yuanyuanke.cn/ecshopx-vshop
APP_IMAGE_CDN_NEW=https://espier-oss-cdn.oss-cn-shanghai.aliyuncs.com/default_project/wxAssets
APP_DIANWU_URL=

15
.env.development.ba Executable file
View File

@ -0,0 +1,15 @@
APP_BASE_URL=https://test.birkenstock.net.cn/api/h5app/wxapp
APP_WEBSOCKET=wss://test.birkenstock.net.cn/ws
APP_COMPANY_ID=1
APP_PLATFORM=standard
APP_CUSTOM_SERVER=https://test.birkenstock.net.cn/
APP_HOME_PAGE=/pages/index
APP_TRACK=youshu
APP_YOUSHU_TOKEN=bi281e87ab2424481a
# APP_ID=wx3e1c17c88abf3e45
APP_ID=wx72e9e1a93420862c
APP_MAP_KEY=1ccc1ebc947719886f0cd766d70241fe
APP_MAP_NAME=BIRKENSTOCK门店定位
APP_IMAGE_CDN=https://b-img-cdn.yuanyuanke.cn/ecshopx-vshop
APP_IMAGE_CDN_NEW=https://espier-oss-cdn.oss-cn-shanghai.aliyuncs.com/default_project/wxAssets
APP_DIANWU_URL=

View File

@ -1,15 +1,15 @@
APP_BASE_URL=http://47.103.169.154:8080/api/h5app/wxapp
APP_WEBSOCKET=wss://http://47.103.169.154:8080/ws
APP_BASE_URL=https://slb.birkenstock.net.cn/api/h5app/wxapp
APP_WEBSOCKET=wss://slb.birkenstock.net.cn/ws
APP_COMPANY_ID=1
APP_PLATFORM=standard
APP_CUSTOM_SERVER=http://47.103.169.154:8081/
APP_CUSTOM_SERVER=https://slb.birkenstock.net.cn/
APP_HOME_PAGE=/pages/index
APP_TRACK=youshu
APP_YOUSHU_TOKEN=bi281e87ab2424481a
# APP_ID=wx3e1c17c88abf3e45
APP_ID=wx55ff808ba0e28b1d
APP_ID=wx72e9e1a93420862c
APP_MAP_KEY=1ccc1ebc947719886f0cd766d70241fe
APP_MAP_NAME=oneX新零售门店定位
APP_MAP_NAME=BIRKENSTOCK门店定位
APP_IMAGE_CDN=https://b-img-cdn.yuanyuanke.cn/ecshopx-vshop
APP_IMAGE_CDN_NEW=https://espier-oss-cdn.oss-cn-shanghai.aliyuncs.com/default_project/wxAssets
APP_DIANWU_URL=

15
.env.production.bak Executable file
View File

@ -0,0 +1,15 @@
APP_BASE_URL=http://47.103.169.154:8080/api/h5app/wxapp
APP_WEBSOCKET=wss://http://47.103.169.154:8080/ws
APP_COMPANY_ID=1
APP_PLATFORM=standard
APP_CUSTOM_SERVER=http://47.103.169.154:8081/
APP_HOME_PAGE=/pages/index
APP_TRACK=youshu
APP_YOUSHU_TOKEN=bi281e87ab2424481a
# APP_ID=wx3e1c17c88abf3e45
APP_ID=wx55ff808ba0e28b1d
APP_MAP_KEY=1ccc1ebc947719886f0cd766d70241fe
APP_MAP_NAME=oneX新零售门店定位
APP_IMAGE_CDN=https://b-img-cdn.yuanyuanke.cn/ecshopx-vshop
APP_IMAGE_CDN_NEW=https://espier-oss-cdn.oss-cn-shanghai.aliyuncs.com/default_project/wxAssets
APP_DIANWU_URL=

81
config/test.js Executable file
View File

@ -0,0 +1,81 @@
/* eslint-disable import/no-commonjs */
const path = require('path')
module.exports = {
env: {
NODE_ENV: '"production"'
},
h5: process.env.APP_CDN
? {
output: {
filename: 'js/[name].[hash:8].js',
chunkFilename: 'js/[name].[chunkhash:8].js'
},
miniCssExtractPluginOption: {
filename: 'css/[name].[hash:8].css',
chunkFilename: 'css/[id].[hash:8].css'
},
webpackChain(chain) {
// const pkg = require(path.resolve(__dirname, '../package.json'))
// const { publicPath, bucket: CDNBucket, path: CDNPath } = pkg.cdn
const publicPath = process.env.APP_PUBLIC_PATH
const CDNPath = process.env.APP_CDN_PATH
let plugin = {}
if (process.env.APP_CDN == 'aws') {
plugin = {
'asw-s3': {
plugin: require('webpack-s3-plugin'),
args: [
{
exclude: /.*\.html$/,
s3Options: {
accessKeyId: process.env.APP_CDN_KEY,
secretAccessKey: process.env.APP_CDN_SCERET,
region: process.env.APP_CDN_REGION,
ACL: ''
},
s3UploadOptions: {
Bucket: process.env.APP_CDN_BUCKET
},
basePath: CDNPath
// cdnizerOptions: {
// defaultCDNBase: 'http://asdf.ca'
// }
}
]
}
}
}
chain.output
.publicPath(`${publicPath}/${CDNPath}/`)
chain.merge({
plugin
// plugin: {
// 'qn-webpack': {
// plugin: require('qn-webpack'),
// args: [{
// accessKey: process.env.CDN_ACCESS_KEY,
// secretKey: process.env.CDN_SECRET_KEY,
// bucket: CDNBucket,
// path: CDNPath,
// exclude: /(?:manifest\.json|\.map)$/
// }]
// }
// }
})
}
}
: {
output: {
filename: 'js/[name].[hash:8].js',
chunkFilename: 'js/[name].[chunkhash:8].js'
},
miniCssExtractPluginOption: {
filename: 'css/[name].[hash:8].css',
chunkFilename: 'css/[id].[hash:8].css'
}
}
}

View File

@ -1,5 +1,5 @@
{
"name": "BIRKENSTOCK",
"name": "bk",
"app_name": "BIRKENSTOCK",
"version": "3.13.20",
"private": true,
@ -7,6 +7,7 @@
"scripts": {
"clean": "rm -rf node_modules/.cache",
"build:weapp": "taro build --type weapp --trace-warnings",
"build:weapp:test": "taro build --type weapp --trace-warnings",
"build:weapp:live": "APP_LIVE=true taro build --type weapp --trace-warnings",
"build:swan": "taro build --type swan",
"build:alipay": "taro build --type alipay",

View File

@ -333,6 +333,7 @@ class API {
} catch (e) {
// console.log(5);
console.log(e)
Taro.hideLoading()
}
if (showLoading) {

View File

@ -79,6 +79,9 @@ export function registrationSubmit (data) {
export function verifyRegistrationRecord (data) {
return req.post('/verifyRegistrationRecord', data)
}
export function getVerifyRegistrationRecordList (data) {
return req.get('/getVerifyRegistrationRecordList', data)
}
export function registrationRecordList (data) {
return req.get('/registrationRecordList', data)

View File

@ -19,7 +19,9 @@ const config = {
'pages/article/index', // 文章页面
'pages/recommend/list', // 推荐软文列表 现在改为活动介绍
'pages/recommend/detail', // 活动介绍
'pages/recommend/apply', // 报名信息
'pages/recommend/status', // 活动状态
'pages/other/goods', // 特殊商品页面
'pages/member/item-fav', // 收藏页面
'pages/custom/custom-page', // 自定义页面
@ -77,6 +79,7 @@ const config = {
root: 'subpages/member',
pages: [
'index', // 会员中心
'qa-page', // 小程序自助服务Q&A
'point-detail', // 积分明细
'point-rule', // 积分规则
'member-level', // 会员等级

BIN
src/assets/hengjiantou.gif Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
src/assets/share.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 709 B

View File

@ -12,7 +12,7 @@ export default class SearchBar extends Component {
isOpened: false,
keyword: '',
showDailog: true,
localStorageKey: 'searchHistory'
localStorageKey: 'searchHistory',
}
constructor(props) {
@ -22,7 +22,12 @@ export default class SearchBar extends Component {
searchValue: '',
showSearchDailog: false,
historyList: [],
isShowAction: false
isShowAction: false,
qaList: [
{ content: '正常版和窄版的区别' },
{ content: '如何区分常规软木鞋床和软底软木鞋床' },
{ content: '人造革和牛皮革的区别' },
]
}
}
@ -123,9 +128,15 @@ export default class SearchBar extends Component {
})
}
handleClickQa = () => {
Taro.navigateTo({
url: '/subpages/member/qa-page?index=0'
})
}
render () {
const { isFixed, keyword, showDailog, placeholder, hotSearch } = this.props
const { showSearchDailog, historyList, isShowAction, searchValue } = this.state
const { showSearchDailog, historyList, isShowAction, searchValue, qaList } = this.state
return (
<View
className={classNames(
@ -236,6 +247,16 @@ export default class SearchBar extends Component {
{/* <View className='at-icon at-icon-chevron-right'></View> */}
</View>)}
</View>
<View className='search-input__history-title hot-title'>
<Text>常见问题</Text>
<Text className='hot-title__desc'></Text>
</View>
<View className='hot-list'>
{qaList.map((item, index) => <View className='hot-list__item' onClick={this.handleClickQa.bind(this)} key={index}>
<Text>{item.content}</Text>
{/* <View className='at-icon at-icon-chevron-right'></View> */}
</View>)}
</View>
</View>
)}
</View>

View File

@ -119,7 +119,8 @@
}
&__input-cnt {
border-radius: 5px !important;
border: 1px solid #000;
/* prettier-ignore */
border: 1PX solid #000;
box-sizing: border-box;
}
}

View File

@ -10,7 +10,8 @@ function SpCheckboxNew (props) {
checked = false,
label,
onChange = () => { },
disabled = false
disabled = false,
isRadio = false
} = props
const [isChecked, setChecked] = useState(checked)
@ -35,7 +36,7 @@ function SpCheckboxNew (props) {
)}
onClick={onChangeCheckbox}
>
{/* <Text
{isRadio ? <Text
className={classNames(
{
iconfont: true
@ -43,17 +44,18 @@ function SpCheckboxNew (props) {
disabled ? 'icon-circle1' : isChecked ? 'icon-roundcheckfill' : 'icon-round',
disabled && isChecked && 'icon-roundcheckfill'
)}
></Text> */}
<Text
className={classNames(
{
// iconfont: true,
"icon-my": true
},
disabled ? 'icon-checkbox-weixuan' : isChecked ? 'icon-checkbox-xuanzhong' : 'icon-checkbox-weixuan',
disabled && isChecked && 'icon-checkbox-xuanzhong'
)}
></Text>
: <Text
style={{ color: disabled ? '#ccc !important' : '#000' }}
className={classNames(
{
// iconfont: true,
"icon-my": true
},
disabled ? 'icon-checkbox-weixuan' : isChecked ? 'icon-checkbox-xuanzhong' : 'icon-checkbox-weixuan',
disabled && isChecked && 'icon-checkbox-xuanzhong'
)}
></Text>}
<View className='sp-checkbox-new__label'>{label || children}</View>
</View>
)

View File

@ -43,14 +43,25 @@ function SpCoupon (props) {
} = info
const { tag, invalidBg, bg } = COUPON_TYPE[cardType]
const couponTagBg = info.tagClass === 'used' || info.tagClass === 'overdue' || !info.valid ? invalidBg : bg
const couponTagFlag = info.tagClass === 'used' || info.tagClass === 'overdue' || !info.valid
const couponTagBg = couponTagFlag ? invalidBg : bg
// (couponStatus && couponStatus != 1) ||
const isInvalid = ((couponStatus && couponStatus != 1) || (info.tagClass === 'used' || info.tagClass === 'overdue') || isNotUse)
return (<View className="coupons-list-item" key={`coupon-item__${id}`} style={styleNames({
background: `url(${process.env.APP_IMAGE_CDN_NEW}/member/${((couponStatus && couponStatus != 1) || (info.tagClass === 'used' || info.tagClass === 'overdue') || isNotUse) ? "quan-hui" : "quan-lan"}.png) no-repeat`,
background: `url(${process.env.APP_IMAGE_CDN_NEW}/member/${isInvalid ? "quan-hui" : "quan-lan"}.png) no-repeat`,
'background-size': '100% 100%'
})}>
<View className="coupons-list-item-left">
<View className='coupons-list-item-money'><Text className='coupons-list-item-unit'>¥</Text><Text className="coupons-list-item-num">{reduceCost || 0}</Text></View>
<View className='coupons-list-item-money'>
{cardType === 'cash' &&
<><Text className='coupons-list-item-unit'>¥</Text><Text className="coupons-list-item-num">{reduceCost || 0}</Text></>
}
{cardType === 'discount' && <>
<Text className="coupons-list-item-num">{discount || 0}</Text>
<Text className='coupons-list-item-unit'></Text>
</>}
</View>
<View className="coupons-list-item-desc">{leastCost}可用</View>
</View>
<View className="coupons-list-item-right">
@ -63,7 +74,7 @@ function SpCoupon (props) {
{/* !valid || */}
{!isNotUse && <>
{info.tagClass === 'used' || info.tagClass === 'overdue' ? <View className="coupons-list-item-btn">{info.tagClass === 'used' ? '使用' : '过期'}</View>
: <View className="coupons-list-item-btn" onClick={onClick}>立即{isNew ? '兑换' : '使用'}</View>}
: isInvalid ? <View className="coupons-list-item-btn">{couponStatus == 0 ? '已领完' : '已领取'}</View> : <View className="coupons-list-item-btn" onClick={onClick}>{isNew ? '' : '使'}</View>}
</>}
</View>
</View>)

View File

@ -246,7 +246,8 @@
}
&-btn {
padding: 15px 20px;
border: 1px solid #fff;
/* prettier-ignore */
border: 1PX solid #fff;
border-radius: 6px;
display: flex;
justify-content: center;

View File

@ -38,7 +38,8 @@
border-radius: 5px;
justify-content: center;
align-items: center;
border: 1px solid#d0d0d0;
/* prettier-ignore */
border: 1PX solid#d0d0d0;
}
}
&__bd {

View File

@ -7,7 +7,7 @@ import { classNames } from '@/utils'
import './index.scss'
function SpGoodsPrice (props) {
const { info } = props
const { info, showMarketPrice = false } = props
const { priceSetting } = useSelector((state) => state.sys)
const { cart_page, item_page, order_page } = priceSetting
const {
@ -45,9 +45,9 @@ function SpGoodsPrice (props) {
{
!isPoint && <SpPrice size={36} className='sale-price' value={price} showSeparator noDecimal />
}
{/* {marketPrice > 0 && enMarketPrice && (
{marketPrice > 0 && enMarketPrice && showMarketPrice && (
<SpPrice className='mkt-price' lineThrough value={marketPrice} />
)} */}
)}
</View>
<View>
{info.memberPrice < info.price && enMemberPrice && (

View File

@ -1,6 +1,6 @@
.sp-goods-price {
.mkt-price {
margin-left: 8px;
margin-left: 18px;
}
.vip-price,
.svip-price {

View File

@ -138,7 +138,7 @@ class AtInputNumber extends AtComponent {
style={inputStyle}
type={type}
value={inputValue}
disabled={disabled}
disabled={true}
onInput={this.handleInput}
onBlur={this.handleBlur}
/>

View File

@ -177,7 +177,8 @@
line-height: 78rpx;
text-align: center;
border-radius: 8rpx;
border: 1px solid #000;
/* prettier-ignore */
border: 1PX solid #000;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;

View File

@ -3,6 +3,7 @@ import React, { useEffect, useState, useCallback, useRef, useImperativeHandle }
import { View, Text, Button, ScrollView } from '@tarojs/components'
import { AtButton, AtCurtain } from 'taro-ui'
import { useImmer } from 'use-immer'
import { useSelector } from 'react-redux'
import S from '@/spx'
import api from '@/api'
import { isWeixin, isAlipay, classNames, showToast, entryLaunch } from '@/utils'
@ -20,12 +21,13 @@ const initialState = {
agreeMentChecked: false
}
function SpLogin (props, ref) {
const { children, className, onChange, newUser = false } = props
const { children, className, onChange, newUser = false, url = '' } = props
const { isLogin, login, setToken, checkPolicyChange } = useLogin({
policyUpdateHook: (isUpdate) => {
// isUpdate && setPolicyModal(true)
}
})
const { appName } = useSelector((_state) => _state.sys)
const [isNewUser, setIsNewUser] = useState(false)
const [policyModal, setPolicyModal] = useState(false)
const [loginModal, setLoginModal] = useState(false)
@ -41,13 +43,11 @@ function SpLogin (props, ref) {
useEffect(() => {
if (loginModal) {
fetchPrivacyData()
Taro.login({
success: ({ code }) => {
codeRef.current = code
},
fail: (e) => {
console.error('[sp-login] taro login fail:', e)
}
})
}
@ -66,58 +66,69 @@ function SpLogin (props, ref) {
const handleBindPhone = async (e) => {
setLoginModal(false)
const { encryptedData, iv, cloudID } = e.detail
if (encryptedData && iv) {
const code = codeRef.current
let params = {
code,
encryptedData,
iv,
cloudID,
user_type: 'wechat',
auth_type: 'wxapp'
}
// 内购分享码
const { code: purchaseCode } = Taro.getStorageSync(SG_ROUTER_PARAMS)
if (purchaseCode) {
params = {
...params,
purchanse_share_code: purchaseCode
}
}
Taro.showLoading({ title: '' })
// const { uid } = entryLaunch.getLaunchParams()
const { uid, dtid } = Taro.getStorageSync(SG_ROUTER_PARAMS)
const { gu_user_id } = Taro.getStorageSync(SG_GUIDE_PARAMS)
if (uid) {
// 分销绑定
params['uid'] = uid
}
if (dtid) {
params['distributor_id'] = dtid
}
// gu_user_id: 欢迎语上带过来的员工编号, 同work_user_id
if (gu_user_id) {
params['channel'] = 1
params['work_userid'] = gu_user_id
}
try {
const { token, is_new } = await api.wx.newlogin(params)
if (token) {
setToken(token)
Taro.hideLoading()
setLoginModal(false)
showToast('恭喜您,注册成功')
onChange && onChange()
} else {
showToast('注册失败')
}
} catch (error) {
// const code = codeRef.current
const auth_type = isWeixin ? 'wxapp' : 'aliapp'
api.wx.login({ code: codeRef.current, showError: false, auth_type }).then(async ({ token }) => {
if (token) {
Taro.showLoading({ title: '' })
await setToken(token)
onChange && onChange()
Taro.hideLoading()
}
}
}).catch(async () => {
const { code } = await Taro.login()
const { encryptedData, iv, cloudID } = e.detail
if (encryptedData && iv) {
let params = {
code,
encryptedData,
iv,
cloudID,
user_type: 'wechat',
auth_type: 'wxapp'
}
// 内购分享码
const { code: purchaseCode } = Taro.getStorageSync(SG_ROUTER_PARAMS)
if (purchaseCode) {
params = {
...params,
purchanse_share_code: purchaseCode
}
}
Taro.showLoading({ title: '' })
// const { uid } = entryLaunch.getLaunchParams()
const { uid, dtid } = Taro.getStorageSync(SG_ROUTER_PARAMS)
const { gu_user_id } = Taro.getStorageSync(SG_GUIDE_PARAMS)
if (uid) {
// 分销绑定
params['uid'] = uid
}
if (dtid) {
params['distributor_id'] = dtid
}
// gu_user_id: 欢迎语上带过来的员工编号, 同work_user_id
if (gu_user_id) {
params['channel'] = 1
params['work_userid'] = gu_user_id
}
try {
const { token, is_new } = await api.wx.newlogin(params)
if (token) {
setToken(token)
Taro.hideLoading()
setLoginModal(false)
showToast('恭喜您,注册成功')
onChange && onChange()
} else {
showToast('注册失败')
}
} catch (error) {
Taro.hideLoading()
}
}
})
}
const handleCloseModal = useCallback(() => {
@ -155,6 +166,7 @@ function SpLogin (props, ref) {
if (isLogin) {
onChange && onChange()
} else {
await fetchPrivacyData()
setLoginModal(true)
}
}
@ -242,7 +254,7 @@ function SpLogin (props, ref) {
</View>
<ScrollView scrollY
scrollWithAnimation className="curtain_content_text" showScrollbar={false} enhanced>
亲爱的用户,感谢您使用Birkenstock微信小程序!为了加强对您个人信息的保护,我们根据最新法律的要求制定/更新了
亲爱的用户,感谢您使用{appName}微信小程序!为了加强对您个人信息的保护,我们根据最新法律的要求制定/更新了
<View className="agreement-list">
<Text className='agreement-name' onClick={handleClickPrivacy.bind(this, 'member_register')}>{registerName}</Text>
<Text className='agreement-name' onClick={handleClickPrivacy.bind(this, 'privacy')}>{privacyName}</Text>
@ -252,24 +264,27 @@ function SpLogin (props, ref) {
通过隐私政策,我们向您主要说明:
</View>
<View className="">
1.您在使用Birkenstock微信小程序时,可以选择浏览模式,也可以选择注册/登录成为Birkenstock微信小程序用户
1.您在使用{appName}微信小程序时,可以选择浏览模式,也可以选择注册/登录成为{appName}微信小程序用户
</View>
<View className="">
2为了向你提供Birkenstock微信小程序的其本服条,我们将基于合法以及正当必要的原则,按照本政策的规定向您提供各项服务
2为了向你提供{appName}微信小程序的其本服条,我们将基于合法以及正当必要的原则,按照本政策的规定向您提供各项服务
</View>
</ScrollView>
<View className='btn-wrap'>
{isNewUser && <AtButton className='btn' type='primary' openType="getPhoneNumber" onGetPhoneNumber={handleBindPhone
<AtButton className='btn' type='primary' openType="getPhoneNumber" onGetPhoneNumber={handleBindPhone
}> 同意并继续
</AtButton>
{/* {isNewUser && <AtButton className='btn' type='primary' openType="getPhoneNumber" onGetPhoneNumber={handleBindPhone
}>
同意并继续
</AtButton>}
{!isNewUser && <AtButton className='btn' type='primary' onClick={handleUserLogin}>
同意并继续
</AtButton>}
</AtButton>} */}
</View>
<View className="no-btn" onClick={() => setLoginModal(false)}>不同意</View>
<View className="no-text">
*如果您不同意Birkenstock隐私政策您可继续浏览小程序但您无法使用购物结算功能
*如果您不同意{appName}隐私政策您可继续浏览小程序但您无法使用购物结算功能
</View>
</View>}
</AtCurtain>

View File

@ -31,7 +31,7 @@
}
&__title {
// font-size: floor(0.95 * $font-size);
@include multi-ellipsis(1);
// @include multi-ellipsis(1);
margin-bottom: 26px;
color: #000;
font-size: 20px;

View File

@ -48,11 +48,13 @@ function SpPage (props, ref) {
isTop = false,
isBlack = false,
title = '', // 页面导航标题
showNavLogo = true,
showNavLogo = false,
showNavkfIcon = false,
showNavHomeIcon = false,
showNavSearchIcon = false,
showLogoLoading = false,
alwaysBackUrl = '',
showNavBackIcon = true
} = props
let { renderTitle } = props
const wrapRef = useRef(null)
@ -132,7 +134,8 @@ function SpPage (props, ref) {
draft.pageTitle = pageTitle
draft.isTabBarPage = isTabBarPage
draft.showLeftContainer = !['/subpages/guide/index', '/pages/index'].includes(`/${page?.route}`)
draft.showCustomNavigation = ['/pages/cart/espier-index', '/pages/index', '/subpages/member/index', '/pages/category/index', '/pages/recommend/list', '/pages/recommend/list'].includes(`/${page?.route}`)
// '/subpages/member/index',
draft.showCustomNavigation = ['/pages/cart/espier-index', '/pages/index', '/pages/category/index', '/pages/recommend/list'].includes(`/${page?.route}`)
// draft.showCustomNavigation = true
draft.showNavCartIcon = ['/subpages/marketing/coupon-center', '/subpages/marketing/coupon', '/pages/item/list'].includes(`/${page?.route}`)
})
@ -196,7 +199,7 @@ function SpPage (props, ref) {
let model = ''
let ipx = false
let gNavbarH = 0, gStatusBarHeight = 0
let gNavbarH = 0, gStatusBarHeight = 0, gAreaH = 0
// let customNavigation = false
// let cusCurrentPage = 0
@ -207,7 +210,8 @@ function SpPage (props, ref) {
ipx = model.search(/iPhone\s*X|iPhone\s*11|iPhone\s*12|iPhone\s*13|iPhone\s*14|iPhone\s*15|iPhone\s*16|iPhone\s*10/g) > -1
const menuButton = Taro.getMenuButtonBoundingClientRect()
const { statusBarHeight } = Taro.getSystemInfoSync()
const { statusBarHeight, safeArea, screenHeight } = deviceInfo
gAreaH = (screenHeight - safeArea.bottom)
gNavbarH = Math.floor(statusBarHeight + menuButton.height + (menuButton.top - statusBarHeight) * 2)
gStatusBarHeight = statusBarHeight
}
@ -255,7 +259,7 @@ function SpPage (props, ref) {
}
}
renderTitle = showCustomNavigation && showNavLogo ? <SpImage src={`member/logo-${isBlack ? "black" : "light"}.png`} height={34} mode='heightFix' isNew /> : undefined
renderTitle = showCustomNavigation || showNavLogo ? <SpImage src={`member/logo-${isBlack ? "black" : "light"}.png`} height={34} mode='heightFix' isNew /> : undefined
const navigationBarTitleText = props.navigationBarTitleText || getCurrentInstance().page?.config?.navigationBarTitleText
return (
<View
@ -295,12 +299,19 @@ function SpPage (props, ref) {
{/* <Image className="chazhao" src={require("@/assets/chazhao-light.png")}></Image> */}
{showCustomNavigation ? <SpImage onClick={() => Taro.navigateTo({ url: '/pages/item/list?showSearch=true' })} src={`member/chazhao-${isBlack ? "black" : "light"}.png`} height={34} mode='heightFix' isNew />
: <View className='icon-wrap'>
<Text
{showNavBackIcon && <Text
className={classNames('iconfont', {
// 'icon-home1': cusCurrentPage == 1,
'icon-fanhui': cusCurrentPage != 1
'icon-fanhui': alwaysBackUrl ? true : cusCurrentPage != 1
})}
// style={{ color: isBlack ? 'white' : 'black' }}
onClick={() => {
if (alwaysBackUrl) {
Taro.navigateTo({
url: alwaysBackUrl,
})
return
}
if (cusCurrentPage == 1) {
Taro.redirectTo({
url: isGoodsShelves() ? '/subpages/guide/index' : '/pages/index'
@ -309,10 +320,10 @@ function SpPage (props, ref) {
Taro.navigateBack()
}
}}
/>
/>}
{showNavCartIcon ? cartCount > 0 ? <AtBadge value={cartCount} maxValue={99}><SpImage src={`member/cart.png`} onClick={() => Taro.redirectTo({ url: '/pages/cart/espier-index' })} height={36} mode='heightFix' isNew /></AtBadge> : <SpImage src={`member/cart.png`} onClick={() => Taro.redirectTo({ url: '/pages/cart/espier-index' })} height={36} mode='heightFix' isNew /> : null}
{showNavHomeIcon && <SpImage src={`cart/home.png`} onClick={() => Taro.redirectTo({ url: '/pages/index' })} height={36} mode='heightFix' isNew />}
{showNavSearchIcon && <SpImage onClick={() => Taro.navigateTo({ url: '/pages/item/list' })} src={`member/chazhao-${isBlack ? "black" : "light"}.png`} height={34} mode='heightFix' isNew />}
{showNavSearchIcon && <SpImage onClick={() => Taro.navigateTo({ url: '/pages/item/list?showSearch=true' })} src={`member/chazhao-${isBlack ? "black" : "light"}.png`} height={34} mode='heightFix' isNew />}
</View>
}
{showNavkfIcon && <SpChat><SpImage className='icon-kf' src={`index/kf.png`} onClick={() => Taro.redirectTo({ url: '/pages/cart/espier-index' })} height={46} mode='heightFix' isNew /></SpChat>}
@ -357,6 +368,7 @@ function SpPage (props, ref) {
...pageTheme, ...lockStyle, ...pageBackground, 'padding-top': isTop ? currentPath === 'pages/index' ? 0 : `${customNavigation ? gStatusBarHeight : 0}px` : `${customNavigation ? gNavbarH : 0}px`,
"--nav-height": `${gNavbarH}px`,
"--status-bar-height": `${gStatusBarHeight}px`,
"--area-bottom-height": `${gAreaH}rpx`,
})}
ref={wrapRef}
>

View File

@ -65,7 +65,7 @@ function SpSkuSelect (props, ref) {
specItems.forEach((item) => {
const key = item.specItem.map((spec) => spec.specId).join('_')
skuDictRef.current[key] = item
console.log("🚀 ~ item库存为:", key, item.specItem.map((item) => item.specName).join('_'), item.store)
// console.log("🚀 ~ item库存为:", key, item.specItem.map((item) => item.specName).join('_'), item.store)
})
let selItem = null
if (skuList.length === 3) {

View File

@ -133,7 +133,8 @@
// }
.at-input-number {
border: 1px solid #999;
/* prettier-ignore */
border: 1PX solid #999;
border-radius: 0;
height: 40px;
&__input {

View File

@ -4,7 +4,7 @@ export const STATUS_TYPES_MAP = {
WAIT_BUYER_CONFIRM: 'WAIT_BUYER_CONFIRM_GOODS',
DONE: 'TRADE_SUCCESS',
CANCEL: 'TRADE_CLOSED',
PART_PAYMENT:'WAIT_BUYER_PAY'
PART_PAYMENT: 'WAIT_BUYER_PAY'
}
export const AFTER_SALE_STATUS = {
@ -84,8 +84,9 @@ export const ACTIVITY_STATUS = {
export const DEFAULT_POINT_NAME = '积分'
export const DEFAULT_THEME = {
colorPrimary: '#d42f29',
colorMarketing: '#fba629',
colorPrimary: '#000',
// colorMarketing: '#fba629',
colorMarketing: '#000',
colorAccent: '#2e3030'
}

View File

@ -70,7 +70,7 @@ export const COUPON = {
getNum: 'get_num',
couponStatus: ({ quantity, get_limit, user_get_num, get_num }) => {
if (quantity - get_num <= 0) {
return 0 // 已领完
return '0' // 已领完
} else if (get_limit - user_get_num > 0) {
return 1 // 立即领取
} else if (get_limit - user_get_num <= 0) {

View File

@ -93,7 +93,7 @@ export const TRADE_AFTER_SALES_ITEM = {
return pickBy(_detail, {
id: 'id',
pic: 'pic',
itemName: 'item_name',
itemName: ({ item_name, item_name_2 }) => item_name_2 || item_name,
price: ({ total_fee }) => total_fee / 100,
num: 'num',
// 可售后商品数
@ -128,7 +128,7 @@ export const TRADE_AFTER_SALES_ITEM = {
afterSalesMobile: ({ aftersales_address }) => aftersales_address.aftersales_mobile,
afterSalesAddress: ({ aftersales_address }) => aftersales_address.aftersales_address,
afterSalesContact: ({ aftersales_address }) => aftersales_address.aftersales_contact,
afterSalesZip: ({ aftersales_address }) => aftersales_address.post_code,
afterSalesZip: ({ aftersales_address }) => aftersales_address.aftersales_post_code,
aftersalesHours: ({ aftersales_address }) => aftersales_address.aftersales_hours,
refundFee: ({ refund_fee }) => refund_fee / 100,
sendbackData: 'sendback_data',

View File

@ -41,23 +41,23 @@ export default (props = {}) => {
// 隐私协议
// const checkResult = await checkPolicyChange()
// if (checkResult) {
Taro.showLoading({ title: '' })
// Taro.showLoading({ title: '' })
let code
try {
const { code: _code } = await getCode()
code = _code
} catch (error) {
Taro.hideLoading()
// Taro.hideLoading()
}
try {
if (!code) {
Taro.hideLoading()
// Taro.hideLoading()
setIsNewUser(true)
return
}
const { token } = await getToken(code)
Taro.hideLoading()
// Taro.hideLoading()
setToken(token)
} catch (e) {
Taro.hideLoading()
@ -91,7 +91,6 @@ export default (props = {}) => {
const setToken = async (token) => {
const { redirect_url } = $instance.router.params
console.log('redirect_url', redirect_url)
S.setAuthToken(token)
setIsLogin(true)
await getUserInfo()
@ -177,15 +176,15 @@ export default (props = {}) => {
*/
const getUserInfoAuth = (validate = true) => {
return new Promise((resolve, reject) => {
console.log('getUserInfoAuth:获取用户信息授权(小程序)')
const token = S.getAuthToken()
console.log('getUserInfoAuth:获取用户信息授权(小程序)', token, userInfo)
if (!token && validate) {
showToast('请先登录')
return
// reject()
}
if (isWeixin) {
const { avatar, username } = userInfo
const { avatar, username } = userInfo || {}
if (avatar && username) {
resolve()
} else {

View File

@ -114,6 +114,7 @@ export default (props = {}) => {
paySuccess(params, orderInfo)
}
} catch (e) {
Taro.hideLoading()
console.error(e)
payError(orderInfo)
}

View File

@ -45,7 +45,7 @@ export default class TradeRate extends Component {
item_id: 'item_id',
item_spec_desc: 'item_spec_desc',
pic_path: 'pic',
title: 'item_name',
title: ({ item_name, item_name_2 }) => item_name_2 || item_name,
price: ({ item_fee }) => (+item_fee / 100).toFixed(2),
num: 'num',
star: 0,

View File

@ -1,19 +1,23 @@
@import "@/style/imports";
@import '@/style/imports';
.destory-member {
position: relative;
height: 100vh;
.sp-page-body {
padding: 0 20rpx;
box-sizing: border-box;
}
.title {
text-align: center;
font-size: 32px;
padding: 50px 0px;
}
.content {
margin: 0px 20px;
// margin: 0px 20px;
background: #fff;
padding: 30px 45px;
border-radius: 16px;
box-shadow: 0px 2px 10px 0px #EAE7E0;
box-shadow: 0px 2px 10px 0px #eae7e0;
}
.margin {
margin-bottom: 35px;
@ -36,9 +40,9 @@
}
.button {
width: 80%;
background: #F4811F;
background: #f4811f;
border-radius: 60px;
color: #FFFFFF;
color: #ffffff;
text-align: center;
margin: 100px auto 50px auto;
padding: 15px 0px;

View File

@ -53,7 +53,7 @@ export default class MemberCode extends Component {
return (
<SpPage>
<View className='member-code-wrap' style={
styleNames({
styleNames({ //member-bg
background: `url(${process.env.APP_IMAGE_CDN_NEW}/member/member-bg.png) no-repeat`,
"backgroundSize": "100% 100%"
})
@ -67,7 +67,7 @@ export default class MemberCode extends Component {
<View className='grade_name'>{gradeInfo.grade_name}</View>
<View className='member-code-box'>
{/* <Image className='member-code-bar' mode='aspectFill' src={info.barcode_url} /> */}
<SpImage className='member-code-box-logo' width={214} mode='aspectFill' src="member/logo-lan.png" isNew />
<SpImage className='member-code-box-logo' height={40} mode='aspectFit' src="member/logo-black.png" isNew />
<Image className='member-code-box-qr' mode='aspectFit' src={info.qrcode_url} />
{/* <View>{info.userCardCode}</View> */}
<View className='member-code-box-txt'>向门店出示二维码</View>

View File

@ -88,7 +88,7 @@ function CompGoodsItem (props) {
<View className='goods-title' onClick={onChangeGoodsIsCheck}>
{/* {info.activity_type == 'package' && <Text className='goods-title__tag'>组合商品</Text>} */}
{info.is_plus_buy && <Text className='goods-title__tag'>加价购</Text>}
{info.item_name}
{info.item_name_2 || info.item_name}
</View>
{isShowDeleteIcon && (
// <Text className='iconfont icon-shanchu-01' onClick={() => onDelete(info)}></Text>

View File

@ -112,7 +112,8 @@
}
.goods-title {
@include multi-ellipsis(2);
width: 300px;
// width: 300px;
width: 360px;
&__tag {
/* prettier-ignore */
border: 1PX solid var(--color-primary);

View File

@ -369,7 +369,7 @@ function CartCheckout (props) {
url: `/subpage/pages/trade/invoice-info?id=${totalInfo.tid || ''}`,
events: {
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
acceptDataFromOpenedPage: function ({ data = {} }) {
acceptDataFromOpenedPage: ({ data = {} }) => {
const { invoiceTitle } = data
setState((draft) => {
draft.invoiceTitle = invoiceTitle
@ -377,9 +377,9 @@ function CartCheckout (props) {
})
},
},
success: function (res) {
success: (res) => {
// 通过eventChannel向被打开页面传送数据
res.eventChannel.emit('acceptDataFromOpenerPage', { data: totalInfo })
res.eventChannel.emit('acceptDataFromOpenerPage', { data: { ...totalInfo, invoiceTitle: state.invoiceTitle, paramsInfo: state.paramsInfo } })
}
})
return
@ -1096,7 +1096,7 @@ function CartCheckout (props) {
/>
)}
{!bargain_id && (
{process.env.NODE_ENV === "development" && !bargain_id && (
<View style={{ marginBottom: '40rpx' }}>
<SpCell
isLink

View File

@ -81,16 +81,16 @@ function CartIndex () {
const getCartList = async () => {
// Taro.showLoading({ title: '', })
setState((draft) => {
draft.loading = true
})
// setState((draft) => {
// draft.loading = true
// })
const { type = 'distributor' } = router?.params || {}
const params = {
shop_type: type
}
await dispatch(fetchCartList(params))
await dispatch(updateCount(params))
Taro.hideLoading()
setState((draft) => {
draft.loading = false
})
@ -188,10 +188,10 @@ function CartIndex () {
// }
const onChangeGoodsIsCheck = async (item, type, checked) => {
// Taro.showLoading({ title: '' })
setState((draft) => {
draft.loading = true
})
Taro.showLoading({ title: '', mask: true })
// setState((draft) => {
// draft.loading = true
// })
let parmas = { is_checked: checked }
if (type === 'all') {
const cartIds = item.list.map((item) => item.cart_id)
@ -224,9 +224,10 @@ function CartIndex () {
const onChangeCartGoodsItem = useDebounce(async (item, num) => {
console.log(`onChangeCartGoodsItem:`, num)
setState((draft) => {
draft.loading = true
})
// setState((draft) => {
// draft.loading = true
// })
Taro.showLoading({ title: '', mask: true })
let { shop_id, cart_id } = item
const { type = 'distributor' } = router.params
await dispatch(updateCartItemNum({ shop_id, cart_id, num, type }))
@ -293,7 +294,7 @@ function CartIndex () {
</SpLogin>
</View>
)} */}
{isLogin && (
{!loading && isLogin && groupsList?.length > 0 && (
<View>
{/* <SpTabs current={current} tablist={tablist} onChange={onChangeSpTab} /> */}
<View className='valid-cart-block'>
@ -471,14 +472,16 @@ function CartIndex () {
)}
{/* && invalidCart.length == 0 */}
{validCart.length == 0 && (
{!loading && validCart.length == 0 && (
<View className='empty-box'>
{/* <SpDefault type='cart' message=''>
<AtButton type='primary' circle onClick={navigateTo.bind(this, '/pages/index', true)}>
去选购
</AtButton>
</SpDefault> */}
<SpImage className='default-img' src='cart/logo-hui.png' width={160} isNew />
<View className='default-img' style={{ height: '80px', width: '100%', display: 'flex', justifyContent: 'center' }} >
<SpImage src='cart/logo-hui.png' width={160} isNew />
</View>
<View className="empty-box-tit">购物车还是空的</View>
<View className="empty-box-sub-tit">快去挑选自己喜欢的宝贝吧~</View>
<SpLogin onChange={() => { }}>
@ -532,9 +535,9 @@ function CartIndex () {
</sView>}
{/* 猜你喜欢 */}
<SpRecommend className='recommend-block' info={recommendList} />
{/* <SpRecommend className='recommend-block' info={recommendList} /> */}
<SpPrivacyModal open={policyModal} onCancel={onPolicyChange} onConfirm={onPolicyChange} />
{/* <SpPrivacyModal open={policyModal} onCancel={onPolicyChange} onConfirm={onPolicyChange} /> */}
</SpPage>
)
}

View File

@ -299,7 +299,7 @@
flex-direction: column;
justify-content: center;
align-items: center;
.sp-image {
.default-img {
margin-bottom: 50px;
}
.at-button {

View File

@ -160,8 +160,8 @@ const CompSeries = (props) => {
</View>
<SpImage
className={classNames(imgType ? 'cat-img' : 'cat-img-no')}
mode={currentID === '18' ? 'aspectFill' : 'aspectFit'}
height={currentID === '18' ? 350 : windowWidth > 400 ? 278 : 242}
mode={currentID === '18' ? 'aspectFill' : 'widthFix'}
height={currentID === '18' ? 350 : windowWidth > 375 ? 278 : 242}
src={item.img}
/>
</View> : <View

View File

@ -60,6 +60,14 @@ page {
/* #endif */
}
.content-box {
--height: calc(var(--status-bar-height) + #{$tabbar-height} + var(--area-bottom-height));
.fadeIn {
animation: fadeInAnimation 0.25s ease-in;
}
&.content-box-ovh {
overflow: hidden;
height: calc(100vh - var(--height));
}
.swiper-wapper {
position: relative;
&::-webkit-scrollbar {
@ -69,10 +77,12 @@ page {
}
.swiper {
width: 100%;
height: calc(100vh - #{$page-ipx-footer-height} - var(--status-bar-height));
// height: calc(100vh - #{$tabbar-height});
transition: height 0.3s ease-in-out;
animation: fadeInAnimation 0.35s ease-in;
// height: calc(100vh - #{$page-ipx-footer-height} - var(--status-bar-height));
height: calc(100vh - var(--height));
transition: height 0.2s linear;
animation: fadeInAnimation 0.25s ease-in;
transform: translateZ(0);
overflow: hidden;
// &.swiper-narrow {
// height: calc(100vh - 620px - #{$tabbar-height} - var(--status-bar-height));
// }
@ -82,9 +92,10 @@ page {
position: absolute;
left: 50%;
transform: translate(-50%, 0%);
transform: translateZ(-1);
bottom: 0px;
z-index: 99;
animation: fadeInAnimation 0.35s ease-in;
z-index: 999;
animation: fadeInAnimation 0.3s ease-in;
display: flex;
flex-direction: column;
justify-content: center;
@ -103,10 +114,10 @@ page {
margin-bottom: 6px;
}
.swiper-narrow {
// height: calc(100vh - 620px - #{$tabbar-height} - var(--status-bar-height));
height: calc(100vh - 420px - #{$tabbar-height} - var(--status-bar-height));
transition: height 0.35s linear;
margin-top: -200px;
height: calc(100vh - 386px - var(--height));
// transform: translateY(-520px);
// transition: all 0.25s ease-in;
}
.item-btns {
display: flex;
@ -144,7 +155,7 @@ page {
}
}
.spot-pagination {
animation: fadeInAnimation 0.35s ease-in;
animation: fadeInAnimation 0.3s ease-in;
position: absolute;
left: 50%;
transform: translateX(-50%);
@ -156,14 +167,15 @@ page {
.spot-pagination-bullet {
// margin-right: 5px;
// border-radius: 20%;
height: 4px;
height: 6px;
width: 30px;
background: #ddd;
background: #d9d9d9;
transition: all 0.3s ease-in-out 0s;
}
//
.spot-pagination-bullet-active {
background: #fff;
// background: #fff;
background: #818181;
}
}
.icon-kf {
@ -180,6 +192,68 @@ page {
height: 100%;
}
}
.item-btns {
display: flex;
flex-direction: column;
align-items: flex-start;
position: absolute;
left: 66px;
bottom: 170px;
z-index: 10;
// justify-content: flex-start;
.item-tit {
font-size: 42px;
font-weight: bold;
margin-bottom: 36px;
color: #fff;
}
.item-btn {
// width: 180px;
// height: 56px;
padding: 20rpx 90rpx 20rpx 50rpx;
color: #fff;
font-size: 28px;
border-radius: 10px;
background-color: #00000085;
border-width: 2px;
border-style: solid;
border-color: #fff;
display: flex;
justify-content: center;
align-items: center;
font-size: 22px;
line-height: 1;
transition: all 0.3s ease-in-out;
position: relative;
.icon-my {
font-size: 28px;
font-weight: bold;
margin-left: 16px;
}
.jiantou {
height: 50rpx;
width: 100rpx;
}
}
}
.mutedBtn {
animation: fadeInAnimation 0.3s ease-in;
// background-color: #fff;
width: 100px;
height: 100px;
border-radius: 50%;
position: absolute;
right: 30px;
bottom: 30px;
z-index: 100;
display: flex;
justify-content: center;
align-items: center;
.muted-icon {
width: 60rpx;
height: 60rpx;
}
}
}
.shop-box {
height: 520px;
@ -269,6 +343,7 @@ page {
flex-direction: column;
position: absolute;
bottom: 10%;
opacity: 0;
&-title {
font-size: 40px;
color: #fff;

View File

@ -19,7 +19,8 @@ import {
SpNavBar,
SpImage,
SpGoodsItem,
SpChat
SpChat,
SpLogin
} from '@/components'
import api from '@/api'
import {
@ -103,7 +104,9 @@ const initialState = {
},
],
goodList: [],
recommend: []
recommend: [],
activeInfo: {},
muted: true,
}
function Home () {
@ -111,6 +114,7 @@ function Home () {
const [startY, setStartY] = useState(0)
const [startX, setStartX] = useState(0)
const [likeList, setLikeList] = useImmer([])
const { isLogin, isNewUser } = useLogin()
const { initState, openRecommend, openLocation, openStore, appName, openScanQrcode } = useSelector(
(state) => state.sys
@ -138,17 +142,17 @@ function Home () {
}
}, [initState])
useEffect(() => {
if (shopInfo && VERSION_STANDARD) {
fetchWgts()
}
}, [shopInfo])
// useEffect(() => {
// if (shopInfo && VERSION_STANDARD) {
// fetchWgts()
// }
// }, [shopInfo])
useEffect(() => {
if (location && VERSION_STANDARD) {
fetchWgts()
}
}, [location])
// useEffect(() => {
// if (location && VERSION_STANDARD) {
// fetchWgts()
// }
// }, [location])
useShareAppMessage(async (res) => {
const { title, imageUrl } = await api.wx.shareSetting({ shareindex: 'index' })
@ -187,7 +191,7 @@ function Home () {
fetchLocation()
// 非云店
if (!VERSION_STANDARD) {
fetchWgts()
// fetchWgts()
} else {
fetchStoreInfo(location)
}
@ -204,9 +208,49 @@ function Home () {
// goodsSort: 6,
distributor_id: 0
}
const { list: jdList } = await api.item.search({ ...req, tag_id: 1 })
const { list: newList } = await api.item.search({ ...req, tag_id: 2 })
const { list: hotList } = await api.item.search({ ...req, tag_id: 3 })
// const { list: jdList } = await api.item.search({ ...req, tag_id: 1 })
const { list: newList = [] } = await api.item.search({ ...req, tag_id: 4 })
const { list: hotList = [] } = await api.item.search({ ...req, tag_id: 3 })
const { list: BOSTON_List = [] } = await api.item.search({ ...req, tag_id: 5 })
const { list: ARIZONA_List = [] } = await api.item.search({ ...req, tag_id: 6 })
const { list: LONDON_List = [] } = await api.item.search({ ...req, tag_id: 7 })
const newSort = {
"BK023": 1,
"BK066": 2,
"BK053": 3,
"BK038": 4,
"BK064": 5,
"BK014": 6
}
const hotSort = {
"BK014": 1,
"BK031": 2,
"BK018": 3,
"BK020": 4,
"BK052": 5,
"BK064": 6,
}
const BOSTON_sort = {
"BK020": 1,
"BK023": 2,
"BK025": 3,
"BK029": 4,
"BK030": 5,
"BK031": 6,
}
const ARIZONA_sort = {
"BK001": 1,
"BK017": 2,
"BK007": 3,
"BK010": 4,
"BK011": 5,
"BK014": 6,
}
const LONDON_sort = {
"BK052": 1,
"BK053": 2,
"BK051": 3,
}
setState((draft) => {
draft.recommend = [{
type: 'new',
@ -214,35 +258,100 @@ function Home () {
btnTxt: '查看更多',
postions: 'left',
url: '',
img: 'index/rec/new.png',
list: newList.map(item => ({ ...item, price: (item.price / 100) }))
tag_id: 4,
img: 'index/rec/new.png?v=1',
list: newList.map(item => ({ ...item, price: (item.price / 100) })).sort((a, b) => {
return newSort[a.item_name_3] - newSort[b.item_name_3]
})
}, {
type: 'hot',
text: "热销单品",
btnTxt: '查看更多',
postions: 'left',
url: '',
img: 'index/rec/hot.png',
list: hotList.map(item => ({ ...item, price: (item.price / 100) }))
tag_id: 3,
img: 'index/rec/hot.png?v=1',
list: hotList.map(item => ({ ...item, price: (item.price / 100) })).sort((a, b) => {
return hotSort[a.item_name_3] - hotSort[b.item_name_3]
})
}, {
type: 'jd',
text: "ARIZONA",
btnTxt: '经典双扣',
postions: 'right',
type: 'BOSTON',
text: "BOSTON",
btnTxt: 'BOSTON',
postions: 'left',
url: '',
img: 'index/rec/jd.png',
list: jdList.map(item => ({ ...item, price: (item.price / 100) }))
tag_id: 5,
img: 'index/rec/Boston.png',
list: BOSTON_List.map(item => ({ ...item, price: (item.price / 100) })).sort((a, b) => {
return BOSTON_sort[a.item_name_3] - BOSTON_sort[b.item_name_3]
})
}, {
type: 'ARIZONA',
text: "ARIZONA",
btnTxt: 'ARIZONA',
url: '',
postions: 'left',
tag_id: 6,
img: 'index/rec/Arizona.png',
list: ARIZONA_List.map(item => ({ ...item, price: (item.price / 100) })).sort((a, b) => {
return ARIZONA_sort[a.item_name_3] - ARIZONA_sort[b.item_name_3]
})
}, {
type: 'LONDON',
text: "LONDON",
btnTxt: 'LONDON',
url: '',
postions: 'left',
tag_id: 7,
img: 'index/rec/London.png',
list: LONDON_List.map(item => ({ ...item, price: (item.price / 100) })).sort((a, b) => {
return LONDON_sort[a.item_name_3] - LONDON_sort[b.item_name_3]
})
}
]
// bak
// draft.recommend = [{
// type: 'new',
// text: "新品推荐",
// btnTxt: '查看更多',
// postions: 'left',
// url: '',
// img: 'index/rec/new.png',
// list: newList.map(item => ({ ...item, price: (item.price / 100) }))
// }, {
// type: 'hot',
// text: "热销单品",
// btnTxt: '查看更多',
// postions: 'left',
// url: '',
// img: 'index/rec/hot.png',
// list: hotList.map(item => ({ ...item, price: (item.price / 100) }))
// }, {
// type: 'jd',
// text: "ARIZONA",
// btnTxt: '经典双扣',
// postions: 'right',
// url: '',
// img: 'index/rec/jd.png',
// list: jdList.map(item => ({ ...item, price: (item.price / 100) }))
// }
// ]
})
}
const getSwiperList = async () => {
const { status, activity_info = {}, total_count } = await api.user.registrationActivity({ activity_id: 2 })
const activeSwiper = activity_info.pics.map(item => ({
type: 'image',
src: item,
goods: []
}))
const res = await api.shop.homeSwiperList({ page: 1, pageSize: 999 })
const list = res?.list?.map((item) => {
const list = (res?.list?.map((item) => {
return {
type: item.type || 'image',
src: item.pic,
sort: item.sort,
goods: (item.goods_info_detail || []).map((ite) => {
return {
itemName: ite.item_name,
@ -256,10 +365,24 @@ function Home () {
}
})
}
}) || []
}) || []).sort((a, b) => a.sort - b.sort)
const _swiperList = [...activeSwiper, {
type: 'image',
src: process.env.APP_IMAGE_CDN_NEW + '/1774/kv.jpg?t' + new Date().getTime(),
goods: [],
onClick: () => {
// Taro.navigateTo({ url: '/pages/other/goods' })
}
}, ...list]
setState((draft) => {
draft.swiperList = list
draft.goodList = list[0].goods || []
draft.swiperList = _swiperList
draft.goodList = _swiperList[0].goods || []
draft.loading = false
draft.activeInfo = {
...activity_info,
total_count,
status
}
})
}
@ -337,7 +460,6 @@ function Home () {
// params.distributor_id = undefined
}
const res = await api.shop.getShop(params)
console.log('fetchStoreInfo:', res)
dispatch(updateShopInfo(res))
}
@ -352,7 +474,6 @@ function Home () {
const deltaY = clientY - startY
const deltaX = clientX - startX
if (Math.abs(deltaY) < 50) return
if (deltaY > 0) {
// 下滑操作
setState((draft) => {
@ -367,6 +488,7 @@ function Home () {
}, 500)
}
} else if (deltaY < 0) {
if (goodList?.length == 0) return
// 上滑操作
setState((draft) => {
draft.showBottom = true
@ -376,16 +498,50 @@ function Home () {
setState((draft) => {
draft.showRecommend = true
})
}, 500)
}, 1000)
if (!state.showBottom) {
}
}
}
const [recommendTouch, setRecommendTouch] = useImmer({
recommendStartY: 0,
recommendStartX: 0,
recommendEndY: 0,
recommendEndX: 0,
})
const onRecommendTouch = (e) => {
const { clientY, clientX } = e.touches[0]
setRecommendTouch(v => v.recommendStartX = clientX)
setRecommendTouch(v => v.recommendStartY = clientY)
}
const onRecommendTouchEnd = (e) => {
const { clientY, clientX } = e.changedTouches[0]
const { recommendStartY, recommendStartX } = recommendTouch
const deltaY = clientY - recommendStartY
const deltaX = clientX - recommendStartX
if (Math.abs(deltaY) < 50) return
if (deltaY > 0) {
// 下滑操作
console.log("🚀 ~ file: index.js:456 ~ 下滑操作:", '下滑操作')
} else if (deltaY < 0) {
// 上滑操作
console.log("🚀 ~ file: index.js:460 ~ 上滑操作:", '上滑操作')
}
}
const onSwiperChange = (e) => {
const { current } = e.detail
const _goodList = swiperList[current].goods || []
if (current === 0 || _goodList.length === 0) {
setState((draft) => {
draft.showBottom = false
draft.isUpOperation = false
})
}
setState((draft) => {
draft.currentIndex = current
draft.goodList = swiperList[current].goods || []
draft.goodList = _goodList
})
}
@ -396,7 +552,31 @@ function Home () {
})
}
const { activeInfo = {}, currentIndex } = state
const handleApply = () => {
// if (!isLogin) return
let url = '/pages/recommend/detail?id='
if (activeInfo.total_count) {
url = `/pages/recommend/status?id=`
}
Taro.navigateTo({
url: url + activeInfo.activity_id
})
}
const handleGoRecommendGoods = (item) => {
const url = `/pages/item/list?tag_id=${item.tag_id || ''}`
Taro.navigateTo({
url: url
})
}
const indexUrl = 'https://mp.weixin.qq.com/s/LBXthKa-P9gNK8FCv3n1pA'
const handleGoWx = () => {
return handleApply()
Taro.navigateTo({ url: '/pages/webview?url=' + encodeURIComponent(indexUrl) })
}
return (
<SpPage
className='page-index'
@ -409,7 +589,7 @@ function Home () {
isTop={!isUpOperation}
isBlack
>
<View
{false && <View
className={classNames('home-body', {
'has-home-header': isShowHomeHeader && isWeixin
})}
@ -421,18 +601,20 @@ function Home () {
<SpRecommend className='recommend-block' info={likeList} />
</HomeWgts>
}
</View>
</View>}
{/* 小程序搜藏提示 */}
{isWeixin && <MCompAddTip />}
{/* {isWeixin && <MCompAddTip />} */}
{/* 开屏广告 */}
{isWeixin && !showAdv && <SpScreenAd />}
{/* {isWeixin && !showAdv && <SpScreenAd />} */}
{/* 优惠券包 */}
{VERSION_STANDARD && <SpCouponPackage />}
{/* {VERSION_STANDARD && <SpCouponPackage />} */}
<View className="content-box">
<View className={classNames('content-box', {
// 'content-box-ovh': !isUpOperation
})}>
<View className="swiper-wapper" onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd}>
{/* <ScrollView
className='swiper-wapper'
@ -458,13 +640,14 @@ function Home () {
duration={800}
// indicatorDots
circular
autoplay={!isUpOperation}
autoplay={process.env.NODE_ENV === 'development' ? false : !isUpOperation}
onChange={onSwiperChange}
>
{state.swiperList.map((item, index) => (
<SwiperItem key={index} className="" style={{ height: "100%" }}>
{item.type === "image" && (
<Image
onClick={item.onClick}
src={item.src}
style={{ width: "100%", height: "100%", objectPosition: "center" }}
mode={isUpOperation ? 'aspectFill' : 'aspectFill'}
@ -481,7 +664,7 @@ function Home () {
controls={false}
autoplay={true}
loop={true}
muted={true}
muted={state.muted}
showProgress={false}
showFullscreenBtn={false}
showPlayBtn={false}
@ -504,18 +687,36 @@ function Home () {
<View className="item-btn-icon icon-my icon-arrow-right"></View>
</View>
</View>} */}
{!isUpOperation && item.type === "video" && <View className="mutedBtn" onClick={() => setState(v => { v.muted = !state.muted })} >
<Image className="muted-icon" src={`${process.env.APP_IMAGE_CDN_NEW}/index/${state.muted ? 'muted' : 'muted-no'}.jpg`}></Image>
</View>}
</SwiperItem>
))}
</Swiper>
{!isUpOperation && <View className="item-img-box">
<View className="item-img-txt"> </View>
<Image className="item-img" height="62" src={require('../assets/i-sou.gif')} isShowMenuByLongpress={false} lazyLoad isNew={false} />
</View>}
{!isUpOperation && <View className='spot-pagination'>
{swiperList.map((_, index) => (
<View key={index} className={'spot-pagination-bullet ' + ((state.currentIndex == index) ? 'spot-pagination-bullet-active' : "")} style={{ width: 1 / state.length * 100 + '%' }}></View>
))}
</View>}
{!isUpOperation && currentIndex === 0 ? <View className="item-btns" style="left: 220rpx;
bottom: 180rpx;" >
{<View onClick={handleGoWx} className="item-btn" style={{ padding: '50rpx 156rpx', opacity: 0, background: 'transparent', border: 'none' }} >
<View className="item-btn-txt"></View>
</View>}
</View> : null}
{!isUpOperation && <>
{/* currentIndex === -1 ? <View className="item-btns">
<View className="item-tit">{activeInfo.activity_name}</View>
{activeInfo.end_time * 1000 >= Date.now() && <View className="item-btn" style={{ padding: '30rpx 60rpx' }} onClick={() => handleApply()}>
<View className="item-btn-txt">{activeInfo.total_count ? '已报名' : '活动申请'}</View>
</View>}
</View> : */}
{goodList?.length > 0 &&
<View className="item-img-box">
<View className="item-img-txt"> </View>
<Image className="item-img" height="62" src={require('../assets/i-sou.gif')} isShowMenuByLongpress={false} lazyLoad isNew={false} />
</View>}
<View className='spot-pagination'>
{swiperList.map((_, index) => (
<View key={index} className={'spot-pagination-bullet ' + ((state.currentIndex == index) ? 'spot-pagination-bullet-active' : "")} style={{ width: 1 / state.length * 100 + '%' }}></View>
))}
</View>
</>}
{isUpOperation && <View className="icon-kf">
<SpChat><SpImage height="62" src='index/kf.png' isShowMenuByLongpress={false} lazyLoad isNew /></SpChat>
</View>}
@ -532,14 +733,14 @@ function Home () {
</View>
))}
</ScrollView>}
{/* 推荐图片+商品 */}
{isUpOperation && <>
{recommend.length > 0 && recommend.map((_item, id) => <View key={id + '__item'}>
{/* 推荐图片+商品 isUpOperation && */}
{isUpOperation && showRecommend && <>
{recommend.length > 0 && recommend.map((_item, id) => <View key={id + '__item'} className="fadeIn" >
<SpImage width={windowWidth * 2} height={windowWidth >= 400 ? 920 : 800} mode='scaleToFill' src={_item.img} isShowMenuByLongpress={false} lazyLoad isNew >
{/* <View className="recommend_btn" style={{ [_item.postions]: '70rpx' }}>
<View onClick={() => handleGoRecommendGoods(_item)} className="recommend_btn" style={{ [_item.postions]: '70rpx', opacity: 0 }}>
<View className="recommend_btn-title">{_item.text}</View>
<View className="recommend_btn-btn">{_item.btnTxt}</View>
</View> */}
</View>
</SpImage>
<ScrollView scrollX scrollWithAnimation showScrollbar={true} scrollLeft={0} className="shop-box fadeIn" >
{_item.list?.map((item, idx) => (

773
src/pages/index.js.bak Executable file
View File

@ -0,0 +1,773 @@
import React, { useEffect, useState, useCallback } from 'react'
import Taro, {
getCurrentInstance,
useShareAppMessage,
useShareTimeline,
useDidShow,
usePageScroll,
usePullDownRefresh
} from '@tarojs/taro'
import { View, Image, Swiper, SwiperItem, Video, ScrollView } from '@tarojs/components'
import { useSelector, useDispatch } from 'react-redux'
import {
SpScreenAd,
SpPage,
SpSearch,
SpRecommend,
SpTabbar,
SpCouponPackage,
SpNavBar,
SpImage,
SpGoodsItem,
SpChat,
SpLogin
} from '@/components'
import api from '@/api'
import {
isWeixin,
isAPP,
isEmpty,
getDistributorId,
VERSION_STANDARD,
VERSION_PLATFORM,
VERSION_IN_PURCHASE,
VERSION_B2C,
classNames,
getCurrentPageRouteParams,
resolveStringifyParams
} from '@/utils'
import entryLaunch from '@/utils/entryLaunch'
import { updateLocation } from '@/store/slices/user'
import { updateShopInfo } from '@/store/slices/shop'
import { useImmer } from 'use-immer'
import { useLogin, useNavigation } from '@/hooks'
import HomeWgts from './home/comps/home-wgts'
import { WgtHomeHeader, WgtHomeHeaderShop } from './home/wgts'
// import CompAddTip from './home/comps/comp-addtip'
// import CompFloatMenu from './home/comps/comp-floatmenu'
import './home/index.scss'
// const MCompAddTip = React.memo(CompAddTip)
const initialState = {
wgts: [],
showBackToTop: false,
loading: false,
searchComp: null,
pageData: null,
fixedTop: false,
filterWgts: [],
isShowHomeHeader: false,
swiperList: [],
list: [
{
type: 'image',
src: process.env.APP_IMAGE_CDN_NEW + '/index/22.jpg'
},
{
type: 'image',
// src: '//img10.360buyimg.com/ling/jfs/t1/181258/24/10385/53029/60d04978Ef21f2d42/92baeb21f907cd24.jpg'
src: process.env.APP_IMAGE_CDN_NEW + '/index/33.jpg'
},
{
type: 'video',
src: 'https://espier-oss-cdn.oss-cn-shanghai.aliyuncs.com/default_project/wxAssets/index/video-1.mp4'
}
],
length: 2,
showBottom: false,
scrollTop: 0,
isUpOperation: false,
showRecommend: false,
currentIndex: 0,
shopList: [
{
brief: "副标题",
itemName: "测试商品1",
price: "1099",
goods_id: 6,
pic: 'https://espier-oss-cdn.oss-cn-shanghai.aliyuncs.com/default_project/image/1/2024/01/15/46fe6ca52277038e39ee2c026a4af3c9xHQuJ96YIcZWtjRS0HBCTzp7dzXIs2pl'
},
{
brief: "副标题",
itemName: "测试商品2",
price: "1099",
goods_id: 6,
pic: 'https://espier-oss-cdn.oss-cn-shanghai.aliyuncs.com/default_project/image/1/2024/01/15/801c18d59d95ea26930fefc43bf66febTQjxb65cpnCqVLaOsYmiHdkDdYqBnXVm'
},
{
brief: "副标题",
itemName: "测试商品3",
price: "1099",
goods_id: 6,
pic: 'https://espier-oss-cdn.oss-cn-shanghai.aliyuncs.com/default_project/image/1/2024/01/15/46fe6ca52277038e39ee2c026a4af3c90XruENsSSAhRiz0HPI3PjR8XQNVgbxHb'
},
],
goodList: [],
recommend: [],
activeInfo: {},
muted: true,
}
function Home () {
const [state, setState] = useImmer(initialState)
const [startY, setStartY] = useState(0)
const [startX, setStartX] = useState(0)
const [likeList, setLikeList] = useImmer([])
const { isLogin, isNewUser } = useLogin()
const { initState, openRecommend, openLocation, openStore, appName, openScanQrcode } = useSelector(
(state) => state.sys
)
const { shopInfo } = useSelector(
(state) => state.shop
)
const showAdv = useSelector((member) => member.user.showAdv)
const { location } = useSelector((state) => state.user)
const { setNavigationBarTitle } = useNavigation()
const { windowWidth } = Taro.getSystemInfoSync()
const imgW = parseFloat(((windowWidth * 2 - 60 - 32) / 3).toFixed(4))
const { wgts, loading, searchComp, pageData, fixedTop, filterWgts, isShowHomeHeader, isUpOperation, showRecommend, shopList, swiperList, goodList, recommend } = state
const dispatch = useDispatch()
useEffect(() => {
if (initState) {
init()
setNavigationBarTitle(appName)
getSwiperList()
getRecommendItems()
}
}, [initState])
// useEffect(() => {
// if (shopInfo && VERSION_STANDARD) {
// fetchWgts()
// }
// }, [shopInfo])
// useEffect(() => {
// if (location && VERSION_STANDARD) {
// fetchWgts()
// }
// }, [location])
useShareAppMessage(async (res) => {
const { title, imageUrl } = await api.wx.shareSetting({ shareindex: 'index' })
let params = getCurrentPageRouteParams()
const dtid = getDistributorId()
if (dtid && !('dtid' in params)) {
params = Object.assign(params, { dtid })
}
let path = `/pages/index${isEmpty(params) ? '' : '?' + resolveStringifyParams(params)}`
console.log('useShareAppMessage path:', path, params)
return {
title: title,
imageUrl: imageUrl,
path
}
})
useShareTimeline(async (res) => {
const { title, imageUrl } = await api.wx.shareSetting({ shareindex: 'index' })
let params = getCurrentPageRouteParams()
const dtid = getDistributorId()
if (dtid && !('dtid' in params)) {
params = Object.assign(params, { dtid })
}
return {
title: title,
imageUrl: imageUrl,
query: resolveStringifyParams(params)
}
})
const init = async () => {
fetchLocation()
// 非云店
if (!VERSION_STANDARD) {
// fetchWgts()
} else {
fetchStoreInfo(location)
}
}
const getRecommendItems = async () => {
const req = {
page: 1,
pageSize: 10,
approve_status: 'onsale',
approve_status: 'onsale,only_show',
item_type: 'normal',
is_point: false,
// goodsSort: 6,
distributor_id: 0
}
// const { list: jdList } = await api.item.search({ ...req, tag_id: 1 })
const { list: newList = [] } = await api.item.search({ ...req, tag_id: 4 })
const { list: hotList = [] } = await api.item.search({ ...req, tag_id: 3 })
const { list: BOSTON_List = [] } = await api.item.search({ ...req, tag_id: 5 })
const { list: ARIZONA_List = [] } = await api.item.search({ ...req, tag_id: 6 })
const { list: LONDON_List = [] } = await api.item.search({ ...req, tag_id: 7 })
const newSort = {
"BK023": 1,
"BK066": 2,
"BK053": 3,
"BK038": 4,
"BK064": 5,
"BK014": 6
}
const hotSort = {
"BK014": 1,
"BK031": 2,
"BK018": 3,
"BK020": 4,
"BK052": 5,
"BK064": 6,
}
const BOSTON_sort = {
"BK020": 1,
"BK023": 2,
"BK025": 3,
"BK029": 4,
"BK030": 5,
"BK031": 6,
}
const ARIZONA_sort = {
"BK001": 1,
"BK017": 2,
"BK007": 3,
"BK010": 4,
"BK011": 5,
"BK014": 6,
}
const LONDON_sort = {
"BK052": 1,
"BK053": 2,
"BK051": 3,
}
setState((draft) => {
draft.recommend = [{
type: 'new',
text: "新品推荐",
btnTxt: '查看更多',
postions: 'left',
url: '',
tag_id: 4,
img: 'index/rec/new.png?v=1',
list: newList.map(item => ({ ...item, price: (item.price / 100) })).sort((a, b) => {
return newSort[a.item_name_3] - newSort[b.item_name_3]
})
}, {
type: 'hot',
text: "热销单品",
btnTxt: '查看更多',
postions: 'left',
url: '',
tag_id: 3,
img: 'index/rec/hot.png?v=1',
list: hotList.map(item => ({ ...item, price: (item.price / 100) })).sort((a, b) => {
return hotSort[a.item_name_3] - hotSort[b.item_name_3]
})
}, {
type: 'BOSTON',
text: "BOSTON",
btnTxt: 'BOSTON',
postions: 'left',
url: '',
tag_id: 5,
img: 'index/rec/Boston.png',
list: BOSTON_List.map(item => ({ ...item, price: (item.price / 100) })).sort((a, b) => {
return BOSTON_sort[a.item_name_3] - BOSTON_sort[b.item_name_3]
})
}, {
type: 'ARIZONA',
text: "ARIZONA",
btnTxt: 'ARIZONA',
url: '',
postions: 'left',
tag_id: 6,
img: 'index/rec/Arizona.png',
list: ARIZONA_List.map(item => ({ ...item, price: (item.price / 100) })).sort((a, b) => {
return ARIZONA_sort[a.item_name_3] - ARIZONA_sort[b.item_name_3]
})
}, {
type: 'LONDON',
text: "LONDON",
btnTxt: 'LONDON',
url: '',
postions: 'left',
tag_id: 7,
img: 'index/rec/London.png',
list: LONDON_List.map(item => ({ ...item, price: (item.price / 100) })).sort((a, b) => {
return LONDON_sort[a.item_name_3] - LONDON_sort[b.item_name_3]
})
}
]
// bak
// draft.recommend = [{
// type: 'new',
// text: "新品推荐",
// btnTxt: '查看更多',
// postions: 'left',
// url: '',
// img: 'index/rec/new.png',
// list: newList.map(item => ({ ...item, price: (item.price / 100) }))
// }, {
// type: 'hot',
// text: "热销单品",
// btnTxt: '查看更多',
// postions: 'left',
// url: '',
// img: 'index/rec/hot.png',
// list: hotList.map(item => ({ ...item, price: (item.price / 100) }))
// }, {
// type: 'jd',
// text: "ARIZONA",
// btnTxt: '经典双扣',
// postions: 'right',
// url: '',
// img: 'index/rec/jd.png',
// list: jdList.map(item => ({ ...item, price: (item.price / 100) }))
// }
// ]
})
}
const getSwiperList = async () => {
// const { status, activity_info = {}, total_count } = await api.user.registrationActivity({ activity_id: 1 })
// const activeSwiper = activity_info.pics.map(item => ({
// type: 'image',
// src: item,
// goods: []
// }))
const res = await api.shop.homeSwiperList({ page: 1, pageSize: 999 })
const list = (res?.list?.map((item) => {
return {
type: item.type || 'image',
src: item.pic,
sort: item.sort,
goods: (item.goods_info_detail || []).map((ite) => {
return {
itemName: ite.item_name,
goods_id: ite.item_id,
itemId: ite.item_id,
pic: ite.pics?.[0],
brief: ite.brief,
price: ite.price ? ite.price / 100 : 0,
spec_images: ite.spec_images || [],
tagList: ite.tagList || []
}
})
}
}) || []).sort((a, b) => a.sort - b.sort)
setState((draft) => {
// draft.swiperList = [...activeSwiper, ...list]
draft.swiperList = list
draft.goodList = list[0].goods || []
draft.loading = false
// draft.activeInfo = {
// ...activity_info,
// total_count,
// status
// }
})
}
const fetchWgts = async () => {
setState((draft) => {
draft.wgts = []
draft.pageData = []
draft.filterWgts = []
draft.loading = true
})
const { config } = await api.shop.getShopTemplate({
distributor_id: getDistributorId()
})
const searchComp = config.find((wgt) => wgt.name == 'search')
const pageData = config.find((wgt) => wgt.name == 'page')
let filterWgts = []
if (searchComp && searchComp.config.fixTop) {
filterWgts = config.filter((wgt) => wgt.name !== 'search' && wgt.name != 'page')
} else {
filterWgts = config.filter((wgt) => wgt.name != 'page')
}
const fixedTop = searchComp && searchComp.config.fixTop
const isShowHomeHeader =
VERSION_PLATFORM ||
(openScanQrcode == 1 && isWeixin) ||
(VERSION_STANDARD && openStore && openLocation == 1) ||
fixedTop
setState((draft) => {
draft.wgts = config
draft.searchComp = searchComp
draft.pageData = pageData
draft.fixedTop = fixedTop
draft.isShowHomeHeader = isShowHomeHeader
draft.filterWgts = filterWgts
draft.loading = false
})
}
const fetchLikeList = async () => {
if (openRecommend == 1) {
const query = {
page: 1,
pageSize: 30
}
const { list } = await api.cart.likeList(query)
setLikeList(list)
}
}
// 定位
const fetchLocation = () => {
if (!location && ((VERSION_STANDARD && openLocation == 1) || VERSION_PLATFORM)) {
try {
entryLaunch.isOpenPosition((res) => {
if (res.lat) {
dispatch(updateLocation(res))
}
})
} catch (e) {
console.error('map location fail:', e)
}
}
}
const fetchStoreInfo = async (location) => {
let params = {
distributor_id: getDistributorId() // 如果店铺id和经纬度都传会根据哪个去定位传参
}
if (openLocation == 1 && location) {
const { lat, lng } = location
params.lat = lat
params.lng = lng
// params.distributor_id = undefined
}
const res = await api.shop.getShop(params)
dispatch(updateShopInfo(res))
}
const handleTouchStart = (e) => {
const { clientY, clientX } = e.touches[0]
setStartY(clientY)
setStartX(clientX)
}
const handleTouchEnd = (e) => {
const { clientX, clientY } = e.changedTouches[0]
const deltaY = clientY - startY
const deltaX = clientX - startX
if (Math.abs(deltaY) < 50) return
if (deltaY > 0) {
// 下滑操作
setState((draft) => {
draft.showBottom = false
draft.showRecommend = false
})
if (state.showBottom) {
setTimeout(() => {
setState((draft) => {
draft.isUpOperation = false
})
}, 500)
}
} else if (deltaY < 0) {
// if (currentIndex === 0) return
// 上滑操作
setState((draft) => {
draft.showBottom = true
draft.isUpOperation = true
})
setTimeout(() => {
setState((draft) => {
draft.showRecommend = true
})
}, 1000)
if (!state.showBottom) {
}
}
}
const [recommendTouch, setRecommendTouch] = useImmer({
recommendStartY: 0,
recommendStartX: 0,
recommendEndY: 0,
recommendEndX: 0,
})
const onRecommendTouch = (e) => {
const { clientY, clientX } = e.touches[0]
setRecommendTouch(v => v.recommendStartX = clientX)
setRecommendTouch(v => v.recommendStartY = clientY)
}
const onRecommendTouchEnd = (e) => {
const { clientY, clientX } = e.changedTouches[0]
const { recommendStartY, recommendStartX } = recommendTouch
const deltaY = clientY - recommendStartY
const deltaX = clientX - recommendStartX
if (Math.abs(deltaY) < 50) return
if (deltaY > 0) {
// 下滑操作
console.log("🚀 ~ file: index.js:456 ~ 下滑操作:", '下滑操作')
} else if (deltaY < 0) {
// 上滑操作
console.log("🚀 ~ file: index.js:460 ~ 上滑操作:", '上滑操作')
}
}
const onSwiperChange = (e) => {
const { current } = e.detail
// if (current === 0) {
// setState((draft) => {
// draft.showBottom = false
// draft.isUpOperation = false
// })
// }
setState((draft) => {
draft.currentIndex = current
draft.goodList = swiperList[current].goods || []
})
}
const handleClickStore = (item) => {
const url = `/subpages/store/index?id=${item.distributor_info?.distributor_id || item.goods_id}`
Taro.navigateTo({
url
})
}
const { activeInfo = {}, currentIndex } = state
const handleApply = () => {
// if (!isLogin) return
let url = '/pages/recommend/detail?id='
if (activeInfo.total_count) {
url = `/pages/recommend/status?id=`
}
Taro.navigateTo({
url: url + activeInfo.activity_id
})
}
const handleGoRecommendGoods = (item) => {
const url = `/pages/item/list?tag_id=${item.tag_id || ''}`
Taro.navigateTo({
url: url
})
}
return (
<SpPage
className='page-index'
scrollToTopBtn
// renderNavigation={<SpNavBar />}
// pageConfig={pageData?.base}
// renderFloat={wgts.length > 0 && <CompFloatMenu />}
renderFooter={<SpTabbar />}
loading={loading}
isTop={!isUpOperation}
isBlack
>
{false && <View
className={classNames('home-body', {
'has-home-header': isShowHomeHeader && isWeixin
})}
>
{isShowHomeHeader && <WgtHomeHeader>{fixedTop && <SpSearch info={searchComp} />}</WgtHomeHeader>}
{
filterWgts.length > 0 && <HomeWgts wgts={filterWgts} onLoad={fetchLikeList}>
{/* 猜你喜欢 */}
<SpRecommend className='recommend-block' info={likeList} />
</HomeWgts>
}
</View>}
{/* 小程序搜藏提示 */}
{/* {isWeixin && <MCompAddTip />} */}
{/* 开屏广告 */}
{/* {isWeixin && !showAdv && <SpScreenAd />} */}
{/* 优惠券包 */}
{/* {VERSION_STANDARD && <SpCouponPackage />} */}
<View className={classNames('content-box', {
// 'content-box-ovh': !isUpOperation
})}>
<View className="swiper-wapper" onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd}>
{/* <ScrollView
className='swiper-wapper'
scrollY
scrollWithAnimation
scrollTop={0}
// style={{ height: "calc(100vh - 140px)" }}
lowerThreshold={0}
upperThreshold={20}
// onScrollToUpper={this.onScrollToUpper.bind(this)} // 使用箭头函数的时候 可以这样写 `onScrollToUpper={this.onScrollToUpper}`
onScroll={onScroll}
onTouchStart={handleTouchStart} onTouchEnd={handleTouchEnd}
showScrollbar={false}
> */}
<Swiper
className={classNames('swiper', {
"swiper-narrow": state.showBottom
})}
indicatorColor="#999"
indicatorActiveColor="#333"
current={state.currentIndex}
interval={5000}
duration={800}
// indicatorDots
circular
autoplay={!isUpOperation}
onChange={onSwiperChange}
>
{state.swiperList.map((item, index) => (
<SwiperItem key={index} className="" style={{ height: "100%" }}>
{item.type === "image" && (
<Image
src={item.src}
style={{ width: "100%", height: "100%", objectPosition: "center" }}
mode={isUpOperation ? 'aspectFill' : 'aspectFill'}
showMenuByLongpress={false}
/>
// <SpImage style={{ width: "100%", height: "100%" }} height="100%" src={item.src} isShowMenuByLongpress={false} lazyLoad isNew></SpImage>
)}
{item.type === "video" && (
<Video
id="video"
src={item.src}
poster={item.poster}
initialTime={0}
controls={false}
autoplay={true}
loop={true}
muted={state.muted}
showProgress={false}
showFullscreenBtn={false}
showPlayBtn={false}
showCenterPlayBtn={false}
enableProgressGesture={false}
objectFit="cover"
style={{ width: "100%", height: "100%" }}
onPlay={() => {
}}
onEnded={() => {
}}
/>
)}
{/* {isUpOperation && <View className="item-btns">
<View className="item-tit">BOSTON</View>
<View className="item-btn">
<View className="item-btn-txt">立即预约</View>
<View className="item-btn-icon icon-my icon-arrow-right"></View>
</View>
</View>} */}
{item.type === "video" && <View className="mutedBtn" onClick={() => setState(v => { v.muted = !state.muted })} >
<Image className="muted-icon" src={`${process.env.APP_IMAGE_CDN_NEW}/index/${state.muted ? 'muted' : 'muted-no'}.jpg`}></Image>
</View>}
</SwiperItem>
))}
</Swiper>
{!isUpOperation && <>
<View className="item-img-box">
<View className="item-img-txt"> </View>
<Image className="item-img" height="62" src={require('../assets/i-sou.gif')} isShowMenuByLongpress={false} lazyLoad isNew={false} />
</View>
<View className='spot-pagination'>
{swiperList.map((_, index) => (
<View key={index} className={'spot-pagination-bullet ' + ((state.currentIndex == index) ? 'spot-pagination-bullet-active' : "")} style={{ width: 1 / state.length * 100 + '%' }}></View>
))}
</View>
</>}
{isUpOperation && <View className="icon-kf">
<SpChat><SpImage height="62" src='index/kf.png' isShowMenuByLongpress={false} lazyLoad isNew /></SpChat>
</View>}
</View>
{isUpOperation && <ScrollView scrollX scrollWithAnimation showScrollbar={true} scrollLeft={0} className="shop-box fadeIn" >
{goodList.map((item, idx) => (
<View className='goods-item-wrap fadeIn' animation={{ duration: 500, timingFunction: 'ease-in-out', delay: 0 }} key={`goods-item-l__${idx + item.goods_id}`}>
<SpGoodsItem
onStoreClick={handleClickStore}
info={{
...item
}}
/>
</View>
))}
</ScrollView>}
{/* 推荐图片+商品 isUpOperation && */}
{isUpOperation && showRecommend && <>
{recommend.length > 0 && recommend.map((_item, id) => <View key={id + '__item'} className="fadeIn" >
<SpImage width={windowWidth * 2} height={windowWidth >= 400 ? 920 : 800} mode='scaleToFill' src={_item.img} isShowMenuByLongpress={false} lazyLoad isNew >
<View onClick={() => handleGoRecommendGoods(_item)} className="recommend_btn" style={{ [_item.postions]: '70rpx', opacity: 0 }}>
<View className="recommend_btn-title">{_item.text}</View>
<View className="recommend_btn-btn">{_item.btnTxt}</View>
</View>
</SpImage>
<ScrollView scrollX scrollWithAnimation showScrollbar={true} scrollLeft={0} className="shop-box fadeIn" >
{_item.list?.map((item, idx) => (
<View className='goods-item-wrap fadeIn' animation={{ duration: 500, timingFunction: 'ease-in-out', delay: 0 }} key={`goods-item-l__${idx + item.goods_id}`}>
<SpGoodsItem
onStoreClick={handleClickStore}
info={{
...item
}}
/>
</View>
))}
</ScrollView>
</View>)}
</>}
{isUpOperation && showRecommend && <View className="brand" style={{ padding: '0 15px 15px', height: '250px' }}>
<SpImage width={windowWidth * 2 - 60} mode='widthFix' src="index/story/story.png" onClick={() => Taro.navigateTo({
url: '/pages/home/story'
})} isShowMenuByLongpress={false} lazyLoad isNew></SpImage>
{/* <SpImage width={windowWidth * 2 - 60} mode='widthFix' src="index/story/more.png" isShowMenuByLongpress={false} lazyLoad isNew></SpImage> */}
{/* <View style={{ marginTop: '30px' }}>
<SpImage onClick={() => Taro.navigateTo({
url: '/pages/webview?url=' + encodeURIComponent('https://www.baidu.com')
})} width={windowWidth * 2 - 60} mode='widthFix' src="index/story/more.png" isShowMenuByLongpress={false} lazyLoad isNew></SpImage>
</View> */}
</View>}
{false && isUpOperation && showRecommend && <View className="brand" style={{ padding: '15px', height: '550px' }}>
<View className="brand-title">品牌介绍</View>
<ScrollView scrollX scrollWithAnimation showScrollbar={false} scrollLeft={0} className="brand-img" style={{ height: '220px' }}>
<View className="brand-img-left brand-img-item" style={{ marginRight: '8px' }}>
<SpImage className="brand-img-top" width={imgW} height={294} mode='aspectFill' src="index/img/1774-1902.jpg" isShowMenuByLongpress={false} lazyLoad isNew></SpImage>
<SpImage width={imgW} height={130} mode='aspectFill' src="index/img/1913.jpg" isShowMenuByLongpress={false} lazyLoad isNew></SpImage>
</View>
<View className="brand-img-center brand-img-item" style={{ marginRight: '8px' }}>
<SpImage height={440} width={imgW} mode='aspectFill' src="index/img/1968.jpg" isShowMenuByLongpress={false} lazyLoad isNew></SpImage>
</View>
<View className="brand-img-right brand-img-item" style={{ marginRight: '0px' }}>
<SpImage className="brand-img-top" width={imgW} height={324} mode='aspectFill' src="index/img/70.jpg" isShowMenuByLongpress={false} lazyLoad isNew></SpImage>
<SpImage width={imgW} height={100} mode='aspectFill' src="index/img/1980.jpg" isShowMenuByLongpress={false} lazyLoad isNew></SpImage>
</View>
</ScrollView>
<SpImage onClick={() => Taro.navigateTo({
url: '/pages/webview?url=' + encodeURIComponent('https://www.baidu.com')
})} className="brand-guanzhu" mode="widthFix" src="index/guanzhu.png" isShowMenuByLongpress={false} lazyLoad isNew></SpImage>
<View className="brand-dy">
<View className="brand-dy-tit">订阅消息</View>
<SpImage width={30} mode="widthFix" src="index/xiaoxi.png" isShowMenuByLongpress={false} lazyLoad isNew></SpImage>
</View>
{/* <SpImage className="brand-logo" width={168} mode="widthFix" src="index/logo.png" isShowMenuByLongpress={false} lazyLoad isNew></SpImage> */}
</View>}
{/* </ScrollView> */}
</View>
</SpPage>
)
}
export default Home

View File

@ -8,7 +8,7 @@ import { addCart } from '@/store/slices/cart'
import { BUY_TOOL_BTNS, ACTIVITY_LIST } from '@/consts'
import { fetchUserFavs, addUserFav, deleteUserFav } from '@/store/slices/user'
import api from '@/api'
import { AtModal } from 'taro-ui'
import { AtModal, AtBadge } from 'taro-ui'
import './comp-buytoolbar.scss'
function CompGoodsBuyToolbar (props) {
@ -161,6 +161,9 @@ function CompGoodsBuyToolbar (props) {
<Text className='toolbar-item-txt'>收藏</Text>
</View> */}
</SpLogin>
<View className='shoucang-wrap' style="marginLeft:30rpx" onClick={() => Taro.redirectTo({ url: '/pages/cart/espier-index' })}>
{cartCount > 0 ? <AtBadge value={cartCount} maxValue={99}><SpImage src={`member/cart.png`} height={50} mode='heightFix' isNew /></AtBadge> : <SpImage src={`member/cart.png`} height={54} mode='heightFix' isNew />}
</View>
{false && <View
className='toolbar-item'
onClick={navigateTo.bind(this, '/pages/cart/espier-index?tabbar=0')}

View File

@ -8,6 +8,20 @@
display: flex;
align-items: center;
flex: 1;
.at-badge {
&__num {
font-size: 14px;
width: 24px;
height: 24px;
line-height: 24px;
top: -6px;
right: 4px;
padding: 0;
border-radius: 50%;
overflow: hidden;
text-align: center;
}
}
}
.sp-login {
margin-left: 30px;

View File

@ -110,13 +110,19 @@ function EspierDetail (props) {
const $instance = getCurrentInstance()
// const { type, id, dtid } = $instance.router.params
// const { type, id, dtid } = await entryLaunch.getRouteParams()
const { getUserInfoAuth } = useLogin()
const { getUserInfoAuth, isLogin } = useLogin()
const pageRef = useRef()
const { userInfo } = useSelector((state) => state.user)
const { colorPrimary, openRecommend } = useSelector((state) => state.sys)
const { setNavigationBarTitle } = useNavigation()
const dispatch = useDispatch()
const skuSelectRef = useRef()
const { windowWidth } = Taro.getSystemInfoSync()
const width = windowWidth * 2
const goods_1774 = {
1: ['1/1-1.jpg', '1/1-2.jpg', '1/1-3.jpg'],
2: ['2/2-1.jpg', '2/2-2.jpg', '2/2-3.jpg'],
}
const [state, setState] = useImmer(initialState)
const {
@ -327,14 +333,14 @@ function EspierDetail (props) {
getRecommendList() // 猜你喜欢
}
api.member.itemHistorySave(data.itemId)
const res = await api.member.itemHistory()
setState((draft) => {
draft.historyList = res.list.filter((item) => item.item_id !== data.itemId && !!item.itemData?.item_id)?.map((item) => ({ ...item.itemData, pic: item.itemData.pics?.[0] || '' })) || []
draft.historyTotal = res.total_count
})
if (isLogin) {
api.member.itemHistorySave(data.itemId)
const res = await api.member.itemHistory()
setState((draft) => {
draft.historyList = res.list.filter((item) => item.item_id !== data.itemId && !!item.itemData?.item_id)?.map((item) => ({ ...item.itemData, pic: item.itemData.pics?.[0] || '' })) || []
draft.historyTotal = res.total_count
})
}
}
const getRecommendList = async () => {
@ -396,7 +402,6 @@ function EspierDetail (props) {
}
}
const { windowWidth } = Taro.getSystemInfoSync()
let sessionFrom = {}
if (info) {
@ -632,7 +637,7 @@ function EspierDetail (props) {
<View className='goods-info-title'>
{/* 拼团、秒杀、限时特惠不显示 */}
{!ACTIVITY_LIST[info.activityType] && (
<SpGoodsPrice info={curItem ? curItem : info} size="30" />
<SpGoodsPrice showMarketPrice={true} info={curItem ? curItem : info} size="30" />
)}
</View>
{showSaleTotal && <View className='item-bn-sales'>
@ -642,7 +647,7 @@ function EspierDetail (props) {
</View>}
</View>
<CompGroup info={info} />
{/* <CompGroup info={info} /> */}
{/* { !info.nospec && (
<View className='sku-block'>
@ -710,7 +715,7 @@ function EspierDetail (props) {
</View>} */}
{/* 店铺 */}
{VERSION_PLATFORM && <CompStore info={info.distributorInfo} />}
{/* {VERSION_PLATFORM && <CompStore info={info.distributorInfo} />} */}
{/* Sku选择器列表 */}
{/* Sku选择器 */}
@ -731,7 +736,7 @@ function EspierDetail (props) {
curItem && setState((draft) => {
draft.skuText = skuText
draft.curItem = curItem
// 切换顶部轮播图
// 切换顶部轮播图
draft.selSkuImg = curItem.specItem?.[0]?.specImgs?.[0]
if (idx === 0) draft.swiperList = curItem?.specItem?.[idx]?.specImgs
})
@ -751,30 +756,53 @@ function EspierDetail (props) {
<Text className='desc-title-txt'>{info?.itemName}</Text>
<SpGoodsPrice info={curItem ? curItem : info} />
</View>
</View> */}
{isArray(info.intro) ? (
<View>
{info.intro.map((item, idx) => (
<View className='wgt-wrap' key={`wgt-wrap__${idx}`}>
{item.name === 'film' && <WgtFilm info={item} />}
{item.name === 'slider' && <WgtSlider info={item} />}
{item.name === 'writing' && <WgtWriting info={item} />}
{/* {item.name === 'heading' && <WgtHeading info={item} />} */}
{item.name === 'headline' && <WgtHeadline info={item} />}
{item.name === 'goods' && <WgtGoods info={item} />}
</View>
))}
</View>
) : (
<>
{/* <SpHtml content={info.intro} /> */}
</>
)}
{introList.length ? introList.map((item, index) => <View className={classNames('sp-accordion')} key={`item__${index}`}>
<AtAccordion
open={item.isOpen}
isAnimation={false}
onClick={() => {
</View>
false ? <>
{goods_1774[1].map((item, index) => <SpImage src={`1774/${item}`} width={width} isNew >
</SpImage>)}
</> :
*/}
{<>
{isArray(info.intro) ? (
<View>
{info.intro.map((item, idx) => (
<View className='wgt-wrap' key={`wgt-wrap__${idx}`}>
{item.name === 'film' && <WgtFilm info={item} />}
{item.name === 'slider' && <WgtSlider info={item} />}
{item.name === 'writing' && <WgtWriting info={item} />}
{item.name === 'headline' && <WgtHeadline info={item} />}
{item.name === 'goods' && <WgtGoods info={item} />}
</View>
))}
</View>
) :
<>
</>}
{introList.length ? introList.length === 2 ? <SpHtml content={introList[0].content} /> : introList.map((item, index) => <View className={classNames('sp-accordion')} key={`item__${index}`}>
<AtAccordion
open={item.isOpen}
isAnimation={false}
onClick={() => {
setState((draft) => {
draft.introList = draft.introList.map((v, i) => {
v.isOpen = false
return v
})
draft.introList[index].isOpen = !item.isOpen
})
// if (!item.isOpen) {
// setState((draft) => {
// draft.scrollTop = 1042 + Math.random() / 10
// })
// }
}}
title={item.title}
>
{item.type !== 'eva' ? <SpHtml content={item.content} /> :
<CompEvaluation list={evaluationList} itemId={info.itemId}></CompEvaluation>
}
</AtAccordion>
<View onClick={() => {
setState((draft) => {
draft.introList = draft.introList.map((v, i) => {
v.isOpen = false
@ -787,51 +815,32 @@ function EspierDetail (props) {
// draft.scrollTop = 1042 + Math.random() / 10
// })
// }
}}
title={item.title}
>
{item.type !== 'eva' ? <SpHtml content={item.content} /> :
<CompEvaluation list={evaluationList} itemId={info.itemId}></CompEvaluation>
}
</AtAccordion>
<View onClick={() => {
setState((draft) => {
draft.introList = draft.introList.map((v, i) => {
v.isOpen = false
return v
})
draft.introList[index].isOpen = !item.isOpen
})
// if (!item.isOpen) {
// setState((draft) => {
// draft.scrollTop = 1042 + Math.random() / 10
// })
// }
}}>
{item.isOpen ? <AtIcon value='subtract' size='16' color='#000' /> :
<AtIcon value='add' size='16' color='#000' />}
{item.isOpen ? <></> : <View className="line"></View>}
</View>
</View>) : <View style={{ height: `calc(100% - 380px)` }}></View>}
{/* 商品评价 */}
}}>
{item.isOpen ? <AtIcon value='subtract' size='16' color='#000' /> :
<AtIcon value='add' size='16' color='#000' />}
{item.isOpen ? <></> : <View className="line"></View>}
</View>
</View>) : <View style={{ height: `calc(100% - 380px)` }}></View>}
{/* 商品评价 */}
{/* <CompEvaluation list={evaluationList} itemId={info.itemId}></CompEvaluation> */}
{isArray(historyList) ? <View className='bottom-box'>
<View className="bottom-box-tit">浏览历史</View>
<ScrollView scrollX scrollWithAnimation showScrollbar={true} scrollLeft={0} className="shop-box">
{historyList.map((item, idx) => (
<View className='goods-item-wrap' key={`goods-item-l__${idx}`}>
<SpGoodsItem
showSalePrice={false}
height={250}
width={250}
onStoreClick={handleClickStore}
info={item}
/>
</View>
))}
</ScrollView>
</View> : <></>}
{/* <CompEvaluation list={evaluationList} itemId={info.itemId}></CompEvaluation> */}
{isArray(historyList) && introList?.length > 2 ? <View className='bottom-box'>
<View className="bottom-box-tit">浏览历史</View>
<ScrollView scrollX scrollWithAnimation showScrollbar={true} scrollLeft={0} className="shop-box">
{historyList.map((item, idx) => (
<View className='goods-item-wrap' key={`goods-item-l__${idx}`}>
<SpGoodsItem
showSalePrice={false}
height={250}
width={250}
onStoreClick={handleClickStore}
info={item}
/>
</View>
))}
</ScrollView>
</View> : <></>}
</>}
</View>
</ScrollView>
)}

View File

@ -50,7 +50,15 @@ const initialState = {
routerParams: null,
card_id: null, // 兑换券
total: undefined,
historyList: []
historyList: [],
loading: true,
tagItem: {
4: 'SS24新品推荐',
3: '热销单品',
5: 'Boston系列',
6: 'Arizona系列',
7: 'London系列',
}
}
function ItemList () {
@ -70,7 +78,9 @@ function ItemList () {
fixTop,
routerParams,
total,
historyList
historyList,
loading,
tagItem
} = state
const [isShowSearch, setIsShowSearch] = useState(false)
const { cat_id, main_cat_id, tag_id, card_id, user_card_id } = routerParams || {}
@ -229,6 +239,7 @@ function ItemList () {
v.rightList[pageIndex - 1] = resRightList
v.brandList = pickBy(brand_list?.list, doc.goods.WGT_GOODS_BRAND)
v.historyList = _historyList?.list || []
v.loading = false
if (v.tagList.length < 1) {
if (select_tags_list.length > 0) {
v.tagList = [
@ -344,6 +355,7 @@ function ItemList () {
<SpPage
scrollToTopBtn
showNavCartIcon
title={tag_id ? tagItem[tag_id] : '搜索列表'}
className={classNames('page-item-list has-navbar', {
'has-tagbar': tagList.length > 0
})}

View File

@ -105,7 +105,7 @@ export default class ItemFav extends Component {
img: 'item_image',
fav_id: 'fav_id',
item_id: 'item_id',
title: 'item_name',
title: ({ item_name, item_name_2 }) => item_name_2 || item_name,
desc: 'brief',
item_type: 'item_type',
distributor_id: 'distributor_id',

View File

@ -120,9 +120,11 @@
flex: 1;
width: 100%;
flex-direction: column;
overflow: hidden;
&__title {
@include text-overflow();
font-size: 22px;
width: 98%;
}
&__price {
display: flex;
@ -130,8 +132,8 @@
font-weight: bold;
font-size: 32px;
line-height: 1;
margin-top: 16px;
margin-bottom: 36px;
margin-top: 26px;
margin-bottom: 20px;
&__symbol {
margin-right: 20px;
}
@ -153,7 +155,8 @@
align-items: center;
}
&__btn {
border: 1px solid #000;
/* prettier-ignore */
border: 1PX solid #000;
border-radius: 6px;
padding: 15px 20px;
font-size: 20px;

75
src/pages/other/goods.js Normal file
View File

@ -0,0 +1,75 @@
import React, { useEffect, useRef } from "react"
import { useImmer } from "use-immer"
import Taro, { getCurrentInstance } from "@tarojs/taro"
import api from "@/api"
import { SpPage, SpImage } from '@/components'
import { View, Text, Picker, Input } from "@tarojs/components"
import './goods.scss'
const initState = {
loading: false,
shopList: []
}
function goods () {
const [state, setState] = useImmer(initState)
const { loading } = state
const { windowHeight, windowWidth } = Taro.getSystemInfoSync()
const width = windowWidth * 2
const goods_1774 = [1, 2, 3, 4, 5, 6, 7]
const { shopList } = state
const handleBackToIndex = () => {
Taro.redirectTo({ url: '/pages/index' })
}
const handleGoBuy = (item, index) => {
if (index === 3) {
Taro.navigateTo({
url: `/pages/item/espier-detail?id=${shopList[0]?.itemId}`
})
}
if (index === 5) {
Taro.navigateTo({
url: `/pages/item/espier-detail?id=${shopList[1]?.itemId}`
})
}
}
useEffect(() => {
getShop()
setTimeout(() => {
setState((draft) => {
draft.loading = false
})
}, 300)
}, [])
const getShop = async () => {
let params = {
page: 1,
pageSize: 10,
keywords: '',
approve_status: 'onsale,only_show,offline_sale',
item_type: 'normal',
is_point: 'false',
goodsSort: 6
}
const { list: BK_075List = [] } = await api.item.search({ ...params, keywords: 'BK075' })
const { list: BK_074List = [] } = await api.item.search({ ...params, keywords: 'BK074' })
setState((draft) => {
draft.shopList = [...BK_075List, ...BK_074List]
})
}
return (
<SpPage loading={loading} title={''} className='page-other-goods has-navbar' showNavSearchIcon showNavLogo>
<View className="" style={{ minHeight: windowHeight * 2, background: '#000' }} >
{goods_1774.map((item, index) => <SpImage src={`1774/${item}.jpg`} width={width} isNew >
{(index === 3 || index === 5) && <View className="go-buy" onClick={() => handleGoBuy(item, index)} ></View>}
</SpImage>)}
</View>
<View className="content-btn" onClick={handleBackToIndex} >
返回首页
</View>
</SpPage>
)
}
export default goods

View File

@ -0,0 +1,34 @@
.page-other-goods {
.custom-navigation {
background-color: #000 !important;
.left-container {
.icon-fanhui {
color: #fff !important;
}
}
}
.content-btn {
margin: 0 auto;
width: 650px;
height: 80px;
line-height: 80px;
text-align: center;
/* prettier-ignore */
border: 1PX solid var(--color-primary);
font-size: 34px;
border-radius: 6px;
margin-top: 30px;
margin-bottom: 30px;
}
.go-buy {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
height: 100%;
width: 100%;
background: transparent;
z-index: 2;
}
}

View File

@ -0,0 +1,485 @@
import React, { useEffect } from 'react'
import { View, Text, Input, Image, Button, Picker } from '@tarojs/components'
import Taro, { getCurrentInstance, useDidShow, useShareAppMessage } from '@tarojs/taro'
import { SpPage, SpHtml, SpCheckbox, SpLogin, SpImage } from '@/components'
import { useSelector } from 'react-redux'
import { useImmer } from 'use-immer'
import api from '@/api'
import dayjs from 'dayjs'
import { AtIcon } from 'taro-ui'
import { classNames, navigateTo, pickBy } from '@/utils'
import { useLogin } from '@/hooks'
import './apply.scss'
const initState = {
activeInfo: {},
isLoading: true,
visible: false,
checked: false,
formInfo: {},
status: '',
isShare: false,
alwaysBackUrl: "/pages/index",
isSub: false,
formData: {},
formList: [{}],
areaList: [],
changci: {},
formDataList: [],
}
export default function detail () {
const $instance = getCurrentInstance()
const [state, setState] = useImmer(initState)
const { appName } = useSelector((_state) => _state.sys)
const { userInfo = {} } = useSelector((_state) => _state.user)
const pages = getCurrentPages()
const current = pages[pages.length - 1]
const eventChannel = current.getOpenerEventChannel()
const { isLogin } = useLogin({
autoLogin: true,
})
const getActiveDetail = async () => {
const { id: activity_id, alwaysBackUrl } = $instance.router.params
if (!activity_id) return
const { status, activity_info = {}, total_count, user_code, recordList = {} } = await api.user.registrationActivity({ activity_id })
if (total_count > 0 && !alwaysBackUrl) {
Taro.redirectTo({ url: '/pages/recommend/status?&id=' + activity_id })
return
}
const _start = dayjs(activity_info.start_time * 1000)
const _end = dayjs(activity_info.end_time * 1000)
if (alwaysBackUrl) {
setState(draft => {
draft.alwaysBackUrl = alwaysBackUrl + "?id=" + activity_id
})
}
const _item = recordList.list?.[0] || {}
const { content = [] } = activity_info.formdata
const formdata = content[0]?.formdata || []
setState(draft => {
draft.isLoading = false
// draft.formList = formdata.sort((a, b) => a.id - b.id)
draft.formDataList = formdata
draft.activeInfo = {
...activity_info,
user_code,
total_count,
start: `${_start.month() + 1}${_start.date()}`,
end: `${_end.month() + 1}${_end.date()}`,
status: _item.is_write_off === '1' ? 'done' : _item.status,
isLoading: false
}
// draft.checked = !!_item
})
}
useEffect(() => {
getActiveDetail()
fetchAreaData()
eventChannel.on('apply', (res) => {
setState(draft => {
draft.changci = res
})
})
}, [])
useEffect(() => {
if (isLogin && userInfo) {
setState(draft => {
draft.formInfo = {
username: userInfo.username,
mobile: userInfo.mobile,
}
draft.formData['username'] = userInfo.username
draft.formData['mobile'] = userInfo.mobile
})
}
}, [userInfo, isLogin])
const { isLoading, activeInfo = {}, visible, formInfo, checked, status, isShare, alwaysBackUrl, isSub, formData, formList, areaList, formDataList, changci } = state
const handleConfirm = async () => {
if (!isLogin || !userInfo) return
if (activeInfo.status) {
Taro.navigateTo({ url: '/pages/recommend/status?success=true&id=' + activeInfo.activity_id })
return
}
if (!checked) {
const res = await Taro.showModal({
title: '提示',
content: `请先阅读并同意${appName}活动细则`,
showCancel: true,
cancel: '取消',
cancelText: '拒绝',
confirmText: '同意',
cancelColor: '#a5a5a5',
confirmColor: '#000'
})
if (!res.confirm) return
setState((draft) => {
draft.checked = true
// draft.visible = true
})
} else {
const _formData = formDataList.map((d) => {
return {
...d,
answer: formData[d.field_name]
}
})
let flag = true
try {
_formData.forEach((d) => {
const { field_name, field_title, answer } = d
const reg = /^[1][3,4,5,7,8,9][0-9]{9}$/
if ((formData['has_partner'] === '否' && field_name.includes('partner') || field_name.includes('city') || (field_name === 'mobile' && answer === userInfo.mobile))) {
return
}
if (field_name === 'mobile' || field_name === 'partner_mobile') {
if (!reg.test(answer)) {
Taro.showToast({
title: `${formData['has_partner'] === '是' ? '同行人' : ''}${field_title}格式不正确`,
icon: 'none'
})
throw new Error(`${field_title}格式不正确`)
}
} else {
if (!answer || !answer.trim()) {
Taro.showToast({
title: `请填写${formData['has_partner'] === '是' ? '同行人' : ''}${field_title}`,
icon: 'none'
})
throw new Error(`${formData['has_partner'] === '是' ? '同行人' : ''}${field_title}不能为空`)
}
}
})
} catch (error) {
flag = false
}
if (!flag) return
const content = {
title: '',
sort: 1,
formdata: _formData
}
const { status } = await api.user.registrationSubmit({
formdata: { content: JSON.stringify([content]) },
activity_id: activeInfo.activity_id,
registration_session_id: changci.id
})
if (status) {
const templeparams = {
temp_name: 'yykweishop',
source_type: 'activity'
}
const { template_id } = await api.user.newWxaMsgTmpl(templeparams)
Taro.requestSubscribeMessage({
tmplIds: template_id,
success: () => {
},
fail: (err) => {
},
complete: () => {
Taro.navigateTo({ url: '/pages/recommend/status?success=true&id=' + activeInfo.activity_id })
}
})
}
}
// setState((draft) => {
// draft.visible = true
// })
}
const fetchAreaData = async () => {
let res = await api.member.areaList()
const _nList = pickBy(res, {
label: 'label',
value: 'id',
// children: 'children'
})
setState(draft => {
draft.areaList = _nList
})
}
const renderFooter = () => {
if (isLoading || status === 'passed') {
return null
}
return <View className={"bottom"}>
<View className='check-box'>
<SpCheckbox disabled={!!activeInfo.status} checked={checked} colors="#000" onChange={() => setState((draft) => { draft.checked = !checked })} />
<View>
<Text onClick={() => !activeInfo.status && setState((draft) => { draft.checked = !checked })} >我已经阅读并同意</Text>
<Text
onClick={() => Taro.navigateTo({ url: '/subpages/auth/reg-rule?type=activity_rule' })}
style={`color: #000000;text-decoration: underline;`}
>
{`${appName}活动细则》`}
</Text>
</View>
</View>
{/* <View onClick={handleConfirm} className={"btn"}>{!status ? '确认报名' : status === 'pending' ? '报名中' : '已报名'}</View> */}
<SpLogin onChange={getActiveDetail}>
<View onClick={handleConfirm} className={"btn"}>{!activeInfo.status ? '确认报名' : '报名详情'}</View>
</SpLogin>
</View>
}
const onIptChange = (e, name) => {
const { value } = e.detail
setState((draft) => {
draft.formData[name] = value
})
}
const handleSubmit = async () => {
if (isSub) {
return
}
setState((draft) => {
draft.isSub = true
})
if (isShare) {
handeleShare()
return
}
if (!formInfo.username?.trim()) {
Taro.showToast({
title: '请输入姓名',
icon: 'none'
})
return
}
if (!formInfo.mobile?.trim()) {
Taro.showToast({
title: '请输入手机号',
icon: 'none'
})
return
}
const content = {
title: '',
sort: 1,
formdata: formItem.map((d) => {
return {
...d,
answer: formInfo[d.field_name]
}
})
}
const { status } = await api.user.registrationSubmit({
formdata: { content: JSON.stringify([content]) },
activity_id: activeInfo.activity_id
})
if (status) {
setState((draft) => {
draft.visible = false
draft.status = status
})
const templeparams = {
temp_name: 'yykweishop',
source_type: 'activity'
}
const { template_id } = await api.user.newWxaMsgTmpl(templeparams)
Taro.requestSubscribeMessage({
tmplIds: template_id,
success: () => {
},
fail: (err) => {
},
complete: () => {
Taro.navigateTo({ url: '/pages/recommend/status?success=true&id=' + activeInfo.activity_id })
}
})
}
setState((draft) => {
draft.isSub = false
})
}
const onClickShare = () => {
setState((draft) => {
draft.visible = true
draft.isShare = true
})
}
useShareAppMessage(() => {
return {
title: activeInfo.activity_name,
path: `/pages/recommend/detail?id=${activeInfo.activity_id}`,
// imageUrl: activeInfo.pics[0]
imageUrl: `${process.env.APP_IMAGE_CDN_NEW}/share-logo.jpg`
}
})
const handleClose = () => {
setState((draft) => {
draft.visible = false
})
setTimeout(() => {
setState((draft) => {
draft.isShare = false
})
}, 800)
}
const pickerChange = (e, key) => {
const { value } = e.detail
setState((draft) => {
draft.formData[key] = areaList[value]?.label
})
}
const handleAddApply = (flag) => {
if (formList.length > 2) {
return
}
if (flag) {
setState((draft) => {
draft.formList = [...formList, {}]
draft.formData['has_partner'] = '是'
})
} else {
setState((draft) => {
draft.formList = [formList[0]]
draft.formData['has_partner'] = '否'
})
}
}
const formItem = activeInfo.formdata?.key_index || []
// !!activeInfo?.total_count ? <></> :
return (
<SpPage title='报名信息' renderFooter={!!activeInfo?.total_count ? <></> : renderFooter()} loading={isLoading} className='page-recommend-apply' >
<View className="activity_apply_time">{changci.index} {changci.start}-{changci.end}</View>
<View className="activity_apply_tit">请填写您的个人信息</View>
{formList.map((item, index) => <View className='user-form' key={index}>
<View className="user-form-item">
<View className="user-form-item-title">姓名</View>
<View className='cell-item'>
<Input
value={formData[index === 0 ? 'username' : 'partner_name']}
className="user-form-item-ipt"
type="text"
placeholder={`请输入${index > 0 ? '他人' : ''}姓名`}
onInput={(e) => onIptChange(e, index === 0 ? 'username' : 'partner_name')}
/>
</View>
</View>
<View className="user-form-item">
<View className="user-form-item-title">手机</View>
<View className='cell-item'>
<Input
value={formData[index === 0 ? 'mobile' : 'partner_mobile']}
className="user-form-item-ipt"
type="text"
placeholder={`请输入${index > 0 ? '他人' : ''}手机号`}
onInput={(e) => onIptChange(e, index === 0 ? 'mobile' : 'partner_mobile')}
/>
</View>
</View>
<View className="user-form-item">
<View className='cell-item'>
<View className="cell-item-tit">性别</View>
<View className='flex-row'>
<View className="flex-row" onClick={() => onIptChange({ detail: { value: '男' } }, index === 0 ? 'gender' : 'partner_gender')} style={{ paddingRight: '10rpx' }} >
<View className="sex-label" ></View>
<View className={classNames("radio ", { checked: formData[index === 0 ? 'gender' : 'partner_gender'] === '男' })}></View>
</View>
<View className="flex-row" onClick={() => onIptChange({ detail: { value: '女' } }, index === 0 ? 'gender' : 'partner_gender')} >
<View className="sex-label"></View>
<View className={classNames("radio ", { checked: formData[index === 0 ? 'gender' : 'partner_gender'] === '女' })}></View>
</View>
</View>
</View>
</View>
<View className="user-form-item">
<View className='cell-item'>
<View className="cell-item-tit">是否拥有BIRKENSTOCK鞋履</View>
<View className='flex-row'>
<View className="flex-row" onClick={() => onIptChange({ detail: { value: '是' } }, index === 0 ? 'has_bought' : 'partner_has_bought')} style={{ paddingRight: '10rpx' }}>
<View className="sex-label"></View>
<View className={classNames("radio ", { checked: formData[index === 0 ? 'has_bought' : 'partner_has_bought'] === '是' })}></View>
</View>
<View className="flex-row" onClick={() => onIptChange({ detail: { value: '否' } }, index === 0 ? 'has_bought' : 'partner_has_bought')}>
<View className="sex-label"></View>
<View className={classNames("radio ", { checked: formData[index === 0 ? 'has_bought' : 'partner_has_bought'] === '否' })}></View>
</View>
</View>
</View>
</View>
<View className="user-form-item">
<View className='cell-item'>
<View className="cell-item-tit">常驻城市选填</View>
<Picker
mode='selector'
onChange={(e) => pickerChange(e, index === 0 ? 'city_name' : 'partner_city_name')}
range={areaList}
rangeKey="label"
>
<View className='flex-row'>
<View className="sex-label" style="minWidth: 120px;text-align: end;" >{formData[index === 0 ? 'city_name' : 'partner_city_name']}</View>
<View className="iconfont icon-arrowRight"></View>
</View>
</Picker>
</View>
</View>
{index === 0 && <View className="user-form-item">
<View className='cell-item'>
<View className="cell-item-tit">是否协同他人一起参加</View>
<View className='flex-row'>
<View onClick={() => handleAddApply(1)} className="flex-row" style={{ paddingRight: '10rpx' }}>
<View className="sex-label"></View>
<View className={classNames("radio ", { checked: formData['has_partner'] === '是' })}></View>
</View>
<View onClick={() => handleAddApply(0)} className="flex-row">
<View className="sex-label"></View>
<View className={classNames("radio ", { checked: formData['has_partner'] === '否' })}></View>
</View>
</View>
</View>
</View>}
</View>)}
<View className="sp-picker">
<View
className={classNames('mask', {
visible: visible
})}
onTap={handleClose}
catchtouchmove
></View>
<View
className={classNames('sp-picker-cnt', {
visible: visible
})}
>
<View className={classNames('sp-picker-hd')} catchtouchmove>
<Text className='center'>{isShare ? '分享' : '报名信息'}</Text>
<AtIcon onClick={handleClose} value='close' size={14} color='#000' ></AtIcon>
</View>
<View className='sp-picker-bd'>
{!isShare && formItem.map((item, index) => (
<View className="user-form-item" key={`userinfo-item__${index}`}>
<View className="user-form-item-title">{item.field_title}</View>
<View className="user-form-item-input">
{item.form_element === 'text' ? <Input
name={item.field_name}
value={formInfo[item.field_name]}
class='input-field-1'
placeholder={`请输入`}
onInput={(e) => onIptChange(e, item.field_name)}
/> : null}
</View>
</View>
))}
{isShare ? <Button openType="share" className={"btn share"} onClick={handleClose} plain>发送给朋友</Button> :
<View onClick={handleSubmit} className={"btn"}>{'确认报名信息'}</View>}
</View>
</View>
</View>
</SpPage>
)
}

View File

@ -0,0 +1,126 @@
.page-recommend-apply {
.sp-page-body {
padding: 0 50px 60px;
}
.activity_apply_time {
font-size: 30rpx;
font-weight: 500;
color: #000;
margin-bottom: 50rpx;
margin-top: 14rpx;
text-align: center;
}
.activity_apply_tit {
font-size: 34rpx;
font-weight: 500;
color: #000;
margin-bottom: 30rpx;
}
.user-form {
margin-bottom: 80px;
.icon-arrowRight {
color: #000;
font-size: 36rpx;
rotate: 90deg;
}
}
.user-form-item {
margin-bottom: 30rpx;
&-title {
margin-bottom: 6rpx;
}
&-ipt {
width: 100%;
color: #000 !important;
}
.cell-item {
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 6rpx;
background: #e1e1e1;
padding: 22rpx 22rpx 22rpx 42rpx;
color: #999;
&-tit {
font-size: 28rpx;
color: #000;
}
.flex-row {
// margin-left: 20rpx;
}
}
}
.flex-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.sex-label {
color: #000;
margin: 0 20px;
}
.radio {
width: 26px;
height: 26px;
border-radius: 50%;
/* prettier-ignore */
border: 1PX solid #000;
position: relative;
transition: all 0.3s ease-in-out 0s;
&.checked::after {
content: '';
display: block;
width: 18px;
height: 18px;
border-radius: 50%;
background-color: #000;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.sp-page-footer {
min-height: 200px;
padding: 0 50px;
.check-box {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
margin: 16px auto;
.icon-my {
font-size: 30px;
}
view {
font-size: 22px;
}
}
.bottom {
// position: fixed;
// bottom: 80px;
// left: 0;
// right: 0;
width: 100%;
margin-bottom: 50px;
.btn {
display: flex;
height: 80px;
align-items: center;
justify-content: center;
font-size: 32px;
line-height: 1;
background: #000;
color: #fff;
border-radius: 6px;
&.notop {
margin-top: 10px;
}
&-disabled {
background: #666;
}
}
}
}
}

View File

@ -1,14 +1,14 @@
import React, { useEffect } from 'react'
import { View, Text, Input, Image } from '@tarojs/components'
import Taro, { getCurrentInstance, useDidShow } from '@tarojs/taro'
import { SpPage, SpHtml, SpCheckbox } from '@/components'
import { View, Text, Input, Image, Button } from '@tarojs/components'
import Taro, { getCurrentInstance, useDidShow, useShareAppMessage } from '@tarojs/taro'
import { SpPage, SpHtml, SpCheckbox, SpLogin, SpImage } from '@/components'
import { useSelector } from 'react-redux'
import { getActiveDetail } from '@/api/community'
import { useImmer } from 'use-immer'
import api from '@/api'
import dayjs from 'dayjs'
import { AtIcon } from 'taro-ui'
import { classNames, navigateTo } from '@/utils'
import { useLogin } from '@/hooks'
import './detail.scss'
const initState = {
@ -17,88 +17,126 @@ const initState = {
visible: false,
checked: false,
formInfo: {},
status: ''
status: '',
isShare: false,
alwaysBackUrl: "/pages/index",
isSub: false,
changci: [],
applyStatus: false,
}
export default function detail () {
const $instance = getCurrentInstance()
const [state, setState] = useImmer(initState)
const { appName } = useSelector((_state) => _state.sys)
const { userInfo = {} } = useSelector((_state) => _state.user)
const { isLogin } = useLogin({
autoLogin: true,
})
useDidShow(() => {
// useDidShow(() => {
// }, [])
const getActiveDetail = async () => {
const { id: activity_id, alwaysBackUrl } = $instance.router.params
if (!activity_id) return
const { status, changci = [], activity_info = {}, total_count, user_code, recordList = {} } = await api.user.registrationActivity({ activity_id })
const _applyStatus = changci.some((item) => item.has_stauts == 1)
if (_applyStatus && !alwaysBackUrl) {
Taro.redirectTo({ url: '/pages/recommend/status?&id=' + activity_id })
return
}
const _start = dayjs(activity_info.start_time * 1000)
const _end = dayjs(activity_info.end_time * 1000)
if (alwaysBackUrl) {
setState(draft => {
draft.alwaysBackUrl = alwaysBackUrl + "?id=" + activity_id
})
}
const _item = recordList.list?.[0] || {}
setState(draft => {
draft.isLoading = false
draft.activeInfo = {
...activity_info,
user_code,
total_count,
start: `${_start.month() + 1}${_start.date()}`,
end: `${_end.month() + 1}${_end.date()}`,
status: _item.is_write_off === '1' ? 'done' : _item.status,
isLoading: false
}
draft.checked = !!_item
// MM-DD
draft.changci = changci.map((item, index) => ({ index: index + 1, start: dayjs(item.start_time).format('HH:mm'), end: dayjs(item.end_time).format('HH:mm'), limit: item.join_limit, join: item.has_join_num, id: item.registration_session_id, activity_id: item.activity_id, has_stauts: item.has_stauts == 1 }))
draft.applyStatus = _applyStatus
})
}
useEffect(() => {
getActiveDetail()
}, [])
useEffect(() => {
setState(draft => {
draft.formInfo = {
username: userInfo.username,
mobile: userInfo.mobile,
}
})
}, [userInfo])
const getActiveDetail = async () => {
const { id: activity_id } = $instance.router.params
if (!activity_id) return
const { status, activity_info = {}, total_count, user_code } = await api.user.registrationActivity({ activity_id })
const _start = dayjs(activity_info.start_time * 1000)
const _end = dayjs(activity_info.end_time * 1000)
setState(draft => {
draft.isLoading = false,
draft.activeInfo = {
...activity_info,
user_code,
total_count,
start: `${_start.month() + 1}${_start.date()}`,
end: `${_end.month() + 1}${_end.date()}`,
status,
isLoading: false
if (isLogin && userInfo) {
setState(draft => {
draft.formInfo = {
username: userInfo.username,
mobile: userInfo.mobile,
}
})
}
}, [userInfo, isLogin])
const { isLoading, activeInfo = {}, changci, visible, formInfo, checked, status, isShare, alwaysBackUrl, isSub, applyStatus } = state
const handleConfirm = async () => {
if (!isLogin || !userInfo) return
if (activeInfo.status) {
Taro.navigateTo({ url: '/pages/recommend/status?success=true&id=' + activeInfo.activity_id })
return
}
if (!checked) {
const res = await Taro.showModal({
title: '提示',
content: `请先阅读并同意${appName}活动细则`,
showCancel: true,
cancel: '取消',
cancelText: '拒绝',
confirmText: '同意',
cancelColor: '#a5a5a5',
confirmColor: '#000'
})
if (!res.confirm) return
setState((draft) => {
draft.checked = true
draft.visible = true
})
}
setState((draft) => {
draft.visible = true
})
}
const { isLoading, activeInfo = {}, visible, formInfo, checked, status } = state
const renderFooter = () => {
if (isLoading || status === 'passed') {
return null
}
return <View className={"bottom"}>
<View className='check-box'>
<SpCheckbox checked={checked} colors="#000" onChange={() => setState((draft) => { draft.checked = !checked })} />
<SpCheckbox disabled={!!activeInfo.status} checked={checked} colors="#000" onChange={() => setState((draft) => { draft.checked = !checked })} />
<View>
<Text onClick={() => setState((draft) => { draft.checked = !checked })} >我已经阅读并同意</Text>
<Text onClick={() => !activeInfo.status && setState((draft) => { draft.checked = !checked })} >我已经阅读并同意</Text>
<Text
onClick={() => Taro.navigateTo({ url: '/subpages/auth/reg-rule?type=member_logout' })}
onClick={() => Taro.navigateTo({ url: '/subpages/auth/reg-rule?type=activity_rule' })}
style={`color: #000000;text-decoration: underline;`}
>
{`${appName}活动细则》`}
</Text>
</View>
</View>
<View onClick={async () => {
if (!checked) {
const res = await Taro.showModal({
title: '提示',
content: `请先阅读并同意${appName}活动细则`,
showCancel: true,
cancel: '取消',
cancelText: '拒绝',
confirmText: '同意',
cancelColor: '#a5a5a5',
confirmColor: '#000'
})
if (!res.confirm) return
setState((draft) => {
draft.checked = true
draft.visible = true
})
}
setState((draft) => {
draft.visible = true
})
}} className={"btn"}>{!status ? '确认报名' : status === 'pending' ? '报名中' : '已报名'}</View>
{/* <View onClick={handleConfirm} className={"btn"}>{!status ? '确认报名' : status === 'pending' ? '报名中' : '已报名'}</View> */}
<SpLogin onChange={getActiveDetail}>
<View onClick={handleConfirm} className={"btn"}>{!activeInfo.status ? '确认报名' : '报名详情'}</View>
</SpLogin>
</View>
}
@ -110,6 +148,16 @@ export default function detail () {
}
const handleSubmit = async () => {
if (isSub) {
return
}
setState((draft) => {
draft.isSub = true
})
if (isShare) {
handeleShare()
return
}
if (!formInfo.username?.trim()) {
Taro.showToast({
title: '请输入姓名',
@ -139,49 +187,109 @@ export default function detail () {
activity_id: activeInfo.activity_id
})
if (status) {
// Taro.showToast({
// title: '报名成功',
// icon: 'none'
// })
setState((draft) => {
draft.visible = false
draft.status = status
})
const templeparams = {
temp_name: 'yykweishop',
source_type: 'activity'
}
const { template_id } = await api.user.newWxaMsgTmpl(templeparams)
Taro.requestSubscribeMessage({
tmplIds: ['tGJR7BS3HM9xLD4QUdBwtTAJkgzfl7cw_8-ngd74JM4'],
tmplIds: template_id,
success: () => {
// onSubscribe()
console.log("🚀 ~ onSubscribe:", 'onSubscribe')
},
fail: (err) => {
console.log("🚀 ~ err:", err)
// onSubscribe()
},
complete: () => {
Taro.navigateTo({ url: '/pages/recommend/status?success=true&id=' + activeInfo.activity_id })
}
})
}
setState((draft) => {
draft.isSub = false
})
}
const onClickShare = () => {
setState((draft) => {
draft.visible = true
draft.isShare = true
})
}
useShareAppMessage(() => {
return {
title: activeInfo.activity_name,
path: `/pages/recommend/detail?id=${activeInfo.activity_id}`,
// imageUrl: activeInfo.pics[0]
imageUrl: `${process.env.APP_IMAGE_CDN_NEW}/share-logo.jpg`
}
})
const handleClose = () => {
setState((draft) => {
draft.visible = false
})
setTimeout(() => {
setState((draft) => {
draft.isShare = false
})
}, 800)
}
const handleGoApply = (item) => {
if (item.has_stauts) {
navigateTo('/pages/recommend/status?id=' + activeInfo.activity_id + '&time=')
} else {
if (applyStatus) return
navigateTo('/pages/recommend/apply?id=' + activeInfo.activity_id + '&time=')
Taro.navigateTo({
url: '/pages/recommend/apply?id=' + activeInfo.activity_id,
success: (res) => {
res.eventChannel.emit('apply', item)
}
})
}
}
const formItem = activeInfo.formdata?.key_index || []
// !!activeInfo?.total_count ? <></> :
// renderFooter={!!activeInfo?.total_count ? <></> : renderFooter()}
return (
<SpPage renderFooter={!!activeInfo?.total_count ? <></> : renderFooter()} loading={isLoading} className='page-recommend-detail' isBlack>
<View className="activity_name">{activeInfo.activity_name}</View>
<View className="activity_time">{activeInfo.start} - {activeInfo.end}</View>
<SpPage loading={isLoading} className='page-recommend-detail' alwaysBackUrl={alwaysBackUrl} isBlack>
<View style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<SpImage src='member/logo-black.png' height={42} mode='heightFix' isNew ></SpImage>
<Image onClick={onClickShare} className="share_icon" src={require('../../assets/share.jpg')} mode='widthFix' ></Image>
</View>
<View className="name-box">
<View className="activity_name">{activeInfo.activity_name}</View>
</View>
<View className="activity_time">{activeInfo.start == activeInfo.end ? activeInfo.start : `${activeInfo.start} - ${activeInfo.end}`}</View>
<View className="activity_addr">
<Image mode="widthFix" src={require('@/assets/icon/map.png')}></Image>
<Text>{activeInfo.address}</Text>
</View>
<SpHtml content={activeInfo.intro} />
<View className="activity_apply_tit">
<View className="big">选择活动时段报名</View>
<View className="small">(为确保您的体验活动当天每场次仅限5人)</View>
</View>
<View style={{ paddingBottom: '80px' }}>
{changci.length > 0 && changci.map((item, index) => <View className='time-item' key={index + '__item'}>
<Text className="time-item-title">{item.index} {item.start}-{item.end}</Text>
<View className={`btn ${(item.limit - item.join <= 0) && !item.has_stauts ? 'disabled' : ''}`} onClick={() => handleGoApply(item)} >{item.has_stauts ? '已报名' : `${item.limit - item.join}席可选`}</View>
</View>)}
</View>
<View className="sp-picker">
<View
className={classNames('mask', {
visible: visible
})}
onTap={() => setState((draft) => {
draft.visible = false
})}
onTap={handleClose}
catchtouchmove
></View>
<View
@ -190,13 +298,11 @@ export default function detail () {
})}
>
<View className={classNames('sp-picker-hd')} catchtouchmove>
<Text className='center'>{'报名信息'}</Text>
<AtIcon onClick={() => setState((draft) => {
draft.visible = false
})} value='close' size={14} color='#000' ></AtIcon>
<Text className='center'>{isShare ? '分享' : '报名信息'}</Text>
<AtIcon onClick={handleClose} value='close' size={14} color='#000' ></AtIcon>
</View>
<View className='sp-picker-bd'>
{formItem.map((item, index) => (
{!isShare && formItem.map((item, index) => (
<View className="user-form-item" key={`userinfo-item__${index}`}>
<View className="user-form-item-title">{item.field_title}</View>
<View className="user-form-item-input">
@ -210,7 +316,8 @@ export default function detail () {
</View>
</View>
))}
<View onClick={handleSubmit} className={"btn"}>确认报名信息</View>
{isShare ? <Button openType="share" className={"btn share"} onClick={handleClose} plain>发送给朋友</Button> :
<View onClick={handleSubmit} className={"btn"}>{'确认报名信息'}</View>}
</View>
</View>
</View>

View File

@ -2,20 +2,30 @@
.sp-page-body {
padding: 30px 58px;
}
.name-box {
display: flex;
align-items: flex-start;
justify-content: space-between;
}
.share_icon {
height: 60px;
width: 40px;
padding: 10px 0 10px 20px;
}
.activity_name {
font-size: 40px;
font-weight: bold;
margin-bottom: 30px;
margin-bottom: 24px;
}
.activity_time {
font-size: 26px;
// color: #999;
margin-bottom: 60px;
margin-bottom: 50px;
}
.activity_addr {
font-size: 26px;
// color: #999;
margin-bottom: 40px;
margin-bottom: 30px;
display: flex;
align-items: center;
> image {
@ -119,6 +129,9 @@
&-disabled {
background: #666;
}
&.share {
margin: 80px 0;
}
}
.user-form {
margin-top: 30px;
@ -190,46 +203,84 @@
opacity: 1;
}
}
}
.sp-page-footer {
min-height: 200px;
padding: 0 50px;
.check-box {
margin-top: 100px;
width: 100%;
.activity_apply_tit {
color: #000;
display: flex;
align-items: baseline;
margin-bottom: 20rpx;
.big {
font-size: 30rpx;
font-weight: 500;
}
.small {
font-size: 20rpx;
margin-left: 10rpx;
}
}
.time-item {
display: flex;
align-items: center;
justify-content: center;
margin: 10px auto;
.icon-my {
font-size: 36px;
}
view {
font-size: 22px;
justify-content: space-between;
border-radius: 6rpx;
background: #e1e1e1;
padding: 16rpx 16rpx 16rpx 36rpx;
color: #999;
margin-bottom: 16rpx;
.btn {
width: 140rpx;
height: 54rpx;
line-height: 54rpx;
border-radius: 6rpx;
font-size: 24rpx;
text-align: center;
color: #fff;
background: #000;
&.disabled {
background: #c7c7c795;
opacity: 0.8;
}
}
}
.bottom {
// position: fixed;
// bottom: 80px;
// left: 0;
// right: 0;
width: 100%;
margin-bottom: 50px;
.btn {
.sp-page-footer {
min-height: 200px;
padding: 0 50px;
.check-box {
margin-top: 100px;
width: 100%;
display: flex;
height: 80px;
align-items: center;
justify-content: center;
font-size: 32px;
line-height: 1;
background: #000;
color: #fff;
border-radius: 6px;
&.notop {
margin-top: 10px;
margin: 10px auto;
.icon-my {
font-size: 30px;
}
&-disabled {
background: #666;
view {
font-size: 22px;
}
}
.bottom {
// position: fixed;
// bottom: 80px;
// left: 0;
// right: 0;
width: 100%;
margin-bottom: 50px;
.btn {
display: flex;
height: 80px;
align-items: center;
justify-content: center;
font-size: 32px;
line-height: 1;
background: #000;
color: #fff;
border-radius: 6px;
&.notop {
margin-top: 10px;
}
&-disabled {
background: #666;
}
}
}
}

View File

@ -96,17 +96,17 @@ export default class RecommendList extends Component {
// this.setState({
// list: []
// })
// setTimeout(() => {
// // this.nextPage()
// // Taro.hideLoading()
// this.setState({
// page: {
// isLoading: false
// }
// })
// }, 200)
setTimeout(() => {
// this.nextPage()
// Taro.hideLoading()
this.setState({
page: {
isLoading: false
}
})
}, 300)
// this.praiseNum()
this.getActiveDetail()
// this.getActiveDetail()
}
onShareAppMessage () {
@ -615,6 +615,11 @@ export default class RecommendList extends Component {
url: url + activeInfo.activity_id
})
}
handleBackToIndex = () => {
Taro.redirectTo({
url: '/pages/index'
})
}
render () {
const {
@ -642,7 +647,7 @@ export default class RecommendList extends Component {
const height = windowWidth * 9 / 17
return (
<SpPage renderFooter={<SpTabbar />} loading={page.isLoading} className='has-nav' title="" isBlack isTop>
<SpPage renderFooter={<SpTabbar />} loading={page.isLoading} className='has-nav' title="" isBlack >
<View className='page-recommend-list'>
{false && <>
<View className='recommend-list__toolbar'>
@ -777,7 +782,9 @@ export default class RecommendList extends Component {
)}
</ScrollView>
</>}
{/* {page.isLoading ? <Loading></Loading> :
{/* 鞋床故事 */}
{page.isLoading ? <Loading></Loading> :
<View className="recommend-content">
<Video
id="recommend-video"
@ -816,9 +823,14 @@ export default class RecommendList extends Component {
<SpImage height={height * 2} width={windowWidth * 2} mode="aspectFill" src='recommend/08.jpg' isShowMenuByLongpress={false} lazyLoad isNew />
<SpImage height={height * 2} width={windowWidth * 2} mode="aspectFill" src='recommend/09.jpg' isShowMenuByLongpress={false} lazyLoad isNew />
</View>
<View className="content-btn" onClick={this.handleBackToIndex} >
返回首页
</View>
</View>
} */}
{page.isLoading ? <Loading></Loading> :
}
{/* 活动部分 */}
{/* {page.isLoading ? <Loading></Loading> :
<View className="active-content">
<Swiper
className={classNames('swiper')}
@ -880,7 +892,7 @@ export default class RecommendList extends Component {
))}
</View>
</View>
}
} */}
<BackToTop show={showBackToTop} onClick={this.scrollBackToTop} />
</View>

View File

@ -38,12 +38,26 @@
.content-item {
margin-bottom: 50px;
}
.content-btn {
margin: 0 auto;
width: 650px;
height: 80px;
line-height: 80px;
text-align: center;
/* prettier-ignore */
border: 1PX solid var(--color-primary);
font-size: 34px;
border-radius: 6px;
margin-top: 30px;
margin-bottom: 70px;
}
}
.active-content {
position: relative;
.swiper {
--height: calc(var(--status-bar-height) + #{$tabbar-height} + var(--area-bottom-height));
width: 100%;
height: calc(100vh - #{$page-ipx-footer-height} - var(--status-bar-height));
height: calc(100vh - var(--height));
transition: height 0.3s ease-in-out;
position: relative;
}

View File

@ -1,13 +1,13 @@
import React, { useEffect } from 'react'
import { View, Text, Input, Image } from '@tarojs/components'
import Taro, { getCurrentInstance, useDidShow } from '@tarojs/taro'
import React, { useEffect, useState } from 'react'
import { View, Text, Input, Image, Button } from '@tarojs/components'
import Taro, { getCurrentInstance, useDidShow, useShareAppMessage } from '@tarojs/taro'
import { SpPage, SpHtml, SpCheckbox, SpImage } from '@/components'
import { useSelector } from 'react-redux'
import { getActiveDetail } from '@/api/community'
import { useImmer } from 'use-immer'
import api from '@/api'
import dayjs from 'dayjs'
import { AtIcon } from 'taro-ui'
import { AtIcon, AtModal } from 'taro-ui'
import { classNames, navigateTo, isArray } from '@/utils'
import QRCode from 'qrcode'
import './status.scss'
@ -17,12 +17,16 @@ const initState = {
cur_activity_info: [],
loading: true,
activeInfo: {},
qrUrl: ''
qrUrl: '',
visible: false,
session: {},
record: {}
}
export default function status () {
const $instance = getCurrentInstance()
const [state, setState] = useImmer(initState)
const { cur_activity_info, loading, activeInfo, qrUrl } = state
const [showModal, setShowModal] = useState(false)
const { cur_activity_info, loading, activeInfo, qrUrl, visible, session, record } = state
useEffect(() => {
getActiveDetail()
@ -30,23 +34,25 @@ export default function status () {
const getActiveDetail = async () => {
const { id, success } = $instance.router.params
const { activity_info = {}, total_count, user_code, recordList = {} } = await api.user.registrationActivity({ activity_id: id })
const { activity_info = {}, changci = [], total_count, recordList = {} } = await api.user.registrationActivity({ activity_id: id })
const _start = dayjs(activity_info.start_time * 1000)
const _end = dayjs(activity_info.end_time * 1000)
const _session = changci.find(item => item.has_stauts == 1) || {}
const _item = _session.recordList?.[0] || {}
let url = ''
const qrData = JSON.stringify({
activity_id: id,
user_code: user_code || ''
user_code: _item.user_code || ''
})
await QRCode.toDataURL(qrData).then((_url) => {
url = _url
})
const _item = recordList.list?.[0] || {}
const list = _item.content?.[0]?.formdata || []
const record = {}
list.map((item) => {
record[item.field_name] = item.answer || ''
})
console.log("🚀 ~ file: status.js:52 ~ record:", _item)
setState(draft => {
draft.activeInfo = {
...activity_info,
@ -58,6 +64,8 @@ export default function status () {
}
draft.loading = false
draft.qrUrl = url
draft.session = _session
draft.record = _item
})
}
@ -110,29 +118,58 @@ export default function status () {
}
const handleCancel = async () => {
const res = await Taro.showModal({
title: '提示',
content: `确定要取消预约吗?`,
showCancel: true,
cancel: '取消',
cancelText: '取消',
confirmText: '确认',
cancelColor: '#a5a5a5',
confirmColor: '#000'
})
if (!res.confirm) return
setShowModal(false)
// const res = await Taro.showModal({
// title: '提示',
// content: `确定要取消预约吗?`,
// showCancel: true,
// cancel: '取消',
// cancelText: '取消',
// confirmText: '确认',
// cancelColor: '#a5a5a5',
// confirmColor: '#000'
// })
// if (!res.confirm) return
const { id } = $instance.router.params
await api.user.cancelRegistrationRecord({
activity_id: id
activity_id: id,
registration_session_id: session?.registration_session_id
})
navigateTo('/pages/recommend/list')
navigateTo('/pages/index')
}
const onClickShare = () => {
setState((draft) => {
draft.visible = true
})
}
const handleClose = () => {
setState((draft) => {
draft.visible = false
})
}
useShareAppMessage(() => {
return {
title: activeInfo.activity_name,
path: `/pages/recommend/detail?id=${activeInfo.activity_id}`,
// imageUrl: activeInfo.pics[0]
imageUrl: `${process.env.APP_IMAGE_CDN_NEW}/share-logo.jpg`
}
})
// {activeInfo.status === 'pending' ? '待审核' : '报名成功'}
return (
<SpPage loading={loading} title={activeInfo.status === 'pending' ? '待审核' : '预约成功'} className='page-recommend-status' isBlack>
<View className="">
<SpCheckbox checked={true} colors="#000" label={activeInfo.status === 'pending' ? '待审核' : activeInfo.status === 'done' ? '已签到' : "已预约"}></SpCheckbox>
<SpPage loading={loading} title="报名成功" className='page-recommend-status' alwaysBackUrl="/pages/index" isBlack>
<View className="tit__label">
{/* <SpCheckbox checked={true} colors="#000" label={activeInfo.status === 'pending' ? '待审核' : activeInfo.status === 'done' ? '已签到' : "已预约"}></SpCheckbox> */}
{activeInfo.status === 'done' ? '已签到' : "待签到"}
</View>
<View style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<SpImage src='member/logo-black.png' height={42} mode='heightFix' isNew ></SpImage>
<Image onClick={onClickShare} className="share_icon" src={require('../../assets/share.jpg')} mode='widthFix' ></Image>
</View>
<View className="name-box">
<View className="activity_name">{activeInfo.activity_name}</View>
</View>
<View className="activity_name">{activeInfo?.activity_name || ''}</View>
<View className="activity_info">
<View className="activity_info-item flex-col">
<Text className="title">姓名</Text>
@ -143,9 +180,22 @@ export default function status () {
<Text className="value">{activeInfo?.mobile}</Text>
</View>
</View>
{activeInfo?.has_partner === '是' && <>
<View style={{ margin: '20px 0 14px' }}>同行朋友</View>
<View className="activity_info">
<View className="activity_info-item flex-col">
<Text className="title">姓名</Text>
<Text className="value">{activeInfo?.partner_name}</Text>
</View>
<View className="activity_info-item flex-col">
<Text className="title">手机号</Text>
<Text className="value">{activeInfo?.partner_mobile}</Text>
</View>
</View>
</>}
<View className="activity_time flex-col">
<Text className="title">活动时间</Text>
<Text className="value">{activeInfo?.start} - {activeInfo?.end}</Text>
<Text className="value">{activeInfo.start == activeInfo.end ? activeInfo.start : `${activeInfo.start} - ${activeInfo.end} ${session.start_time.substr(11, 5)} - ${session.end_time.substr(11, 5)}`}</Text>
</View>
<View className="activity_addr flex-col">
<Text className="title">活动地点</Text>
@ -153,15 +203,50 @@ export default function status () {
<Image mode="widthFix" src={require('@/assets/icon/map.png')}></Image>
<Text className='value'>{activeInfo?.address}</Text></View>
</View>
<View className="activity_intro" onClick={() => Taro.navigateTo({ url: '/pages/recommend/detail?id=' + activeInfo?.activity_id })}>活动介绍</View>
<View className="activity_intro" onClick={() => Taro.navigateTo({ url: '/pages/recommend/detail?id=' + activeInfo?.activity_id + '&alwaysBackUrl=/pages/recommend/status' })}>活动介绍</View>
{activeInfo.status === 'passed' && activeInfo.status !== 'done' ? <View className="code-box flex-col">
<SpImage src={`member/logo-lan.png`} height={40} mode='heightFix' isNew />
<View className="img-box">
<Image className='member-code-box-qr' mode='aspectFit' src={qrUrl} />
</View>
<View className="code-box-txt">入场请出示预约凭证</View>
</View> : <View style={'height:315px;'}></View>}
{activeInfo.status !== 'done' && <View className="cancel-txt" onClick={handleCancel}>取消预约</View>}
</View> : <View style={{ height: activeInfo.status === 'done' ? '0px' : '315px' }}></View>}
{activeInfo.status !== 'done' && <View className="cancel-txt" onClick={() => setShowModal(true)}>取消预约</View>}
<View className="sp-picker">
<View
className={classNames('mask', {
visible: visible
})}
onTap={handleClose}
catchtouchmove
></View>
<View
className={classNames('sp-picker-cnt', {
visible: visible
})}
>
<View className={classNames('sp-picker-hd')} catchtouchmove>
<Text className='center'>{'分享'}</Text>
<AtIcon onClick={handleClose} value='close' size={14} color='#000' ></AtIcon>
</View>
<View className='sp-picker-bd'>
<Button openType="share" className={"btn share"} onClick={handleClose} plain>发送给朋友</Button>
</View>
</View>
</View>
<AtModal
isOpened={showModal}
title=''
cancelText='是,我要取消'
confirmText='否,我要保留'
onClose={() => setShowModal(false)}
onCancel={handleCancel}
onConfirm={() => {
setShowModal(false)
}}
content={'尊敬的用户:\n现场活动席位数量有限如取消目前报名\n可能导致您无法选择其他时间段活动\n请问您确认要取消吗'}
/>
</SpPage>
)
}

View File

@ -1,5 +1,8 @@
.page-recommend-status {
padding: 10px 58px;
.sp-page-body {
padding-bottom: 50px;
}
.sp-checkbox-new {
padding: 30px 0;
.icon-checkbox-xuanzhong {
@ -9,6 +12,12 @@
font-size: 40px;
}
}
.tit__label {
font-size: 40px;
text-align: center;
margin-bottom: 20px;
font-weight: bold;
}
.activity_name {
font-size: 40px;
font-weight: bold;
@ -49,14 +58,14 @@
.activity_time {
font-size: 24px;
color: #999;
margin-bottom: 50px;
margin-bottom: 80px;
}
.activity_addr {
font-size: 24px;
color: #999;
}
.activity_intro {
font-size: 30px;
font-size: 34px;
text-decoration: underline;
margin: 90px 0 50px;
}
@ -91,9 +100,195 @@
}
}
.cancel-txt {
font-size: 18px;
font-size: 22px;
text-align: center;
margin-top: 30px;
margin-top: 20px;
text-decoration: underline;
font-weight: bold;
}
.name-box {
display: flex;
align-items: flex-start;
justify-content: space-between;
}
.share_icon {
height: 60px;
width: 40px;
padding: 10px 0 10px 20px;
}
.sp-picker {
.mask {
position: fixed;
z-index: 302;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
visibility: hidden;
opacity: 0;
transition: all 0.3s ease;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
// color: #fff;
&.visible {
visibility: visible;
opacity: 1;
}
}
&-cnt {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
transition: all 0.3s ease-in-out;
transform: translateY(100%);
z-index: 503;
background-color: #fff;
border-radius: 30rpx 30rpx 0 0;
&.visible {
transform: translateY(0);
}
}
&-hd {
padding: 30px 50px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: none;
position: relative;
font-size: 26px;
.center {
margin: auto;
}
.at-icon-close {
padding: 20px 30px;
position: absolute;
right: 20px;
}
}
&-bd {
padding: 0 50px 50px;
&-item {
display: flex;
align-items: center;
border-bottom: none;
padding: 0 90px;
view {
color: #000;
font-size: 26px;
line-height: 1;
}
.tit {
padding: 28px 50px 28px 30px;
box-sizing: border-box;
}
.content {
display: flex;
flex: 1;
color: #000;
.icon-qianwang-01 {
font-size: 20px;
}
}
}
.btn {
margin-top: 130px;
display: flex;
height: 80px;
align-items: center;
justify-content: center;
font-size: 32px;
line-height: 1;
background: #000;
color: #fff;
border-radius: 6px;
&.notop {
margin-top: 10px;
}
&-disabled {
background: #666;
}
&.share {
margin: 80px 0;
}
}
.user-form {
margin-top: 30px;
&-item {
margin-bottom: 50px;
&-title {
font-size: 24px;
color: #000;
margin-bottom: 10px;
}
&-input {
background: #e5e5e5;
border-radius: 6px;
padding: 20px 40px;
color: #000;
position: relative;
.icon-arrowRight {
font-size: 34px;
position: absolute;
right: 30px;
top: 30%;
// transform: translateY(-50%);
color: #000;
rotate: 90deg;
}
}
&-phone {
width: 100%;
}
.picker {
height: 40px;
width: 100%;
color: #a5a5a5;
&-value {
color: #000;
&.placeholder {
color: #a5a5a5 !important;
}
}
}
}
}
}
}
.at-modal {
&__overlay {
background-color: rgba(0, 0, 0, 0.6);
}
&__container {
width: 560px;
border-radius: 10px;
}
&__header {
font-size: 40px;
font-weight: bold;
padding-top: 40px;
}
&__content {
padding: 60rpx 20rpx 50rpx;
text-align: center;
min-height: auto;
display: flex;
.content-simple {
font-size: 28px;
white-space: pre-wrap;
min-height: 150px;
text-align: left;
display: flex;
text {
margin: 0 auto;
}
}
}
.at-modal__footer--simple .at-modal__action > button:last-child:nth-child(2) {
color: #222;
}
}
}

View File

@ -66,7 +66,7 @@ const initialState = {
market_price: false
},
item_page: {
market_price: false,
market_price: true,
member_price: false,
svip_price: false
},

View File

@ -193,7 +193,8 @@
/* prettier-ignore */
// border: 1PX solid #E5E5E5;
// color: #444;
border: 1px solid #000;
/* prettier-ignore */
border: 1PX solid #000;
color: #000;
}
&--default {

View File

@ -4,6 +4,11 @@
padding: 36px 0 37px;
&-good {
position: relative;
.sp-order-item {
&__bd {
width: 66%;
}
}
}
// &__fix {
// display: flex;

View File

@ -77,7 +77,6 @@ export default class TradeItem extends Component {
// 修改地址
clickToEditAddress () {
const { choose } = this.props.info
console.log("🚀 ~ TradeItem ~ this.props.info:", this.props.info)
return
Taro.navigateTo({
url: `/marketing/pages/member/address?isSelected=${choose}`
@ -174,18 +173,18 @@ export default class TradeItem extends Component {
<View className='trade-item__ft-actions'></View>
<View className='trade-item__ft-bd'>
{/* <Text className='trade-item__status'>{info.status_desc}</Text> */}
{false && (info.order_status_des === 'PAYED' || info.order_status_des === 'NOTPAY') &&
{(info.order_status_des === 'PAYED' || info.order_status_des === 'NOTPAY') &&
info.can_apply_cancel != 0 &&
!info.is_logistics &&
(info.receipt_type !== 'dada' || (info.dada && info.dada.dada_status === 0)) ? (
<Button
className='btn-action'
style={`box-shadow: 0 0 0 1PX ${colors.data[0].primary}; color: ${colors.data[0].primary}`}
// onClick={this.handleClickBtn.bind(this, 'cancel')}
onClick={this.clickToEditAddress.bind(this)}
onClick={this.handleClickBtn.bind(this, 'cancel')}
// onClick={this.clickToEditAddress.bind(this)}
>
{/* 取消订单 */}
修改地址
取消订单
{/* 修改地址 */}
</Button>
) : null}
{info.pay_status === 'PAYED' &&
@ -268,7 +267,7 @@ export default class TradeItem extends Component {
查看物流
</Button>
)}
{!info.aftersales_bn ? <Button
{!info.aftersales_status ? <Button
className='btn-action'
style={`background: ${colors.data[0].primary}`}
// onClick={this.handleClickBtn.bind(this, 'detail')}
@ -314,7 +313,7 @@ export default class TradeItem extends Component {
</Button>
) : null} */}
{
!info.aftersales_bn && (
info.can_apply_aftersales === 1 && (!info.aftersales_status) && info.is_rate != 1 && (
<Button
className='btn-action'
style={`box-shadow: 0 0 0 1PX ${colors.data[0].primary}; color: ${colors.data[0].primary}`}
@ -336,7 +335,7 @@ export default class TradeItem extends Component {
</View>
</View>
)}
{!customFooter && !!info.aftersales_bn && info.status !== 'WAIT_BUYER_CONFIRM_GOODS' && (
{!customFooter && info.aftersales_status && info.status !== 'WAIT_BUYER_CONFIRM_GOODS' && (
<View className='trade-item__ft'>
<View className='trade-item__ft-actions'></View>
<View className='trade-item__ft-bd'>

View File

@ -138,7 +138,7 @@ export default class TradeDetail extends Component {
delivery_time: 'delivery_time',
aftersales_status: 'aftersales_status',
pic_path: 'pic',
title: ({ item_name }) => item_name,
title: ({ item_name, item_name_2 }) => item_name_2 || item_name,
type: 'type',
delivery_status: 'delivery_status',
origincountry_name: 'origincountry_name',
@ -304,6 +304,7 @@ export default class TradeDetail extends Component {
tradeInfo,
distributor: data.distributor
})
console.log("🚀 ~ file: detail.js:307 ~ TradeDetail ~ info:", info)
}
handleCopy = async () => {
@ -468,8 +469,12 @@ export default class TradeDetail extends Component {
// Taro.navigateTo({
// url: `/subpage/pages/trade/after-sale-detail?id=${info.tid}`
// })
let url = `/subpages/trade/after-sale?id=${info.tid}`
if (info.status === "WAIT_SELLER_SEND_GOODS") {
url += '&type=ONLY_REFUND'
}
Taro.navigateTo({
url: `/subpages/trade/after-sale?id=${info.tid}`
url
})
return
}
@ -756,7 +761,7 @@ export default class TradeDetail extends Component {
</View>
)}
<ScrollView scroll-y className='scroll-view' style={{ bottom: info.status === 'WAIT_BUYER_PAY' || info.can_apply_aftersales === 1 || info.status === 'WAIT_BUYER_CONFIRM_GOODS' ? '140rpx' : '40rpx' }} scrollIntoView={scrollIntoView}>
<ScrollView scroll-y className='scroll-view' style={{ bottom: info.status === 'WAIT_BUYER_PAY' || info.can_apply_aftersales === 1 || info.status === 'WAIT_BUYER_CONFIRM_GOODS' || info.status === "WAIT_SELLER_SEND_GOODS" ? '150rpx' : '40rpx' }} scrollIntoView={scrollIntoView}>
{false && <View className='trade-detail-header' id='order-0'>
<View className='trade-detail-waitdeliver'>
{info.is_logistics && <View className='oneline'>线上订单</View>}
@ -1036,18 +1041,18 @@ export default class TradeDetail extends Component {
)}
</View> */}
{/* {!info.is_logistics &&
info.can_apply_cancel != 0 &&
(info.status === 'WAIT_BUYER_PAY' ||
(info.status === 'WAIT_SELLER_SEND_GOODS' &&
info.order_status_des !== 'PAYED_WAIT_PROCESS' &&
info.order_status_des !== 'PAYED_PARTAIL')) &&
(info.receipt_type !== 'dada' || (info.dada && info.dada.dada_status === 0)) && (
<View className='cancel__btn'>
<View className='btn' onClick={this.handleClickBtn.bind(this, 'cancel')}>
取消订单
</View>
info.can_apply_cancel != 0 &&
(info.status === 'WAIT_BUYER_PAY' ||
(info.status === 'WAIT_SELLER_SEND_GOODS' &&
info.order_status_des !== 'PAYED_WAIT_PROCESS' &&
info.order_status_des !== 'PAYED_PARTAIL')) &&
(info.receipt_type !== 'dada' || (info.dada && info.dada.dada_status === 0)) && (
<View className='cancel__btn'>
<View className='btn' onClick={this.handleClickBtn.bind(this, 'cancel')}>
取消订单
</View>
)} */}
</View>
)} */}
{/* </View> */}
{/* {info.remark && (
<View className='trade-detail-remark'>
@ -1222,7 +1227,8 @@ export default class TradeDetail extends Component {
// !VERSION_IN_PURCHASE &&
// !this.isPointitemGood() && (
// 先禁止掉!!!
info.can_apply_aftersales === 1 && (
// info.status === 'WAIT_SELLER_SEND_GOODS' || 未发货的
(info.can_apply_aftersales === 1) ? (
<View
className={`trade-detail__footer__btn ${info.is_logistics &&
'trade-detail__footer_active trade-detail__footer_allWidthBtn'
@ -1231,8 +1237,21 @@ export default class TradeDetail extends Component {
>
申请售后
</View>
)
) : <></>
}
{!info.is_logistics &&
info.can_apply_cancel != 0 &&
(info.status === 'WAIT_BUYER_PAY' ||
(info.status === 'WAIT_SELLER_SEND_GOODS' &&
info.order_status_des !== 'PAYED_WAIT_PROCESS' &&
info.order_status_des !== 'PAYED_PARTAIL')) &&
(info.receipt_type !== 'dada' || (info.dada && info.dada.dada_status === 0)) && (
<View className={`trade-detail__footer__btn ${info.is_logistics &&
'trade-detail__footer_active trade-detail__footer_allWidthBtn'
}`} onClick={this.handleClickBtn.bind(this, 'cancel')}>
取消订单
</View>
)}
{
// 继续购物 先禁止掉!!!
false && (info.status === 'WAIT_SELLER_SEND_GOODS' ||

View File

@ -26,7 +26,7 @@ $paddingBottom: 100px;
}
.scroll-view {
@include page-scroll(calc(var(--nav-height) + 16px), 140px);
@include page-scroll(calc(var(--nav-height) + 16px), 190px);
}
&.has-navbar {
@ -456,13 +456,14 @@ $paddingBottom: 100px;
position: fixed;
left: 0;
width: 100%;
height: 100px;
height: 150px;
// bottom: $edge-margin;
bottom: 0;
background: #fff;
display: flex;
justify-content: space-evenly;
align-items: center;
z-index: 10;
&__btn {
width: 338px;
height: 80px;

View File

@ -77,12 +77,13 @@ const initState = {
title: '',
totalFee: '',
toastShow: false,
invoiceInfo: {}
invoiceInfo: {},
oss_invoice_url: ''
}
function InvoiceInfo (props) {
const $instance = getCurrentInstance()
const [state, setState] = useImmer(initState)
const { formList, form, showModal, visible, showDetail, invoiceId, invoice, orderInfo, loading, title, totalFee, toastShow, invoiceInfo } = state
const { formList, form, showModal, visible, showDetail, invoiceId, invoice, orderInfo, loading, title, totalFee, toastShow, invoiceInfo, oss_invoice_url } = state
const pages = getCurrentPages()
const current = pages[pages.length - 1]
const eventChannel = current.getOpenerEventChannel()
@ -96,12 +97,13 @@ function InvoiceInfo (props) {
})
}
// 监听acceptDataFromOpenerPage事件获取上一页面通过eventChannel传送到当前页面的数据
eventChannel?.on('acceptDataFromOpenerPage', function ({ data }) {
eventChannel?.on('acceptDataFromOpenerPage', ({ data }) => {
setState((draft) => {
draft.orderInfo = data.order || data || {}
draft.oss_invoice_url = data.oss_invoice_url || ''
draft.invoiceInfo = data.invoice || {}
draft.form = data.order?.invoice || {}
draft.title = data.order?.title ? data.order.title === 'unit' ? '个人' : '企业' : ''
draft.form = data.order?.invoice || data.paramsInfo?.invoice_content || {}
draft.title = data.order ? data.order.title === 'unit' ? '个人' : '企业' : ''
draft.totalFee = data.order?.total_fee ?? ''
})
})
@ -183,7 +185,20 @@ function InvoiceInfo (props) {
})
return
}
eventChannel?.emit('acceptDataFromOpenedPage', { data: invoice })
let invoice_parmas = {
invoice_type: 'normal',
invoice_content: {
...form
}
}
const _invoice = {
invoiceTitle: content,
paramsInfo: invoice_parmas
}
setState((draft) => {
draft.invoice = _invoice
})
eventChannel?.emit('acceptDataFromOpenedPage', { data: _invoice })
Taro.navigateBack()
}
const handleInvoiceClick = () => {
@ -210,7 +225,8 @@ function InvoiceInfo (props) {
registration_number,
bankname,
bankaccount,
company_phone
company_phone,
email: form.email
}
}
// console.log("🚀 ~ invoice_parmas:", invoice_parmas)
@ -227,16 +243,23 @@ function InvoiceInfo (props) {
// 预览文件
const preview = (url, fileName) => {
console.log(invoiceInfo, 'invoiceInfoinvoiceInfoin')
if (!oss_invoice_url) {
Taro.showToast({
title: '暂无可预览发票',
icon: 'none',
})
}
Taro.showLoading({ title: '正在加载中', mask: true })
Taro.downloadFile({
url: url,
url: oss_invoice_url,
success: function (res) {
console.log("下载:", res)
var filePath = res.tempFilePath
Taro.hideLoading()
Taro.openDocument({
filePath: filePath,
fileType: getFileType(url),
fileType: getFileType(oss_invoice_url),
fileName: fileName,
success: function (res) {
console.log("打开:", res)
@ -257,7 +280,19 @@ function InvoiceInfo (props) {
}
}
const handleReSubmit = () => {
const reg = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
if (!reg.test(form.email)) {
Taro.showToast({
title: '邮箱格式不正确!',
icon: 'none'
})
return
}
setState((draft) => {
draft.visible = true
})
}
return <SpPage className='page-invoice-info has-navbar' loading={loading} navigationBarTitleText='开票信息'>
@ -269,7 +304,7 @@ function InvoiceInfo (props) {
<Text>电子发票</Text>
{showDetail ? <View className='flex'>
{orderInfo.is_invoiced == 1 && <>
<Text className='ck' onClick={() => preview(invoiceInfo.pdf_info, invoiceInfo.invoice_title + invoiceInfo.invoice_no)}>查看</Text>
<Text className='ck' onClick={() => preview(invoice.oss_invoice_url, invoiceInfo.invoice_title + invoiceInfo.invoice_no)}>查看</Text>
<Text className='iconfont icon-qianwang-01'></Text>
</>}
{/* <AtIcon value='chevron-right' size='18' color='#000'></AtIcon> */}
@ -325,11 +360,7 @@ function InvoiceInfo (props) {
// })
}} className={classNames("btn", { "btn-disabled": !form.title || !form.content || !form.email })}>提交申请</View>
</View> : orderInfo.is_invoiced == 1 && <View className={classNames("bottom")}>
<View onClick={() => {
setState((draft) => {
draft.visible = true
})
}} className={classNames("btn")}>重发发票</View>
<View onClick={handleReSubmit} className={classNames("btn")}>重发发票</View>
</View>}
<View className="sp-picker">

View File

@ -18,7 +18,8 @@ export default class InvoiceList extends Component {
this.state = {
...this.state,
list: []
list: [],
isLoading: true
}
}
@ -54,6 +55,7 @@ export default class InvoiceList extends Component {
id: 'id',
order_id: 'order_id',
status: 'status',
oss_invoice_url: ({ send_params }) => send_params?.oss_invoice_url,
order: ({ order: { orderInfo }, order }) => {
return order.orderInfo ? {
time: formatDateTime(orderInfo.create_time),
@ -70,7 +72,8 @@ export default class InvoiceList extends Component {
log.debug('[trade list] list fetched and processed: ', nList)
this.setState({
list: [...this.state.list, ...nList]
list: [...this.state.list, ...nList],
isLoading: false
})
return { total }
@ -145,12 +148,12 @@ export default class InvoiceList extends Component {
}
render () {
const { list, page } = this.state
const { list, page, isLoading } = this.state
return (
<SpPage className='page-invoice-info has-navbar' navigationBarTitleText='发票记录'>
<ScrollView scrollY className='trade-list__scroll' onScrollToLower={this.nextPage}>
{list.map((item, idx) => {
{list?.length ? list.map((item, idx) => {
return (
<View className='invoice-item' onClick={() => this.goDetail(item)} key={`invoice_item_${idx}`}>
<View className="right-item">商品名称{item.order?.title}</View>
@ -172,7 +175,9 @@ export default class InvoiceList extends Component {
</View>
</View>
)
})}
}) : !isLoading && <SpNote isUrl img={`${process.env.APP_IMAGE_CDN_NEW}/cart/logo-hui.png`} height={144} width={144}>
您的发票记录为空
</SpNote>}
{page.isLoading && <Loading>正在加载...</Loading>}
</ScrollView>
</SpPage>

View File

@ -7,6 +7,17 @@
@include page-scroll(var(--nav-height), 10px);
padding-top: 20px;
padding-bottom: 50px;
.sp-note {
.sp-image {
margin-top: 400px;
}
&__text {
margin-top: 24px;
font-weight: bold;
font-size: 40px;
color: #000;
}
}
}
}
.invoice-item {

View File

@ -172,6 +172,12 @@ export default class TradeList extends Component {
aftersales_type: ({ aftersales }) => {
return aftersales?.aftersales_type
},
aftersales_progress: ({ aftersales }) => {
return aftersales?.progress
},
aftersales_status: ({ aftersales, aftersales_bn }) => {
return (aftersales_bn || aftersales?.aftersales_bn) && aftersales?.progress !== 3
},
status: ({ order_status }) => resolveOrderStatus(order_status),
totalItems: ({ items }) => items?.reduce((acc, item) => +item.num + acc, 0),
// payment: ({ item_fee_new }) => (item_fee_new / 100).toFixed(2),
@ -207,7 +213,7 @@ export default class TradeList extends Component {
order_id: 'order_id',
item_id: 'item_id',
pic_path: 'pic',
title: 'item_name',
title: ({ item_name, item_name_2 }) => item_name_2 || item_name,
origincountry_name: 'origincountry_name',
origincountry_img_url: 'origincountry_img_url',
type: 'type',
@ -273,6 +279,7 @@ export default class TradeList extends Component {
handleClickItemBtn = async (trade, type) => {
console.log(trade)
// return this.handleClickDelivery(true, { delivery_id: 'SF1651636948873' })
const { tid, aftersales_bn } = trade
let detailUrl = `/subpage/pages/trade/detail?id=${tid}`
@ -352,6 +359,7 @@ export default class TradeList extends Component {
title: 'AcceptStation',
content: ({ AcceptTime }) => AcceptTime ? AcceptTime.substring(5, 16) : ''
})
console.log("🚀 ~ file: list.js:357 ~ TradeList ~ nList:", nList)
this.setState({
deliveryList: nList,
deliveryName: trade.delivery_corp_name,
@ -404,7 +412,7 @@ export default class TradeList extends Component {
className={classNames('page-trade-list', {
'has-navbar': true || isNavbar()
})}
showNavSearchIcon
// showNavSearchIcon
>
<SpNavBar title='订单列表' leftIconType='chevron-left' fixed='true' />
<AtTabs

View File

@ -42,7 +42,11 @@ export default class RegRule extends Component {
})
data = registerContent + privacyContent
navBarTitle = `${registerTitle}${privactTitle}`
} else if (type) {
} else if (type === 'activity_rule') {
data = 'xxxx'
navBarTitle = 'BIRKENSTOCK活动细则'
}
else if (type) {
// 隐私政策
const { content, title = '充值协议' } = await api.shop.getRuleInfo({
type

View File

@ -38,7 +38,8 @@ function CouponCenter (props) {
end_date: 1,
card_id,
distributor_id,
item_id: item_id || itemid
item_id: item_id || itemid,
receive: true
}
const {
list,
@ -59,6 +60,14 @@ function CouponCenter (props) {
showToast('积分不足')
return
}
if (item.couponStatus == 0) {
showToast('优惠券已领完')
return
}
if (item.couponStatus == 2) {
showToast('已领取该优惠券')
return
}
const res = await Taro.showModal({
title: '提示',
content: `确定要领取该优惠券吗?`,
@ -72,9 +81,7 @@ function CouponCenter (props) {
if (!res.confirm) {
return
}
if (item.couponStatus == 0) {
showToast('优惠券已领完')
} else if (item.couponStatus == 1) {
if (item.couponStatus == 1) {
if (isWeixin) {
const templeparams = {
temp_name: 'yykweishop',
@ -97,12 +104,11 @@ function CouponCenter (props) {
} else {
getCoupon(item, index)
}
} else {
showToast('优惠券已领取完啦')
}
}
const getCoupon = async ({ cardId }, index) => {
Taro.showLoading({ title: '', mask: true })
const { status } = await api.member.getCardDetail({
card_id: cardId
})
@ -121,6 +127,7 @@ function CouponCenter (props) {
} else {
showToast('优惠券领取失败')
}
Taro.hideLoading()
}
const { point } = state

View File

@ -117,7 +117,8 @@
}
&-btn {
padding: 15px 20px;
border: 1px solid #fff;
/* prettier-ignore */
border: 1PX solid #fff;
border-radius: 6px;
display: flex;
justify-content: center;

View File

@ -33,7 +33,7 @@ function CouponIndex () {
status: '1',
page: pageIndex,
pageSize,
card_type: couponType,
// card_type: couponType,
scope_type: 'all'
}
const { list, total_count: total } = await api.member.getUserCardList(params)

View File

@ -70,7 +70,8 @@
}
&-btn {
padding: 15px 20px;
border: 1px solid #fff;
/* prettier-ignore */
border: 1PX solid #fff;
border-radius: 6px;
display: flex;
justify-content: center;

View File

@ -127,6 +127,7 @@ function MemberIndex (props) {
const { pointName } = useSelector((state) => state.sys)
// log.debug(`store userInfo: ${JSON.stringify(userInfo)}`)
const dispatch = useDispatch()
const { windowWidth } = Taro.getSystemInfoSync()
Taro.setNavigationBarColor({
frontColor: '#000000',
@ -468,7 +469,7 @@ function MemberIndex (props) {
// console.log('====config===', config.menu)
return (
<SpPage loading={state.loading} className='pages-member-index has-navbar' renderFooter={<SpTabbar />} isTop>
<SpPage loading={state.loading} className='pages-member-index has-navbar' renderFooter={<SpTabbar />} title='' showNavSearchIcon={false} showNavBackIcon={false} showNavLogo isBlack isTop>
<View
className='header-block'
style={styleNames({
@ -551,14 +552,12 @@ function MemberIndex (props) {
{isLogin && <View className="header-code">
<Text className="" onClick={() => {
Taro.navigateTo({ url: '/subpages/member/member-level' })
// Taro.navigateTo({ url: '/subpages/member/member-level' })
}}>{
{
true: vipInfo.grade_name || '会员',
false: userInfo?.gradeInfo?.grade_name || ''
}[vipInfo.isVip]
vipInfo.isVip ? vipInfo.grade_name || '会员' : userInfo?.gradeInfo?.grade_name || ''
}</Text>
<SpImage onClick={handleClickLink.bind(this, '/marketing/pages/member/member-code')} src='member/qr-code.png' height={30} width={30} isNew />
<Text></Text>
{/* <SpImage onClick={handleClickLink.bind(this, '/marketing/pages/member/member-code')} src='member/qr-code.png' height={30} width={30} isNew /> */}
</View>}
</View>
@ -710,26 +709,30 @@ function MemberIndex (props) {
<View className="member_con_left">
{/* /subpages/pointshop/list */}
<View className="member_con_item" onClick={isLogin && handleClickLink.bind(this, '/subpages/marketing/coupon-center')}>
<SpImage className="member_con_item_img" src="member/jifen.png" height={290} mode='aspectFill' isNew />
<View className="member_con_item_txt">积分兑换</View>
<SpImage className="member_con_item_img" src="member/jifen.png" height={windowWidth < 400 ? 200 : 220} mode='aspectFill' isNew />
<View className="member_con_item_txt">卡券与兑换</View>
</View>
<View className="member_con_item" onClick={isLogin && handleClickLink.bind(this, '/subpages/member/qa-page')}>
<SpImage className="member_con_item_img" src="member/wenti.png" height={windowWidth < 400 ? 200 : 220} mode='aspectFill' isNew />
<View className="member_con_item_txt">常见问题</View>
</View>
<View className="member_con_item" onClick={isLogin && handleClickLink.bind(this, '/pages/member/item-fav')}>
<SpImage className="member_con_item_img" src="member/shoucang.png" height={290} mode='aspectFill' isNew />
<SpImage className="member_con_item_img" src="member/shoucang.png" height={windowWidth < 400 ? 200 : 220} mode='aspectFill' isNew />
<View className="member_con_item_txt">个人收藏</View>
</View>
</View>
<View className='gap'></View>
<View className="member_con_right">
<View className="member_con_item" onClick={isLogin && handleClickLink.bind(this, '/subpages/member/user-info')}>
<SpImage className="member_con_item_img" src="member/geren.png" height={190} mode='aspectFill' isNew />
<SpImage className="member_con_item_img" src="member/geren.png" height={windowWidth < 400 ? 200 : 220} mode='aspectFill' isNew />
<View className="member_con_item_txt">个人信息</View>
</View>
<View className="member_con_item" onClick={handleClickLink.bind(this, '/marketing/pages/member/address')}>
<SpImage className="member_con_item_img" src="member/dizhi.png" height={190} mode='aspectFill' isNew />
<SpImage className="member_con_item_img" src="member/dizhi.png" height={windowWidth < 400 ? 200 : 220} mode='aspectFill' isNew />
<View className="member_con_item_txt">地址管理</View>
</View>
<View className="member_con_item" onClick={isLogin && handleClickLink.bind(this, '/subpage/pages/trade/invoice-record')}>
<SpImage className="member_con_item_img" src="member/fapiao.png" height={190} mode='aspectFill' isNew />
<SpImage className="member_con_item_img" src="member/fapiao.png" height={windowWidth < 400 ? 200 : 220} mode='aspectFill' isNew />
<View className="member_con_item_txt">发票管理</View>
</View>
</View>

View File

@ -310,14 +310,14 @@
justify-content: space-between;
&_left {
display: grid;
grid-template-rows: repeat(2, auto);
grid-template-rows: repeat(3, auto);
grid-gap: 10px;
}
&_item {
position: relative;
&_txt {
position: absolute;
left: 20px;
right: 20px;
bottom: 30px;
color: #fff;
font-size: 32px;
@ -406,7 +406,8 @@
line-height: 78rpx;
text-align: center;
border-radius: 8rpx;
border: 1px solid #000;
/* prettier-ignore */
border: 1PX solid #000;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;

View File

@ -0,0 +1,111 @@
const data = [{
title: "购物相关", isOpen: false, content: [{ subTit: "如何选择鞋子尺码?", subCon: "先量脚长再看尺码会更准确喔。如果您平日穿着的鞋履是42码或42码以下您可以按照正码选购如果您平日穿着的鞋履是42码以上建议您可选小一码。在此判断标准上如您的脚背高、脚宽或者计划搭配袜子穿建议您选择大一码的鞋子或如您打算购买带有羊毛衬里的拖鞋搭配袜子穿着也建议您选择大一码的鞋子。" },
{ subTit: "如何测量脚长?", subCon: "建议您赤脚,脚后紧靠墙面站立,脚下放一把卷尺;读取最长脚趾长度以(毫米为单位)做为依据来选鞋子尺码。" },
{ subTit: "鞋子的窄版和常规版是指什么?", subCon: "一般来说我们40码以下的鞋子为窄版40码以上的鞋子为常规版从解剖学上来说我们常规版的设计更加适合男性的足部构造窄版设计更加适合女性的足部构造。除此之外我们的部分款式39码也有常规版可选您可以点击具体商品的详情页面查看相关信息进行选购。" },
{ subTit: "如何区分常规软木鞋床和软底软木鞋床?", subCon: `我们的软底鞋床印有"Soft-footbed"的蓝色标记,软底鞋床有特殊材料制成的填充物,该材料由数以百万计的微小气泡组成,可以有效缓解由行走或站立带来的疲劳感;常规款的鞋床标记为黑色或金色,环保鞋款鞋床标记则为绿色。` },
{ subTit: "所有BIRKENSTOCK鞋都是男女同款吗", subCon: `视具体鞋款而定我们的大多数鞋款是不分性别皆可穿着的例如Arizona, Boston……某些特定鞋款是在产品设计时就结合了女性的造型时尚和生理学特征例如MayariMadrid……详情可参考具体的产品页面。` },
{ subTit: '为什么一些鞋子看起来款式和颜色都一样,但是价格不同?', subCon: `同款同色的BIRKENSTOCK鞋履可能会因材质不同而有价格略有差异视具体情况而定。` },
{ subTit: '什么是环保商品?所有款式都有环保材质的吗?', subCon: `BIRKENSTOCK 一直秉持环保生产的理念环境保护一直是我们的的首要任务我们使用的绝大部分原料皆为纯天然材料软木、天然乳胶、黄麻等等。BIRKENSTOCK 环保鞋是指在生产过程中完全不使用任何动物性材料,而是有意识地只使用人工合成材料和天然材料,在保证 BIRKENSTOCK 鞋款的功能性和时尚性的同时,打造一个完全动物友好的产品系列。` },
{ subTit: `BIRKENSTOCK鞋防水吗`, subCon: `我们有 EVA 材质制成的防水款式。但大多数款式都不能浸泡在水中,因为过度浸泡会损害密封材料的完整性。` },
{ subTit: `你网站上的所有商品在商店里也有售吗?`, subCon: `线上官方小程序的商品种类,与其他官方渠道可能略有不同,请以实际情况为准。` },
{ subTit: '有固定的促销活动和新品上架时间吗?', subCon: `建议您添加我们的微信官方小程序关注BIRKENSTOCK微信公众号、小红书官方账号、新浪官方微博及时掌握新品上架或促销活动第一手信息。` },
{ subTit: '港澳台及海外地区是否可以购买?', subCon: `我们的配送地址范围为中国大陆地区,暂不支持港澳台及海外地区的配送。` },
{ subTit: `可以使用哪些付款方式?`, subCon: `您可以使用微信支付,目前我们暂不支持其他支付方式。` },
{ subTit: `发货时效和发货快递`, subCon: `您的订单将通过顺丰快递从上海发出顺丰快递服务范围不到的地区我们会为您选用其他的快递服务商。根据地点不同配送所花费的时间也有所差异一般送货周期为2-5天偏远地区送货周期可能会有相应延长。由于物流配送中的不确定性请您谅解我们无法承诺绝对准确的送达时间。` },
{ subTit: `我收到鞋子了,看起来都被刮伤了?`, subCon: `我们的部分特定皮革鞋面是经过油脂涂覆处理的,这能使皮革本身呈现出更加有质感的外观和丰富的色彩变化。经过油脂处理的皮革鞋面上出现表面划痕或看起来像的划痕是正常的,随着皮革在穿着过程中与您足部的磨合,它们会自行淡化。您也可以尝试用手指轻拭,因为您的自然体温可以帮助皮革重新分配其表面的油脂涂层,从而达到柔化痕迹的效果。如果您更喜欢带有统一颜色的外观,我们建议您可以选择磨毛皮、光滑皮革或合成材料制作的鞋履。` },
{ subTit: `怎样进行日常护理清洁?`, subCon: `不同材质的鞋履的护理方式均有所不同建议您关注我们的官方微信公众号或小红书账号”BIRKENSTOCK"并查看相关鞋履的护理、清洁信息。` }]
},
{
title: '订单相关', isOpen: false, content: [{ subTit: "我可以修改订单吗?", subCon: `如果您单次购买多件商品,可在购物车内勾选相关商品一并下单,我们将为你按照一笔订单同时发货。对于来自同一个账户的分时不同批次多订单,我们不能将多张订单进行合并,也不能将多张订单合并发货;另外您一旦点击确认并提交订单后,我们客服将无法修改订单内容,包括商品信息、总价金额等等。` },
{ subTit: '我未付款的订单可以保留多久?', subCon: `若您在提交订单后未在规定的时间内及时付款则在该时限届满后已提交的相关订单将被自动取消。除非本商城的商品详情页面另有不同的说明或该商品使用的销售规则或活动规则另有不同说明如果我们在收到您确认提交订单后30分钟内没有收到全额付款您的该笔订单将被自动取消。` },
{ subTit: `已经发货了,我能取消订单吗?`, subCon: `如果您的订单已经提交且尚未支付,您可以自行取消订单;对于已经发货的订单,您可以在收到商品后七天之内,且商品保持完好的情况下申请无理由退货。` },
{ subTit: `当天购物会当天发货吗?`, subCon: `一般情况下当日15:00之前付款的订单可以当天发货15:00之后的订单为您安排隔日发货。` },
{ subTit: `哪里可以看到发货?为什么很久没收到货品?`, subCon: `您可以登录BIRKENSTOCK微信小程序商城在“我的订单”中找到需要查询的订单订单详情中会有相关物流公司的物流信息。您可直接登陆到相关的物流公司网站查询物流信息或联系在线客服为您进行物流查询服务。为了顾客能尽快收到货品一般情况下我们在您付款后24小时左右会为您安排发货周六、周日均正常发货。而在大型促销活动期间发货会有稍许延迟在已发货的情况下如您长时间未收到货请耐心等待或与物流公司联系。如遇到特殊情况(仓库盘点,节假日)、天气、人力等因素导致延迟发货或延长送货时间,我们将会提前以公告或其他形式告知。` },
{
subTit: `为什么我的订单没发货?`, subCon: `您的订单未发货可能有以下原因:
(1)您的订单中可能有尚待确认的信息所以订单处于保留状态通常在您下单后我们的客服会第一时间与您取得联系请您保持手机畅通一旦确认后将马上进行发货处理;
(2)可能您的订单仓库正在发货订单信息还没有更新成功还请您耐心等待`},
{ subTit: '商品已经发货了,但是我需要更改收货地址,可以吗?', subCon: `我们会联系快递尝试修改地址,已经发货的订单需要到中转站点后才能知晓修改是否成功,相对比较耗时,建议您可以安排拒收,我们也会通知物流进行包裹拦截。若您仍需要此款商品,建议重新下单,非常抱歉由此给您带来的不便,我们会尽快为您跟进处理新的订单。` },
{ subTit: '如果在收到商品时发现错发或者质量有问题的情况怎么办?', subCon: `"请与快递沟通在签收之前检查外包装是否破损以及打开包装验视商品本身,如果商品发生错发或有任何质量问题,请保留相关单据完整并第一时间联系我们 服人员帮您进行后续操作。"` },
{ subTit: '在BIRKENSTOCK小程序官方店购买的商品可以在实体店铺内退换货吗', subCon: '非常抱歉如您对BIRKENSTOCK小程序官方店购买的商品有任何问题请联系在线客服。实体店铺不受理在线上购买商品的退货同样BIRKENSTOCK小程序官方店也不受理在实体店铺购买商品的退货。' },
{ subTit: '退换货政策', subCon: `所有退换商品的包装及鞋子在符合退换货的条件下可进行退换货。详情请查看BIRKENSTOCK勃肯退换货政策word文档加链接` },
{ subTit: '收货后我还可以通过支付差价来换不同的款式吗?', subCon: `非常抱歉,我们只有只能对相同的商品更换不同的尺寸的服务。不提供不同款式的换货服务,如果您的订单已经提交且尚未支付,您可以自行取消订单,并重新下单您心仪的商品。` },
{ subTit: '我可以在同一个退货包中包含多个订单吗?', subCon: `为了能够及时处理您的退货和退款,我们建议您同一订单中的多件商品可以使用同一退货包裹退回; 多个订单中的商品请分别按照原订单中的数量及型号退回,请勿混合退回多个订单中的商品。` },
{ subTit: '我的退货跟踪显示已送达,但我尚未收到退款。我能做什么?', subCon: `我们在收到您的退货要求后会及时为您发起退款流程通常所需时间为1-3周不定如果超出该时间范围请及时联系我们的在线客服。` },
{ subTit: `收到退款需要多长时间?`, subCon: `我们在收到您的退货后会及时为您处理退款流程通常所需时间为1-3周如果超出该时间范围请联系我们的在线客服。` }]
},
{
title: '发票相关', isOpen: false, content: [{ subTit: '可以开具发票吗?', subCon: `可以。如有需要,请您在订单结算时选择“开发票”并在备注栏中正确填写发票抬头,发票金额为您实际支付的商品金额。折扣与快递费用不开具发票,请您谅解。` },
{ subTit: '可以指定开票日期吗?', subCon: `很抱歉,根据税务相关规定我们不提供指定开票日期的服务。` },
{ subTit: `退货后发票怎么办?`, subCon: `订单发生退货,您原来的发票会自动作废,无法再下载使用。如您购买多件商品后申请退货,在退货完成后,您的电子发票信息将会自动更新,在您的历史订单中下载发票。` },
{ subTit: `可以补开发票吗?`, subCon: `可以,您可以通过联系我们的在线客服申请开具已完成订单的发票。` },
{ subTit: `发票抬头如何修改?`, subCon: `如您购买的商品还未付款建议您在有库存的情况下重新下单填并写正确的开票信息。如您购买的商品全部发货未满7天客服查询到您的订单处于未完成状态目前还不能为您更改发票相关信息。待您的订单发货时长达到7天后可联系客服办理。如您购买的商品发货时间达到7天请您提供正确的相关信息给到客服客服会在1-5个工作日为您修改正确的发票抬头并更新在您的订单信息内。` }]
},
{
title: '意见反馈', isOpen: false, content: [{ subTit: `如何反馈其他问题?`, subCon: '如果您对本平台显示的材料或者购物过程中又任何疑虑或异议或希望提供建议和意见您可以联系我们的客服021-62716091或者写信给我们bscn_mp_store@birkenstock.com。' }]
},
{
title: '退换货政策', isOpen: false, content: [
{ subTit: `BIRKENSTOCK官方网站退换货政策中国大陆`, subCon: '' },
{ subTit: `一、政策适用范围`, subCon: `诚挚欢迎您光临BIRKENSTOCK微信小程序官方店以下是我们的退换货政策。` },
{ subTit: `二、退换货条件`, subCon: `为了确保您的购物体验顺利愉快,我们需要您注意以下退换货条件:`, subContents: ['&nbsp;&nbsp;1.商品应保持完好,包括商品本身及其鞋盒、配件、吊牌等完整无损。', '&nbsp;&nbsp;2.请提供原始收银凭证或购物凭证以办理退换货。', '&nbsp;&nbsp;3.申请退换货应在签收之日起7天内进行。'] },
{ subTit: `三、退换货特别约定`, subCon: `针对特定情形的退换货特别处理:`, subContents: ['&nbsp;&nbsp;1.鞋类商品的合格证及三包服务卡以鞋盒上粘贴的规定为准。', '&nbsp;&nbsp;2.退货仅限在原购买商品的微信小程序平台进行。', '&nbsp;&nbsp;3.不同渠道购买的商品暂不支持跨渠道退换货。', '&nbsp;&nbsp;4.在下单过程中使用优惠券、积分兑换券等折扣券,该笔订单如需退货,折扣券将不予返还。'] },
{
subTit: '四、鞋类商品质保规定',
subCon: '为了保障您的权益,敬请留意以下信息:',
subContents: ['&nbsp;&nbsp;1.质保期限',
'&nbsp;&nbsp;质保期限为自鞋类商品购买之日起90天。',
'&nbsp;&nbsp;2.质保范围',
'&nbsp;&nbsp;&nbsp;&nbsp;1)质保期内如鞋类商品发生质量问题可凭原始购物凭证办理退货或换货。BIRKENSTOCK暂不提供维修服务。如您购买的鞋类商品因质量问题需要维修请按照下述退换货流程操作。',
'&nbsp;&nbsp;&nbsp;&nbsp;2)如您购买的鞋类商品在正常穿着情况下存在以下任一质量问题,您可以选择退货或换货处理:',
'&nbsp;&nbsp;&nbsp;&nbsp;a.凡在第一个月内出现断底、断跟、断面、断帮质量问题之一者。',
'&nbsp;&nbsp;&nbsp;&nbsp;b.凡属包换的质量问题而因故无法调换者,可予以退货。',
`&nbsp;&nbsp;&nbsp;&nbsp;c.在第一个月内出现“包修”质量问题且无法予以调换者可酌情按购买产品实际支付价格的每日0.5%收取折旧费,并予以退货。`,
`&nbsp;&nbsp;&nbsp;&nbsp;d.凡未经穿过的新鞋不成双,鞋子大小或鞋内出现开胶之一者。`,
`&nbsp;&nbsp;&nbsp;&nbsp;e.凡在第一周内胶黏皮鞋发生开胶(帮底结合处脱落或弹开长度2cm深度0.5cm以上者)`,
`&nbsp;&nbsp;&nbsp;&nbsp;f.凡属“包修”的质量问题,在第一个月予以更换。`,
`&nbsp;&nbsp;&nbsp;&nbsp;g.包修帮底结合处开胶脱落或弹出长度2cm深度0.5cm以下者;`,
`&nbsp;&nbsp;&nbsp;&nbsp;--第一周外胶黏皮皮鞋发生开胶;`,
`&nbsp;&nbsp;&nbsp;&nbsp;--胶粘鞋发生开胶;`,
`&nbsp;&nbsp;&nbsp;&nbsp;--出现断底、断跟、断面、断帮;`,
`&nbsp;&nbsp;&nbsp;&nbsp;h.两只鞋颜色明显不一、尺码不等或一边脚;`,
`&nbsp;&nbsp;&nbsp;&nbsp;i.其他法律规定的质量问题。`,
`&nbsp;&nbsp;3)您在不同渠道 (微信小程序官方店、天猫官方旗舰店、京东官方旗舰店、抖音官方旗舰店、实体店) 购买的鞋类商品,暂不支持跨渠道办理退换货,敬请谅解。鞋类商品的退换货操作流程详见下述退换货流程。`,
'&nbsp;&nbsp;3.质保例外',
`&nbsp;&nbsp;以下情形不属于质保服务范围,敬请谅解:`,
`&nbsp;&nbsp;&nbsp;&nbsp;a.因穿着、保养、使用或保管不当等造成的损坏;`,
`&nbsp;&nbsp;&nbsp;&nbsp;b.因自行拆改或修理造成的损坏;`,
`&nbsp;&nbsp;&nbsp;&nbsp;c.超出质保期限的商品;`,
`&nbsp;&nbsp;&nbsp;&nbsp;d.无原始购物凭证的商品。`]
},
{
subTit: '五、退换货流程',
subCon: `购买于BIRKENSTOCK微信小程序官方店的商品退换货流程如下`,
subContents: [`&nbsp;&nbsp;1.购买于微信小程序官方店的商品,若符合本政策约定的退换货条件,可按以下流程操作退货:`,
`&nbsp;&nbsp;&nbsp;&nbsp;a.请您在收到商品之日以快递签收日期为准7天内联系微信小程序官方店的客服申请退货`,
`&nbsp;&nbsp;&nbsp;&nbsp;b.在与客服确认符合退货条件后,可予退货。请在“我的订单”页面提交退货申请,并填写退货快递单号。`,
`&nbsp;&nbsp;退货申请提交后,请将您的原始购物明细单随退货商品一并快递至以下地址及收件人:`,
`&nbsp;&nbsp;退货地址:`,
`&nbsp;&nbsp;上海市奉贤区 奉城镇东新市村朝阳1160号`,
`&nbsp;&nbsp;奉城普洛斯物流园B1库1FU3单元圆具嘉 大叶公路靠申江南路`,
`&nbsp;&nbsp;收件人勃肯退货组XCX) 19901781571`,
`&nbsp;&nbsp;2.微信小程序官方店目前暂时仅提供相同商品不同尺寸的更换服务,不提供不同款式的换货服务。若您对购买的商品不满意,需要退换,请按照上述流程操作,或联系我们的在线客服询问详情。`,
`&nbsp;&nbsp;3.退回商品的运费将由您承担BIRKENSTOCK暂不接受到付、平邮、邮政小包退件。为了您的方便与顺利建议您使用顺丰快递以确保快速安全地退回商品。`,
`&nbsp;&nbsp;4.如果您退货的商品享受了价格优惠,最终退款金额将以您实际支付的金额为准。退货退款的到账时间会根据您原始支付方式的不同而有所差异。如有任何疑问,请联系我们的在线客服。`]
},
{
subTit: '六、售后客服时间',
subCon: '我们的售后客服团队随时为您提供支持,您可以通过在线客服咨询,或者电话联系我们。',
subContents: ['售后服务热线021-62716091',
`在线客服服务时间周一至周日9:00 - 24:00法定节假日或大促期间的服务时间将另行通知`,]
}
]
}
]
export default data

View File

@ -0,0 +1,3 @@
export default {
navigationBarTitleText: '小程序自助服务Q&A',
}

View File

@ -0,0 +1,102 @@
import React, { useEffect } from 'react'
import { View, Text, ScrollView } from '@tarojs/components'
import { AtAccordion, AtIcon } from 'taro-ui'
import { SpPage, SpHtml } from '@/components'
import { useImmer } from 'use-immer'
import introData from './qa-data'
import { classNames } from '@/utils'
import './qa-page.scss'
import { getCurrentInstance } from '@tarojs/taro'
const initState = {
introList: introData,
scrollTop: 0,
}
export default function qaPage () {
const [state, setState] = useImmer(initState)
const { introList, scrollTop } = state
const $instance = getCurrentInstance()
useEffect(() => {
const { index } = $instance.router.params
if (index) {
setState((draft) => {
draft.introList = draft.introList.map((v, i) => {
if (i == index) {
v.isOpen = true
} else {
v.isOpen = false
}
return v
})
})
}
}, [])
return (
<SpPage className="page-member-qa">
<ScrollView scrollY scrollWithAnimation showScrollbar={false} scrollTop={scrollTop} className="qa-page-scrool">
{introList.length ? introList.map((item, index) => <View className={classNames('sp-accordion')} key={`item__${index}`}>
<AtAccordion
open={item.isOpen}
isAnimation={false}
onClick={() => {
setState((draft) => {
draft.introList = draft.introList.map((v, i) => {
v.isOpen = false
return v
})
draft.introList[index].isOpen = !item.isOpen
draft.scrollTop = 0
})
// if (!item.isOpen) {
// setState((draft) => {
// draft.scrollTop = 1042 + Math.random() / 10
// })
// }
}}
title={item.title}
>
{/* <SpHtml content={item.content} /> */}
<View className="content">
{item.content.map((v, i) => (
<View className="content-item" key={i + '_content'}>
<View className="content-item-title" >
{v.subTit}
{/* <Text className="title"></Text> */}
</View>
{!!v.subCon && <View className="title-desc">
<View style={{ marginBottom: v.subContents ? '4px' : '0' }} >{v.subCon}</View>
{/* {v.subContents ? v.subContents.map(s => <View style={{ marginBottom: '4px' }} > {s}</View >) : null} */}
{v.subContents ? v.subContents.map(s => <SpHtml content={s} style={{ marginBottom: '4px' }} />) : null}
</View>}
</View>
))}
</View>
</AtAccordion>
<View onClick={() => {
setState((draft) => {
draft.introList = draft.introList.map((v, i) => {
v.isOpen = false
return v
})
draft.introList[index].isOpen = !item.isOpen
})
// if (!item.isOpen) {
// setState((draft) => {
// draft.scrollTop = 1042 + Math.random() / 10
// })
// }
}}>
{item.isOpen ? <AtIcon value='subtract' size='16' color='#000' /> :
<AtIcon value='add' size='16' color='#000' />}
{item.isOpen ? <></> : <View className="line"></View>}
</View>
</View>) : <View style={{ height: `calc(100% - 380px)` }}></View>}
</ScrollView>
</SpPage>
)
}

View File

@ -0,0 +1,86 @@
.page-member-qa {
// height: 95vh;
// overflow: hidden;
.sp-page-body {
position: relative;
margin-top: 30rpx;
/* prettier-ignore */
border-top: 1PX solid #9e9e9e80;
}
.scroll-box {
// @include page-scroll(calc(var(--nav-height) + 150px), 40px);
// height: calc(var(--nav-height) + 150px);
margin-bottom: 10px;
box-sizing: border-box;
flex-direction: column;
display: flex;
flex: 1;
overflow-y: scroll;
}
.qa-page-scrool {
--height: calc(var(--status-bar-height) + #{$tabbar-height} + var(--area-bottom-height));
overflow: hidden;
height: calc(100vh - var(--height));
}
.sp-accordion {
position: relative;
&:last-child {
margin-bottom: 40rpx;
}
.at-accordion__header {
padding: 30px 40px;
color: #000;
&::after {
border: none;
// border-bottom: 1px solid #9e9e9e80;
}
.at-accordion__info__title {
font-size: 30px;
}
.at-accordion__arrow {
display: none;
}
}
.at-accordion__content {
&::after {
border: none;
// border-bottom: 1px solid #9e9e9e80;
}
}
.at-accordion__body {
padding: 0 40px;
padding-bottom: 30px;
.content {
&-item {
&-title {
font-size: 30px;
font-weight: bold;
margin-bottom: 10px;
}
.title-desc {
margin-bottom: 40px;
}
}
}
}
.at-icon {
position: absolute;
z-index: 0;
right: 40px;
top: 54px;
transform: translateY(-50%);
transition: all 0.2s ease-in-out;
}
.line {
display: block;
position: absolute;
width: 100%;
height: 1px;
background: #9e9e9e80;
top: 104px;
right: 0;
left: 0;
transition: all 0.2s ease-in-out;
}
}
}

View File

@ -60,8 +60,8 @@ export default function scan () {
}
const getRecords = async () => {
const data = await api.user.registrationRecordList()
const _list = (data?.list || []).filter(n => n.is_write_off == 1).map(item => {
const data = await api.user.getVerifyRegistrationRecordList({ activity_id: 2 })
const _list = (data?.list || []).map(item => {
let formData = item.content?.[0]?.formdata || []
if (formData.length > 0) {
formData.forEach(_item => {

View File

@ -20,7 +20,7 @@ const initialState = {
showCheckboxPicker: false,
checkboxKey: '',
checkboxList: [],
checked: false,
checked: true,
info: {},
areaList: [],
multiIndex: [],
@ -450,9 +450,10 @@ function MemberUserInfo () {
const handleLogOff = async () => {
const { status, msg } = await api.member.deleteMember({ is_delete: '0' })
if (!status) {
await Taro.showModal({
Taro.showModal({
content: msg,
confirmText: '我知道了'
confirmText: '我知道了',
showCancel: false,
})
} else {
Taro.navigateTo({
@ -617,27 +618,28 @@ function MemberUserInfo () {
<View className='block-container'>
<View className='check-box'>
{/* <Checkbox value='选中' checked={state.checked} >选中</Checkbox> */}
<SpCheckbox checked={checked} colors="#000" onChange={() => setState((draft) => { draft.checked = !checked })} />
<SpCheckbox checked={checked} disabled colors="#000" onChange={() => setState((draft) => { draft.checked = !checked })} />
<View>
<Text onClick={() => setState((draft) => { draft.checked = !draft.checked })} >我已经阅读并同意</Text>
<Text onClick={() => false && setState((draft) => { draft.checked = !draft.checked })} >我已经阅读并同意</Text>
<Text
onClick={() => Taro.navigateTo({ url: '/subpages/auth/reg-rule?type=member_logout' })}
onClick={() => Taro.navigateTo({ url: '/subpages/auth/reg-rule?type=member_register' })}
style={`color: #000000`}
>
{`${appName}使用条款》`}
</Text>
<Text
onClick={() => Taro.navigateTo({ url: '/subpages/auth/reg-rule?type=privacyAndregister' })}
onClick={() => Taro.navigateTo({ url: '/subpages/auth/reg-rule?type=privacy' })}
style={`color: #000000`}
>
隐私政策
</Text>
{/* privacyAndregister */}
</View>
</View>
{/* 注销账号 */}
<View className="cancel-account">
<View className="cancel-account-left" onClick={() => Taro.navigateTo({ url: '/subpages/auth/reg-rule?type=privacyAndregister' })}>会员规则</View>
{/* <View className="cancel-account-left" onClick={() => Taro.navigateTo({ url: '/subpages/auth/reg-rule?type=privacyAndregister' })}>会员规则</View> */}
<View className="cancel-account-right" onClick={handleLogOff}>账户注销</View>
</View>
{/* <SpCell

View File

@ -278,7 +278,8 @@
}
&-btn {
padding: 15px 20px;
border: 1px solid #fff;
/* prettier-ignore */
border: 2px solid #fff;
border-radius: 6px;
display: flex;
justify-content: center;

View File

@ -57,6 +57,12 @@ function TradeAfterSale (props) {
refundStore, contact, mobile, afterSaleDesc, offlineAftersalesIsOpen, offlineAftersales, afterSaleTotalNum, allClicked, afterSaleTotalprice, loading, isOpened, isAddrOpened, aftersales, expressList, corpIndex, logi_no } = state
useEffect(() => {
const { id, type } = $instance.router.params
if (type) {
setState(v => {
v.curTabIdx = tabList.findIndex(item => item.type == type)
})
}
fetch()
Taro.eventCenter.on('onEventPickerStore', (item) => {
console.log('onEventPickerStore:', item)
@ -137,7 +143,6 @@ function TradeAfterSale (props) {
// order_id
})
const _aftersales = pickBy(resInfo, doc.trade.TRADE_AFTER_SALES_ITEM)
console.log("🚀 ~ _aftersales:", _aftersales)
if (_aftersales.sendbackData) {
const { corp_code } = _aftersales.sendbackData
_aftersales.sendbackData.name = LOGISTICS_CODE[corp_code]
@ -228,7 +233,7 @@ function TradeAfterSale (props) {
}
const onSubmit = async () => {
const { id } = $instance.router.params
const { id, type } = $instance.router.params
const checkedItems = info?.items.filter(item => !!item.checked)
if (checkedItems.length == 0) {
return showToast('请选择需要售后的商品')
@ -237,7 +242,7 @@ function TradeAfterSale (props) {
if (!reasons?.[reasonIndex]) {
return showToast('请选择退货原因')
}
const aftersales_type = tabList[curTabIdx].type
let aftersales_type = tabList[curTabIdx].type
const reason = reasons?.[reasonIndex]
let params = {
detail: checkedItems.map(({ id: _id, refundNum, num }) => {
@ -291,13 +296,17 @@ function TradeAfterSale (props) {
const handleClickCopy = (val) => {
copyText(val)
Taro.showToast({
title: '复制成功',
icon: 'none'
})
// Taro.showToast({
// title: '复制成功',
// icon: 'none'
// })
}
const handleClickCopyAddr = () => {
const addr = `收货人:${aftersales?.afterSalesContact || ''}; 联系电话:${aftersales?.afterSalesMobile || ''}; 收货地址:${aftersales?.afterSalesAddress || ''}; 邮编:${aftersales?.afterSalesZip || ''}`
copyText(addr)
}
return <SpPage ref={pageRef} loading={loading} className='page-trade-after-sale has-navbar' isBlack showNavSearchIcon renderFooter={
return <SpPage ref={pageRef} loading={loading} title={!afterSaleTid ? '申请售后' : '售后进度'} className='page-trade-after-sale has-navbar' isBlack renderFooter={
!loading && !afterSaleTid ? <View className='btn-wrap'>
<AtButton type='primary' onClick={onSubmit}>提交售后申请</AtButton>
</View> : null
@ -640,7 +649,7 @@ function TradeAfterSale (props) {
<View className="receiver_name op">如商家拒绝您可以修改申请后再次发起商家会重新处理</View>
<View className="receiver_name op" style={{ marginBottom: '50rpx' }}>如商家超时未处理退货申请将达成请按系统给出的退货地址退货</View>
<View className={`receiver_name ${[1, 2].includes(aftersales?.progress) && 'active'}`}>寄回商品</View>
<View className={`receiver_name ${aftersales?.progress == 4 && aftersales?.aftersalesStatus != 2 && 'active'}`}>商家退款</View>
<View className={`receiver_name ${((aftersales?.progress == 8 && aftersales?.aftersalesStatus == 1) || (aftersales?.progress == 4 && aftersales?.aftersalesStatus != 2)) && 'active'}`}>商家退款</View>
<View className={`receiver_name ${aftersales?.progress == 4 && aftersales?.aftersalesStatus == 2 && 'active'}`}>退款成功</View>
<View className="line"></View>
<View className="curtain_content_text">
@ -682,7 +691,7 @@ function TradeAfterSale (props) {
<View className="addr_item_left">邮编</View>
<View className="addr_item_right">{aftersales?.afterSalesZip}</View>
</View>
<View className="fuzhi">复制地址</View>
<View className="fuzhi" onClick={handleClickCopyAddr} >复制地址</View>
<View className="line" style={{ margin: '130rpx 0 110rpx 0' }}></View>
<View className="curtain_content_text">
<View className="curtain_content_text_title">温馨提示</View>

View File

@ -51,7 +51,7 @@
}
}
.btn-wrap {
padding: 50px;
padding: 20rpx 50px;
// margin-bottom: 100px;
.at-button__text {
font-size: 36px;

View File

@ -429,8 +429,8 @@ export const meiqiaInit = () => {
}
const redirectUrl = async (api, url, type = 'redirectTo') => {
if (!browser.weixin) {
Taro[type]({ url })
if (!browser?.weixin) {
typeof url === 'string' && Taro[type]({ url })
return
}
let newUrl = getUrl(url)