Commit 2a508a8f authored by 贾慧斌's avatar 贾慧斌

feat: 转换代码临时更新

parent 343da196
...@@ -21,18 +21,32 @@ if ( ...@@ -21,18 +21,32 @@ if (
const input = normalizePath(process.env.UNI_INPUT_DIR); const input = normalizePath(process.env.UNI_INPUT_DIR);
try { try {
plugins.push([ plugins.push(
require("@dcloudio/vue-cli-plugin-hbuilderx/packages/babel-plugin-console"), [
{ require("@dcloudio/vue-cli-plugin-hbuilderx/packages/babel-plugin-console"),
file(file) { {
file = normalizePath(file); file(file) {
if (file.indexOf(input) === 0) { file = normalizePath(file);
return path.relative(input, file); if (file.indexOf(input) === 0) {
return path.relative(input, file);
}
return false;
} }
return false;
} }
} ],
]); [
"import",
{
libraryName: "@qg/cherry-ui",
libraryDirectory: "src",
style: name => {
// eslint-disable-next-line no-useless-escape
const lessName = name.match(/[^\/]+$/)[0];
return `${name}/${lessName}.less`;
}
}
]
);
} catch (e) {} } catch (e) {}
} }
......
<template>
<view class="home">这里是test 页面</view>
</template>
<script></script>
/*eslint-disable*/
import { stringTrim } from './utils.service';
// 判断输入内容是否为空
export function isNull(str) {
return str === undefined || str.length === 0 || str === null;
}
// 判断输入内容去掉空格是否为空
export function isTrimNull(str) {
if (str === undefined || str.length === 0 || str === null) {
return true;
}
return stringTrim(str).length === 0;
}
// 判断日期类型是否为YYYY-MM-DD格式的类型
export function isDate(str) {
if (!isNull(str)) {
const reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/;
const r = str.match(reg);
return r !== null;
}
}
// 判断日期类型是否为YYYY-MM-DD hh:mm:ss格式的类型
export function isDateTime(str) {
if (!isNull(str)) {
const reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;
const r = str.match(reg);
return r !== null;
}
return false;
}
// 判断日期类型是否为hh:mm:ss格式的类型
export function isTime(str) {
if (!isNull(str)) {
const reg = /^((20|21|22|23|[0-1]\d)\:[0-5][0-9])(\:[0-5][0-9])?$/;
return reg.test(str);
}
return false;
}
// 校验是否合法日期
export function isValidDate(date) {
return date instanceof Date && !isNaN(date.getTime());
}
// 判断输入的字符是否为英文字母
export function isLetter(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z]+$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为整数
export function isInteger(str) {
if (!isNull(str)) {
const reg = /^[-+]?\d*$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为身份证号
export function isIdNo(str) {
if (!isNull(str)) {
const reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为中文姓名最少两个中文字符
export function isChineseName(str) {
if (!isNull(str)) {
const reg = /^[\u0391-\uFFE5\·]{2,}$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否以数字开头
export function isStartWithInteger(str) {
if (!isNull(str)) {
const reg = /^[0-9].*$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为双精度
export function isDouble(str) {
if (!isNull(str)) {
const reg = /^[-\+]?\d+(\.\d+)?$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为:a-z,A-Z,0-9,_,并以字母开头
export function isProgramVar(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z][a-zA-Z0-9_]*$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为:a-z,A-Z,0-9,_,并以大写字母开头
export function isProgramClassName(str) {
if (!isNull(str)) {
const reg = /^[A-Z][a-zA-Z0-9_]*$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为中文
export function isChinese(str) {
if (!isNull(str)) {
const reg = /^[\u0391-\uFFE5]+$/;
return reg.test(str);
}
return false;
}
// 判断输入的EMAIL格式是否正确
export function isEmail(str) {
if (!isNull(str)) {
const reg = /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/g;
return reg.test(str);
}
return false;
}
// 判断输入的邮编(只能为六位)是否正确
export function isZIP(str) {
if (!isNull(str)) {
const reg = /^\d{6}$/;
return reg.test(str);
}
}
// 判断字符串的长度是否满足条件
export function isLengthValidate(str, len) {
if (str) {
if (str.length <= len) {
return true;
} else {
return false;
}
} else {
return true;
}
}
// 判断输入的字符是否为:a-z,A-Z,0-9,_,汉字
export function isProgramName(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z0-9_\u4e00-\u9fa5]+$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否为:a-z,A-Z,0-9,_,汉字
export function isProgramCode(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z0-9_\u4e00-\u9fa5]+$/;
return reg.test(str);
}
return false;
}
// 判断输入的字符是否以http://或者https://开头,且必须是个网址
export function isProgramWeb(str) {
if (!isNull(str)) {
let reg = /^((https|http)?:\/\/)[^\s]+/;
return reg.test(str);
}
return false;
}
export function isValueTypeMatched(type, value) {
switch (type) {
case 'Integer':
if (!/^\-?\d+$/.test(value)) {
return false;
}
break;
case 'Double':
if (!/^\-?\d+\.\d+$/.test(value)) {
return false;
}
break;
case 'Long':
if (!/^\-?\d+$/.test(value)) {
return false;
}
break;
case 'Boolean':
if (value !== 'true' && value !== 'false') {
return false;
}
break;
default:
return true;
}
return true;
}
export function isProperties(str) {
if (!isNull(str)) {
let reg = /^[a-zA-Z\u4e00-\u9fa5][a-zA-Z_0-9\u4e00-\u9fa5]*\s*=\s*[a-zA-Z_0-9\u4e00-\u9fa5]+/;
return reg.test(str);
}
return false;
}
// 拒绝码以大写字母开头,包含数字、大写字母、下划线,且为四段式
export function isUppercase(str) {
const reg = /^[A-Z]([A-Z0-9]*_){1}([A-Z0-9]+_){2}[A-Z0-9]+$/;
return reg.test(str);
}
//判断用户名
export function isUserName(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z\d_]{4,20}$/;
return reg.test(str);
}
return false;
}
//判断密码
export function isPassword(str) {
if (!isNull(str)) {
const reg = /^[a-zA-Z\d]{6,14}$/;
return reg.test(str);
}
return false;
}
//判断手机号
export function isPhone(str) {
if (!isNull(str)) {
const reg = /^1[3456789]\d{9}$/;
return reg.test(str);
}
return false;
}
// 判断税号
export function isTax(str) {
if (!isNull(str)) {
const reg = /^[A-Z0-9]{15}$|^[A-Z0-9]{17}$|^[A-Z0-9]{18}$|^[A-Z0-9]{20}$/;
return reg.test(str);
}
return false;
}
// 判断银行号
export function isBankNumber(str) {
if (!isNull(str)) {
const reg = /^[0-9]{16}$|^[0-9]{17}$|^[0-9]{19}$/;
return reg.test(str);
}
return false;
}
// 判断中文地址不能少于5个汉字,且必须有一位数字
export function isChnAddress(str) {
const isNum = /[0-9]\d*/;
const isChinese_var = /[\u4e00-\u9fa5]/g;
if (!isNull(str)) {
return isNum.test(str) && str.match(isChinese_var).length >= 5;
}
return false;
}
const ua = uni.getSystemInfoSync().ua
// 判断微信环境
export const isWechat = ua.match(/MicroMessenger/i) == 'micromessenger';
// 是否信用钱包
export const isXYQB = ua.indexOf("xyqb") > -1;
// 判断微信小程序环境
export const isWxMp = uni.getSystemInfoSync().platform === 'mp-weixin'
// 判断羊小咩(信用钱包)环境
export const isApp = ua.match(/xyqb/i) == 'xyqb';
// 判断真享生活
export const isVcc = ua.match(/VCC/i) == 'vcc';
// 判断IOS环境
export const isIOS = /iphone|ipad|ipod/.test(ua);
// 判读Android环境
export const isAndroid = /android/.test(ua);
// 判断
export const appVersion = ua.match(/xyqb\/([\d|.]+)/) ? ua.match(/xyqb\/([\d|.]+)/)[1] : '8.8.00';
export const isQQ = ua.match(/QQ/i) == 'qq';
export const isWeiBo = ua.match(/Weibo/i) == 'weibo';
export const isDingTalk = ua.match(/DingTalk/i) == 'dingtalk';
// 判读非微信浏览器和appwebview和小程序webview
export const isH5Normal = !isWechat && !isWxMp && !isApp;
This diff is collapsed.
.good-del{
::v-deep .cancel .uni-dialog-button-text {
color: $font-color-search !important;
}
::v-deep .confirm .uni-dialog-button-text {
color: $font-color-base !important;
}
}
.shopping{
::v-deep .uni-swipe{
box-sizing: border-box;
// border-right: 1px solid #fff;
border-radius: $border-radius-base;
}
}
.good {
.good-footer-num{
::v-deep .uni-numbox{
width: 96px;
height: 24px;
}
::v-deep .uni-numbox__value{
font-size: 14px;
height: 24px;;
line-height: 24px;
width: 45px;
}
::v-deep .uni-numbox__minus, ::v-deep .uni-numbox__plus{
height: 24px;;
line-height: 24px;
width: 24px;
}
}
}
// 全局设置复选框样式
.global-radio {
.wx-checkbox-input {
width: 28rpx;
height: 28rpx;
}
}
.global-checkbox {
.wx-checkbox-input {
margin-top: 0;
width: 28rpx;
height: 28rpx;
border-radius: 50%;
&.wx-checkbox-input-checked {
background: #ec1500;
border-color: #ec1500;
&::before {
width: 28rpx;
height: 28rpx;
line-height: 28rpx;
text-align: center;
font-size: 20rpx;
color: #fff;
background: transparent;
transform: translate(-50%, -50%) scale(1);
-webkit-transform: translate(-50%, -50%) scale(1);
}
}
}
}
.one-hide{
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
\ No newline at end of file
// Color Palette
$black: #333333;
$white: #fff;
$gray-1: #f7f8fa;
$gray-2: #dcdcdc;
$gray-3: #c8c9cc;
$gray-4: #999999;
$gray-5: #666666;
$gray-6: #D8D8D8;
$red: #ec1500;
$red-light: #ec3333;
$red-dark: #ee0a24;
$orange: #faab0c;
$pink: #FFECE6;
$grey-border: #f2f3f5;
// Gradient Colors
$gradient-red: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%);
$gradient-red-reverse: linear-gradient(270deg, #FF4B00 0%, #FF7705 100%);;
$gradient-pink: linear-gradient(180deg, #fff7f0 0%, #ffe4dc 100%);
// Component Colors
$text-color: $black;
$text-grey: $gray-4;
$active-opacity: 0.8;
$disabled-opacity: 0.7;
$background-color: $gray-1;
$line-height-sm: 32rpx;
$line-height-md: 44rpx;
$line-height-lg: 48rpx;
// Border
$border-width-base: 1rpx;
$border-radius-sm: 12rpx;
$border-radius-md: 16rpx;
$border-radius-lg: 32rpx;
$border-radius-lx: 40rpx;
$border-radius-max: 999rpx;
// Padding
$padding-unit: 8rpx;
$padding-xs: $padding-unit * 2;
$padding-sm: $padding-unit * 3;
$padding-md: $padding-unit * 4;
$padding-lg: $padding-unit * 5;
$padding-xl: $padding-unit * 8;
// Font
$font-size-list: 10, 11, 12, 13, 14, 16, 17, 18, 20, 26, 28, 30, 52;
@mixin text-size($f) {
$font: $f;
font-size: #{$font}rpx;
line-height: #{($font + 12)}rpx;
};
$font-weight-bold: 600;
$font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
// 页面内边距
$page-padding: $padding-sm;
$page-padding-lg: $padding-lg;
// ios底部防遮挡高度
$ios-bottom-height: 120rpx;
// 页面顶部header高度
$nav-bar-height: 96rpx;
// 多行...
@mixin mx_multline_overwrite($line: 2) {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
word-wrap: break-word;
white-space: normal !important;
-webkit-line-clamp: $line;
-webkit-box-orient: vertical;
}
const fs = require("fs");
const path = require("path");
const less = require("less");
// 设置需要转换的目录路径和输出目录路径
const srcDir = "./source";
const outDir = "./out";
// 递归遍历 srcDir 目录下的所有 less 文件,并进行转换
const convertLessToScss = (dir, out) => {
const files = fs.readdirSync(dir);
for (const file of files) {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
convertLessToScss(filePath, path.join(out, file));
} else if (stat.isFile() && path.extname(file) === ".less") {
const scss = convertLessFile(filePath);
const outPath = path.join(out, path.basename(file, ".less") + ".scss");
fs.writeFileSync(outPath, scss);
console.log(`Converted ${filePath} to ${outPath}`);
}
}
};
// 将单个 less 文件进行转换
const convertLessFile = filePath => {
const lessContent = fs.readFileSync(filePath, "utf-8");
return less.renderSync(lessContent, { syntax: "scss" }).css.toString();
};
// 创建输出目录
if (!fs.existsSync(outDir)) {
fs.mkdirSync(outDir);
}
// 开始转换
convertLessToScss(srcDir, outDir);
This diff is collapsed.
...@@ -71,7 +71,11 @@ ...@@ -71,7 +71,11 @@
"sa-sdk-smartprogram": "0.4.0-rc", "sa-sdk-smartprogram": "0.4.0-rc",
"uuid": "3.4.0", "uuid": "3.4.0",
"vue": "^2.6.11", "vue": "^2.6.11",
"vuex": "^3.2.0" "vuex": "^3.2.0",
"@qg/cherry-ui": "3.4.5-beta.1",
"@qg/js-bridge": "1.1.12",
"@qg/ui-request": "0.0.24",
"@qg/ui-track-web": "0.0.8"
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1",
...@@ -101,6 +105,8 @@ ...@@ -101,6 +105,8 @@
"husky": "^4.2.5", "husky": "^4.2.5",
"inquirer": "^8.2.0", "inquirer": "^8.2.0",
"jest": "^25.4.0", "jest": "^25.4.0",
"less": "^3.0.4",
"less-loader": "^5.0.0",
"lint-staged": "^10.2.11", "lint-staged": "^10.2.11",
"mini-types": "*", "mini-types": "*",
"miniprogram-api-typings": "*", "miniprogram-api-typings": "*",
...@@ -108,9 +114,10 @@ ...@@ -108,9 +114,10 @@
"postcss-comment": "^2.0.0", "postcss-comment": "^2.0.0",
"sass": "^1.26.11", "sass": "^1.26.11",
"sass-loader": "^10.0.2", "sass-loader": "^10.0.2",
"less": "^3.0.4", "style-resources-loader": "^1.5.0",
"less-loader": "^5.0.0", "vue-template-compiler": "^2.6.11",
"vue-template-compiler": "^2.6.11" "dingtalk-jsapi": "^2.13.53",
"js-cookie": "^2.2.1"
}, },
"browserslist": [ "browserslist": [
"Android >= 4", "Android >= 4",
......
...@@ -133,10 +133,11 @@ export default { ...@@ -133,10 +133,11 @@ export default {
} }
}; };
</script> </script>
<style lang="less">
@import "@/style/index.less";
</style>
<style lang="scss"> <style lang="scss">
@import "@/style/icon.scss"; @import "@/style/icon.scss";
@import "@/style/uni-ui.scss";
page { page {
background: $page-color-base; background: $page-color-base;
height: 100%; height: 100%;
......
<template>
<cr-popup v-model="popupShow" class="popup-head" closeable position="bottom">
<view class="popup-title">配送至</view>
<view class="goods-area">
<template v-if="addressList && addressList.length">
<view
v-for="(item, index) in addressList"
:key="index"
class="goods-area-item "
:class="{
'goods-area-item_selected': item.addrReceiverId === selectedAddressId
}"
@click="changeAddress(item)"
>
<span class="iconfont icon-location-line" />
<span class="secondText">{{ item.addrFullName }}</span>
</view>
</template>
<span v-else class="goods-area-none">暂未添加地址哦~</span>
<view class="goods-area-button" @click="addAddress">
<cr-button block type="primary" shape="circle">添加新地址</cr-button>
</view>
</view>
</cr-popup>
</template>
<script>
import goods from '@/api/goods.api.js';
import localStorage from '@/service/localStorage.service';
const EVENT_ADDRESS_SELECT = 'address-select';
const EVENT_ADDRESS_SHOW = 'input';
export default {
name: 'AddressListPopup',
props: {
value: Boolean,
selectedAddressId: {
type: [String, Number],
default: ''
}
},
data() {
return {
popupShow: this.value,
addressList: [],
hasLogin: false
};
},
watch: {
popupShow(val) {
this.$emit(EVENT_ADDRESS_SHOW, val);
},
value(val) {
this.popupShow = val;
}
},
created() {
this.hasLogin = !!localStorage.get('vccToken');
this.getAddr();
},
methods: {
changeAddress(item) {
this.$emit(EVENT_ADDRESS_SELECT, item);
this.$emit(EVENT_ADDRESS_SHOW, false);
},
addAddress() {
if (!this.hasLogin) {
this.$router.push({ name: 'Login' });
return;
}
this.$router.push({ name: 'addressManage' });
},
async getAddr() {
if (!this.hasLogin) {
return;
}
const [addressInfo] = await goods.addrList();
if (addressInfo) {
this.addressList = (addressInfo && addressInfo.addrReceiverList) || [];
const selectedAddr = this.selectedAddressId
? this.addressList.find(item => item.addrReceiverId === this.selectedAddressId)
: this.addressList.find(item => item.addrDefault === 1);
this.$emit(EVENT_ADDRESS_SELECT, selectedAddr);
}
}
}
};
</script>
<style lang="less" scoped>
// 弹出框头部
.popup-head {
border-radius: 20px 20px 0 0;
.popup-title {
.text-size(16);
font-weight: @font-weight-bold;
color: @black;
text-align: center;
padding: 10px 0;
}
}
.goods-area {
height: 65vh;
overflow: scroll;
padding: @padding-md;
position: relative;
&-item {
display: flex;
align-items: center;
margin-bottom: @padding-lg;
span {
.text-size(13);
color: @gray-4;
&:first-child {
width: 20px;
height: 20px;
line-height: 20px;
.text-size(16);
}
&:second-child {
flex: 1;
}
}
&_selected {
span {
&:first-child {
color: @red;
}
&.secondText {
color: @black;
font-weight: @font-weight-bold;
}
}
}
}
&-none {
display: inline-block;
width: 100%;
line-height: 65vh;
.text-size(13);
color: @gray-5;
text-align: center;
}
&-button {
display: flex;
justify-content: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
width: calc(100% - @padding-md * 2);
margin: 0 auto;
}
}
.goods-bottom-buy {
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
width: 335px;
height: 40px;
.text-size(14);
font-weight: bold;
border-radius: @padding-lg;
color: @white;
background-image: @gradient-red;
&.disabled {
opacity: 0.7;
}
}
</style>
<template>
<cr-overlay custom-class="net-error-mask" :show="showError">
<!-- https://img.lkbang.net/ufo.svg -->
<cr-image
src="https://img.lkbang.net/ufo.1758f833.png"
width="160px"
height="160px"
class="ufo-icon"
/>
<p class="net-error-title">网络竟然崩溃了,试试看刷新页面~</p>
<cr-button type="default" hairline shape="circle" @click="refresh">
刷新
</cr-button>
<!-- <cr-button type="danger" size="large" @click="refresh">刷新试试</cr-button> -->
</cr-overlay>
</template>
<script>
export default {
name: 'NetError',
data() {
return {
showError: false
};
},
mounted() {
this.init();
},
methods: {
refresh() {
window.location.reload();
},
init() {
window.addEventListener(
'online',
() => {
this.showError = false;
},
true
);
window.addEventListener(
'offline',
() => {
this.showError = true;
},
true
);
}
}
};
</script>
<style lang="less" scoped>
.net-error {
&-mask {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 101;
background-color: @gray-1;
.ufo-icon {
margin-top: -120px;
}
.cr-button {
color: @black;
margin-top: 13px;
width: 132px;
// border-radius: 6px;
}
}
&-title {
color: @black;
.text-size(14);
margin-top: 14px;
}
}
</style>
<template>
<view class="goods">
<template v-for="item in data">
<view v-if="item.goods" :key="item.goodsId" :class="['card']" @click="toDetail(item.goods)">
<view class="card__top">
<view class="card__head">
<image class="card__head__image" object-fit="contain" :src="item.goods.goodsImage" />
</view>
<p class="card__name">
{{ item.goods.goodsName }}
</p>
<p v-if="item.goods.serviceTypeList" class="card__service">
"{{ item.goods.serviceTypeList[0] }}"
</p>
<view class="card__tag">
<view v-for="(tag, index) in item.goods.tagList" :key="index" class="card__tag-wrap">
<span v-if="tag.type == 2" :key="index" class="card__tag-normal">{{ tag.name }}</span>
<image v-if="tag.type == 1" class="card__tag-icon" :src="tag.icon" alt="" />
</view>
</view>
</view>
<view class="card__bottom">
<view class="price">
<p>
<span class="price__icon">¥</span>
<span class="price__text">{{
item.goods.goodsSalePrice && item.goods.goodsSalePrice.replace('', '')
}}</span>
</p>
<p class="sale">已售{{ item.goods.saleCount }}</p>
</view>
</view>
</view>
</template>
</view>
</template>
<script>
export default {
props: {
data: {
type: Array,
default: () => []
}
},
methods: {
toDetail(item) {
const params = {
count: 1,
goodsName: item.goodsName,
goodsimg: item.goodsImage
};
const query = {
skuNo: item.goodsId
};
this.$router.push({ name: 'goodDetail', params, query });
}
}
};
</script>
<style lang="less" scoped>
.goods {
height: 100%;
}
.card {
// width: 49%;
font-size: 0;
background-color: #fff;
border-radius: 6px;
margin-bottom: 10px;
display: flex;
flex-direction: column;
position: relative;
justify-content: space-between;
&__head {
height: 173px;
border-radius: 6px;
overflow: hidden;
&__image {
height: 100%;
width: 100%;
}
}
&__name {
font-size: 13px;
line-height: 18px;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin: 8px 5px 0px 14px;
.shop-tag {
vertical-align: middle;
margin-top: -2px;
}
}
&__service {
font-size: 13px;
color: #e1a069;
margin: 5px 14px;
}
&__tag {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
margin: 3px 5px 0 14px;
&-wrap {
margin-bottom: 5px;
}
&-text {
color: #e1a069;
font-size: 13px;
}
&-normal {
display: inline-block;
font-size: 10px;
box-sizing: border-box;
border: 1px solid #ff5a4b;
color: #ff5a4b;
padding: 0px 4px;
border-radius: 3px;
margin-right: 5px;
line-height: 14px;
}
&-icon {
height: 15px;
margin-right: 5px;
}
&-warn {
color: #ff4b00;
border: 1px solid #ff4b00;
}
}
&__bottom {
padding: 5px 5px 6px 14px;
.activity {
display: flex;
align-items: bottom;
&__free {
height: 14px;
margin-right: 3px;
}
}
.price__raw {
float: left;
color: #999;
font-size: 10px;
line-height: 14px;
text-decoration: line-through;
}
.sale {
color: #999;
font-size: 10px;
height: 20px;
display: flex;
align-items: flex-end;
margin-left: 5px;
}
.price {
display: flex;
align-items: flex-start;
&__icon {
font-size: 12px;
color: #ec3333;
}
&__text {
font-size: 18px;
line-height: 25px;
color: #ec3333;
}
}
}
&::after {
clear: both;
}
}
</style>
<template>
<view class="reco">
<cr-divider v-show="list.length" :hairline="false">{{ desc }}</cr-divider>
<cr-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
offset="100"
@load="onLoad"
>
<view class="list">
<view class="left">
<Goods :data="leftList" />
</view>
<view class="right">
<Goods :data="rightList" />
</view>
</view>
</cr-list>
</view>
</template>
<script>
import { getGoodsList } from '@/api/pay.api.js';
import Goods from './Goods.vue';
export default {
components: {
Goods
},
props: {
desc: {
type: String,
default: '猜你喜欢'
},
pageSize: {
type: Number,
default: 20
}
},
data() {
return {
finished: false,
loading: false,
list: [],
pageNo: 1,
leftList: [],
rightList: []
};
},
mounted() {},
methods: {
async loadReco() {
this.loading = true;
try {
const [data] = await getGoodsList({
pageType: 6,
phoneNo: this.phoneNo,
pageSize: this.pageSize,
pageNo: this.pageNo
});
if (data) {
this.loading = false;
this.list = [...this.list, ...data.goodsList] || [];
this.leftList = this.list.filter((item, index) => {
if (index % 2 === 0) {
return item;
}
});
this.rightList = this.list.filter((item, index) => index % 2);
if (!data.hasNext) {
this.finished = true;
} else {
this.pageNo++;
}
} else {
this.loading = false;
this.finished = true;
}
} catch (error) {
this.loading = false;
this.finished = true;
}
},
onLoad() {
this.loadReco();
}
}
};
</script>
<style lang="less" scoped>
.reco {
width: 100%;
height: 100%;
.cr-divider {
margin: 0;
margin-bottom: 12px;
padding: 0 60px;
color: #999;
border: 0 solid #dcdcdc;
font-size: 12px;
}
& /deep/ .cr-list__finished-text {
display: none;
}
& /deep/ .cr-list__loading {
margin: 0 auto;
}
.cr-list {
box-sizing: border-box;
padding: 10px 0;
height: 100%;
.list {
height: 100%;
overflow: auto;
clear: both;
}
.left {
float: left;
width: 49%;
height: 100%;
display: flex;
flex-direction: column;
}
.right {
float: right;
width: 49%;
height: 100%;
display: flex;
flex-direction: column;
}
}
}
</style>
<template>
<view>
<view v-if="showShareOverlay" class="share-overlay" @click.self="onShareOverlayClick" />
</view>
</template>
<script>
import { isWechat, isWxMp, isH5Normal } from '@/service/validation.service';
import localStorageService from '@/service/localStorage.service';
// import { queryStringify } from '@/service/utils.service';
import cfg from '@/config';
import qs from 'qs';
const APP_PATH = 'xyqb://openHttp';
export default {
props: {
nWeb: {
type: Boolean,
default: false
},
params: Object,
appUrl: String
},
data() {
return {
showShareOverlay:
((isWechat && !isWxMp) || isH5Normal) && !localStorageService.get('vccChannel')
};
},
methods: {
openAppSchemeUrl() {
if (isH5Normal) {
window.location.href = this.appUrl;
setTimeout(() => {
this.navToDlApp();
}, 2000);
} else if (isWechat && !isWxMp) {
window.location.href = `${
cfg.mallUIHost
}/common/launch?jumpUrl=${APP_PATH}&terminal=2&extraInfo=${encodeURIComponent(
JSON.stringify({ url: this.appUrl })
)}`;
}
},
onShareOverlayClick() {
if (this.nWeb) {
this.openAppSchemeUrl();
return;
}
let url = `${window.location.origin}${
window.location.pathname
}?vccToken={token}&${qs.stringify(this.params)}`;
console.log(url, '000000');
if (isH5Normal) {
url += `&exposure_source=${this.$route.query.exposure_source}`;
window.location.href = `${APP_PATH}?jumpUrl=${this.appUrl || url}`;
} else if (isWechat && !isWxMp) {
url += `&exposure_source=wechat`;
window.location.href = `${
cfg.mallUIHost
}/common/launch?jumpUrl=${APP_PATH}&terminal=2&extraInfo=${encodeURIComponent(
JSON.stringify({ url: this.appUrl || url })
)}`;
}
setTimeout(() => {
this.navToDlApp();
}, 6000);
},
navToDlApp() {
if (process.server) return;
// window.location.href = 'xyqb://openApp';
window.location.href = cfg.appDownUrl;
const nextPage = document.createElement('a');
nextPage.setAttribute('href', cfg.appDownUrl);
nextPage.click();
}
}
};
</script>
<style lang="less" scoped>
.share-overlay {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%;
z-index: 999;
}
</style>
<template>
<svg :class="[className, 'svg-icon']" aria-hidden="true">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: [String, Array],
required: true
},
className: {
type: [String, Array],
default: ''
}
},
computed: {
iconName() {
return `#icon-${this.iconClass}`;
}
}
};
</script>
<style>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>
<template>
<view class="tag-item">
<view v-if="item.type === 1" class="tag-item--icon">
<image v-if="item.icon" :src="item.icon" />
</view>
<view v-else-if="item.type === 2" class="tag-item--text">{{ item.name }}</view>
<view v-else-if="item.type === 3" class="tag-item--text tag-item--radius">{{ item.name }}</view>
<view v-else-if="item.type === 4" class="tag-item--text tag-item--coupon">
<view class="tag-item--coupon__label">{{ item.head }}</view>
<view class="tag-item--coupon__content">{{ item.name }}</view>
</view>
</view>
</template>
<script>
export default {
props: {
item: {
type: Object,
default: () => ({})
}
},
computed: {
imgWidth() {
return 12 * +this.item.iconRate + 'px';
}
}
};
</script>
<style lang="less">
@itemHeight: 12px;
.tag-item {
display: flex;
align-items: center;
justify-content: flex-start;
height: 14px;
margin-right: 3px;
.text-size(8px);
overflow: hidden;
&--icon {
img {
display: block;
height: @itemHeight;
}
}
&--text {
border-radius: 3px;
border: 1px solid @red;
height: @itemHeight;
line-height: @itemHeight;
box-sizing: border-box;
padding: 0 5px;
color: @red;
}
&--radius {
position: relative;
&::after,
&::before {
content: '';
position: absolute;
right: 0;
top: 50%;
width: 6px;
height: 6px;
border-radius: 50%;
box-sizing: border-box;
border: 1px solid @red;
background-color: #fff;
transform: translate(4px, -50%);
}
&::before {
left: 0;
transform: translate(-4px, -50%);
}
}
&--coupon {
display: flex;
padding: 0;
&__label {
height: 100%;
width: @itemHeight;
background-color: @red;
color: #fff;
text-align: center;
}
&__content {
flex: 1;
text-align: center;
padding: 0 2px;
}
}
}
</style>
<template>
<view class="x-page-container">
<template v-if="showOption.showFirst">
<slot name="first-screen" />
<!-- 首屏分割线-->
<view ref="first-line" />
</template>
<template v-if="showOption.showTwo">
<slot name="two-screen" />
</template>
<template v-if="showOption.other">
<slot name="other-screen" />
</template>
</view>
</template>
<script>
/**
* 1. showFirst 首屏渲染开关
* 2. showTwo other 非首屏渲染开关
*思路:
* 通过定时器轮训首屏分割线距离顶部的距离,距离不发生变化或者超过首屏高度后,骨架屏消失
* 调整刷新频率为30ms 最大重试次数为15次
*/
export default {
data() {
return {
showOption: {
showFirst: true,
showTwo: false,
other: false
}
};
},
mounted() {
const windowHeight = window.screen.height;
let equalCount = 0; // 距离顶部距离相同计数器
let showOther = false; // 展示非首屏逻辑
let lineTop = -1; // 首屏分割线距离顶部的距离
let count = 0; // 重试计时器 超过10次之后,设置为true
const timer = setInterval(
() => {
const data = this.$refs['first-line']?.getBoundingClientRect();
count++;
if (!data?.top) return;
if (showOther) {
return;
}
if (data?.top) {
if (lineTop !== data?.top) {
lineTop = data?.top;
} else {
equalCount++;
// 超过首屏高度,给展示
if (data?.top > windowHeight) {
showOther = true;
}
// 高度连续2次不变化,设置为true
if (equalCount > 2) {
showOther = true;
}
}
}
if (count > 15) {
showOther = true;
}
if (showOther) {
Object.assign(this.showOption, {
showTwo: true,
other: true
});
console.log('移除遮罩');
this.$emit('loadFirstScreen');
clearInterval(timer);
}
// 这个
},
30,
true
);
}
};
</script>
<style lang="less" scoped>
#first-line {
height: 1px;
//background: red; // 这里是测试
background: transparent;
}
</style>
.baseInfo {
color: #999999;
font-size: 12px;
text-align: center;
font-weight: bold;
padding: 30px 24px 30px 24px;
box-sizing: border-box;
&-title {
margin-bottom: 8px;
}
&-agreement-item {
margin-bottom: 8px;
font-size: 10px;
}
&-item {
line-height: 17px;
&-jump {
line-height: 14px;
font-size: 10px;
color: #999;
text-decoration: underline !important;
}
}
&-des {
line-height: 14px;
margin-bottom: 8px;
font-size: 10px;
// transform: scale(0.83, 0.83);
// -webkit-transform: scale(0.83, 0.83);
// -moz-transform: scale(0.83, 0.83);
// -o-transform: scale(0.83, 0.83);
}
}
.baseInfo {
color: #999999;
font-size: 12px;
text-align: center;
font-weight: bold;
padding: 30px 24px 30px 24px;
box-sizing: border-box;
&-title {
margin-bottom: 8px;
}
&-agreement-item {
margin-bottom: 8px;
font-size: 10px;
}
&-item {
line-height: 17px;
&-jump {
line-height: 14px;
font-size: 10px;
color: #999;
text-decoration: underline !important;
}
}
&-des {
line-height: 14px;
margin-bottom: 8px;
font-size: 10px;
// transform: scale(0.83, 0.83);
// -webkit-transform: scale(0.83, 0.83);
// -moz-transform: scale(0.83, 0.83);
// -o-transform: scale(0.83, 0.83);
}
}
<template>
<view class="baseInfo">
<view class="baseInfo-title">
<p class="baseInfo-item">羊小咩·美好生活更从容</p>
<p class="baseInfo-item">北京量化派科技有限公司</p>
</view>
<p class="baseInfo-agreement-item">
您可以点击查看相关:
<a class="baseInfo-item-jump" href="https://mall.91xr.cn/spreadApplication">应用权限</a>
<a
class="baseInfo-item-jump"
href="https://appsync.lkbang.net/agreement-three.html?contractTemplateId=8&title=信用钱包隐私政策"
>隐私政策</a
>
<a
class="baseInfo-item-jump"
href="https://appsync.lkbang.net/agreement-three.html?contractTemplateId=280&title=%E6%B3%A8%E5%86%8C%E5%8D%8F%E8%AE%AE"
>
用户注册协议</a
>
</p>
<view>
<view class="baseInfo-des">
羊小咩是北京量化派科技有限公司旗下产品,其面向追求美好生活的年轻人,为他们提供便捷且高性价比的商品及生活服务。
</view>
<view class="baseInfo-des">北京市海淀区丹棱街3号电子大厦B座701-705,1707-1712</view>
</view>
</view>
</template>
<script>
export default {
props: {
isBaiduChannel: {
type: Boolean,
default: false
}
}
};
</script>
<style lang="less" scoped src="./index.less" />
<template> <template>
<view> <view>
<view v-if="type === 'shoppingCar'" class="goods-bottom"> <view v-if="type === 'shoppingCar'" class="goods-bottom goods-car">
<!-- <navigator url="/pages/index/index" class="goods-bottom-icon" @click="goHome" hover-class="none"> <view v-if="noStock" class="no-stock-tip">
<text class="iconfont icon-home"></text> 抱歉,当前商品无库存,可查看相似商品
<text>首页</text> </view>
</navigator> --> <view class="goods-car-icon" @click="goShopCart">
<!-- <navigator v-if="type === 'shoppingCar'" url="/pages/cart/cart" class="goods-bottom-icon"> <image class="goods-car-icon-img" src="https://img.lkbang.net/cart.b2b405fb.png" alt="car" />
<text class="iconfont icon-cart-card" /> <span class="goods-car-icon-name">购物车</span>
<text>购物车</text> <span v-if="cartCount" class="badge">{{ cartCount }}</span>
</navigator> </view>
<button class="goods-bottom-car">加入购物车</button> --> <view class="goods-car-bottom-group">
<button class="goods-bottom-buy" :class="{ disabled: disabled }" @click="buy"> <button
{{ shopBtnName }} v-if="!noStock"
</button> :class="['goods-bottom-car', disabled && 'disabled']"
</view> @click="addToCart"
<view v-if="type === 'settlement'" class="goods-bottom"> >
<radio-group class="goods-bottom-radio" @change="radioChange"> 加入购物车
<label> </button>
<radio /> <button v-if="!noStock" :class="['goods-bottom-buy', disabled && 'disabled']" @click="buy">
<text>全选</text> {{ shopBtnName }}
</label> </button>
</radio-group> <button v-if="noStock" class="similar" @click="goSimilar">
<view class="goods-bottom-text"> 查看相似
<view class="Gb-text-top"> </button>
<text>合计:</text>
<text>¥</text>
<text>627.00</text>
</view>
<text class="Gb-text-bottom">免运费</text>
</view> </view>
<button class="goods-bottom-buy" @click="buy">结算(5)</button>
</view> </view>
<view v-if="type === 'submitOrder'" class="goods-bottom"> <view v-if="type === 'submitOrder'" class="goods-bottom">
<view class="goods-bottom-text"> <view class="goods-bottom-text">
<view class="Gb-text-top"> <view class="Gb-text-top">
<text>合计:</text> <span>合计:</span>
<text>¥</text> <span>¥</span>
<text>{{ info.totalPayFee || "0.00" }}</text> <span>{{ info.totalPayFee || '0.00' }}</span>
</view> </view>
</view> </view>
<button class="goods-bottom-buy confirm-order-btn" @click="buy">提交订单</button> <cr-button
class="goods-bottom-buy confirm-order-btn"
:disabled="goodsList.length === 0"
type="primary"
@click="buy"
>提交订单</cr-button
>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import { saTrackEvent } from "@/utils/sa.js"; import { mapGetters as ShopCartMapGetters } from '@/pages/shopCart/shopCartModules.js';
export default { export default {
name: "BottomNav", name: 'BottomNav',
props: { props: {
noStock: {
type: Boolean,
default: false
},
type: { type: {
type: String, type: String,
default: "shopCar" // shoppingCar 购物车;settlement 结算;submitOrder 确认订单 default: 'shopCar' // shoppingCar 购物车;settlement 结算;submitOrder 确认订单
}, },
shopBtnName: { shopBtnName: {
type: String, type: String,
default: "立即购买" // shoppingCar 购物车;settlement 结算;submitOrder 确认订单 default: '立即购买' // shoppingCar 购物车;settlement 结算;submitOrder 确认订单
}, },
info: { info: {
type: Object, type: Object,
...@@ -68,56 +73,74 @@ export default { ...@@ -68,56 +73,74 @@ export default {
}, },
goodsId: { goodsId: {
type: String, type: String,
default: "" default: ''
},
goodsList: {
type: Array,
default() {
return [];
}
} }
}, },
computed: {
...ShopCartMapGetters(['cartCount'])
},
methods: { methods: {
buy() { buy() {
this.$emit("buy"); // 如果操作为提交订单
if (this.type === 'submitOrder') {
// 如果购物车有商品
if (this.goodsList.length > 0) {
// 触发打开商品弹窗事件
this.$emit('buy', 'openGoodsPopup');
}
} else {
// 如果操作为购买商品
// 触发打开商品弹窗事件
this.$emit('buy', 'openGoodsPopup');
}
},
goSimilar() {
this.$emit('goSimilar');
}, },
goHome() { addToCart() {
const that = this; this.$emit('addToCart', 'openGoodsPopup');
// const currentPage = getCurrentPages(); },
saTrackEvent("PD_YXMMAEC_UserClickCommodityDetailHomePageBtn", { goShopCart() {
commodity_id: that.goodsId
});
uni.reportAnalytics("c_commoditydetailhomepagebtn", {
commodity_id: that.goodsId
});
setTimeout(() => { setTimeout(() => {
uni.switchTab({ this.$router.push({ name: 'Cart' });
url: "/pages/index/index"
});
}, 500); }, 500);
} }
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="less" scoped>
@import "@/style/icon.scss";
.goods-bottom { .goods-bottom {
position: fixed; position: fixed;
left: 0; left: 0;
bottom: 0; bottom: 0;
display: flex; display: flex;
justify-content: space-between; justify-content: space-evenly;
align-items: center; align-items: center;
width: 100%; width: 100%;
height: 120rpx; // height: 33px;
padding: 30rpx 15rpx 30rpx 30rpx; padding-top: 8px;
background: $white; padding-bottom: calc(8px + constant(safe-area-inset-bottom));
border-top: $border-sm solid $bg-color-g1; padding-bottom: calc(8px + env(safe-area-inset-bottom));
background: @white;
border-top: 2px solid #f7f7f7;
// box-sizing: border-box;
&-radio { &-radio {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-around; justify-content: space-around;
padding-top: 8rpx; padding-top: 8px;
width: 140rpx; width: 140px;
radio { radio {
transform: scale(0.7); transform: scale(0.7);
} }
text { span {
font-size: 24rpx; font-size: 24px;
color: #999999; color: #999999;
} }
} }
...@@ -126,72 +149,132 @@ export default { ...@@ -126,72 +149,132 @@ export default {
flex-direction: column; flex-direction: column;
align-items: flex-end; align-items: flex-end;
flex: 1; flex: 1;
margin: 0 20rpx; margin: 0 20px;
.Gb-text-top { .Gb-text-top {
display: flex; display: flex;
align-items: center; align-items: center;
text { span {
&:nth-child(1) { &:nth-child(1) {
padding-top: 8rpx; padding-top: 4px;
font-size: 24rpx; .text-size(12);
color: #333333; color: #333333;
} }
&:nth-child(2) { &:nth-child(2) {
padding-top: 8rpx; padding-top: 4px;
font-size: 24rpx; .text-size(12);
color: #ec3333; color: #ec3333;
} }
&:nth-child(3) { &:nth-child(3) {
font-size: 38rpx; .text-size(18);
font-weight: bold; font-weight: bold;
color: #ec3333; color: #ec3333;
} }
} }
} }
.Gb-text-bottom { .Gb-text-bottom {
font-size: 24rpx; .text-size(12);
color: #999999; color: #999999;
} }
} }
&-icon {
display: flex;
align-items: center;
flex-direction: column;
text {
&:first-child {
font-size: $font-2;
}
&:last-child {
font-size: $font-sm;
color: $text-color-n1;
}
}
}
&-car { &-car {
border: $border-sm solid $border-color-search; position: relative;
background: $white; // border: @border-sm solid @border-color-search;
color: $font-color-search; // .mx_order_one(@border-color-search, solid, 40px);
border: 1.5px solid @border-color-search;
background: @white;
color: @font-color-search;
} }
&-buy { &-buy {
color: $white; color: @white;
background-image: $background-primary; background-image: @background-primary;
} }
button { button {
margin: 0; margin: 0;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
width: 100%; // width: 305px;
height: 80rpx; height: 40px;
font-size: 34rpx; .text-size(14);
// font-weight: bold; font-weight: bold;
border-radius: $border-radius-2; border-radius: 20px;
&.disabled { &.disabled {
opacity: 0.7; opacity: 0.7;
} }
} }
} }
.confirm-order-btn { .confirm-order-btn {
width: 200rpx !important; width: 130px !important;
margin-right: 10px !important;
}
.goods-car {
width: 100%;
display: flex;
.no-stock-tip {
position: absolute;
background: #ffece6;
color: #ec1500;
font-size: 14px;
line-height: 25px;
padding-left: 10px;
width: 100%;
box-sizing: border-box;
top: -25px;
}
&-icon {
width: 70px;
position: relative;
height: 100%;
text-align: center;
&-img {
max-width: 24px;
width: 24px;
height: 24px;
display: block;
margin: 0 auto;
object-fit: contain;
position: relative;
left: -2px;
}
&-name {
.text-size(11);
color: #999999;
display: block;
}
.badge {
position: absolute;
right: 10px;
top: -8px;
min-width: 16px;
border-radius: 16px;
padding: 2px 3px;
font-size: 12px;
color: #fff;
font-weight: 500;
text-align: center;
box-sizing: border-box;
margin-top: 2px;
background-color: #ec1500;
}
}
&-bottom-group {
width: 305px;
display: flex;
box-sizing: border-box;
padding-right: 10px;
justify-content: space-between;
.similar {
width: 100%;
color: @white;
background-image: @background-primary;
}
.goods-bottom-car,
.goods-bottom-buy {
width: 48.5%;
}
}
} }
</style> </style>
<template> <template>
<view class="coupon-list"> <view class="coupon-list">
<view class="coupon-title">选择{{ feeTitle }}</view> <h3 class="coupon-title">选择{{ feeTitle }}</h3>
<view class="coupon-list__list"> <view class="coupon-list__list">
<template v-if="list.length"> <template v-if="list.length">
<scroll-view :scroll-y="true" class="coupon-list__scroll"> <view v-for="(info, index) in list" :key="index" @click="handleSelectCoupon(info.id)">
<view v-for="(info, index) in list" :key="index" @click="handleSelectCoupon(info.id)"> <view v-if="couponType == 4" class="minus-list__item">
<view v-if="couponType == 4" class="minus-list__item"> <view class="minus-list__left">
<view class="minus-list__left"> <p>{{ info.activityDesc }}</p>
<view>{{ info.activityDesc }}</view> <span>活动有效期:{{ info.startDate }}-{{ info.endDate }}</span>
<text>活动有效期:{{ info.startDate }}-{{ info.endDate }}</text>
</view>
<view class="minus-list__right">
<radio :value="index" color="#EC1500" :checked="info.isSelect" />
<view class="coupon-list__radio--cover" />
</view>
</view> </view>
<view v-else class="coupon-list__item"> <view class="minus-list__right">
<image v-if="info.iconUrl" :src="info.iconUrl" class="coupon-list__tag" /> <cr-icon v-if="info.isSelect" type="checked" color="#ec3333" size="25px" />
<view class="coupon-list__left"> <cr-icon v-else type="circle" color="#dcdcdc" size="25px" />
<view class="coupon-list__amount"> </view>
<text>{{ currency }}</text> </view>
{{ info.faceValue }} <view v-else class="coupon-list__item">
</view> <image :src="info.iconUrl" class="coupon-list__tag" />
<view class="coupon-list__limit">{{ info.limitDesc }}</view> <view class="coupon-list__left">
</view> <view class="coupon-list__amount">
<view class="coupon-list__content"> <span>{{ currency }}</span>
<view class="coupon-list__desc">{{ info.name }}</view> {{ info.faceValue }}
<view class="coupon-list__date">{{ info.couponValidTime }}</view>
</view>
<view class="coupon-list__right">
<radio :value="index" color="#EC1500" :checked="info.isSelect" />
<view class="coupon-list__radio--cover" />
</view> </view>
<view class="coupon-list__limit">{{ info.limitDesc }}</view>
</view>
<view class="coupon-list__content">
<view class="coupon-list__desc">{{ info.name }}</view>
<view class="coupon-list__date">{{ info.couponValidTime }}</view>
</view>
<view class="coupon-list__right">
<cr-icon v-if="info.isSelect" type="checked" color="#ec3333" size="25px" />
<cr-icon v-else type="circle" color="#dcdcdc" size="25px" />
</view> </view>
</view> </view>
</scroll-view> </view>
</template> </template>
<view v-else class="coupon-list__empty"><empty text="暂无优惠券"/></view> <view v-else class="coupon-list__empty"><empty text="暂无优惠券" /></view>
</view> </view>
<view v-if="list.length" class="coupon-list__bottom"> <view v-if="list.length" class="coupon-list__bottom">
<button @click="handleRadioSubmit">确定</button> <button @click="handleRadioSubmit">确定</button>
...@@ -44,11 +42,11 @@ ...@@ -44,11 +42,11 @@
</view> </view>
</template> </template>
<script> <script>
import { getCouponChooseList } from "../api/home.api"; import { getCouponChooseList } from '@/api/home.api';
import Empty from "./empty"; import { TITLE_LIST } from '@/constants/order';
import { TITLE_LIST } from "@/constants/order.js"; import Empty from './empty';
export default { export default {
name: "CouponList", name: 'CouponList',
components: { components: {
Empty Empty
}, },
...@@ -60,7 +58,7 @@ export default { ...@@ -60,7 +58,7 @@ export default {
couponType: [String, Number], couponType: [String, Number],
currency: { currency: {
type: String, type: String,
default: "¥" default: '¥'
}, },
goodsInfo: { goodsInfo: {
type: Array, type: Array,
...@@ -70,12 +68,15 @@ export default { ...@@ -70,12 +68,15 @@ export default {
type: Array, type: Array,
default: () => [] default: () => []
}, },
commonPopup: Number isShow: {
type: Boolean,
default: false
}
}, },
data() { data() {
return { return {
list: [], list: [],
selectedCouponIndex: null couponList: []
}; };
}, },
computed: { computed: {
...@@ -89,31 +90,10 @@ export default { ...@@ -89,31 +90,10 @@ export default {
} }
}, },
watch: { watch: {
couponActivityInfoList: { isShow(v) {
handler() { v && this.getCouponChooseList();
this.getCouponChooseList();
},
deep: true,
immediate: true
},
couponType: {
handler: function() {
this.getCouponChooseList();
},
deep: true,
immediate: true
},
couponId: {
handler: function() {
this.getCouponChooseList();
},
deep: true,
immediate: true
} }
}, },
mounted() {
this.getCouponChooseList();
},
methods: { methods: {
handleSelectCoupon(num) { handleSelectCoupon(num) {
this.list.map(item => { this.list.map(item => {
...@@ -125,7 +105,7 @@ export default { ...@@ -125,7 +105,7 @@ export default {
}); });
}, },
handleRadioSubmit() { handleRadioSubmit() {
this.$emit("select", this.selectedCoupon); this.$emit('coupon-select', this.selectedCoupon);
}, },
async getCouponChooseList() { async getCouponChooseList() {
if (!this.goodsInfo.length) return; if (!this.goodsInfo.length) return;
...@@ -154,7 +134,6 @@ export default { ...@@ -154,7 +134,6 @@ export default {
const data = this.couponType == 4 ? res.activityList : res.coupons; const data = this.couponType == 4 ? res.activityList : res.coupons;
data.forEach(u => { data.forEach(u => {
u.id = this.couponType == 4 ? u.activityId : u.pickupId; u.id = this.couponType == 4 ? u.activityId : u.pickupId;
u.couponCategory = this.couponType == 4 ? 4 : u.couponCategory;
if (u.id == this.couponId) u.isSelect = true; if (u.id == this.couponId) u.isSelect = true;
else u.isSelect = false; else u.isSelect = false;
}); });
...@@ -164,30 +143,32 @@ export default { ...@@ -164,30 +143,32 @@ export default {
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="less" scoped>
.coupon-title { .coupon-title {
text-align: center; text-align: center;
margin: 0 auto; margin: 0 auto;
padding-top: 30rpx; margin-top: 15px;
width: 50%; width: 50%;
font-size: 36rpx; .text-size(18);
} }
.coupon-list { .coupon-list {
&__bottom { &__bottom {
padding: 20rpx 40rpx 30rpx; padding: 10px 20px 15px 20px;
position: relative; position: relative;
box-sizing: border-box;
button { button {
width: 100%;
background-image: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%); background-image: linear-gradient(269deg, #ff5d00 12%, #ff1900 86%);
border-radius: 160rpx; border-radius: 80px;
height: 80rpx; height: 40px;
font-size: 28rpx; .text-size(14);
line-height: 80rpx; line-height: 40px;
color: #fff; color: #fff;
} }
} }
&__list { &__list {
padding: 20rpx 20rpx 0; padding: 10px 10px 0;
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
height: 50vh; height: 50vh;
...@@ -196,7 +177,7 @@ export default { ...@@ -196,7 +177,7 @@ export default {
height: 100%; height: 100%;
} }
&__empty { &__empty {
padding-top: 100rpx; padding-top: 50px;
} }
&__item { &__item {
...@@ -204,9 +185,9 @@ export default { ...@@ -204,9 +185,9 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
background: #ffece6; background: #ffece6;
border-radius: 12rpx; border-radius: 6px;
padding: 37.5rpx 20rpx; padding: 18px 10px;
margin-bottom: 20rpx; margin-bottom: 10px;
&--disabled { &--disabled {
-webkit-filter: grayscale(100%) opacity(0.8); /* Chrome, Safari, Opera */ -webkit-filter: grayscale(100%) opacity(0.8); /* Chrome, Safari, Opera */
...@@ -217,20 +198,12 @@ export default { ...@@ -217,20 +198,12 @@ export default {
} }
} }
} }
&__radio--cover {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 1;
}
&__tag { &__tag {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 88rpx; width: 44px;
height: 32rpx; height: 16px;
} }
&__left { &__left {
text-align: center; text-align: center;
...@@ -238,78 +211,77 @@ export default { ...@@ -238,78 +211,77 @@ export default {
} }
&__amount { &__amount {
font-size: 60rpx; font-size: 30px;
font-weight: 500; font-weight: 500;
line-height: 72rpx; line-height: 36px;
margin: 0; margin: 0;
text { text {
font-size: 32rpx; font-size: 16px;
line-height: 44rpx; line-height: 22px;
} }
} }
&__limit { &__limit {
font-size: 24rpx; .text-size(12);
color: #ec3333; color: #ec3333;
line-height: 34rpx; line-height: 17px;
margin: 0; margin: 0;
} }
&__content { &__content {
padding: 0 36rpx; padding: 0 18px;
} }
&__desc { &__desc {
font-size: 28rpx; .text-size(14);
line-height: 40rpx; line-height: 20px;
font-weight: 500; font-weight: 500;
color: #333; color: #333;
margin-bottom: 6rpx; margin-bottom: 3px;
} }
&__date { &__date {
font-size: 24rpx; .text-size(12);
color: #666666; color: #666666;
line-height: 34rpx; line-height: 17px;
} }
&__right { &__right {
margin-left: auto; margin-left: auto;
position: relative; .radio {
&.wx-radio-input { width: 30px;
background-color: #ffece6 !important; height: 30px;
} display: block;
radio {
transform: scale(0.8); transform: scale(0.8);
background-color: red !important;
} }
} }
} }
::v-deep .cr-icon {
line-height: 28px !important;
}
.minus-list { .minus-list {
&__list {
padding: 10px 10px 0;
overflow-y: scroll;
overflow-x: hidden;
height: 50vh;
}
&__item { &__item {
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
border-radius: 12rpx; border-radius: 6px;
padding: 12rpx 20rpx; padding: 6px 10px;
margin-bottom: 20rpx; margin-bottom: 10px;
} }
&__left { &__left {
font-size: 28rpx; .text-size(14);
span { span {
color: $font-color-base; color: @font-color-base;
font-size: 24rpx; .text-size(12);
}
}
&__right {
margin-left: auto;
position: relative;
&.wx-radio-input {
background-color: #ffece6 !important;
}
radio {
transform: scale(0.8);
} }
} }
} }
......
...@@ -4,20 +4,20 @@ ...@@ -4,20 +4,20 @@
<view class="Gc-item-left"> <view class="Gc-item-left">
<image class="Gci-left-type" :src="item.iconUrl" /> <image class="Gci-left-type" :src="item.iconUrl" />
<view class="Gci-left-amount"> <view class="Gci-left-amount">
<view class="Gcil-amount-price" <view class="Gcil-amount-price">
><text>{{ item.faceValue }}</text></view <span>{{ item.faceValue }}</span>
> </view>
<view class="Gci-amount-desc">{{ item.limitDesc }}</view> <view class="Gci-amount-desc">{{ item.limitDesc }}</view>
</view> </view>
<view class="Gci-left-desc"> <view class="Gci-left-desc">
<text class="Gcil-desc-name">{{ item.name }}</text> <span class="Gcil-desc-name">{{ item.name }}</span>
<!-- <text v-if="!item.pickupAble" class="Gcil-desc-time" <!-- <span v-if="!item.pickupAble" class="Gcil-desc-time"
>{{ item.startDate }}-{{ item.endDate }}</text >{{ item.startDate }}-{{ item.endDate }}</span
> --> > -->
<text class="Gcil-desc-time">{{ item.couponValidTime }}</text> <span class="Gcil-desc-time">{{ item.couponValidTime }}</span>
<view> <view>
<text class="Gcil-desc-detail" /> <span class="Gcil-desc-detail" />
<text /> <span />
</view> </view>
</view> </view>
</view> </view>
...@@ -30,9 +30,9 @@ ...@@ -30,9 +30,9 @@
<button <button
class="Gci-right-button" class="Gci-right-button"
:class="{ 'Gci-right-button_received': item.pickupAble }" :class="{ 'Gci-right-button_received': item.pickupAble }"
@click="pickupCoupon(item)" @click="pickupCoupon(item, index)"
> >
{{ item.pickupAble ? "已领取" : "立即领取" }} {{ item.pickupAble ? '已领取' : '立即领取' }}
</button> </button>
</view> </view>
</view> </view>
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
</template> </template>
<script> <script>
export default { export default {
name: "CouponCard", name: 'CouponCard',
props: { props: {
couponList: { couponList: {
type: Array, type: Array,
...@@ -49,85 +49,75 @@ export default { ...@@ -49,85 +49,75 @@ export default {
}, },
data() { data() {
return { return {
list: [] // list: []
}; };
}, },
computed: { computed: {
// list() { list() {
// const coupon = [] return this.couponList.map(el => {
// this.couponList.map(el => { el.startDate = (el.startDate && el.startDate.replace(/-/g, '.').slice(0, 10)) || '';
// el.startDate = el.startDate && el.startDate.replace(/-/g, '.').slice(0,10) || '' el.endDate = (el.endDate && el.endDate.replace(/-/g, '.').slice(0, 10)) || '';
// el.endDate = el.endDate && el.endDate.replace(/-/g, '.').slice(0,10) || '' return el;
// coupon.push(el) });
// });
// return coupon
// }
},
watch: {
couponList: {
handler() {
this.list = [];
this.couponList.map(el => {
el.startDate = (el.startDate && el.startDate.replace(/-/g, ".").slice(0, 10)) || "";
el.endDate = (el.endDate && el.endDate.replace(/-/g, ".").slice(0, 10)) || "";
this.list.push(el);
});
},
immediate: true
} }
}, },
methods: { methods: {
pickupCoupon(coupon) { pickupCoupon(coupon, index) {
if (coupon.pickupAble) { if (coupon.pickupAble) {
return; return;
} }
this.$emit("pickupCoupon", coupon); this.$emit('pickupCoupon', coupon, index);
} }
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="less" scoped>
.goods-coupon { .goods-coupon {
margin: 0 24rpx; // margin: 0 12px;
// padding-bottom: 30px;
// padding-top: 20px;
// height: 350px;
// overflow-y: scroll;
&-item { &-item {
position: relative; position: relative;
margin-bottom: 20rpx; margin-bottom: 10px;
width: 100%; // width: 100%;
height: 180rpx; height: 90px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 0 $padding-md; padding: 0 @padding-md;
border-radius: $border-radius-base; border-radius: 6px;
.Gc-item-left { .Gc-item-left {
display: flex; display: flex;
flex: 1; flex: 1;
padding-right: 16rpx; padding-right: 12rpx;
.Gci-left-type { .Gci-left-type {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 88rpx; width: 44px;
height: 32rpx; height: 16px;
} }
.Gci-left-amount { .Gci-left-amount {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 140rpx; width: 70px;
margin-right: $margin-1 - 4; margin-right: 18px;
align-items: center; align-items: center;
.Gcil-amount-price { .Gcil-amount-price {
font-size: $font-lg; .text-size(16);
color: $font-color-red; color: #f23e33;
font-weight: bold; font-weight: bold;
text { span {
font-size: $font-1; font-size: 30px;
} }
} }
.Gci-amount-desc { .Gci-amount-desc {
font-size: $font-sm; // font-size: 12px;
color: $font-color-red; .text-size(12);
width: 150rpx; color: #f23e33;
width: 75px;
text-align: center; text-align: center;
} }
} }
...@@ -137,12 +127,15 @@ export default { ...@@ -137,12 +127,15 @@ export default {
justify-content: center; justify-content: center;
.Gcil-desc-name { .Gcil-desc-name {
font-weight: bold; font-weight: bold;
font-size: $font-base; // font-size: 14px;
color: $text-color-n5; .text-size(14);
color: #333;
text-align: left;
} }
.Gcil-desc-time { .Gcil-desc-time {
font-size: $font-sm; // font-size: 12px;
color: $text-color-n3; .text-size(12);
color: #666;
} }
} }
} }
...@@ -150,31 +143,32 @@ export default { ...@@ -150,31 +143,32 @@ export default {
.Gci-right-receive { .Gci-right-receive {
position: absolute; position: absolute;
top: 0; top: 0;
right: 20rpx; right: 10px;
width: 120rpx; width: 60px;
height: 100rpx; // height: 25px;
} }
.Gci-right-button { .Gci-right-button {
width: 164rpx; width: 82px;
height: 48rpx; height: 24px;
line-height: 48rpx; line-height: 24px;
text-align: center; text-align: center;
font-size: $font-sm; font-size: 12px;
color: $white; color: @white;
background-image: $background-primary; background: @background-primary;
border-radius: $border-radius-2; border-radius: 20px;
vertical-align: super;
&_received { &_received {
opacity: 0.6; opacity: 0.6;
// background-image: $background-primary; // background-img: @background-primary;
} }
} }
} }
} }
.Gc-item_pink { .Gc-item_pink {
background: $bg-color-pink; background: #ffece6;
} }
.Gc-item_white { .Gc-item_white {
background: $white; background: @white;
} }
} }
</style> </style>
<template> <template>
<view class="empty-content" :style="{ background: backColor }"> <view class="empty-content">
<image src="https://img.lkbang.net/xcx/empty@2x.png" mode="aspectFit" /> <image src="https://img.lkbang.net/xcx/empty@2x.png" mode="aspectFit" />
<text v-if="text">{{ text }}</text> <text v-if="text">{{ text }}</text>
</view> </view>
...@@ -8,24 +8,20 @@ ...@@ -8,24 +8,20 @@
<script> <script>
export default { export default {
props: { props: {
backColor: {
type: String,
default: "#fff"
},
src: { src: {
type: String, type: String,
default: "empty" default: 'empty'
}, },
text: { text: {
type: String, type: String,
default: "暂无订单~" default: '暂无订单~'
} }
}, },
data() { data() {
return { return {
typeSrc: { typeSrc: {
empty: "" empty: ''
} }
}; };
}, },
...@@ -37,24 +33,25 @@ export default { ...@@ -37,24 +33,25 @@ export default {
}; };
</script> </script>
<style lang="scss"> <style lang="less">
.empty-content { .empty-content {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
margin: 0 20rpx 20rpx; margin: 0 10px 10px;
padding: 20rpx; padding: 10px;
height: 422rpx; height: 211px;
border-radius: 12rpx; background: @white;
border-radius: 6px;
image { image {
margin-bottom: 20rpx; margin-bottom: 10px;
width: 300rpx; width: 150px;
height: 300rpx; height: 150px;
} }
text { text {
font-size: 32rpx; font-size: 16px;
color: #666666; color: #333333;
} }
} }
</style> </style>
<template>
<view class="page error">
<cr-image src="@/static/images/error/error404.png" width="298px" height="153px" />
<p>你要访问的页面找不到了</p>
<cr-button type="primary" block shape="circle" @click="backurl">返回</cr-button>
</view>
</template>
<script>
export default {
name: '',
data() {
return {};
},
mounted() {},
methods: {
backurl() {
this.$router.go(-1);
}
}
};
</script>
<style lang="less" scoped>
.error {
text-align: center;
padding-top: 0;
padding-bottom: 0;
.cr-image {
margin-top: @padding-sm * 3;
}
p {
color: @black;
.text-size(14);
margin: @padding-unit * 7 0;
}
}
</style>
<template>
<view class="page error">
<cr-image src="@/static/images/error/error.png" width="298px" height="153px" />
<p>oh,no…出错了</p>
<cr-button type="primary" block shape="circle" @click="backurl">返回</cr-button>
</view>
</template>
<script>
export default {
name: '',
data() {
return {};
},
mounted() {},
methods: {
backurl() {
this.$router.go(-1);
}
}
};
</script>
<style lang="less" scoped>
.error {
text-align: center;
padding-top: 0;
padding-bottom: 0;
.cr-image {
margin-top: @padding-sm * 3;
}
p {
color: @black;
.text-size(14);
margin: @padding-unit * 7 0;
}
}
</style>
<template> <template>
<div class="gfcard" :class="{ 'gfcard-disabled': isDisabled }" @click="bindGiftClick"> <view class="gfcard" :class="{ 'gfcard-disabled': isDisabled }">
<div class="gfcard-header"> <view v-if="cardItem" class="gfcard-header">
<div class="gfcard-header-top gfcard-flex"> <view class="gfcard-header-top gfcard-flex">
<text class="gfcard-header-title">{{ <span class="gfcard-header-title">{{
cardItem.createModeDesc || cardItem.cardName || "" cardItem.createModeDesc || cardItem.cardName || ''
}}</text> }}</span>
<template v-if="showRecord"> <!-- 移除使用记录外显功能-->
<text <!-- <template v-if="showRecord">-->
v-if="cardItem.giftStatus != 0" <!-- <span-->
class="gfcard-header-record" <!-- v-if="cardItem.giftStatus != 0"-->
@click.stop="bindRecordClick" <!-- class="gfcard-header-record"-->
>消费记录</text <!-- @click.stop="bindRecordClick"-->
> <!-- >使用记录</span-->
<text v-else>确认收货后即可激活</text> <!-- >-->
</template> <!-- <span v-else>确认收货后即可激活</span>-->
</div> <!-- </template>-->
<div class="gfcard-header-bottom gfcard-flex"> </view>
<text class="gfcard-header-amount"> <view class="gfcard-header-bottom gfcard-flex">
<span class="gfcard-header-amount">
面值:{{ (+cardItem.denomination || 0).toFixed(2) }}元 面值:{{ (+cardItem.denomination || 0).toFixed(2) }}元
</text> </span>
<text class="gfcard-header-time"> <span class="gfcard-header-time">
<template v-if="$config('qinghai') && cardItem.validTimeStart && cardItem.validTimeEnd"> <template v-if="$config.qinghai">
{{ cardItem.validTimeStart | format }} - {{ cardItem.validTimeEnd | format }} {{ cardItem.validTimeStart | format }} - {{ cardItem.validTimeEnd | format }}
</template> </template>
<template v-if="$config('yxm') && cardItem.validDateStart && cardItem.validDateEnd"> <template v-else>
{{ cardItem.validDateStart }} - {{ cardItem.validDateEnd }} <template v-if="cardItem.validDateStart && cardItem.validDateEnd">
{{ cardItem.validDateStart }} - {{ cardItem.validDateEnd }}
</template>
</template> </template>
</text> </span>
</div> </view>
</div> </view>
<div class="gfcard-bottom"> <view class="gfcard-bottom">
<div class="gfcard-bottom-money"> <view class="gfcard-bottom-money">
<text class="gfcard-bottom-balance">余额</text> <span class="gfcard-bottom-balance">余额</span>
<text class="gfcard-bottom-num"> <span class="gfcard-bottom-num">
¥<text class="gfcard-bottom-bold">{{ formatPrice[0] }}</text> ¥<b class="gfcard-bottom-bold">{{ formatPrice[0] }}</b>
<text class="gfcard-bottom-zero">.{{ formatPrice[1] }}</text> <b class="gfcard-bottom-zero">.{{ formatPrice[1] }}</b>
</text> </span>
</div> </view>
<p class="gfcard-bottom-describe">{{ cardItem.cardDesc || "" }}</p> <p class="gfcard-bottom-describe">{{ cardItem.cardDesc || '' }}</p>
<view class="gfcard-checkbox-click" />
<!-- 1-未到期2-使用中3-已失效4-已使用 --> <!-- 1-未到期2-使用中3-已失效4-已使用 -->
<div v-if="cardItem.status !== 2" :class="['gfcard-bg', `bg-${cardItem.status}`]" /> <view v-if="cardItem.status !== 2" :class="['gfcard-bg', `bg-${cardItem.status}`]" />
<radio <cr-checkbox v-if="showCheckbox" :value="selectChecked" shape="round" class="gfcard-check" />
v-if="showCheckbox" </view>
class="gfcard-checkbox" </view>
color="#EC1500"
style="transform: scale(0.7)"
:checked="selectChecked"
/>
</div>
</div>
</template> </template>
<script> <script>
const BINDRECORD_CLICK = "bind-record-click"; const BINDRECORD_CLICK = 'bind-record-click';
const BINDGIFT_CLICK = "bind-gift-click"; import { parseTime } from '@/service/utils.service';
import { parseTime } from "@/utils";
export default { export default {
filters: { filters: {
format(time) { format(time) {
return parseTime(time, "{y}.{m}.{d}"); return parseTime(time, '{y}.{m}.{d}');
} }
}, },
props: { props: {
...@@ -72,7 +69,7 @@ export default { ...@@ -72,7 +69,7 @@ export default {
type: Boolean, type: Boolean,
default: false default: false
}, },
// 是否显示消费记录文案 // 是否显示使用记录文案
showRecord: { showRecord: {
type: Boolean, type: Boolean,
default: true default: true
...@@ -90,10 +87,10 @@ export default { ...@@ -90,10 +87,10 @@ export default {
formatPrice() { formatPrice() {
const balance = this.cardItem.balance; const balance = this.cardItem.balance;
let price = !isNaN(balance) ? +balance : 0; let price = !isNaN(balance) ? +balance : 0;
return price.toFixed(2).split("."); return price.toFixed(2).split('.');
}, },
showCheckbox() { showCheckbox() {
return typeof this.checked === "boolean"; return this.checked !== undefined;
} }
}, },
watch: { watch: {
...@@ -105,88 +102,92 @@ export default { ...@@ -105,88 +102,92 @@ export default {
} }
}, },
methods: { methods: {
bindGiftClick() {
this.$emit(BINDGIFT_CLICK, this.cardItem);
},
bindRecordClick() { bindRecordClick() {
this.$emit(BINDRECORD_CLICK, this.cardItem); this.$emit(BINDRECORD_CLICK, this.cardItem);
} }
} }
}; };
</script> </script>
<style lang="scss"> <style scoped lang="less">
.gfcard { .gfcard {
font-size: $uni-font-size-sm; border-radius: 8px;
border-radius: 16rpx; margin-bottom: 8px;
margin-bottom: 16rpx;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
margin-bottom: 16rpx; margin-bottom: 8px;
&-checkbox { .text-size(12);
&-check {
position: absolute;
right: 0;
}
&-checkbox-click {
position: absolute; position: absolute;
right: 20rpx; right: 0;
height: 20px;
width: 40px;
z-index: 3;
} }
&-flex { &-flex {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
} }
&-header { &-header {
color: $white; color: @white;
height: 112rpx; height: 56px;
padding: 16rpx 24rpx; padding: 8px 12px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
background: url(https://img.lkbang.net/xcx/gift-header.png) no-repeat; background: url(~@/static/images/gift/gift-header.png) no-repeat;
background-size: 101%; background-size: 101%;
border-radius: 16rpx 16rpx 0 0; border-radius: 8px 8px 0 0;
box-sizing: border-box; box-sizing: border-box;
&-title { &-title {
font-size: $uni-font-size-base; .text-size(14);
} }
&-record { &-record {
padding-left: 32rpx; padding-left: 16px;
background: url(https://img.lkbang.net/xcx/gift-header-record.png) no-repeat left center; background: url(~@/static/images/gift/gift-header-record.png) no-repeat left center;
background-size: 24rpx 28rpx; background-size: 12px 14px;
} }
&-time { &-time {
opacity: 0.7; opacity: 0.7;
} }
} }
&-bottom { &-bottom {
height: 180rpx; overflow: hidden;
height: 90px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
text-align: center; text-align: center;
background: url(https://img.lkbang.net/xcx/gift-bottom.png) no-repeat; background: url(~@/static/images/gift/gift-bottom.png) no-repeat;
background-size: 102%; background-size: 102%;
border: 1px solid #ebebeb; border: 1px solid #ebebeb;
border-top: 0; border-top: 0;
box-sizing: border-box; box-sizing: border-box;
border-radius: 0 0 16rpx 16rpx; border-radius: 0 0 8px 8px;
position: relative; position: relative;
overflow: hidden;
&-money { &-money {
font-size: $uni-font-size-base; .text-size(14);
color: $font-color-red; color: @red-light;
} }
&-num { &-num {
font-weight: bold; font-weight: bold;
font-size: $font-lg; .text-size(16);
margin-left: 10rpx;
} }
&-bold { &-bold {
font-size: 60rpx; font-size: 30px;
} }
&-zero { &-zero {
font-size: 40rpx; font-size: 20px;
} }
&-describe { &-describe {
font-size: $font-sm; .text-size(12);
color: $uni-text-color-grey; color: @gray-4;
margin-top: 10rpx; margin-top: 5px;
} }
} }
} }
...@@ -199,26 +200,29 @@ export default { ...@@ -199,26 +200,29 @@ export default {
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: 100%; background-size: 100%;
&.bg-1 { &.bg-1 {
background-image: url(https://img.lkbang.net/xcx/gift-use-v2.png); background-image: url(~@/static/images/gift/gift-use-v2.png);
} }
&.bg-3 { &.bg-3 {
background-image: url(https://img.lkbang.net/xcx/gift-overdue-v2.png); background-image: url(~@/static/images/gift/gift-overdue-v2.png);
} }
&.bg-4 { &.bg-4 {
background-image: url(https://img.lkbang.net/xcx/gift-used-v2.png); background-image: url(~@/static/images/gift/gift-used-v2.png);
} }
} }
.gfcard-disabled { .gfcard-disabled {
.gfcard-header { .gfcard-header {
background-image: url(https://img.lkbang.net/xcx/gift-header-dis.png); background-image: url(~@/static/images/gift/gift-header-dis.png);
} }
.gfcard-bottom { .gfcard-bottom {
background-image: url(https://img.lkbang.net/xcx/gift-bottom-dis.png); background-image: url(~@/static/images/gift/gift-bottom-dis.png);
position: relative; position: relative;
overflow: hidden; overflow: hidden;
&-money { &-money {
color: $text-color-n3; color: @gray-5;
} }
} }
} }
::v-deep .cr-icon {
line-height: inherit !important;
}
</style> </style>
This diff is collapsed.
...@@ -5,44 +5,28 @@ ...@@ -5,44 +5,28 @@
v-for="(item, index) in goodsList" v-for="(item, index) in goodsList"
:key="index" :key="index"
class="Hl-container-item" class="Hl-container-item"
@click="goDetail(item, index)" @click="goDetail(item.goods, index)"
> >
<image lazy-load class="Hlc-item-img" mode="aspectFit" :src="item.goods.goodsImage" /> <cr-image class="Hlc-item-img" :src="item.goods.goodsImage | Img2Thumb" lazy-load />
<!-- <image :src="item." -->
<view class="Hlc-item-info"> <view class="Hlc-item-info">
<view> <view class="Hlc-item-info-title">
<view class="Hlc-item-info-title"> <span class="Hlc-item-info-title-name">{{ item.goods.goodsName }}</span>
<text>{{ item.goods.goodsName }}</text> <view
</view> v-if="item.goods.tagList && item.goods.tagList.length"
<!-- <img class="Hlc-item-info-title-active"
v-if="item.goods.userBenefitsLabelImgUrl" >
:src="item.goods.userBenefitsLabelImgUrl" <view v-for="(itm, idx) in item.goods.tagList" :key="idx">
class="memberImg" <span>{{ itm.name }}</span>
/> -->
<!-- 商品列表商品标签 -->
<view class="Hlc-item-tag">
<view v-for="(tag, i) in item.goods.tagList" :key="i" class="Hlc-item-tag-wrap">
<span v-if="tag.type == 2" :key="i" class="Hlc-item-tag-normal">{{
tag.name
}}</span>
<img
v-if="tag.type == 1"
mode="heightFix"
class="Hlc-item-tag-icon"
:src="tag.icon"
alt=""
/>
</view> </view>
</view> </view>
</view> </view>
<!-- 商品列表商品标签 -->
<view class="Hlc-item-info-count"> <view class="Hlc-item-info-count">
<view class="Hlc-item-info-count-left"> <view class="Hlc-item-info-count-left">
<text>¥{{ item.goods.goodsSalePrice }}</text> <span>¥{{ item.goods.goodsSalePrice }}</span>
<!-- <text v-if="item.goods.goodsPrice">¥{{ item.goods.goodsPrice }}</text> --> <!-- <span v-if="item.goods.goodsPrice">¥{{ item.goods.goodsPrice }}</span> -->
</view> </view>
<view class="Hlc-item-info-count-right"> <view class="Hlc-item-info-count-right">
<text v-if="item.goods.saleCount">已售{{ item.goods.saleCount }}</text> <span>已售{{ item.goods.saleCount }}</span>
</view> </view>
</view> </view>
</view> </view>
...@@ -51,10 +35,12 @@ ...@@ -51,10 +35,12 @@
</view> </view>
</template> </template>
<script> <script>
import { saTrackEvent } from "@/utils/sa.js"; import { Img2Thumb } from '@/filters/img2Thumb.filter';
import { debounce } from "@/utils";
export default { export default {
name: "GoodsCard", name: 'GoodsCard',
filters: {
Img2Thumb
},
props: { props: {
goodsList: { goodsList: {
type: Array, type: Array,
...@@ -65,140 +51,114 @@ export default { ...@@ -65,140 +51,114 @@ export default {
return {}; return {};
}, },
methods: { methods: {
goDetail(good, index) { goDetail(item, index) {
const currentPage = getCurrentPages(); console.log(item);
saTrackEvent("PD_YXMMAEC_UserClickProductlistPageCommodityCard", { this.$track.registeredEvents(
page_id: currentPage[currentPage.length - 1].route, 'H5_2B_CommodityListPageCommodityClick',
commodity_id: good.goods.goodsId, {
position_number: index, commodity_id: item.goodsId,
is_landingpage: uni.getStorageSync("is_landingpage") || 0 position_number: index
}); },
uni.reportAnalytics("c_productlistpagecommoditycard", { () => {
page_id: currentPage[currentPage.length - 1].route, setTimeout(() => {
commodity_id: good.goods.goodsId, const params = {
position_number: index count: 1,
}); goodsName: item.goodsName,
debounce( goodsimg: item.goodsImage
uni.navigateTo({ };
url: `/pages/product/goodDetail?skuNo=${ const query = {
good.goods.goodsId skuNo: item.goodsId
}&count=1&receiverId=&goodsName=${encodeURIComponent(good.goods.goodsName)}&goodsImage=${ };
good.goods.goodsImage this.$router.push({ name: 'goodDetail', params, query });
}` }, 300);
}), }
300
); );
} }
} }
}; };
</script> </script>
<style lang="scss" scoped> <style lang="less" scoped>
.home-list { .home-list {
background: $white; background: @white;
padding: 0 $space-md * 2; padding: 0 @padding-md - 2;
// background: @gray-6;
&-container { &-container {
.Hl-container-item { .Hl-container-item {
display: flex; display: flex;
margin: 40rpx 0; margin: @padding-lg 0;
&:last-child {
margin-bottom: 0;
}
.Hlc-item-img { .Hlc-item-img {
width: 270rpx; width: 135px !important;
height: 270rpx; height: 135px !important;
border-radius: 12rpx; border-radius: @border-radius-sm;
// background: #aaa;
} }
.Hlc-item-info { .Hlc-item-info {
width: 450rpx; width: 225px;
height: 260rpx; height: 130px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
margin-left: 20rpx; margin-left: @padding-sd;
&-title { &-title {
text { &-name {
font-size: 26rpx; .text-size(13);
line-height: 36rpx; line-height: 18px;
color: #333333; color: @black;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
} }
&-active {
font-size: 0;
padding-top: @padding-unit;
overflow: hidden;
height: 43px;
div {
display: inline-block;
span {
display: inline-block;
border: 1px solid @border-red;
font-size: 10px;
color: @red;
border-radius: 5px;
padding: 2px 5px;
margin: 2px 2px 2px 0;
}
}
}
} }
&-count { &-count {
&-left { &-left {
color: #ec3333; color: @red-light;
margin: 1px; margin: 1px;
text { font-size: 0;
span {
&:nth-child(1) { &:nth-child(1) {
margin-right: 10rpx; margin-right: 5px;
font-size: $uni-font-size-lg; .text-size(16);
line-height: 34rpx; line-height: 17px;
color: #ec3333; .text-size(16);
font-weight: bold; color: @red-light;
font-weight: @font-weight-bold;
} }
&:nth-child(2) { &:nth-child(2) {
font-size: $uni-font-size-tiny; .text-size(11);
line-height: 24rpx; line-height: 12px;
color: #999999; color: @gray-4;
text-align: right; text-align: right;
text-decoration: line-through; text-decoration: line-through;
} }
} }
} }
&-right { &-right {
font-size: $uni-font-size-tiny; .text-size(11);
line-height: 24rpx; line-height: 12px;
color: #999999; color: @gray-4;
}
}
}
.Hlc-item-tag {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
height: 60rpx;
// margin-top: -40rpx;
&-normal {
display: inline-block;
font-size: 22rpx;
box-sizing: border-box;
border: none;
color: #ec1500;
padding: 0px 4px;
// border-radius: 3px;
margin-right: 5px;
position: relative;
&::after {
display: flex;
box-sizing: border-box;
align-items: center;
content: "";
position: absolute;
top: 0;
left: 0;
width: 200%;
height: 200%;
transform: scale(0.5);
transform-origin: 0 0;
/* #ifndef MP-ALIPAY */
border: 1rpx solid #ff5a4b;
/* #endif */
/* #ifdef MP-ALIPAY */
border: 1px solid #ff5a4b;
/* #endif */
border-radius: 14rpx;
pointer-events: none;
} }
// line-height: 14px;
}
&-icon {
height: 28rpx;
margin-right: 5px;
vertical-align: middle;
} }
} }
} }
......
<template>
<!-- 可用于切换布局方式 1行1 1行2 -->
<view
class="multi-layout-list"
:class="{
'multi-list': layoutType == 2
}"
>
<view
v-for="(item, index) in goodsList"
:key="index"
class="goods-item"
:class="{
multi: layoutType == 2
}"
@click="goDetail(item.goods, index)"
>
<cr-image class="goods-item-img" :src="item.goods.goodsImage | Img2Thumb" lazy-load />
<view class="goods-item-info">
<view class="goods-item-info-title">
<span
class="goods-item-info-title-name"
:class="{
'double-line': !item.goods.sellPoint || layoutType == 2,
normal: item.goods.sellPoint && layoutType == 1
}"
>{{ item.goods.goodsName }}</span
>
<view v-if="item.goods && item.goods.sellPoint" class="sellpoint">
{{ item.goods.sellPoint }}
</view>
<view
v-if="item.goods.tagList && item.goods.tagList.length"
class="goods-item-info-title-active"
>
<view v-for="(itm, idx) in item.goods.tagList" :key="idx">
<span>{{ itm.name }}</span>
</view>
</view>
</view>
<!-- discountType 8-新人专享、9-max会员价、10-抢购活动 -->
<view class="goods-item-info-count">
<view class="goods-item-info-count-left">
<view class="goods-item-info-count-left-top">
<span class="goods-item-info-count-left-top-sale"
>¥<a>{{ item.goods.goodsSalePrice }}</a></span
>
<view v-if="item.goods.discountShow" class="goods-item-info-count-left-top-activity">
<span
:style="{
color: colorJudgment(item.goods.discountShow)
}"
{{ item.goods.discountShow.discountPrice }}</span
>
<image :src="item.goods.discountShow.icon" />
</view>
</view>
<view class="goods-item-info-count-left-bottom">
<span>已售{{ item.goods.saleCount }}</span>
</view>
</view>
<view v-if="item.goods" class="goods-item-info-count-right">
<cr-image
v-show="item.goods.shopcartIconType == 1"
src="https://img.lkbang.net/shopcart.ec1a992c.png"
width="24px"
height="24px"
@click.stop="addSkuToCart(item.goods)"
/>
<cr-image
v-show="item.goods.shopcartIconType == 2"
src="https://img.lkbang.net/multi-sec.ec1a992c.png"
width="24px"
height="24px"
@click.stop="showMultiSecPreview(item.goods.sameSpu)"
/>
</view>
</view>
</view>
</view>
<cr-popup v-model="showMultiSec" class="secPopup" @close="closeMultiModal">
<secSwiper v-if="showMultiSec" :sec-arr="secArr" />
<cr-icon type="close" size="34px" color="#FFF" @click="closeMultiModal" />
</cr-popup>
</view>
</template>
<script>
import { Img2Thumb } from '@/filters/img2Thumb.filter';
import secSwiper from '@/components/secSwiper.vue';
import { colorJudgment } from '../constants/max';
export default {
name: 'GoodsCard',
components: {
secSwiper
},
filters: {
Img2Thumb
},
props: {
goodsList: {
type: Array,
default: () => []
},
layoutType: {
type: Number,
default: 1
}
},
data() {
return {
showMultiSec: false,
secArr: [],
colorJudgment
};
},
methods: {
closeMultiModal() {
this.showMultiSec = false;
this.secArr = [];
},
showMultiSecPreview(sameSpu) {
console.log(sameSpu);
this.secArr = sameSpu;
this.showMultiSec = true;
},
goDetail(item, index) {
console.log(item);
this.$track.registeredEvents(
'H5_2B_CommodityListPageCommodityClick',
{
commodity_id: item.goodsId,
position_number: index
},
() => {
setTimeout(() => {
const query = {
skuNo: item.goodsId
};
this.$router.push({ name: 'goodDetail', query });
}, 300);
}
);
},
async addSkuToCart(goods) {
const { goodsId: skuId, goodsType: skuSource, goodsName } = goods;
this.$track.registeredEvents(
'H5_SearchingSecPageAddShoppingCartBtnClick',
{
commodity_id: skuId,
commodity_name: goodsName
},
async () => {
const [res, error] = await this.$store.dispatch('shopCart/good_add', {
type: 'ADD_CART',
goodInfo: { selected: true, skuId, skuSource, skuNum: 1 }
});
if (!error) {
this.$emit('addProduct', goods.goodsSalePrice);
this.$toast('购物车添加成功');
this.$store.dispatch('shopCart/saveCartCount', res?.count);
}
}
);
}
}
};
</script>
<style lang="less" scoped>
.multi-layout-list {
background: @white;
padding: 6px @padding-sm;
box-sizing: border-box;
&.multi-list {
background: #f7f8fa;
display: flex;
flex-flow: row wrap;
justify-content: space-between;
}
.goods-item {
background: @white;
min-height: 116px;
margin-bottom: 10px;
display: flex;
align-items: center;
&.multi {
width: 172px;
height: auto;
flex-shrink: 0;
flex-direction: column;
border-radius: @padding-x;
.goods-item-img {
flex-shrink: 0;
width: 172px !important;
height: 172px !important;
margin-bottom: @padding-unit;
margin-right: 0;
text-align: center;
border-radius: @padding-x;
overflow: hidden;
/deep/ img {
margin: 0 auto;
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
}
}
.goods-item-info {
width: 100%;
&-count {
margin-top: @padding-sm;
}
}
}
&-img {
flex-shrink: 0;
width: 116px !important;
height: 100% !important;
// margin-right: @padding-x;
border-radius: 7px;
overflow: hidden;
/deep/ img {
margin: 0 auto;
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
}
}
&-info {
min-height: 116px;
padding: 0 5px 5px;
box-sizing: border-box;
width: calc(100% - 110px);
flex: 1;
.text-size(13);
display: flex;
flex-direction: column;
justify-content: space-between;
overflow: hidden;
&-title {
width: 100%;
&-name {
display: block;
color: @black;
font-size: 13px;
word-break: break-all;
&.double-line {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
word-break: break-all;
}
&.normal {
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
&-active {
font-size: 0;
padding-top: @padding-unit;
overflow: hidden;
div {
display: inline-block;
span {
height: 12px;
display: flex;
align-items: center;
border: 1px solid @border-red;
font-size: 12px;
color: @red;
border-radius: 3px;
padding: 1px 3px;
margin: 0 3px 0 0;
}
}
}
.sellpoint {
color: #999;
font-size: 12px;
}
}
&-count {
display: flex;
align-items: center;
&-left {
flex: 1;
&-top {
display: flex;
align-items: flex-end;
&-sale {
font-weight: bold;
color: @red;
font-size: 12px;
a {
color: @red;
font-size: 18px;
}
}
&-activity {
padding-left: 3px;
span {
font-size: 14px;
padding-right: 3px;
}
img {
width: auto;
height: 10px;
}
}
}
&-bottom {
color: @gray-4;
.text-size(12);
}
}
&-right {
width: 24px;
flex-shrink: 0;
margin-right: @padding-unit;
}
}
}
}
}
.secPopup {
width: 100%;
background: transparent;
overflow: hidden;
}
.cr-icon {
display: block;
margin: 20px auto 0;
}
</style>
<template>
<view class="load-more">
<span class="load-more__text" :style="{ color: color }">{{
status === 'more'
? contentText.contentdown
: status === 'loading'
? contentText.contentrefresh
: contentText.contentnomore
}}</span>
</view>
</template>
<script>
export default {
name: 'LoadMore',
props: {
status: {
//上拉的状态:more-loading前;loading-loading中;noMore-没有更多了
type: String,
default: 'more'
},
showIcon: {
type: Boolean,
default: true
},
color: {
type: String,
default: '#999'
},
contentText: {
type: Object,
default() {
return {
contentdown: '上拉显示更多',
contentrefresh: '正在加载...',
contentnomore: '没有更多数据了'
};
}
}
},
data() {
return {};
}
};
</script>
<style lang="less">
@charset "UTF-8";
.load-more {
display: flex;
height: 40px;
align-items: center;
justify-content: center;
}
.load-more__text {
.text-size(12);
color: @gray-4;
}
</style>
<template>
<cr-popup
v-model="show"
class="cp-login"
:style="{ height: '60%' }"
round
closeable
position="bottom"
>
<image :src="'https://img.lkbang.net/tenant/yxm-logo.5h67.png' | imogr" alt="" class="img" />
<p class="yxm">羊小咩</p>
<view class="checkbox-content">
<cr-checkbox v-model="checked" icon-size="14px" shape="round" class="agreement">
<span class="text">我已阅读并同意 </span>
</cr-checkbox>
<a :href="$config.privacyRreaty.url" class="link">{{ $config.privacyRreaty.label }}</a>
<a :href="$config.registerRreaty.url" class="link">{{ $config.registerRreaty.label }}</a>
<a :href="configTmd.tianmeidaiRreaty.url" class="link"
>{{ configTmd.tianmeidaiRreaty.label }}</a
>
</view>
<cr-button
shape="circle"
block
type="primary"
native-type="submit"
class="login-form-submit login-now"
@click="handelNowLogin"
>
立即授权
</cr-button>
<p class="login-more" @click="handelLogin">更多登录方式</p>
</cr-popup>
</template>
<script>
import localStorage from '@/service/localStorage.service';
import { getTmdToken } from '@/api/tianmeidai.api';
import TMDConfig from '@/customize/tmd-config';
export default {
name: 'LoginAuthorize',
data() {
return {
show: false,
checked: false,
phoneNum: '',
configTmd: ''
};
},
watch: {
$route(to) {
if (to.query[this.configTmd.channelId.lable]) {
this.handelPopupShow(
to.query[this.configTmd.channelId.lable] || '',
to.query[this.configTmd.channelPhone.lable]
);
}
}
},
created() {
const config = new TMDConfig();
this.configTmd = config;
},
mounted() {
if (this.$route.query[this.configTmd.channelId.lable]) {
this.handelPopupShow(
this.$route.query[this.configTmd.channelId.lable],
this.$route.query[this.configTmd.channelPhone.lable]
);
}
},
methods: {
handelLogin() {
this.show = false;
this.$router.replace({ name: 'Login', query: { backUrl: location.href } });
},
handelPopupShow(id, phone) {
if (id == this.configTmd.channelId.id && !localStorage.get('vccToken')) {
this.show = true;
localStorage.set('vccChannel', this.configTmd.channelId.id);
// 种 获取天美贷 提供的参数 调取接口获取token
localStorage.set('vccPhone', phone);
this.phoneNum = phone;
}
},
async handelNowLogin() {
if (this.checked) {
this.show = false;
const [data] = await getTmdToken(this.phoneNum);
if (!data.token) {
// 无 token 跳转到登录页
this.$router.replace({ name: 'Login', query: { backUrl: location.href } });
return;
}
localStorage.set('vccToken', data.token);
} else {
this.$toast('请仔细阅读并同意相关协议');
}
}
}
};
</script>
<style lang="less" scoped>
.img {
width: 120px;
height: 120px;
display: block;
margin: 0 auto;
margin-top: 68px;
}
.yxm {
font-size: 18px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
line-height: 25px;
text-align: center;
margin-top: 4px;
}
.checkbox-content {
text-align: center;
margin-bottom: 16px;
margin-top: 28px;
.link {
font-size: 12px;
}
}
.agreement {
display: inline-block;
.text {
font-size: 12px;
color: @gray-5;
}
}
.cp-login {
height: 406px;
}
::v-deep {
.cr-checkbox__icon {
display: inline-block;
}
.login-now {
width: 335px;
margin: 0 auto;
display: block;
}
.login-more {
text-align: center;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
line-height: 20px;
margin-top: 20px;
// margin-bottom: 30px;
}
}
</style>
<template>
<view ref="loginGuide" class="login-guide">
<svg-icon icon-class="closeLoginGuide" class="closeLoginGuide" @click.native="close" />
<cr-image src="https://img.lkbang.net/auth-logo.1c5fddec.png" />
<span class="desc">登录羊小咩打开美好生活</span>
<cr-button shape="circle" type="primary" @click="handleLogin">立即登录</cr-button>
</view>
</template>
<style lang="less" scoped>
.login-guide {
width: 355px;
height: 54px;
background: rgba(0, 0, 0, 0.7);
position: absolute;
bottom: 12px;
left: 50%;
transform: translateX(-50%);
border-radius: 8px 47px 47px 8px;
padding: 0 5px;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
.closeLoginGuide {
position: absolute;
width: 18px;
height: 18px;
top: -7px;
left: -7px;
z-index: 2;
}
/deep/ .cr-image {
width: 44px !important;
height: 44px !important;
img {
width: 44px;
height: 44px;
border-radius: 6px;
}
}
.desc {
color: @white;
font-size: 14px;
}
/deep/ .cr-button {
width: 115px;
}
}
</style>
<script>
import { mapState } from 'vuex';
export default {
data() {
return {};
},
computed: {
...mapState({
userInfo: state => state.pay.userInfo || {}
})
},
methods: {
handleLogin() {
if (!this.userInfo.phoneNumber && (this.$config.qinghai || this.$config.yxm)) {
this.$track.registeredEvents('H5_HomePageLoginSuspendedWindowClick');
this.$router.push({ path: '/login', query: { backUrl: location.href } });
}
},
close() {
// console.log(this.$refs.loginGuide)
if (this.$refs.loginGuide) {
this.$refs.loginGuide.style.display = 'none';
}
}
}
};
</script>
This diff is collapsed.
This diff is collapsed.
<template>
<view v-if="orderStatus == 11" class="prepayArea" :class="{ listPage: listPage }">
<span
v-if="
!!orderData &&
orderData.giftCardReturnInfo &&
orderData.giftCardReturnInfo.giftCardReturnAmt
"
class="giftCardReturnInfo"
>
<span class="content">{{ orderData.giftCardReturnInfo.giftCardReturnAmt }}元礼品卡</span>
</span>
<button class="prepayBtn" @click.stop="clickBtn">
付款
</button>
</view>
</template>
<script>
export default {
props: {
orderStatus: {
type: [Number, String],
default: ''
},
orderData: {
type: Object,
default() {
return {};
}
},
listPage: {
type: Boolean,
default: false
}
},
methods: {
clickBtn() {
this.$emit('clickBtn');
}
}
};
</script>
<style lang="less" scoped>
// 因待付款增加返礼品卡标识,无法使用cherry-ui button组件进行二次开发
.prepayArea {
display: inline-block;
position: relative;
margin-left: @padding-unit;
&.listPage {
margin-top: @padding-sm;
}
.prepayBtn {
display: block;
position: relative;
color: @red;
border: 1px solid @red;
background: @white;
width: 86px;
border-radius: 999px;
height: 30px;
z-index: 2;
font-size: 14px;
}
.giftCardReturnInfo {
max-width: 86px;
position: absolute;
right: 0.5px;
top: -11px;
display: inline-block;
// padding: 0 @padding-unit;
height: 25px;
background-image: linear-gradient(270deg, #ff5d00 50%, #fff 91%);
color: @white;
font-size: 8px;
// box-sizing: border-box;
border-top-left-radius: 7px;
border-top-right-radius: 7px;
border-bottom-left-radius: 7px;
border-bottom-right-radius: 0;
display: flex;
align-items: flex-start;
.content {
max-width: 86px;
position: relative;
padding: 0 @padding-unit + 2 0 @padding-unit;
display: inline-block;
box-sizing: border-box;
background-image: linear-gradient(270deg, #ff5d00 10%, #ff1900 91%);
border-top-left-radius: 7px;
border-top-right-radius: 7px;
border-bottom-left-radius: 7px;
border-bottom-right-radius: 0;
z-index: 3;
height: 16px;
line-height: 17px;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
</style>
<template>
<view class="list-wrap">
<view ref="scrollContent" class="content" @scroll="onScroll">
<slot />
</view>
</view>
</template>
<script>
export default {
props: {
loading: {
type: Boolean,
default: false
},
toTop: {
type: Number,
default: 0
},
beforeBottomHeight: {
type: Number,
default: 50
}
},
data() {
return {
activated: false
};
},
watch: {
toTop: {
handler(val) {
this.$nextTick(() => {
if (this.activated) this.$refs.scrollContent.scrollTop = val;
});
}
}
},
activated() {
this.activated = true;
},
methods: {
onScroll() {
const obj = this.$refs.scrollContent; // clientHeight 视口高度 scrollTop 滚动条离顶部的高度 scrollHeight 列表内容的高度
if (obj.clientHeight + (obj.scrollTop + this.beforeBottomHeight) >= obj.scrollHeight) {
this.$emit('toBottom');
}
this.activated = false;
this.$emit('scroll', obj.scrollTop);
}
}
};
</script>
<style lang="less" scoped>
.list-wrap {
width: 100%;
height: 100%;
position: relative;
}
.list-wrap {
width: 100%;
height: 100%;
position: relative;
}
.content {
width: 100%;
height: 100%;
overflow-y: scroll;
overflow-x: hidden;
}
.loading {
position: absolute;
bottom: -20px;
width: 100%;
height: 20px;
text-align: center;
.text-size(12);
color: @black;
}
::-webkit-scrollbar {
// 去除滚动条边框
width: 0 !important;
}
::-webkit-scrollbar {
width: 0 !important;
height: 0;
}
</style>
<template>
<view class="SearchPanel" @click="resetSearch">
<cr-search
ref="searchInput"
v-model.trim="keyWords"
shape="round"
left-icon="search"
placeholder="搜索你想要的宝贝"
@search="searchEnterEvent"
@clear="clearInputText"
/>
<cr-tag
v-if="isSearch"
size="medium"
color="#999"
shape="round"
closable
@close="resetSearch"
>{{ keyWords }}</cr-tag
>
</view>
</template>
<script>
const SEARCH_EVENT = 'enter';
const CLEAR_EVENT = 'clear';
export default {
props: {
isSearch: {
type: Boolean,
default: false
}
},
data() {
return {
keyWords: ''
};
},
watch: {
keyWords(val) {
if (val) this.$track.registeredEvents('H5_2B_CommodityListPageExposure');
}
},
methods: {
clearInputText() {
this.keyWords = '';
},
resetSearch() {
this.clearInputText();
this.$emit(CLEAR_EVENT);
},
searchEnterEvent() {
if (!this.keyWords) {
return this.$dialog({
message: '请输入内容',
showCancelButton: false
});
}
this.$refs.searchInput.$el.querySelector('input').blur();
this.$emit(SEARCH_EVENT, this.keyWords);
}
}
};
</script>
<style lang="less" scoped>
.SearchPanel {
@{deep} .cr-icon--cross {
position: absolute;
right: 5px;
top: 5px;
}
@{deep} .cr-search {
padding: @padding-sm @padding-sm + 4;
.cr-icon--search {
.text-size(16);
color: #999;
}
}
position: relative;
.cr-tag {
padding-left: 10px;
padding-right: 20px;
position: absolute;
top: @padding-sm + 3;
left: 45px;
max-width: 84%;
display: -webkit-box;
-webkit-line-clamp: 1;
box-sizing: border-box;
-webkit-box-orient: vertical;
word-break: break-all;
}
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment