Commit b651a42c authored by 郭志伟's avatar 郭志伟

feat: 商品和底部提示

parent 4387946b
......@@ -44,6 +44,12 @@ export default {
accessToken: true
});
},
// 商品管理-商品标签列表_分页
labelPage(params) {
return http.post(`${config.opapiHost}/kdspOp/api/kdsp/activity/activity-goods/label-info/list-page`, params, {
accessToken: true
});
},
// todo: 对外接口需提供x-auth-token
// 购物车-添加商品
addShopCart(params) {
......@@ -57,52 +63,6 @@ export default {
// 商品组或专题查询
getGoods(params) {
return http.post(`${config.kdspHost}/api/kdsp/activity/activity-goods-special/skus`, params);
// return {
// skus: [
// {
// skuNo: '100014565800',
// skuName: '【自营】【自营】小米手机 陶瓷黑 8GB+128GB 官方标配',
// skuUrl: 'https://img14.360buyimg.com/n0/jfs/t1/141986/32/5318/98164/5f3236baE713fd239/5f2746db41f3e9c0.jpg',
// salePrice: 2.85,
// marketPrice: 293
// },
// {
// skuNo: '100014565820',
// skuName: '【自营】[自营][自营]0',
// skuUrl: 'https://img14.360buyimg.com/n0/jfs/t1/141986/32/5318/98164/5f3236baE713fd239/5f2746db41f3e9c0.jpg',
// salePrice: 264,
// marketPrice: 300
// },
// {
// skuNo: '100014565820',
// skuName: '【自营】[自营][自营]0',
// skuUrl: 'https://img14.360buyimg.com/n0/jfs/t1/141986/32/5318/98164/5f3236baE713fd239/5f2746db41f3e9c0.jpg',
// salePrice: 264,
// marketPrice: 300
// },
// {
// skuNo: '100014565800',
// skuName: '【自营】【自营】小米手机 陶瓷黑 8GB+128GB 官方标配',
// skuUrl: 'https://img14.360buyimg.com/n0/jfs/t1/141986/32/5318/98164/5f3236baE713fd239/5f2746db41f3e9c0.jpg',
// salePrice: 2.85,
// marketPrice: 293
// },
// {
// skuNo: '100014565820',
// skuName: '【自营】[自营][自营]0',
// skuUrl: 'https://img14.360buyimg.com/n0/jfs/t1/141986/32/5318/98164/5f3236baE713fd239/5f2746db41f3e9c0.jpg',
// salePrice: 264,
// marketPrice: 300
// },
// {
// skuNo: '100014565820',
// skuName: '【自营】[自营][自营]0',
// skuUrl: 'https://img14.360buyimg.com/n0/jfs/t1/141986/32/5318/98164/5f3236baE713fd239/5f2746db41f3e9c0.jpg',
// salePrice: 264,
// marketPrice: 300
// }
// ]
// };
},
// 根据id查询优惠券列表
getCoupons(params) {
......@@ -113,78 +73,6 @@ export default {
'x-auth-token': '7386386a-3a78-41f9-8584-14933823bf20'
}
});
// return {
// coupons: [
// {
// id: 1,
// pickupId: 1,
// name: '3C数码会场',
// startDate: '2021-02-22',
// endDate: '2021-02-22',
// faceValue: 100,
// limitAmount: 300,
// limitDesc: '满300减100',
// couponCategory: 1,
// iconUrl: 'in esse',
// description: 'officia do',
// status: 19667180,
// navUrl: 'exercitation est',
// pickupAble: false,
// publishCountFinished: false
// },
// {
// id: 2,
// pickupId: 1,
// name: '3C数码会场',
// startDate: '2021-02-22',
// endDate: '2021-02-22',
// faceValue: 100,
// limitAmount: 300,
// limitDesc: '满300减100',
// couponCategory: 1,
// iconUrl: 'oc',
// description: 'minim dolore tempor',
// status: 63205995,
// navUrl: 'cupidat',
// pickupAble: true,
// publishCountFinished: false
// },
// {
// id: 3,
// pickupId: 1,
// name: '3C数码会场',
// startDate: '2021-02-22',
// endDate: '2021-02-22',
// faceValue: 100,
// limitAmount: 300,
// limitDesc: '满300减100',
// couponCategory: 1,
// iconUrl: 'eu fugiat commodo voluptate exercitation',
// description: 'nisi',
// status: 43999314,
// navUrl: 'commodo in reprehenderit',
// pickupAble: false,
// publishCountFinished: true
// },
// {
// id: 4,
// pickupId: 1,
// name: '3C数码会场',
// startDate: '2021-02-22',
// endDate: '2021-02-22',
// faceValue: 100,
// limitAmount: 300,
// limitDesc: '满300减100',
// couponCategory: 1,
// iconUrl: 'eu fugiat commodo voluptate exercitation',
// description: 'nisi',
// status: 43999314,
// navUrl: 'commodo in reprehenderit',
// pickupAble: false,
// publishCountFinished: true
// }
// ]
// };
},
// 领取优惠券
pickupCoupon(params) {
......
......@@ -3,12 +3,12 @@ const protocol = EASY_ENV_IS_BROWSER ? window.location.protocol : 'http';
export default {
apiHost: `http://localhost:7001/`,
// apiHost: `http://192.168.28.199:7001/`,
// apiHost: 'https://quantum-blocks-vcc2.liangkebang.net/',
h5Host: 'https://quantum-h5-vcc2.liangkebang.net',
// apiHost: 'https://quantum-blocks-test1.liangkebang.net/',
h5Host: 'https://quantum-h5-test1.liangkebang.net',
qiniuHost: `https://appsync.lkbang.net`,
shenceUrl: `${protocol}//bn.xyqb.com/sa?project=default`,
opapiHost: `https://opapi-vcc2.liangkebang.net`,
opapiHost: `https://opapi-test1.liangkebang.net`,
qiniuUpHost: `${protocol}//up-z0.qiniup.com`,
// kdspHost: 'https://kdsp-api-vcc2.liangkebang.net',
kdspHost: 'https://talos-vcc2.liangkebang.net'
// kdspHost: 'https://kdsp-api-test1.liangkebang.net',
kdspHost: 'https://talos-test1.liangkebang.net'
};
\ No newline at end of file
......@@ -50,7 +50,7 @@
goods: {
type: Object,
default: () => ({
type: 'goodsGroup',
type: 'goods',
ids: []
})
},
......@@ -87,7 +87,7 @@
handler: async function (newVal) {
if (newVal.ids.length) {
let records = [];
if(newVal.type === 'goodsGroup') {
if(newVal.type === 'goodsSpecial') {
({ skus: records } = await operationApi.getGoods({ specialId: newVal.ids[0] }));
} else if (newVal.type === 'goods') {
({ skus: records } = await operationApi.getGoods({ skus: newVal.ids }));
......@@ -119,17 +119,20 @@
<style lang="less" scoped>
.container {
margin: 0 12px;
.goods {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 4px;
font-size: 0;
&-item {
border-radius: 8px;
background: #fff;
margin-bottom: 4px;
overflow: hidden;
&-title {
height: 36px;
font-size: 12px;
......@@ -140,39 +143,46 @@
-webkit-box-orient: vertical;
text-align: left;
}
&-bottom {
display: flex;
justify-content: space-between;
align-items: center;
.Gi-bottom-left {
display: flex;
flex-direction: column;
align-items: center;
p {
max-width: 55px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-align: left;
&:first-child {
font-size: 15px;
color: #EC3333;
color: #ec3333;
}
&:last-child {
font-size: 13px;
color: #999999;
text-decoration:line-through;
color: #999;
text-decoration: line-through;
}
}
}
.Gi-bottom-right {
width: 30px;
height: 30px;
display: flex;
justify-content: center;
align-items: center;
background: #FFF3F3;
background: #fff3f3;
border-radius: 50%;
/deep/ .cr-image {
width: 18px !important;
height: 18px !important;
......@@ -183,16 +193,19 @@
&_one {
display: flex;
width: 100%;
.goods-item-img {
width: 112px !important;
height: 109px !important;
}
&-right {
padding: 6px 8px;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.Gi-bottom-left {
margin-right: 10px;
flex: 1;
......@@ -200,6 +213,7 @@
justify-content: space-around;
flex-direction: row;
align-items: flex-end;
p {
max-width: 55px;
overflow: hidden;
......@@ -219,13 +233,16 @@
&_two {
width: 49%;
.goods-item-img {
width: 100% !important;
height: 180px !important;
}
.goods-item-title {
margin: 8px 8px;
}
.goods-item-bottom {
margin: 0 8px 6px;
}
......@@ -233,15 +250,19 @@
&_three {
width: 32%;
.goods-item-img {
width: 100% !important;
height: 117px !important;
}
.goods-item-title {
margin: 8px 4px;
}
.goods-item-bottom {
margin: 0 4px 6px;
.goods-item-bottom {
}
......@@ -251,7 +272,6 @@
&_empty {
height: 0;
}
}
}
}
......
const groupColumns = function() {
return [
{
type: 'selection',
width: 60,
hideSearch: true
},
{
title: '标签ID',
key: 'id',
formType: 'input'
},
{
title: '标签名称',
key: 'labelName',
formType: 'input'
},
{
title: '商品数量',
key: 'skuNum',
hideSearch: true
},
{
title: '品类数量',
key: 'cidNum',
hideSearch: true
},
{
title: '创建时间',
key: 'createdAt',
hideSearch: true,
}
];
};
export default groupColumns;
\ No newline at end of file
import {Component, Prop, Watch, Vue} from 'vue-property-decorator';
import TableModal from '../TableModal/index.vue';
import goodsColumn from './columns/goods.column';
import goodsGroupColumn from './columns/goodsGroup.column';
import goodsSpecialColumn from './columns/goodsSpecial.column';
import goodsLabelColumn from './columns/goodsLabel.column';
import { cloneDeep } from 'lodash';
import operationApi from '@api/operation.api';
......@@ -25,12 +26,20 @@ export default class GoodsTableModal extends Vue {
query: this.query
},
{
title: '选择商品',
title: '选择商品专题',
type: 'goodsGroup',
key: 'id',
multiple: false,
columns: goodsGroupColumn.call(this),
query: this.queryGroup
columns: goodsSpecialColumn.call(this),
query: this.querySpecial
},
{
title: '选择商品标签',
type: 'goodsLabel',
key: 'id',
multiple: false,
columns: goodsLabelColumn.call(this),
query: this.queryLabel
}
];
......@@ -65,7 +74,7 @@ export default class GoodsTableModal extends Vue {
const res = await operationApi.categoryQuery();
return recursionData(res.level1List || []);
},
async queryGroup(data) {
async querySpecial(data) {
const { records, total } = await operationApi.specialPage(data);
const selections = this.templates?.ids ? this.templates.ids : this.goods.ids;
console.log('query', selections, this.templates.ids);
......@@ -75,5 +84,16 @@ export default class GoodsTableModal extends Vue {
}
});
return { data: records || [], total };
},
async queryLabel(data) {
const { records, total } = await operationApi.labelPage(data);
const selections = this.templates?.ids ? this.templates.ids : this.goods.ids;
console.log('query', selections, this.templates.ids);
records?.forEach(record => {
if (selections.some(v => v === record.id)) {
record._checked = true;
}
});
return { data: records || [], total };
}
}
\ No newline at end of file
......@@ -17,16 +17,17 @@
@on-ok="ok"
@on-cancel="cancel"
class="table-modal-popup"
:class="{ 'has-menu': table.length > 1 }"
:title="editText('choose')">
<div class="Tm-popup-body" v-if="modal">
<Menu v-if="table.length > 1" width="90px" :active-name="activeName" @on-select="menuChange">
<Menu v-if="table.length > 1" width="110px" :active-name="activeName" @on-select="menuChange">
<MenuItem :name="index" :key="index" v-for="(item, index) in table">
<span>{{item.title}}</span>
</MenuItem>
</Menu>
<div class="Tmp-body-content">
<template v-for="(item, index) in table">
<div v-show="activeName === index" >
<div v-show="activeName === index">
<QGTable
:ref="`qgTable${index}`"
:columns="item.columns"
......@@ -48,38 +49,62 @@
<style lang="less" scoped>
.table-modal {
&-card {
/deep/ .ivu-card-head{
/deep/ .ivu-card-head {
background: #f0f2f5;
}
/deep/ .ivu-form {
.ivu-form-item-label {
width: 100px !important;
text-align: left;
}
}
.Fl-card-title {
text-align: right;
}
}
&-popup {
/deep/ .tableComStyle {
min-height: 0;
// .tableGroupStyle {
// height: 500px;
// overflow: scroll;
// }
// }
}
.Tm-popup-body {
display: flex;
.Tmp-body-content {
flex: 1;
}
/deep/ .ivu-menu-item {
text-align: center;
padding: 10px 0;
justify-content: center;
}
}
&.has-menu {
/deep/ .ivu-modal-body {
padding: 0;
.tableComStyle {
padding: 0;
.tableStyle {
margin-top: 0;
}
}
.tableGroupStyle {
margin-top: 1px;
}
}
}
}
}
</style>
\ No newline at end of file
......@@ -34,6 +34,21 @@ export default class DynamicPageForm extends Mixins(ContextMenuMixin) {
key: 'showBackTop',
name: '返回顶部',
type: 'checkbox'
},
{
key: 'showPageBottomTip',
name: '底部提示',
type: 'checkbox'
},
{
key: 'pageBottomTxt',
name: '提示文案',
type: 'Input'
},
{
key: 'pageBottomColor',
name: '提示颜色',
type: 'ColorSelector'
}
];
......
<template>
<div class="Pb-container">
<span class="Pb-text" :style="style">{{ txt }}</span>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: 'PageBottomTip',
computed: {
...mapGetters(['pageData']),
txt() {
return this.pageData.props.pageBottomTxt;
},
style() {
return {
color: this.pageData.props.pageBottomColor
};
}
}
}
</script>
<style lang="less">
.Pb {
&-container {
height: 60px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
&-text {
font-size: 14px;
color: #333;
}
}
</style>
\ No newline at end of file
......@@ -3,8 +3,9 @@ import { Getter, Action, State, Mutation } from 'vuex-class';
import type { PageInfo, Page, GridLayout } from '@store/modules/editor/state';
import TransformStyleMixin from '@page/mixins/transformStyle.mixin';
import FreedomContainer from '@editor/component/FreedomContainer/index.vue';
import PageBottomTip from './component/PageBottomTip/index.vue';
@Component({ components: { FreedomContainer }, name: 'OperationPanel' })
@Component({ components: { FreedomContainer, PageBottomTip }, name: 'OperationPanel' })
export default class OperationPanel extends Mixins(TransformStyleMixin) {
@Getter('pageData') pageData;
@State(state => state.editor.gridLayout) gridLayout?: GridLayout;
......@@ -14,10 +15,28 @@ export default class OperationPanel extends Mixins(TransformStyleMixin) {
@Prop(Boolean) isDraging;
@Prop(Boolean) isDragIn;
bottomInfo: object = {};
get layout() {
return this.pageData.elements.map(v => v.point);
}
@Watch('layout')
onLayoutChange(val) {
const lastGridItemPoint = val[val.length - 1];
if (lastGridItemPoint.w) {
this.bottomInfo = {
x: 0,
y: 0,
w: 0,
h: 60,
i: 'page-bottom-top'
};
if (lastGridItemPoint.w > this.bottomInfo.w) { this.bottomInfo.w = lastGridItemPoint.w; }
this.bottomInfo.y = this.bottomInfo.y + lastGridItemPoint.y + lastGridItemPoint.h;
}
}
@Emit('update:isDragIn')
dragenter() {
return true;
......
......@@ -11,7 +11,7 @@
:is-mirrored="false"
:vertical-compact="true"
:use-css-transforms="true"
:style="transformStyle(pageData.commonStyle)"
:style="transformStyle(pageData.commonrtyle)"
@click.native.stop="toggle(false)"
>
<grid-item @click.native.stop="handleElementClick(index, null)" v-for="(item, index) in pageData.elements"
......@@ -28,13 +28,25 @@
:class="{'Dcmcp-item_selected': curEleIndex === index && curChildIndex === null}">
<component ref="container" :id="item.id" class="Dcmcp-item-com" @handleElementClick="handleElementClick" :containerIndex="index" :childItem="item" :is="item.name" :key="index" v-bind="item.props"></component>
</grid-item>
<grid-item
v-if="pageData.props.showPageBottomTip"
:x="bottomInfo.x"
:y="bottomInfo.y"
:w="bottomInfo.w"
:h="bottomInfo.h"
:i="bottomInfo.i"
:static="true"
:key="bottomInfo.i + pageData.elements.length"
>
<page-bottom-tip />
</grid-item>
</grid-layout>
</div>
</template>
<script lang="ts" src="./index.ts"></script>
<style lang="less" scoped>
.border() {
&:before {
&::before {
position: absolute;
content: '';
border: 3px solid #2d8cf0 !important;
......@@ -42,9 +54,10 @@
height: 100%;
top: 0;
left: 0;
z-index: 1
z-index: 1;
}
}
.Dcm-container-panel {
margin: 30px auto;
width: 375px;
......@@ -52,16 +65,18 @@
min-height: 667px;
overflow-y: scroll;
background-color: rgb(244, 244, 244);
box-shadow: 2px 0px 10px rgba(0, 0, 0, 0.2);
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.2);
/deep/ .vue-grid-layout {
min-height: 667px;
.vue-grid-item {
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
&:after {
&::after {
position: absolute;
top: 0;
left: 0;
......@@ -70,24 +85,28 @@
height: 100%;
z-index: 100;
}
&:hover {
.border();
}
.vue-resizable-handle {
z-index: 10000;
}
}
.Dcmcp-item_selected {
.border();
}
}
&_draging {
.Dcmcp-item-com {
* {
pointer-events: none;
}
}
opacity: 0.7;
}
}
......
......@@ -59,5 +59,6 @@ export default class AutoSaveMixin extends Vue {
cancel() {
// console.log('cancel');
this.hasCompared = true;
localStorage.remove(`${this.account}-${this.pageInfo.id}`);
}
}
\ No newline at end of file
......@@ -13,7 +13,7 @@ export default class TransformStyleMixin extends Vue {
if (!styleObj) { return style; }
for (const key of Object.keys(styleObj)) {
if ( typeof styleObj[key] === 'number') {
if (key === 'height') styleObj[key] = Math.ceil(styleObj[key]);
if (key === 'height') { styleObj[key] = Math.ceil(styleObj[key]); }
style[key] = `${(styleObj[key] / 37.5).toFixed(2)}rem`;
} else {
style[key] = styleObj[key]?.includes('px') ? `${(+(styleObj[key].slice(0, -2)) / 37.5).toFixed(2)}rem` : styleObj[key];
......
......@@ -83,6 +83,9 @@ export const defaultState = {
},
props: {
showBackTop: true,
showPageBottomTip: true,
pageBottomTxt: '没有更多啦~',
pageBottomColor: '#fff'
},
elements: [],
}
......
......@@ -26,18 +26,18 @@ export default (appInfo: EggAppConfig) => {
dialect: 'mysql',
username: 'qa',
password: 'qatest',
host: '172.17.5.9',
port: 31024,
host: '172.17.5.5',
port: 31548,
database: 'low_code',
};;
};
exports.redis = {
default: {
keyPrefix: appInfo.name + ':',
},
client: {
port: 31565, // Redis port
host: '172.17.5.13', // Redis host
port: 31400, // Redis port
host: '172.17.5.17', // Redis host
password: '',
db: 0
}
......
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