mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-08-06 10:57:26 +08:00
refactor: 重构组件逻辑与样式优化
- 在 App.vue 中重构站点信息的获取与应用逻辑,提升代码可读性与维护性。 - 更新 Search.vue 组件,优化搜索框的样式与结构,增强用户体验。 - 在 element.scss 中注释掉不再使用的样式,并新增确认收货按钮的样式。 - 改进多个页面的布局与样式,确保响应式设计的一致性与美观性。 - 更新订单相关组件的按钮样式,提升视觉一致性与可用性。
This commit is contained in:
@@ -13,50 +13,45 @@ export default {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
init(){
|
||||
if(!storage.getItem("siteName")||!storage.getItem("logoImg")||!storage.getItem("sitelogo_expiration_time")) {
|
||||
this.getSite();
|
||||
}else{
|
||||
// 如果缓存过期,则获取最新的信息
|
||||
if (new Date() > storage.getItem("sitelogo_expiration_time")) {
|
||||
this.getSite();
|
||||
return;
|
||||
}else{
|
||||
window.document.title = storage.getItem("siteName");
|
||||
//动态获取icon
|
||||
let link =document.querySelector("link[rel*='icon']") ||document.createElement("link");
|
||||
link.type = "image/x-icon";
|
||||
link.href = storage.getItem("siteIcon");
|
||||
link.rel = "shortcut icon";
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
getSite(){
|
||||
//获取基本站点信息
|
||||
getBaseSite().then((res) => {
|
||||
if (res.success && res.result.settingValue) {
|
||||
let data = JSON.parse(res.result.settingValue);
|
||||
// 过期时间
|
||||
var expirationTime = new Date().setHours(new Date().getHours() + 1);
|
||||
// 存放过期时间
|
||||
applySiteInfo(data) {
|
||||
const expirationTime = new Date().setHours(new Date().getHours() + 1);
|
||||
storage.setItem("sitelogo_expiration_time", expirationTime);
|
||||
// 存放信息
|
||||
storage.setItem('siteName', data.siteName);
|
||||
storage.setItem('logoImg', data.buyerSideLogo);
|
||||
storage.setItem("siteName", data.siteName);
|
||||
storage.setItem("logoImg", data.buyerSideLogo);
|
||||
storage.setItem("siteIcon", data.buyerSideIcon);
|
||||
this.$store.commit("SET_SITENAME", data.siteName);
|
||||
this.$store.commit("SET_LOGOIMG", data.buyerSideLogo);
|
||||
window.document.title = data.siteName;
|
||||
//动态获取icon
|
||||
let link =document.querySelector("link[rel*='icon']") ||document.createElement("link");
|
||||
let link =
|
||||
document.querySelector("link[rel*='icon']") ||
|
||||
document.createElement("link");
|
||||
link.type = "image/x-icon";
|
||||
link.href = data.buyerSideIcon;
|
||||
link.rel = "shortcut icon";
|
||||
document.getElementsByTagName("head")[0].appendChild(link);
|
||||
}
|
||||
},
|
||||
init() {
|
||||
const expirationTime = storage.getItem("sitelogo_expiration_time");
|
||||
const cacheValid =
|
||||
expirationTime && new Date() <= new Date(Number(expirationTime));
|
||||
if (cacheValid) {
|
||||
this.applySiteInfo({
|
||||
siteName: storage.getItem("siteName"),
|
||||
buyerSideLogo: storage.getItem("logoImg"),
|
||||
buyerSideIcon: storage.getItem("siteIcon"),
|
||||
});
|
||||
}
|
||||
this.getSite();
|
||||
},
|
||||
getSite() {
|
||||
getBaseSite().then((res) => {
|
||||
if (res.success && res.result.settingValue) {
|
||||
const data = JSON.parse(res.result.settingValue);
|
||||
this.applySiteInfo(data);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
:root {
|
||||
--el-color-primary: #ff5c58;
|
||||
--el-color-success: #68cabe;
|
||||
--el-color-warning: #fa6419;
|
||||
--el-color-danger: #ff3c2a;
|
||||
// --el-color-primary: #ff5c58;
|
||||
// --el-color-success: #68cabe;
|
||||
// --el-color-warning: #fa6419;
|
||||
// --el-color-danger: #ff3c2a;
|
||||
--el-font-size-base: 14px;
|
||||
}
|
||||
|
||||
.el-button--primary {
|
||||
--el-button-bg-color: #ff5c58;
|
||||
--el-button-border-color: #ff5c58;
|
||||
--el-button-hover-bg-color: #ff7875;
|
||||
--el-button-hover-border-color: #ff7875;
|
||||
}
|
||||
// .el-button--primary {
|
||||
// --el-button-bg-color: #ff5c58;
|
||||
// --el-button-border-color: #ff5c58;
|
||||
// --el-button-hover-bg-color: #ff7875;
|
||||
// --el-button-hover-border-color: #ff7875;
|
||||
// }
|
||||
|
||||
.el-table--border {
|
||||
.el-table__cell {
|
||||
@@ -33,3 +33,17 @@
|
||||
margin: 0 8px;
|
||||
color: #dcdfe6;
|
||||
}
|
||||
|
||||
/* 与「我的订单」确认收货按钮一致的橙色操作按钮 */
|
||||
.confirm-receipt-btn {
|
||||
background-color: #ff9900 !important;
|
||||
border-color: #ff9900 !important;
|
||||
color: #fff !important;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: #e68a00 !important;
|
||||
border-color: #e68a00 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
<template>
|
||||
<div class="navbar" :class="{'small-search-box': useClass == 'fixed-show'}">
|
||||
<template v-if="useClass == 'fixed-show'">
|
||||
<div class="search search-embedded">
|
||||
<el-input
|
||||
v-model="searchData"
|
||||
size="large"
|
||||
class="search-input"
|
||||
placeholder="输入你想查找的商品"
|
||||
@keyup.enter="search"
|
||||
/>
|
||||
<div class="search-btn" @click="search">
|
||||
<el-icon :size="21"><SearchIcon /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="container width_1200_auto flex flex-a-c">
|
||||
<img
|
||||
:src="$store.state.logoImg"
|
||||
@@ -8,21 +23,19 @@
|
||||
alt=""
|
||||
@click="$router.push('/')"
|
||||
/>
|
||||
<div :class="{'small-search-box':useClass == 'fixed-show'}" class="search-box">
|
||||
<div class="search-box">
|
||||
<div class="search">
|
||||
<el-input
|
||||
v-model="searchData"
|
||||
size="large"
|
||||
class="search "
|
||||
class="search-input"
|
||||
placeholder="输入你想查找的商品"
|
||||
@keyup.enter="search"
|
||||
>
|
||||
|
||||
<template #append>
|
||||
<div class="search-icon" @click="search">
|
||||
/>
|
||||
<div class="search-btn" @click="search">
|
||||
<el-icon :size="21"><SearchIcon /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<template v-if="showTag">
|
||||
<div class="only-store" v-if="storeId" @click="research()">
|
||||
切换为{{!onlyStore ? '店铺内' : '平台'}}搜索
|
||||
@@ -41,7 +54,7 @@
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -154,14 +167,19 @@ export default {
|
||||
height: 113px;
|
||||
background: #fff;
|
||||
}
|
||||
.search-icon{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.small-search-box{
|
||||
height: 60px;
|
||||
|
||||
margin: 0 !important;
|
||||
.navbar.small-search-box {
|
||||
height: 60px;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.search-embedded {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
@@ -171,47 +189,47 @@ export default {
|
||||
}
|
||||
|
||||
.search {
|
||||
$btn-gap: 4px;
|
||||
$btn-width: 60px;
|
||||
$input-height: 37.8px;
|
||||
|
||||
position: relative;
|
||||
width: 778.4px;
|
||||
height: $input-height;
|
||||
margin: 10px 0px 5px 0;
|
||||
|
||||
border-radius: 18.9px;
|
||||
.search-input {
|
||||
width: 100%;
|
||||
|
||||
|
||||
:deep(.el-input--large .el-input__wrapper) {
|
||||
:deep(.el-input__wrapper) {
|
||||
border: 1.4px solid $theme_color;
|
||||
box-sizing: border-box;
|
||||
border-radius: 19.6px;
|
||||
position: relative;
|
||||
padding-left: 26px;
|
||||
padding-right: calc(#{$btn-gap * 2} + #{$btn-width});
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
height: 37.8px;
|
||||
height: $input-height;
|
||||
color: #999;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-input-group__append) {
|
||||
border-radius: 19.6px !important;
|
||||
.search-btn {
|
||||
position: absolute;
|
||||
right: $btn-gap;
|
||||
top: $btn-gap;
|
||||
bottom: $btn-gap;
|
||||
width: $btn-width;
|
||||
border-radius: calc((#{$input-height} - #{$btn-gap * 2}) / 2);
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
border: 1.4px solid $theme_color;
|
||||
width: 67.2px;
|
||||
height: 37.8px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
top: 0;
|
||||
z-index: 99;
|
||||
z-index: 1;
|
||||
background-color: $theme_color;
|
||||
color: #ffffff;
|
||||
|
||||
button {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.search-box{
|
||||
|
||||
@@ -278,7 +278,7 @@
|
||||
>加入购物车</el-button
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
class="confirm-receipt-btn"
|
||||
:loading="loading1"
|
||||
:disabled="skuDetail.quantity === 0"
|
||||
@click="buyNow"
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
<template>
|
||||
<div class="scroll-show">
|
||||
<div class="content clearfix">
|
||||
<cateNav class="cate" :hover="true" :showNavBar="false"
|
||||
useClass="fixed-show"></cateNav>
|
||||
<div class="content">
|
||||
<cateNav
|
||||
class="cate"
|
||||
:hover="true"
|
||||
:showNavBar="false"
|
||||
useClass="fixed-show"
|
||||
/>
|
||||
<Search
|
||||
class="search-con"
|
||||
:hover="true"
|
||||
@@ -10,97 +14,113 @@
|
||||
:showLogo="false"
|
||||
:showTag="false"
|
||||
useClass="fixed-show"
|
||||
></Search>
|
||||
<div class="flex flex-a-c cart">
|
||||
/>
|
||||
<div class="cart">
|
||||
<span @mouseenter="getCartList">
|
||||
<el-icon class="cart-icon" :size="20" @click="goCartList"><ShoppingCart /></el-icon>
|
||||
</span>
|
||||
<i class="cart-badge">{{ cartNum < 100 ? cartNum : "99" }}</i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { cartCount } from "@/api/cart.js";
|
||||
import storage from "@/plugins/storage.js";
|
||||
import { ShoppingCart } from "@element-plus/icons-vue";
|
||||
import Search from '@/components/Search.vue'
|
||||
import cateNav from '@/components/nav/CateNav.vue'
|
||||
import { cartCount } from '@/api/cart.js'
|
||||
import storage from '@/plugins/storage.js'
|
||||
import { ShoppingCart } from '@element-plus/icons-vue'
|
||||
|
||||
export default {
|
||||
components: { ShoppingCart },
|
||||
components: { ShoppingCart, Search, cateNav },
|
||||
data() {
|
||||
return {
|
||||
userInfo: {}, // 用户信息
|
||||
};
|
||||
userInfo: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cartNum() {
|
||||
// 购物车商品数量
|
||||
return this.$store.state.cartNum;
|
||||
},
|
||||
return this.$store.state.cartNum
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goCartList() {
|
||||
// 跳转购物车页面
|
||||
let routerUrl = this.$router.resolve({
|
||||
path: "/cart",
|
||||
});
|
||||
window.open(routerUrl.href, "_blank");
|
||||
const routerUrl = this.$router.resolve({ path: '/cart' })
|
||||
window.open(routerUrl.href, '_blank')
|
||||
},
|
||||
getCartList() {
|
||||
// 获取购物车列表
|
||||
if (storage.getItem("userInfo")) {
|
||||
if (storage.getItem('userInfo')) {
|
||||
cartCount().then((res) => {
|
||||
this.$store.commit("SET_CARTNUM", res.result);
|
||||
this.Cookies.setItem("cartNum", res.result);
|
||||
});
|
||||
this.$store.commit('SET_CARTNUM', res.result)
|
||||
this.Cookies.setItem('cartNum', res.result)
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
||||
if (storage.getItem("userInfo")) {
|
||||
this.userInfo = JSON.parse(storage.getItem("userInfo"));
|
||||
if (storage.getItem('userInfo')) {
|
||||
this.userInfo = JSON.parse(storage.getItem('userInfo'))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
$side-col-width: 263.2px;
|
||||
$col-gap: 10px;
|
||||
$cart-col-width: 40px;
|
||||
|
||||
.scroll-show {
|
||||
height: 60px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 1200px;
|
||||
height: 40px;
|
||||
height: 60px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: $side-col-width 1fr $cart-col-width;
|
||||
column-gap: $col-gap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cate {
|
||||
float: left;
|
||||
width: 200px !important;
|
||||
min-width: 0;
|
||||
|
||||
:deep(.cate-nav) {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
.search-con {
|
||||
float: left;
|
||||
width: 800px;
|
||||
overflow: hidden;
|
||||
margin-top: -27px;
|
||||
}
|
||||
.cart{
|
||||
|
||||
:deep(.nav-con) {
|
||||
height: 60px;
|
||||
}
|
||||
.cart-icon {
|
||||
width: 30px;
|
||||
float: left;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
color: $theme_color;
|
||||
z-index: 1;
|
||||
.search-con {
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cart {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 60px;
|
||||
position: relative;
|
||||
&:hover {
|
||||
}
|
||||
|
||||
.cart-icon {
|
||||
font-size: 25px;
|
||||
color: $theme_color;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.cart-badge {
|
||||
position: absolute;
|
||||
font-style: normal;
|
||||
right: 165px;
|
||||
top: 12px;
|
||||
right: -2px;
|
||||
display: block;
|
||||
background-color: $theme_color;
|
||||
color: #fff;
|
||||
@@ -111,6 +131,5 @@ export default {
|
||||
line-height: 17px;
|
||||
text-align: center;
|
||||
z-index: 5;
|
||||
top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -45,6 +45,7 @@ export default {
|
||||
width: 100%;
|
||||
min-height: 1200px;
|
||||
box-sizing: border-box;
|
||||
overflow-x: hidden;
|
||||
/* 勿设 overflow-x: hidden,会裁切 discountAdvert 的 margin-left: -100px 左溢背景 */
|
||||
overflow-x: visible;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -17,30 +17,30 @@
|
||||
</template>
|
||||
<!-- 热门广告 -->
|
||||
<template v-if="element.type == 'hotAdvert'">
|
||||
<div class="mb_20 width_1200_auto">
|
||||
<div class="hot-advert mb_20 width_1200_auto">
|
||||
<div class="hot-advert-banner">
|
||||
<img
|
||||
style="display: block; width: 100%; max-width: 1200px; height: auto"
|
||||
class="hover-pointer"
|
||||
:src="element.options.list[0].img"
|
||||
@click="linkTo(element.options.list[0].url)"
|
||||
width="1200"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<ul class="advert-list width_1200_auto">
|
||||
<ul class="advert-list">
|
||||
<template v-for="(item, index) in element.options.list" :key="index">
|
||||
<li
|
||||
v-if="index !== 0"
|
||||
@click="linkTo(item.url)"
|
||||
class="hover-pointer"
|
||||
>
|
||||
<img :src="item.img" width="230" height="190" alt="" />
|
||||
<img :src="item.img" alt="" />
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 限时秒杀 待完善 -->
|
||||
<template v-if="element.type == 'seckill' && element.options.list.length">
|
||||
<template v-if="element.type == 'seckill' && element.options?.list?.length">
|
||||
<seckill :data="element" class="mb_20 width_1200_auto"></seckill>
|
||||
</template>
|
||||
<!-- 折扣广告 -->
|
||||
@@ -121,15 +121,12 @@
|
||||
></first-page-advert>
|
||||
</template>
|
||||
<!-- 横幅广告 -->
|
||||
<template v-if="element.type == 'bannerAdvert'">
|
||||
<div style="width: 100%; text-align: center">
|
||||
<img
|
||||
width="1200"
|
||||
class="hover-pointer mb_20 bannerAd"
|
||||
<template v-if="element.type == 'bannerAdvert' && element.options.img">
|
||||
<div
|
||||
class="horizontal-advert width_1200_auto mb_20 hover-pointer"
|
||||
@click="linkTo(element.options.url)"
|
||||
:src="element.options.img"
|
||||
alt=""
|
||||
/>
|
||||
>
|
||||
<img class="bannerAd" :src="element.options.img" alt="" />
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="element.type == 'notEnough'"
|
||||
@@ -198,22 +195,55 @@ export default {
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
.bannerAd{
|
||||
/** 横幅广告 */
|
||||
.horizontal-advert {
|
||||
width: 100%;
|
||||
height: 166.6px;
|
||||
max-width: 1200px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
box-sizing: border-box;
|
||||
line-height: 0;
|
||||
}
|
||||
.bannerAd {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 166px;
|
||||
object-fit: cover;
|
||||
}
|
||||
/** 热门广告 */
|
||||
.hot-advert {
|
||||
width: 1200px;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.hot-advert-banner {
|
||||
line-height: 0;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
.advert-list {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 5px 0;
|
||||
list-style: none;
|
||||
box-sizing: border-box;
|
||||
background: $theme_color;
|
||||
height: 200px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 3px 10px;
|
||||
box-sizing: border-box;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
> li {
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 190px;
|
||||
cursor: pointer;
|
||||
border-radius: 10px;
|
||||
transition: all 150ms ease-in-out;
|
||||
@@ -227,34 +257,36 @@ export default {
|
||||
|
||||
/** 折扣广告 */
|
||||
.discountAdvert-wrap {
|
||||
width: 1200px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
}
|
||||
.discountAdvert {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
height: 520px;
|
||||
margin: 0 auto;
|
||||
width: 1300px;
|
||||
height: 585px;
|
||||
margin-left: -100px;
|
||||
box-sizing: border-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1200px 520px;
|
||||
background-position: center top;
|
||||
background-size: 1300px 585px;
|
||||
background-position: left top;
|
||||
position: relative;
|
||||
padding: 10px 0 0 330px;
|
||||
overflow: hidden;
|
||||
> div {
|
||||
padding-left: 295px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
img {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
&:nth-child(1) img {
|
||||
margin: 10px 10px 0 0;
|
||||
transition: all 150ms ease-in-out;
|
||||
&:hover {
|
||||
box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.4);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
}
|
||||
&:nth-child(2) {
|
||||
margin-top: 10px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 10px;
|
||||
img {
|
||||
margin: 0 10px 0 0;
|
||||
transition: all 150ms ease-in-out;
|
||||
&:hover {
|
||||
box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.4);
|
||||
@@ -263,5 +295,6 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div class="not-enough" ref="obtain" id="demo">
|
||||
<el-affix :offset-top="62" @change="change">
|
||||
<ul class="nav-bar" v-show="topSearchShow">
|
||||
<el-affix :offset-top="62" @change="change" class="nav-affix">
|
||||
<div class="nav-bar" v-show="topSearchShow">
|
||||
<ul class="nav-list">
|
||||
<li
|
||||
v-for="(item, index) in conData.options.navList"
|
||||
:class="currentIndex === index ? 'curr' : ''"
|
||||
@@ -12,6 +13,7 @@
|
||||
<p @click="gotoDemo">{{ item.desc }}</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</el-affix>
|
||||
<div class="content" v-if="showContent">
|
||||
<div
|
||||
@@ -95,18 +97,34 @@ export default {
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.not-enough {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:deep(.nav-affix.el-affix) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
background-color: #f8f8f8;
|
||||
height: 60px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-list {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
box-sizing: border-box;
|
||||
|
||||
li {
|
||||
padding: 0 30px;
|
||||
text-align: center;
|
||||
@@ -114,11 +132,15 @@ export default {
|
||||
font-size: 16px;
|
||||
border-radius: 50px;
|
||||
padding: 0 7px;
|
||||
margin: 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
p:nth-child(2) {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin: 2px 0 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@@ -129,6 +151,7 @@ export default {
|
||||
}
|
||||
border-right: 1px solid #eee;
|
||||
}
|
||||
|
||||
li:last-of-type {
|
||||
border: none;
|
||||
}
|
||||
@@ -136,7 +159,6 @@ export default {
|
||||
.curr {
|
||||
p:nth-child(1) {
|
||||
background-color: $theme_color;
|
||||
|
||||
color: #fff;
|
||||
}
|
||||
p:nth-child(2) {
|
||||
@@ -146,6 +168,8 @@ export default {
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="seckill" v-if="goodsList.length">
|
||||
<div class="seckill" v-if="goodsList && goodsList.length">
|
||||
<div class="aside hover-pointer" @click="goToSeckill">
|
||||
<div class="title">{{ actName }}</div>
|
||||
<div class="hour">
|
||||
@@ -54,7 +54,7 @@ export default {
|
||||
clearInterval(this.interval);
|
||||
this.interval = null;
|
||||
this.countDown(val);
|
||||
this.goodsList = this.list[val].seckillGoodsList;
|
||||
this.goodsList = this.list[val]?.seckillGoodsList || [];
|
||||
},
|
||||
diffSeconds(val) {
|
||||
const hours = Math.floor(val / 3600);
|
||||
@@ -106,9 +106,15 @@ export default {
|
||||
}, 1000);
|
||||
},
|
||||
getListByDay() {
|
||||
this.list = this.data.options.list;
|
||||
this.goodsList = this.list[0].seckillGoodsList;
|
||||
this.list = this.data?.options?.list || [];
|
||||
if (!this.list.length) {
|
||||
this.goodsList = [];
|
||||
return;
|
||||
}
|
||||
this.goodsList = this.list[0]?.seckillGoodsList || [];
|
||||
if (this.goodsList.length) {
|
||||
this.countDown(this.currIndex);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -241,8 +241,10 @@ export default {
|
||||
}
|
||||
.fixed-show{
|
||||
margin-top: 0 !important;
|
||||
width: 100%;
|
||||
>.nav-con{
|
||||
>.all-categories{
|
||||
width: 100%;
|
||||
align-items: center !important;
|
||||
height: 60px;
|
||||
display: inherit;
|
||||
|
||||
@@ -222,12 +222,7 @@ export default {
|
||||
transition: 0.35s;
|
||||
}
|
||||
.show {
|
||||
transform: translateY(0);
|
||||
-webkit-transform: translateZ(0);
|
||||
-moz-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
-o-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
transform: translateY(0) translateZ(0);
|
||||
top: 0;
|
||||
}
|
||||
.fixed-bar{
|
||||
@@ -241,12 +236,7 @@ export default {
|
||||
.show-fixed{
|
||||
height: 354px !important;
|
||||
opacity: 1 !important;
|
||||
transform: translateY(0);
|
||||
-webkit-transform: translateZ(0);
|
||||
-moz-transform: translateZ(0);
|
||||
-ms-transform: translateZ(0);
|
||||
-o-transform: translateZ(0);
|
||||
transform: translateZ(0);
|
||||
transform: translateY(0) translateZ(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -48,13 +48,13 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div v-if="storeMsg.pageShow&&storeMsg.pageShow==='1'">
|
||||
<div v-if="showFloorView">
|
||||
<!-- 楼层装修部分 -->
|
||||
<model-form ref="modelForm" :data="modelForm"></model-form>
|
||||
</div>
|
||||
|
||||
|
||||
<div v-else>
|
||||
<div v-else class="store-goods-section">
|
||||
<div class="promotion-decorate">{{ cateName }}</div>
|
||||
<div class="goods-list">
|
||||
<empty v-if="goodsList.length === 0"/>
|
||||
@@ -108,6 +108,7 @@ import ModelForm from "@/components/indexDecorate/ModelForm";
|
||||
import HoverSearch from "@/components/header/hoverSearch";
|
||||
import storage from "@/plugins/storage";
|
||||
import {getFloorStoreData} from "@/api/index.js";
|
||||
import { seckillByDay } from "@/api/promotion";
|
||||
import imTalk from '@/components/mixes/talkIm'
|
||||
|
||||
export default {
|
||||
@@ -125,6 +126,7 @@ export default {
|
||||
carouselOpacity: false, // 不同轮播分类样式,
|
||||
enablePageData: false, //是否显示楼层装修内容
|
||||
basePageData: false, //基础店铺信息
|
||||
showFloorView: false, // 是否展示楼层装修(有有效装修数据时为 true)
|
||||
storeMsg: {}, // 店铺信息
|
||||
cateList: [], // 店铺分裂
|
||||
goodsList: [], // 商品列表
|
||||
@@ -145,35 +147,61 @@ export default {
|
||||
this.getStoreMsg();
|
||||
},
|
||||
methods: {
|
||||
isFloorEnabled() {
|
||||
const pageShow = this.storeMsg.pageShow;
|
||||
return pageShow === "1" || pageShow === 1 || pageShow === "OPEN" || pageShow === true;
|
||||
},
|
||||
loadStoreGoodsView() {
|
||||
this.showFloorView = false;
|
||||
this.getGoodsList();
|
||||
this.getCateList();
|
||||
},
|
||||
getIndexData() {
|
||||
// 获取首页装修数据
|
||||
getFloorStoreData({clientType: "PC", num: this.$route.query.id, pageType: 'STORE'}).then(
|
||||
(res) => {
|
||||
if (res.success) {
|
||||
let dataJson = JSON.parse(res.result.pageData);
|
||||
// 秒杀活动不是装修的数据,需要调用接口判断是否有秒杀商品
|
||||
// 轮播图根据不同轮播,样式不同
|
||||
for (const element of dataJson.list) {
|
||||
let type = element.type;
|
||||
getFloorStoreData({
|
||||
clientType: "PC",
|
||||
num: this.$route.query.id,
|
||||
pageType: "STORE",
|
||||
})
|
||||
.then(async (res) => {
|
||||
if (res.success && res.result?.pageData) {
|
||||
try {
|
||||
await this.parsePageData(res.result.pageData);
|
||||
this.showFloorView = true;
|
||||
} catch {
|
||||
this.loadStoreGoodsView();
|
||||
}
|
||||
} else {
|
||||
this.loadStoreGoodsView();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loadStoreGoodsView();
|
||||
});
|
||||
},
|
||||
async parsePageData(pageData) {
|
||||
const dataJson = JSON.parse(pageData);
|
||||
for (let i = 0; i < dataJson.list.length; i++) {
|
||||
const type = dataJson.list[i].type;
|
||||
if (type === "carousel2") {
|
||||
this.carouselLarge = true;
|
||||
} else if (type === "carousel1") {
|
||||
this.carouselLarge = true;
|
||||
this.carouselOpacity = true;
|
||||
} else if (type === "seckill") {
|
||||
dataJson.list[i].options.list = await this.getListByDay();
|
||||
}
|
||||
|
||||
// else if (type === "seckill") {
|
||||
// let seckill = this.getListByDay();
|
||||
// dataJson.list[i].options.list = seckill;
|
||||
// }
|
||||
}
|
||||
this.modelForm = dataJson;
|
||||
storage.setItem("navList", dataJson.list[1]);
|
||||
this.showNav = true;
|
||||
this.topAdvert = dataJson.list[0];
|
||||
},
|
||||
async getListByDay() {
|
||||
const res = await seckillByDay();
|
||||
if (res.success && res.result?.length) {
|
||||
return res.result;
|
||||
}
|
||||
}
|
||||
);
|
||||
return [];
|
||||
},
|
||||
|
||||
|
||||
@@ -208,15 +236,11 @@ export default {
|
||||
if (res.success) {
|
||||
|
||||
this.storeMsg = res.result;
|
||||
console.log(this.storeMsg)
|
||||
|
||||
//判定如果开启楼层展示,则获取页面信息 否则读取商品信息
|
||||
if (this.storeMsg.pageShow && this.storeMsg.pageShow === '1') {
|
||||
|
||||
if (this.isFloorEnabled()) {
|
||||
this.getIndexData();
|
||||
} else {
|
||||
this.getGoodsList();
|
||||
this.getCateList();
|
||||
this.loadStoreGoodsView();
|
||||
}
|
||||
let that = this;
|
||||
window.onscroll = function () {
|
||||
@@ -379,4 +403,32 @@ export default {
|
||||
.promotion-decorate::after {
|
||||
background-image: url("/src/assets/images/sprite@2x.png");
|
||||
}
|
||||
|
||||
.store-goods-section {
|
||||
width: 1200px;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.goods-list {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.goods-show-info {
|
||||
width: calc(20% - 8px);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.seckill-price {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.goods-show-detail {
|
||||
height: 32px;
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="gradeNameRow">
|
||||
<span class="gradeNameText">{{ currentGrade.gradeName || '暂无等级' }}</span>
|
||||
<span v-if="currentGradeBenefits.length" class="benefitTagsInline">
|
||||
<el-tag v-for="b in currentGradeBenefits" :key="b.id" class="benefitTag" color="blue">{{ b.benefitName || '-' }}</el-tag>
|
||||
<el-tag v-for="b in currentGradeBenefits" :key="b.id" class="benefitTag" type="primary">{{ b.benefitName || '-' }}</el-tag>
|
||||
</span>
|
||||
</div>
|
||||
<div class="gradeExp">
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<span style="margin-left: 10px;color: #ff9900;">{{refundPriceList(goods.isRefund)}}</span>
|
||||
</div>
|
||||
<el-button v-if="goods.commentStatus == 'UNFINISHED'" @click="comment(order.sn, goodsIndex)" size="small" type="success" class="fontsize_12" style="position:relative;top:-22px;left:190px;margin-right:10px">评价</el-button>
|
||||
<el-button v-if="goods.complainStatus == 'NO_APPLY'" @click="complain(order.sn, goodsIndex)" type="warning" class="fontsize_12" size="small" style="position:relative;top:-22px;left:190px">投诉</el-button>
|
||||
<el-button v-if="goods.complainStatus == 'NO_APPLY'" @click="complain(order.sn, goodsIndex)" type="danger" class="fontsize_12" size="small" style="position:relative;top:-22px;left:190px">投诉</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -65,7 +65,7 @@
|
||||
<el-button @click="orderDetail(order.sn)" type="warning" size="small">订单详情</el-button>
|
||||
<el-button @click="handleCancelOrder(order.sn)" type="danger" v-if="order.allowOperationVO.cancel" size="small">取消订单</el-button>
|
||||
<el-button @click="goPay(order.sn)" size="small" type="success" v-if="order.allowOperationVO.pay">去支付</el-button>
|
||||
<el-button @click="received(order.sn)" size="small" class="confirm-receipt-btn" v-if="order.allowOperationVO.rog">确认收货</el-button>
|
||||
<el-button @click="received(order.sn)" size="small" type="primary" v-if="order.allowOperationVO.rog">确认收货</el-button>
|
||||
<!-- 售后 -->
|
||||
<el-button v-if="order.groupAfterSaleStatus && (order.groupAfterSaleStatus.includes('NOT_APPLIED')|| order.groupAfterSaleStatus.includes('PART_AFTER_SALE'))"
|
||||
@click="applyAfterSale(order.orderItems)" size="small">申请售后</el-button>
|
||||
@@ -391,19 +391,6 @@ export default {
|
||||
margin: 0;
|
||||
min-width: 88px;
|
||||
}
|
||||
|
||||
:deep(.confirm-receipt-btn) {
|
||||
background-color: #ff9900 !important;
|
||||
border-color: #ff9900 !important;
|
||||
color: #fff !important;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: #e68a00 !important;
|
||||
border-color: #e68a00 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
v-if="order.allowOperationVO.pay"
|
||||
>去支付</el-button>
|
||||
<el-button
|
||||
type="info"
|
||||
type="primary"
|
||||
@click="received(order.order.sn)"
|
||||
size="small"
|
||||
v-if="order.allowOperationVO.rog"
|
||||
@@ -180,7 +180,7 @@
|
||||
goods.afterSaleStatus.includes('PART_AFTER_SALE')
|
||||
"
|
||||
@click="applyAfterSale(goods.sn)"
|
||||
type="warning"
|
||||
type="default"
|
||||
size="small"
|
||||
class="order-item-action-btn mb_5"
|
||||
>申请售后</el-button
|
||||
@@ -196,7 +196,7 @@
|
||||
<el-button
|
||||
v-if="goods.complainStatus == 'NO_APPLY'"
|
||||
@click="complain(order.order.sn, goodsIndex)"
|
||||
type="warning"
|
||||
type="danger"
|
||||
class="order-item-action-btn fontsize_12 mb_5"
|
||||
size="small"
|
||||
>投诉</el-button
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<el-divider />
|
||||
<div class="content width_1200">
|
||||
<div class="content width_1200_auto">
|
||||
<!-- 收货地址 -->
|
||||
<div class="address" v-if="selectedDeliverMethod === 'LOGISTICS' && goodsType !== 'VIRTUAL_GOODS'">
|
||||
<div class="card-head">
|
||||
@@ -30,11 +30,11 @@
|
||||
:key="index">
|
||||
<div>
|
||||
<span>{{ item.name }}</span>
|
||||
<el-tag class="ml_10 address-default-tag" v-if="item.isDefault" color="red" effect="dark">默认</el-tag>
|
||||
<el-tag class="ml_10 address-default-tag" v-if="item.isDefault" type="danger" effect="dark">默认</el-tag>
|
||||
<el-tag
|
||||
class="ml_10 address-alias-tag"
|
||||
v-if="item.alias"
|
||||
color="rgb(255, 153, 0)"
|
||||
type="warning"
|
||||
effect="dark"
|
||||
>{{ item.alias }}
|
||||
</el-tag>
|
||||
@@ -280,9 +280,8 @@
|
||||
<span>应付金额:</span><span class="actrual-price">{{ $filters.unitPrice(priceDetailDTO.flowPrice, "¥") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 底部支付栏 -->
|
||||
<div class="order-footer width_1200">
|
||||
<div class="order-footer">
|
||||
<div class="pay ml_20" @click="pay">提交订单</div>
|
||||
<div class="pay-address" v-if="addressList.length && selectedDeliverMethod === 'LOGISTICS'">
|
||||
配送至:{{ $filters.unitAddress(selectedAddress.consigneeAddressPath) }}
|
||||
@@ -294,6 +293,7 @@
|
||||
自提地点:{{selectedStoreAddress.address}} 联系方式:{{ selectedStoreAddress.mobile }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<BaseFooter></BaseFooter>
|
||||
<!-- 添加发票模态框 -->
|
||||
<invoice-modal ref="invModal" :invoiceData="invoiceData" @change="getInvMsg" />
|
||||
@@ -922,6 +922,7 @@ export default {
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
span {
|
||||
@include content_color($light_content_color);
|
||||
@@ -930,6 +931,12 @@ export default {
|
||||
line-height: 30px;
|
||||
display: inline-block;
|
||||
padding: 0 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.icon-next {
|
||||
flex-shrink: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
@@ -956,6 +963,7 @@ export default {
|
||||
background-color: #fff;
|
||||
min-height: 200px;
|
||||
padding: 15px 25px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.delivery-method {
|
||||
@@ -1034,13 +1042,15 @@ export default {
|
||||
flex-wrap: wrap;
|
||||
|
||||
:deep(.address-default-tag) {
|
||||
--el-tag-bg-color: var(--el-color-danger);
|
||||
--el-tag-border-color: var(--el-color-danger);
|
||||
--el-tag-text-color: #fff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
:deep(.address-alias-tag) {
|
||||
--el-tag-bg-color: rgb(255, 153, 0);
|
||||
--el-tag-border-color: rgb(255, 153, 0);
|
||||
--el-tag-bg-color: var(--el-color-warning);
|
||||
--el-tag-border-color: var(--el-color-warning);
|
||||
--el-tag-text-color: #fff;
|
||||
color: #fff;
|
||||
}
|
||||
@@ -1306,7 +1316,9 @@ export default {
|
||||
align-items: center;
|
||||
flex-direction: row-reverse;
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 10px auto;
|
||||
margin: 10px -25px 0;
|
||||
width: calc(100% + 50px);
|
||||
box-sizing: border-box;
|
||||
|
||||
div {
|
||||
text-align: center;
|
||||
|
||||
@@ -104,7 +104,7 @@ export default {
|
||||
onOk: () => {
|
||||
pay(params).then(res => {
|
||||
if (res.success) {
|
||||
this.$Message.warning(res.message)
|
||||
this.$Message.success(res.message)
|
||||
this.$router.push('/payDone');
|
||||
} else {
|
||||
this.$Message.warning(res.message)
|
||||
|
||||
@@ -120,18 +120,25 @@ export default {
|
||||
this.dateList.forEach((res) => {
|
||||
res.selected = false;
|
||||
});
|
||||
this.selectedWay.year = this.month.split("-")[0];
|
||||
this.selectedWay.month = this.month.split("-")[1];
|
||||
this.selectedWay.searchType = "";
|
||||
const parts = String(this.month).split("-");
|
||||
this.selectedWay = {
|
||||
...this.selectedWay,
|
||||
year: parts[0],
|
||||
month: parts[1],
|
||||
searchType: "",
|
||||
storeId: this.storeId,
|
||||
};
|
||||
this.$emit("selected", this.selectedWay);
|
||||
} else {
|
||||
const current = this.dateList.find((item) => item.selected);
|
||||
this.selectedWay = current;
|
||||
const current =
|
||||
this.dateList.find((item) => item.selected) ||
|
||||
this.dateList.find((item) => item.title === this.selectedWay.title) ||
|
||||
this.dateList.find((item) => item.searchType === "LAST_SEVEN");
|
||||
this.clickBreadcrumb(current);
|
||||
this.$emit("selected", this.selectedWay);
|
||||
}
|
||||
},
|
||||
clickBreadcrumb(item) {
|
||||
if (!item) return;
|
||||
let currentIndex;
|
||||
this.dateList.forEach((res, index) => {
|
||||
res.selected = false;
|
||||
@@ -143,8 +150,8 @@ export default {
|
||||
item.storeId = this.storeId;
|
||||
this.month = "";
|
||||
if (item.searchType === "") {
|
||||
const currentDate = this.originDateList[currentIndex].searchType;
|
||||
item.searchType = currentDate || "LAST_SEVEN";
|
||||
const origin = this.originDateList[currentIndex];
|
||||
item.searchType = (origin && origin.searchType) || "LAST_SEVEN";
|
||||
}
|
||||
this.selectedWay = item;
|
||||
this.selectedWay.year = new Date().getFullYear();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
v-model="category"
|
||||
:options="skuList"
|
||||
placeholder="请选择商品分类"
|
||||
popper-class="goods-dialog-cascader-popper"
|
||||
style="width: 250px"
|
||||
clearable
|
||||
/>
|
||||
@@ -260,3 +261,8 @@ export default {
|
||||
background-size: 10%;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.goods-dialog-cascader-popper {
|
||||
z-index: 10001 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<el-button @click="handleCLickImg('storeLogo')">选择图片</el-button>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="viewImage" title="图片预览" width="480px" append-to-body :z-index="3500">
|
||||
<el-dialog v-model="viewImage" title="图片预览" width="480px" append-to-body>
|
||||
<img
|
||||
:src="currentValue"
|
||||
alt="该资源不存在"
|
||||
@@ -51,13 +51,24 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="picModalFlag" width="1200px" append-to-body :z-index="3500" destroy-on-close>
|
||||
<el-dialog
|
||||
v-model="picModalFlag"
|
||||
title="选择图片"
|
||||
width="1200px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@closed="resetPicModal"
|
||||
>
|
||||
<ossManage
|
||||
ref="ossManage"
|
||||
:is-component="true"
|
||||
:initialize="picModalFlag"
|
||||
@callback="callbackSelected"
|
||||
@selected="handleOssSelected"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="cancelPicModal">取消</el-button>
|
||||
<el-button type="primary" @click="confirmPicModal">确认</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -106,12 +117,14 @@ export default {
|
||||
viewImage: false,
|
||||
uploadFileUrl: uploadFile,
|
||||
picModalFlag: false,
|
||||
pendingSelection: [],
|
||||
selectedFormBtnName: "",
|
||||
picIndex: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleCLickImg(val, index) {
|
||||
this.pendingSelection = [];
|
||||
this.picModalFlag = true;
|
||||
this.selectedFormBtnName = val;
|
||||
this.picIndex = index;
|
||||
@@ -121,11 +134,41 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
callbackSelected(val) {
|
||||
handleOssSelected(list) {
|
||||
this.pendingSelection = Array.isArray(list) ? list : [];
|
||||
},
|
||||
parseOssSelectionUrl(item) {
|
||||
if (!item) {
|
||||
return "";
|
||||
}
|
||||
if (typeof item === "string") {
|
||||
const index = item.indexOf(",");
|
||||
return index >= 0 ? item.slice(index + 1) : item;
|
||||
}
|
||||
return item.url || "";
|
||||
},
|
||||
confirmPicModal() {
|
||||
const list = this.pendingSelection || [];
|
||||
if (!list.length) {
|
||||
this.$Message.warning("请先选择图片");
|
||||
return;
|
||||
}
|
||||
const url = this.parseOssSelectionUrl(list[list.length - 1]);
|
||||
if (!url) {
|
||||
this.$Message.warning("请选择有效图片");
|
||||
return;
|
||||
}
|
||||
this.picModalFlag = false;
|
||||
this.currentValue = val.url;
|
||||
this.currentValue = url;
|
||||
this.picIndex = "";
|
||||
this.emitValue(this.currentValue);
|
||||
this.pendingSelection = [];
|
||||
},
|
||||
cancelPicModal() {
|
||||
this.picModalFlag = false;
|
||||
},
|
||||
resetPicModal() {
|
||||
this.pendingSelection = [];
|
||||
},
|
||||
init() {
|
||||
this.accessToken = {
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="upload-pic-thumb">
|
||||
<vuedraggable
|
||||
:list="uploadList"
|
||||
:disabled="!draggable || !multiple"
|
||||
:animation="200"
|
||||
class="list-group"
|
||||
ghost-class="thumb-ghost"
|
||||
@end="onEnd"
|
||||
>
|
||||
<div v-for="(item, index) in uploadList" :key="index" class="upload-list">
|
||||
<div v-if="!multiple" class="list-group">
|
||||
<div v-for="item in uploadList" :key="draggableItemKey(item)" class="upload-list">
|
||||
<div v-if="item.status == 'finished'" style="height: 60px">
|
||||
<img :src="item.url" alt="" />
|
||||
<div class="upload-list-cover">
|
||||
@@ -25,19 +18,47 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<vuedraggable
|
||||
v-else
|
||||
v-model="uploadList"
|
||||
:disabled="!draggable"
|
||||
:animation="200"
|
||||
class="list-group"
|
||||
ghost-class="thumb-ghost"
|
||||
:item-key="draggableItemKey"
|
||||
@end="onEnd"
|
||||
>
|
||||
<template #item="{ element: item }">
|
||||
<div class="upload-list">
|
||||
<div v-if="item.status == 'finished'" style="height: 60px">
|
||||
<img :src="item.url" alt="" />
|
||||
<div class="upload-list-cover">
|
||||
<el-icon class="action-icon" @click="handleView(item.url)"><View /></el-icon>
|
||||
<el-icon class="action-icon" @click="handleRemove(item)"><Delete /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-progress
|
||||
v-if="item.showProgress"
|
||||
:percentage="item.percentage"
|
||||
:show-text="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</vuedraggable>
|
||||
<el-upload
|
||||
ref="upload"
|
||||
class="upload-box"
|
||||
:action="uploadFileUrl"
|
||||
:headers="accessToken"
|
||||
:multiple="multiple"
|
||||
:show-file-list="false"
|
||||
accept=".jpg,.jpeg,.png,.gif"
|
||||
drag
|
||||
:before-upload="handleBeforeUpload"
|
||||
:on-success="handleSuccess"
|
||||
:on-error="handleError"
|
||||
style="display: inline-block; width: 58px"
|
||||
>
|
||||
<div class="upload-trigger">
|
||||
<el-icon :size="20"><Camera /></el-icon>
|
||||
@@ -99,6 +120,9 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
draggableItemKey(item) {
|
||||
return item.url || item.uid || item.name;
|
||||
},
|
||||
onEnd() {
|
||||
this.returnValue();
|
||||
},
|
||||
@@ -265,12 +289,29 @@ export default {
|
||||
opacity: 0.5;
|
||||
background: #c8ebfb;
|
||||
}
|
||||
.upload-box {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
:deep(.el-upload) {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
.upload-trigger {
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
line-height: 58px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px dashed #dcdfe6;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--el-color-primary);
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,2 +1,12 @@
|
||||
export default (url) =>()=>import(`@/views/${url}.vue`)
|
||||
const viewContext = require.context("@/views", true, /\.vue$/);
|
||||
|
||||
/** 后端菜单 frontRoute 与前端实际路径不一致时的映射 */
|
||||
const VIEW_ALIASES = {
|
||||
"live/list": "promotions/live/live",
|
||||
};
|
||||
|
||||
function resolveViewPath(url) {
|
||||
return VIEW_ALIASES[url] || url;
|
||||
}
|
||||
|
||||
export default (url) => () => Promise.resolve(viewContext(`./${resolveViewPath(url)}.vue`));
|
||||
|
||||
@@ -46,6 +46,13 @@
|
||||
clear: both;
|
||||
}
|
||||
.width_1200{width: 1200px;}
|
||||
.width_1200_auto {
|
||||
width: 1200px;
|
||||
max-width: 1200px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.width_800{width: 800px;}
|
||||
.width_400{width: 400px;}
|
||||
.width_300{width: 300px;}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/* Element Plus 主题覆盖(对齐原 iView 主色) */
|
||||
:root {
|
||||
--el-color-primary: #ff5c58;
|
||||
--el-color-success: #68cabe;
|
||||
--el-color-warning: #fa6419;
|
||||
--el-color-danger: #ff3c2a;
|
||||
// --el-color-primary: #ff5c58;
|
||||
// --el-color-success: #68cabe;
|
||||
// --el-color-warning: #fa6419;
|
||||
// --el-color-danger: #ff3c2a;
|
||||
--el-font-size-extra-small: 12px;
|
||||
--el-font-size-small: 13px;
|
||||
--el-font-size-base: 14px;
|
||||
--el-font-size-large: 16px;
|
||||
}
|
||||
|
||||
.el-button--primary {
|
||||
--el-button-bg-color: #ff5c58;
|
||||
--el-button-border-color: #ff5c58;
|
||||
--el-button-hover-bg-color: #ff7875;
|
||||
--el-button-hover-border-color: #ff7875;
|
||||
}
|
||||
// .el-button--primary {
|
||||
// --el-button-bg-color: #ff5c58;
|
||||
// --el-button-border-color: #ff5c58;
|
||||
// --el-button-hover-bg-color: #ff7875;
|
||||
// --el-button-hover-border-color: #ff7875;
|
||||
// }
|
||||
|
||||
/* 全局表格:去掉列竖线,保留行横线 */
|
||||
.el-table--border {
|
||||
|
||||
@@ -1,5 +1,41 @@
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
|
||||
const MESSAGE_BOX_Z_STYLE_ID = "lili-message-box-z-style";
|
||||
|
||||
/** EP 2.14 打开 MessageBox 时会用 nextZIndex() 覆盖 options.zIndex,需动态压过当前最高遮罩 */
|
||||
function getMaxOverlayZIndex() {
|
||||
if (typeof document === "undefined") {
|
||||
return 2000;
|
||||
}
|
||||
let max = 2000;
|
||||
document.querySelectorAll(".el-overlay").forEach((el) => {
|
||||
const z = Number.parseInt(window.getComputedStyle(el).zIndex, 10);
|
||||
if (Number.isFinite(z) && z > max) {
|
||||
max = z;
|
||||
}
|
||||
});
|
||||
return max + 100;
|
||||
}
|
||||
|
||||
function applyMessageBoxLayerZIndex(zIndex) {
|
||||
if (typeof document === "undefined") {
|
||||
return;
|
||||
}
|
||||
let styleEl = document.getElementById(MESSAGE_BOX_Z_STYLE_ID);
|
||||
if (!styleEl) {
|
||||
styleEl = document.createElement("style");
|
||||
styleEl.id = MESSAGE_BOX_Z_STYLE_ID;
|
||||
document.head.appendChild(styleEl);
|
||||
}
|
||||
styleEl.textContent = `.el-overlay.is-message-box { z-index: ${zIndex} !important; }`;
|
||||
}
|
||||
|
||||
function prepareMessageBoxLayer(options = {}) {
|
||||
const zIndex = options.zIndex ?? getMaxOverlayZIndex();
|
||||
applyMessageBoxLayerZIndex(zIndex);
|
||||
return zIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容原 view-design Message API,便于业务页渐进迁移
|
||||
*/
|
||||
@@ -39,6 +75,7 @@ export const Notice = {
|
||||
|
||||
export const Modal = {
|
||||
confirm(options = {}) {
|
||||
prepareMessageBoxLayer(options);
|
||||
const content = normalizeModalContent(options.content || options.title || "确认操作?");
|
||||
const title = options.title || "提示";
|
||||
return ElMessageBox.confirm(content, title, {
|
||||
@@ -77,6 +114,7 @@ export const Modal = {
|
||||
});
|
||||
},
|
||||
warning(options = {}) {
|
||||
prepareMessageBoxLayer(options);
|
||||
const content = normalizeModalContent(options.content || options.title || "");
|
||||
const title = options.title || "提示";
|
||||
return ElMessageBox.alert(content, title, {
|
||||
|
||||
@@ -159,7 +159,7 @@ export default {
|
||||
background-image: url("../assets/background.png");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center bottom;
|
||||
background-size: 100% auto;
|
||||
background-size: cover;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
<el-form-item label="支持电子面单">
|
||||
<el-switch
|
||||
v-model="form.standBy"
|
||||
active-value="true"
|
||||
inactive-value="false"
|
||||
inline-prompt
|
||||
active-text="开"
|
||||
inactive-text="关"
|
||||
@@ -106,10 +108,12 @@ import {
|
||||
const defaultForm = () => ({
|
||||
name: "",
|
||||
code: "",
|
||||
standBy: false,
|
||||
standBy: "false",
|
||||
disabled: "CLOSE",
|
||||
});
|
||||
|
||||
const normalizeStandBy = (value) => (value === true || value === "true" ? "true" : "false");
|
||||
|
||||
export default {
|
||||
name: "logistics",
|
||||
data() {
|
||||
@@ -159,7 +163,7 @@ export default {
|
||||
const data = res.result.records;
|
||||
data.forEach((e) => {
|
||||
e.switch = e.disabled === "OPEN";
|
||||
e.standBy = e.standBy == "null" || !e.standBy ? false : !!e.standBy;
|
||||
e.standBy = normalizeStandBy(e.standBy);
|
||||
});
|
||||
this.data = data;
|
||||
this.total = res.result.total;
|
||||
@@ -167,11 +171,12 @@ export default {
|
||||
});
|
||||
},
|
||||
changeSwitch(row) {
|
||||
this.form.name = row.name;
|
||||
this.form.code = row.code;
|
||||
this.form.standBy = row.standBy;
|
||||
this.form.disabled = row.disabled === "CLOSE" ? "OPEN" : "CLOSE";
|
||||
updateLogistics(row.id, this.form).then((res) => {
|
||||
updateLogistics(row.id, {
|
||||
name: row.name,
|
||||
code: row.code,
|
||||
standBy: normalizeStandBy(row.standBy),
|
||||
disabled: row.disabled === "CLOSE" ? "OPEN" : "CLOSE",
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getDataList();
|
||||
@@ -186,7 +191,10 @@ export default {
|
||||
this.submitLoading = true;
|
||||
|
||||
if (this.modalTitle === "添加") {
|
||||
const payload = { ...this.form };
|
||||
const payload = {
|
||||
...this.form,
|
||||
standBy: normalizeStandBy(this.form.standBy),
|
||||
};
|
||||
delete payload.id;
|
||||
addLogistics(payload).then((res) => {
|
||||
this.submitLoading = false;
|
||||
@@ -197,7 +205,10 @@ export default {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
updateLogistics(this.id, this.form).then((res) => {
|
||||
updateLogistics(this.id, {
|
||||
...this.form,
|
||||
standBy: normalizeStandBy(this.form.standBy),
|
||||
}).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
@@ -222,7 +233,7 @@ export default {
|
||||
this.form = {
|
||||
name: v.name,
|
||||
code: v.code,
|
||||
standBy: v.standBy == "null" || !v.standBy ? false : !!v.standBy,
|
||||
standBy: normalizeStandBy(v.standBy),
|
||||
disabled: v.disabled,
|
||||
};
|
||||
this.modalVisible = true;
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
<div class="operation padding-row">
|
||||
<el-button type="primary" @click="openAdd">添加权益设置</el-button>
|
||||
</div>
|
||||
<div class="benefit-list-panel">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
stripe
|
||||
:data="data"
|
||||
empty-text="暂无数据"
|
||||
class="mt_10 benefit-list-table benefit-list-table--no-vertical-borders"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column label="权益类型" width="132">
|
||||
<el-table-column label="权益类型" min-width="132">
|
||||
<template #default="{ row }">
|
||||
<span
|
||||
v-if="row"
|
||||
@@ -22,7 +22,7 @@
|
||||
{{ benefitTypeLabel(row.benefitType) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="权益名称" width="188">
|
||||
<el-table-column label="权益名称" min-width="188">
|
||||
<template #default="{ row }">
|
||||
<span
|
||||
v-if="row"
|
||||
@@ -32,7 +32,7 @@
|
||||
{{ row.benefitName || "-" }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="权益LOGO" width="116" align="center">
|
||||
<el-table-column label="权益LOGO" min-width="116" align="center">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row && !row.benefitLogo">-</span>
|
||||
<div v-else-if="row" class="benefit-logo-thumb benefit-logo-thumb--table">
|
||||
@@ -40,7 +40,7 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="118" align="center">
|
||||
<el-table-column label="状态" min-width="118" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-if="row"
|
||||
@@ -53,7 +53,7 @@
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" width="140">
|
||||
<el-table-column label="操作" align="center" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<div v-if="row" class="ops" style="display: flex; justify-content: center">
|
||||
<a class="link-text" @click="openEdit(row)">编辑</a>
|
||||
@@ -63,6 +63,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="mt_10" style="display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
v-model:current-page="searchForm.pageNumber"
|
||||
@@ -81,18 +82,24 @@
|
||||
v-model="couponPickerVisible"
|
||||
title="选择优惠券"
|
||||
width="80%"
|
||||
:z-index="3000"
|
||||
append-to-body
|
||||
modal-class="member-benefit-coupon-picker-modal"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
@close="handleCouponPickerClose"
|
||||
>
|
||||
<couponTemplate
|
||||
v-if="couponPickerVisible"
|
||||
ref="couponPicker"
|
||||
manualConfirm
|
||||
:selectedList="couponPickerSelectedList"
|
||||
getType="ACTIVITY"
|
||||
promotionStatus="START"
|
||||
@selected="onCouponTemplateSelected"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="couponPickerVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmCouponPicker">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-drawer
|
||||
@@ -140,21 +147,22 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="formAdd.benefitType === 'COUPON_PACKAGE'"
|
||||
class="benefit-coupon-form-item"
|
||||
label="赠送优惠券"
|
||||
prop="couponPackageRows"
|
||||
:required="formAdd.benefitType === 'COUPON_PACKAGE'"
|
||||
>
|
||||
<div>
|
||||
<div class="benefit-coupon-field">
|
||||
<el-button plain class="mb_10" @click="openCouponPicker('add')">添加优惠券</el-button>
|
||||
<el-table
|
||||
border
|
||||
size="small"
|
||||
class="benefit-coupon-table"
|
||||
:data="formAdd.couponPackageRows"
|
||||
empty-text="请添加优惠券"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="couponName" label="优惠券名称" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="有效期" min-width="100">
|
||||
<el-table-column prop="couponName" label="优惠券名称" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="有效期" min-width="280">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row" v-html="row.validRange || '-'" />
|
||||
</template>
|
||||
@@ -259,21 +267,22 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-show="formEdit.benefitType === 'COUPON_PACKAGE'"
|
||||
class="benefit-coupon-form-item"
|
||||
label="赠送优惠券"
|
||||
prop="couponPackageRows"
|
||||
:required="formEdit.benefitType === 'COUPON_PACKAGE'"
|
||||
>
|
||||
<div>
|
||||
<div class="benefit-coupon-field">
|
||||
<el-button plain class="mb_10" @click="openCouponPicker('edit')">添加优惠券</el-button>
|
||||
<el-table
|
||||
border
|
||||
size="small"
|
||||
class="benefit-coupon-table"
|
||||
:data="formEdit.couponPackageRows"
|
||||
empty-text="请添加优惠券"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="couponName" label="优惠券名称" min-width="100" show-overflow-tooltip />
|
||||
<el-table-column label="有效期" min-width="100">
|
||||
<el-table-column prop="couponName" label="优惠券名称" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="有效期" min-width="280">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row" v-html="row.validRange || '-'" />
|
||||
</template>
|
||||
@@ -405,14 +414,20 @@ export default {
|
||||
const opt = this.benefitTypeOptions.find((o) => o.value === v);
|
||||
return opt ? opt.description : v;
|
||||
},
|
||||
touchFormField(refName, field) {
|
||||
this.$nextTick(() => {
|
||||
const ref = this.$refs[refName];
|
||||
if (ref && typeof ref.validateField === "function") {
|
||||
// validateField rejects on failure; catch to avoid dev-server [object Object] overlay
|
||||
ref.validateField(field, () => {});
|
||||
}
|
||||
});
|
||||
},
|
||||
onCouponQuantityChange(which, index, val) {
|
||||
const formKey = which === "add" ? "formAdd" : "formEdit";
|
||||
const refName = which === "add" ? "addForm" : "editForm";
|
||||
this[formKey].couponPackageRows[index].quantity = val;
|
||||
this.$nextTick(() => {
|
||||
const ref = this.$refs[refName];
|
||||
if (ref) ref.validateField("couponPackageRows");
|
||||
});
|
||||
this.touchFormField(refName, "couponPackageRows");
|
||||
},
|
||||
buildFormRules(which) {
|
||||
const formKey = which === "add" ? "formAdd" : "formEdit";
|
||||
@@ -524,14 +539,12 @@ export default {
|
||||
if (val !== COUPON_PACKAGE) {
|
||||
this.formAdd.couponPackageRows = [];
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.addForm && val !== GIFT_POINT) {
|
||||
this.$refs.addForm.validateField("giftPoint");
|
||||
this.touchFormField("addForm", "giftPoint");
|
||||
}
|
||||
if (this.$refs.addForm && val !== COUPON_PACKAGE) {
|
||||
this.$refs.addForm.validateField("couponPackageRows");
|
||||
this.touchFormField("addForm", "couponPackageRows");
|
||||
}
|
||||
});
|
||||
},
|
||||
onEditBenefitTypeChange(val) {
|
||||
if (val !== GIFT_POINT) {
|
||||
@@ -540,14 +553,12 @@ export default {
|
||||
if (val !== COUPON_PACKAGE) {
|
||||
this.formEdit.couponPackageRows = [];
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.editForm && val !== GIFT_POINT) {
|
||||
this.$refs.editForm.validateField("giftPoint");
|
||||
this.touchFormField("editForm", "giftPoint");
|
||||
}
|
||||
if (this.$refs.editForm && val !== COUPON_PACKAGE) {
|
||||
this.$refs.editForm.validateField("couponPackageRows");
|
||||
this.touchFormField("editForm", "couponPackageRows");
|
||||
}
|
||||
});
|
||||
},
|
||||
parseCouponsFromConfig(str) {
|
||||
if (!str) return [];
|
||||
@@ -627,6 +638,15 @@ export default {
|
||||
this.couponPickerWhich = which;
|
||||
this.couponPickerVisible = true;
|
||||
},
|
||||
confirmCouponPicker() {
|
||||
const list = this.$refs.couponPicker?.getSelection?.() || [];
|
||||
if (!list.length) {
|
||||
this.$Message.warning("请至少选择一张优惠券");
|
||||
return;
|
||||
}
|
||||
this.onCouponTemplateSelected(list);
|
||||
this.couponPickerVisible = false;
|
||||
},
|
||||
onCouponTemplateSelected(selectedRows) {
|
||||
const which = this.couponPickerWhich;
|
||||
const form = which === "add" ? this.formAdd : this.formEdit;
|
||||
@@ -638,19 +658,13 @@ export default {
|
||||
return this.buildCouponDisplayRow(row, qty);
|
||||
});
|
||||
form.couponPackageRows = rows;
|
||||
this.$nextTick(() => {
|
||||
const ref = this.$refs[refName];
|
||||
if (ref) ref.validateField("couponPackageRows");
|
||||
});
|
||||
this.touchFormField(refName, "couponPackageRows");
|
||||
},
|
||||
removeCouponRow(which, index) {
|
||||
const form = which === "add" ? this.formAdd : this.formEdit;
|
||||
const refName = which === "add" ? "addForm" : "editForm";
|
||||
form.couponPackageRows.splice(index, 1);
|
||||
this.$nextTick(() => {
|
||||
const ref = this.$refs[refName];
|
||||
if (ref) ref.validateField("couponPackageRows");
|
||||
});
|
||||
this.touchFormField(refName, "couponPackageRows");
|
||||
},
|
||||
init() {
|
||||
this.loadBenefitTypes();
|
||||
@@ -902,6 +916,13 @@ export default {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.member-benefit .benefit-list-panel {
|
||||
width: 50%;
|
||||
max-width: 100%;
|
||||
}
|
||||
.member-benefit .benefit-list-panel .benefit-list-table {
|
||||
width: 100%;
|
||||
}
|
||||
.member-benefit .benefit-list-table table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
@@ -924,6 +945,25 @@ export default {
|
||||
.member-benefit .benefit-list-table--no-vertical-borders .el-table td {
|
||||
border-right: none !important;
|
||||
}
|
||||
|
||||
.member-benefit-coupon-picker-modal {
|
||||
z-index: 2700 !important;
|
||||
}
|
||||
|
||||
.benefit-form-drawer .benefit-coupon-form-item.el-form-item .el-form-item__content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
max-width: none;
|
||||
}
|
||||
.benefit-form-drawer .benefit-coupon-field {
|
||||
width: 100%;
|
||||
}
|
||||
.benefit-form-drawer .benefit-coupon-table {
|
||||
width: 100%;
|
||||
}
|
||||
.benefit-form-drawer .benefit-coupon-table table {
|
||||
width: 100% !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -709,10 +709,8 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.getData();
|
||||
if (!this.selectedMember) {
|
||||
this.loadMemberGroupList();
|
||||
this.loadMemberGradeList();
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -308,7 +308,7 @@ export const modelData = [{
|
||||
bgImg: {
|
||||
img: require('@/assets/nav/decorate.png'),
|
||||
url: '',
|
||||
size: "1300*586"
|
||||
size: "1300*596"
|
||||
},
|
||||
classification: [{
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
|
||||
@@ -27,11 +27,12 @@
|
||||
<div class="search-con">
|
||||
<img :src="require('@/assets/logo.png')" class="logo" alt="" />
|
||||
<div class="search">
|
||||
<el-input size="large" placeholder="输入你想查找的商品">
|
||||
<template #append>
|
||||
<el-button>搜索</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-input
|
||||
size="large"
|
||||
class="search-input"
|
||||
placeholder="输入你想查找的商品"
|
||||
/>
|
||||
<div class="search-btn">搜索</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-con" v-if="$route.query.pageType !== 'SPECIAL'">
|
||||
@@ -73,17 +74,18 @@
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@close="handleCancelTopAdvertModal"
|
||||
>
|
||||
<div class="modal-top-advert">
|
||||
<div class="modal-top-advert" v-if="draftTopAdvert">
|
||||
<div>
|
||||
<img class="show-image" width="600" height="40" :src="topAdvert.img" alt />
|
||||
<img class="show-image" width="600" height="40" :src="draftTopAdvert.img" alt />
|
||||
</div>
|
||||
<div class="tips">建议尺寸:<span>{{ topAdvert.size }}</span></div>
|
||||
<div class="tips">建议尺寸:<span>{{ draftTopAdvert.size }}</span></div>
|
||||
<div>
|
||||
图片链接:<el-input
|
||||
class="outsideUrl"
|
||||
v-model="topAdvert.url"
|
||||
:disabled="!!topAdvert.type && topAdvert.type !== 'link'"
|
||||
v-model="draftTopAdvert.url"
|
||||
:disabled="!!draftTopAdvert.type && draftTopAdvert.type !== 'link'"
|
||||
placeholder="https://"
|
||||
/>
|
||||
<el-button size="small" type="primary" @click="handleSelectLink">选择链接</el-button>
|
||||
@@ -91,8 +93,12 @@
|
||||
<div>
|
||||
选择图片:<el-button size="small" type="primary" @click="handleSelectImg">选择图片</el-button>
|
||||
</div>
|
||||
<div>选择背景色:<el-color-picker v-model="topAdvert.bgColor" /></div>
|
||||
<div>选择背景色:<el-color-picker v-model="draftTopAdvert.bgColor" /></div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelTopAdvertModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmTopAdvertModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-model="showModalNav"
|
||||
@@ -101,6 +107,7 @@
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@close="handleNavDialogClose"
|
||||
>
|
||||
<div class="modal-tab-bar">
|
||||
<el-button type="primary" size="small" @click="handleAddNav">添加分类</el-button>
|
||||
@@ -129,6 +136,10 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelNavModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmNavModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
|
||||
<el-dialog v-model="picModelFlag" width="1200px" append-to-body destroy-on-close>
|
||||
@@ -136,6 +147,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -160,6 +172,8 @@ export default {
|
||||
picModelFlag: false,
|
||||
showModal: false,
|
||||
showModalNav: false,
|
||||
navListBackup: null,
|
||||
draftTopAdvert: null,
|
||||
selectedNav: null,
|
||||
promotionTags: ["买2免1", "领200神券", "199减100", "母婴5折抢", "充100送20"],
|
||||
topAdvert: {
|
||||
@@ -204,31 +218,54 @@ export default {
|
||||
if (this.showModalNav) {
|
||||
this.selectedNav.url = this.$filters.formatLinkType(val);
|
||||
this.selectedNav.type = val.___type === "other" && val.url === "" ? "link" : "other";
|
||||
} else {
|
||||
this.topAdvert.url = this.$filters.formatLinkType(val);
|
||||
this.topAdvert.type = val.___type === "other" && val.url === "" ? "link" : "other";
|
||||
}
|
||||
this.navList.list[this.currentIndex].title = val.title;
|
||||
} else if (this.showModal && this.draftTopAdvert) {
|
||||
this.draftTopAdvert.url = this.$filters.formatLinkType(val);
|
||||
this.draftTopAdvert.type = val.___type === "other" && val.url === "" ? "link" : "other";
|
||||
}
|
||||
},
|
||||
handleDelNav(index) {
|
||||
this.navList.list.splice(index, 1);
|
||||
},
|
||||
handleAddNav() {
|
||||
this.navList.list.push({ name: "", url: "", title: "" });
|
||||
this.$nextTick(() => {
|
||||
this.selectedNav.title = val.title;
|
||||
});
|
||||
},
|
||||
handleMoveEnd({ newIndex, oldIndex }) {
|
||||
console.log("index", newIndex, oldIndex);
|
||||
},
|
||||
handleModel(type) {
|
||||
if (type == "topAdvert") {
|
||||
this.draftTopAdvert = JSON.parse(JSON.stringify(this.topAdvert));
|
||||
this.showModal = true;
|
||||
} else {
|
||||
this.navListBackup = JSON.parse(JSON.stringify(this.navList));
|
||||
this.showModalNav = true;
|
||||
}
|
||||
},
|
||||
handleCancelTopAdvertModal() {
|
||||
this.draftTopAdvert = null;
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmTopAdvertModal() {
|
||||
if (this.draftTopAdvert) {
|
||||
Object.assign(this.topAdvert, JSON.parse(JSON.stringify(this.draftTopAdvert)));
|
||||
}
|
||||
this.draftTopAdvert = null;
|
||||
this.showModal = false;
|
||||
},
|
||||
handleCancelNavModal() {
|
||||
this.showModalNav = false;
|
||||
},
|
||||
handleConfirmNavModal() {
|
||||
this.navListBackup = null;
|
||||
this.showModalNav = false;
|
||||
},
|
||||
handleNavDialogClose() {
|
||||
if (this.navListBackup) {
|
||||
this.navList = JSON.parse(JSON.stringify(this.navListBackup));
|
||||
this.navListBackup = null;
|
||||
}
|
||||
},
|
||||
handleSelectImg() {
|
||||
this.picModelFlag = true;
|
||||
this.$nextTick(() => {
|
||||
@@ -239,7 +276,8 @@ export default {
|
||||
},
|
||||
callbackSelected(item) {
|
||||
this.picModelFlag = false;
|
||||
this.topAdvert.img = item.url;
|
||||
if (!item?.url || !this.draftTopAdvert) return;
|
||||
this.draftTopAdvert.img = item.url;
|
||||
},
|
||||
handleModelAdd(evt) {
|
||||
const newIndex = evt.newIndex;
|
||||
@@ -264,15 +302,18 @@ export default {
|
||||
@import "./modelList/setup-box.scss";
|
||||
.model-form {
|
||||
width: 1500px;
|
||||
max-width: 100%;
|
||||
}
|
||||
.model-content {
|
||||
width: 1200px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
min-height: 1200px;
|
||||
overflow-x: visible;
|
||||
}
|
||||
.model-form-list {
|
||||
min-height: 500px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.top-fixed-advert {
|
||||
display: flex;
|
||||
@@ -329,26 +370,47 @@ export default {
|
||||
height: 50px;
|
||||
}
|
||||
.search {
|
||||
$search-height: 34px;
|
||||
$search-btn-width: 60px;
|
||||
$btn-gap: 3px;
|
||||
|
||||
position: relative;
|
||||
width: 460px;
|
||||
height: $search-height;
|
||||
margin: 0 auto;
|
||||
:deep(.el-input--large .el-input__wrapper) {
|
||||
|
||||
.search-input {
|
||||
width: 100%;
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
border: 2px solid $theme_color;
|
||||
border-radius: calc($search-height / 2);
|
||||
box-sizing: border-box;
|
||||
padding-right: calc($search-btn-width + $btn-gap * 2);
|
||||
font-size: 12px;
|
||||
height: 34px;
|
||||
height: $search-height;
|
||||
box-shadow: none;
|
||||
}
|
||||
:deep(.el-input-group__append) {
|
||||
border: 1px solid $theme_color;
|
||||
border-left: none;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
position: absolute;
|
||||
top: $btn-gap;
|
||||
right: $btn-gap;
|
||||
bottom: $btn-gap;
|
||||
width: $search-btn-width;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
border-radius: calc(($search-height - $btn-gap * 2) / 2);
|
||||
background-color: $theme_color;
|
||||
color: #ffffff;
|
||||
.el-button {
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
color: #fff;
|
||||
}
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,24 +2,25 @@
|
||||
<div class="model-item" v-if="element && element.key">
|
||||
<!-- 轮播图模块,包括个人信息,快捷导航模块 -->
|
||||
<template v-if="element.type == 'carousel'">
|
||||
<div class="carousel-wrap mb_20 width_1200_auto">
|
||||
<model-carousel :data="element"></model-carousel>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 轮播图模块,100%宽度,无个人信息栏 -->
|
||||
<template v-if="element.type == 'carousel1'">
|
||||
<model-carousel1 class="mb_20" :data="element"></model-carousel1>
|
||||
<model-carousel1 class="mb_20 width_1200_auto" :data="element"></model-carousel1>
|
||||
</template>
|
||||
<!-- 轮播图模块,包括个人信息,两个轮播模块 -->
|
||||
<template v-if="element.type == 'carousel2'">
|
||||
<model-carousel2 class="mb_20" :data="element"></model-carousel2>
|
||||
<model-carousel2 class="mb_20 width_1200_auto" :data="element"></model-carousel2>
|
||||
</template>
|
||||
<!-- 热门广告 -->
|
||||
<template v-if="element.type == 'hotAdvert'">
|
||||
<div class="setup-content">
|
||||
<div class="hot-advert mb_20 width_1200_auto">
|
||||
<div class="hot-advert-banner setup-content">
|
||||
<img
|
||||
style="display: block"
|
||||
:src="element.options.list[0].img"
|
||||
@click="$router.push(element.options.list[0].url)"
|
||||
width="1200"
|
||||
alt=""
|
||||
/>
|
||||
<div class="setup-box">
|
||||
@@ -40,7 +41,7 @@
|
||||
class="setup-content"
|
||||
:key="index"
|
||||
>
|
||||
<img :src="item.img" width="230" height="190" alt="" />
|
||||
<img :src="item.img" alt="" />
|
||||
<div class="setup-box">
|
||||
<div>
|
||||
<el-button size="small" @click.stop="handleSelectModel(item)"
|
||||
@@ -51,18 +52,19 @@
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 限时秒杀 待完善 -->
|
||||
<template v-if="element.type == 'seckill'">
|
||||
<seckill :data="element"></seckill>
|
||||
<seckill :data="element" class="mb_20 width_1200_auto"></seckill>
|
||||
</template>
|
||||
<!-- 限时秒杀 待完善 -->
|
||||
<template v-if="element.type == 'seckill-only-album'">
|
||||
<seckill-only-album :data="element"></seckill-only-album>
|
||||
<seckill-only-album :data="element" class="mb_20 width_1200_auto"></seckill-only-album>
|
||||
</template>
|
||||
<!-- 折扣广告 -->
|
||||
<template v-if="element.type == 'discountAdvert'">
|
||||
<div class="discountAdvert-wrap">
|
||||
<div class="discountAdvert-wrap width_1200_auto mb_20">
|
||||
<div
|
||||
class="discountAdvert"
|
||||
:style="{
|
||||
@@ -107,15 +109,15 @@
|
||||
</template>
|
||||
<!-- 好货推荐 -->
|
||||
<template v-if="element.type == 'recommend'">
|
||||
<recommend :data="element"></recommend>
|
||||
<recommend :data="element" class="mb_20 width_1200_auto"></recommend>
|
||||
</template>
|
||||
<!-- 新品排行 -->
|
||||
<template v-if="element.type == 'newGoodsSort'">
|
||||
<new-goods-sort :data="element"></new-goods-sort>
|
||||
<new-goods-sort :data="element" class="mb_20 width_1200_auto"></new-goods-sort>
|
||||
</template>
|
||||
<!-- 首页广告 -->
|
||||
<template v-if="element.type == 'firstAdvert'">
|
||||
<first-page-advert :data="element"></first-page-advert>
|
||||
<first-page-advert :data="element" class="mb_20 width_1200_auto"></first-page-advert>
|
||||
</template>
|
||||
<!-- 商品模块 -->
|
||||
<template v-if="element.type == 'goodsType'">
|
||||
@@ -139,10 +141,10 @@
|
||||
</template>
|
||||
<!-- 横幅广告 -->
|
||||
<template v-if="element.type == 'bannerAdvert'">
|
||||
<div class="horizontal-advert setup-content">
|
||||
<div class="horizontal-advert setup-content width_1200_auto mb_20">
|
||||
<img
|
||||
v-if="element.options.img"
|
||||
width="1200"
|
||||
class="banner-ad-img"
|
||||
:src="element.options.img"
|
||||
alt=""
|
||||
/>
|
||||
@@ -162,7 +164,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="element.type == 'notEnough'">
|
||||
<not-enough :data="element"></not-enough>
|
||||
<not-enough :data="element" class="mb_20 width_1200_auto"></not-enough>
|
||||
</template>
|
||||
<div class="del-btn">
|
||||
<el-button size="small" type="danger" @click="handleModelDelete">删除</el-button>
|
||||
@@ -176,13 +178,13 @@
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="modal-top-advert">
|
||||
<div>
|
||||
<div class="modal-form-item modal-form-preview">
|
||||
<!-- 热门广告两种图片尺寸 -->
|
||||
<img
|
||||
class="show-image"
|
||||
width="600"
|
||||
height="40"
|
||||
v-if="selected.size && selected.size.indexOf('1200') >= 0"
|
||||
v-if="selected.size && selected.size.indexOf('1200') >= 0 && selected.img"
|
||||
:src="selected.img"
|
||||
alt
|
||||
/>
|
||||
@@ -198,7 +200,7 @@
|
||||
<img
|
||||
class="show-image"
|
||||
width="600"
|
||||
height="300"
|
||||
height="275"
|
||||
v-if="selected.size && selected.size.indexOf('1300') >= 0"
|
||||
:src="selected.img"
|
||||
alt
|
||||
@@ -220,11 +222,11 @@
|
||||
alt
|
||||
/>
|
||||
</div>
|
||||
<div class="tips">
|
||||
建议尺寸:<span>{{ selected.size }}</span>
|
||||
</div>
|
||||
<div>
|
||||
图片链接:<el-input
|
||||
<div class="tips">建议尺寸:{{ selected.size }}</div>
|
||||
<div class="modal-form-item modal-form-link">
|
||||
<span class="modal-label">图片链接:</span>
|
||||
<div class="modal-link-field">
|
||||
<el-input
|
||||
class="outsideUrl"
|
||||
v-model="selected.url"
|
||||
:disabled="!!selected.type && selected.type !== 'link'"
|
||||
@@ -234,12 +236,18 @@
|
||||
>选择链接</el-button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
选择图片:<el-button size="small" type="primary" @click="handleSelectImg"
|
||||
</div>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">选择图片:</span>
|
||||
<el-button size="small" type="primary" @click="handleSelectImg"
|
||||
>选择图片</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 选择商品。链接 -->
|
||||
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
|
||||
@@ -249,6 +257,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -296,14 +305,19 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
showModal: false, // modal显隐
|
||||
selected: {}, // 已选数据
|
||||
selected: {}, // 弹窗编辑草稿
|
||||
editTarget: null, // 确认后写回的原数据
|
||||
picModelFlag: false, // 图片选择器
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
cloneItem(item) {
|
||||
return JSON.parse(JSON.stringify(item || {}));
|
||||
},
|
||||
// 编辑模块
|
||||
handleSelectModel(item) {
|
||||
this.selected = item;
|
||||
this.editTarget = item;
|
||||
this.selected = this.cloneItem(item);
|
||||
this.showModal = true;
|
||||
},
|
||||
// 删除模块
|
||||
@@ -341,8 +355,22 @@ export default {
|
||||
// 回显图片
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (!val?.url) return;
|
||||
this.selected.img = val.url;
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
if (this.editTarget) {
|
||||
Object.assign(this.editTarget, this.cloneItem(this.selected));
|
||||
}
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -351,12 +379,21 @@ export default {
|
||||
.model-item {
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
&:hover {
|
||||
.del-btn {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.carousel-wrap {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
.del-btn {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
@@ -364,6 +401,7 @@ export default {
|
||||
position: absolute;
|
||||
right: -100px;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
&:hover {
|
||||
display: block;
|
||||
}
|
||||
@@ -371,23 +409,59 @@ export default {
|
||||
/** 横幅广告 */
|
||||
.horizontal-advert {
|
||||
width: 1200px;
|
||||
max-width: 1200px;
|
||||
overflow: hidden;
|
||||
line-height: 0;
|
||||
|
||||
.banner-ad-img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 166px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.default-con {
|
||||
height: 100px;
|
||||
padding-top: 30px;
|
||||
text-align: center;
|
||||
background: #ddd;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
/** 热门广告 */
|
||||
.hot-advert {
|
||||
width: 1200px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
|
||||
.hot-advert-banner {
|
||||
line-height: 0;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
.advert-list {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 5px 6px;
|
||||
list-style: none;
|
||||
box-sizing: border-box;
|
||||
background: $theme_color;
|
||||
height: 200px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 3px 10px;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
> li {
|
||||
flex: 0 0 calc((100% - 24px) / 5);
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 190px;
|
||||
cursor: pointer;
|
||||
border-radius: 10px;
|
||||
transition: all 150ms ease-in-out;
|
||||
@@ -414,11 +488,11 @@ export default {
|
||||
}
|
||||
.discountAdvert {
|
||||
width: 1300px;
|
||||
height: 566px;
|
||||
height: 596px;
|
||||
margin-left: -100px;
|
||||
box-sizing: border-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1300px 566px;
|
||||
background-size: 1300px 596px;
|
||||
position: relative;
|
||||
> div {
|
||||
padding-left: 295px;
|
||||
@@ -428,11 +502,14 @@ export default {
|
||||
&:nth-child(1) img {
|
||||
margin: 10px 10px 0 0;
|
||||
}
|
||||
&:nth-child(2) img {
|
||||
&:nth-child(2) {
|
||||
margin-top: 10px;
|
||||
img {
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 首页品牌 */
|
||||
.brand {
|
||||
.brand-view {
|
||||
@@ -535,11 +612,61 @@ export default {
|
||||
/** 装修模态框 内部样式start */
|
||||
.modal-top-advert {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
> * {
|
||||
margin-bottom: 10px;
|
||||
align-items: stretch;
|
||||
padding: 0 20px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.modal-form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.modal-label {
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-form-preview {
|
||||
justify-content: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.modal-form-link {
|
||||
align-items: flex-start;
|
||||
|
||||
.modal-label {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.modal-link-field {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
|
||||
.outsideUrl {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
padding-left: 112px;
|
||||
margin-bottom: 16px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -52,11 +52,9 @@
|
||||
<el-dialog
|
||||
v-model="showModal"
|
||||
title="快捷导航"
|
||||
|
||||
width="800"
|
||||
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
append-to-body destroy-on-close @close="handleCancelModal">
|
||||
<div class="modal-tab-bar">
|
||||
<el-button type="primary" size="small" @click="handleAdd">添加轮播</el-button>
|
||||
|
||||
@@ -72,7 +70,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, index) in data.options.list" :key="index">
|
||||
<tr v-for="(item, index) in draftList" :key="index">
|
||||
<td>
|
||||
<img
|
||||
style="cursor: pointer"
|
||||
@@ -113,6 +111,10 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 选择商品。链接 -->
|
||||
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
|
||||
@@ -122,6 +124,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -140,6 +143,7 @@ export default {
|
||||
return {
|
||||
showModal: false, // modal显隐
|
||||
selected: null, // 已选数据
|
||||
draftList: [], // 弹窗编辑草稿
|
||||
picModelFlag: false, // 选择图片modal
|
||||
userInfo: {},
|
||||
articleList: [
|
||||
@@ -152,14 +156,29 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
cloneList(list) {
|
||||
return JSON.parse(JSON.stringify(list || []));
|
||||
},
|
||||
handleSelectModel() {
|
||||
// 编辑模块
|
||||
this.draftList = this.cloneList(this.data.options.list);
|
||||
this.showModal = true;
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.draftList = [];
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
this.data.options.list.splice(
|
||||
0,
|
||||
this.data.options.list.length,
|
||||
...this.cloneList(this.draftList)
|
||||
);
|
||||
this.draftList = [];
|
||||
this.showModal = false;
|
||||
},
|
||||
// 添加轮播图
|
||||
handleAdd() {
|
||||
this.data.options.list.push({ img: "", url: "", type: "" });
|
||||
this.$forceUpdate();
|
||||
this.draftList.push({ img: "", url: "", type: "" });
|
||||
},
|
||||
handleSelectLink(item) {
|
||||
// 选择链接
|
||||
@@ -169,11 +188,11 @@ export default {
|
||||
callbackSelected(item) {
|
||||
// 选择图片回调
|
||||
this.picModelFlag = false;
|
||||
if (!item?.url) return;
|
||||
this.selected.img = item.url;
|
||||
},
|
||||
handleDel(index) {
|
||||
// 删除图片
|
||||
this.data.options.list.splice(index, 1);
|
||||
this.draftList.splice(index, 1);
|
||||
},
|
||||
selectedLink(val) {
|
||||
// 选择链接回调
|
||||
@@ -268,18 +287,24 @@ export default {
|
||||
}
|
||||
}
|
||||
.shop-msg {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
margin: 10px 27px;
|
||||
margin: 10px 0;
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-left: 5px;
|
||||
margin-left: 0;
|
||||
}
|
||||
span:nth-child(1) {
|
||||
color: $theme_color;
|
||||
margin-left: 0;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
font-weight: normal;
|
||||
@@ -290,11 +315,15 @@ export default {
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0 30px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
cursor: pointer;
|
||||
margin: 5px 0;
|
||||
color: #999395;
|
||||
text-align: center;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
|
||||
<!-- 选择图片 -->
|
||||
<el-dialog v-model="picModelFlag" width="1200px" append-to-body destroy-on-close>
|
||||
<ossManage @callback="callbackSelected" :is-component="true" :initialize="picModelFlag" ref="ossManage" />
|
||||
<ossManage @callback="callbackSelected" :is-component="true" :initialize="picModelFlag" :max-select="1" ref="ossManage" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -130,6 +130,7 @@ export default {
|
||||
callbackSelected(item) {
|
||||
// 选择图片回调
|
||||
this.picModelFlag = false;
|
||||
if (!item?.url) return;
|
||||
this.selected.img = item.url;
|
||||
},
|
||||
// 删除图片
|
||||
|
||||
@@ -204,7 +204,7 @@
|
||||
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
|
||||
<!-- 选择图片 -->
|
||||
<el-dialog v-model="picModelFlag" width="1200px" append-to-body destroy-on-close>
|
||||
<ossManage @callback="callbackSelected" :is-component="true" :initialize="picModelFlag" ref="ossManage" />
|
||||
<ossManage @callback="callbackSelected" :is-component="true" :initialize="picModelFlag" :max-select="1" ref="ossManage" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -262,6 +262,7 @@ export default {
|
||||
callbackSelected(item) {
|
||||
// 选择图片回调
|
||||
this.picModelFlag = false;
|
||||
if (!item?.url) return;
|
||||
this.selected.img = item.url;
|
||||
},
|
||||
// 删除图片
|
||||
@@ -367,18 +368,24 @@ export default {
|
||||
}
|
||||
}
|
||||
.shop-msg {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
margin: 10px 27px;
|
||||
margin: 10px 0;
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-left: 5px;
|
||||
margin-left: 0;
|
||||
}
|
||||
span:nth-child(1) {
|
||||
color: $theme_color;
|
||||
margin-left: 0;
|
||||
}
|
||||
span:nth-child(2) {
|
||||
font-weight: normal;
|
||||
@@ -387,13 +394,19 @@ export default {
|
||||
color: $theme_color;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
cursor: pointer;
|
||||
margin: 5px 0;
|
||||
color: #999395;
|
||||
width: 150px;
|
||||
width: auto;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
&:hover {
|
||||
color: $theme_color;
|
||||
}
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
<el-dialog
|
||||
v-model="showModal"
|
||||
title="装修"
|
||||
|
||||
width="800"
|
||||
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="modal-top-advert">
|
||||
<div>
|
||||
<div class="modal-form-item modal-form-preview">
|
||||
<img
|
||||
class="show-image"
|
||||
width="170"
|
||||
@@ -41,13 +41,19 @@
|
||||
alt
|
||||
/>
|
||||
</div>
|
||||
<div><span>图片主标题:</span><el-input v-model="selected.name" /></div>
|
||||
<div><span>图片描述:</span><el-input v-model="selected.describe" /></div>
|
||||
<div class="tips">
|
||||
建议尺寸:<span>{{ selected.size }}</span>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">图片主标题:</span>
|
||||
<el-input v-model="selected.name" />
|
||||
</div>
|
||||
<div>
|
||||
图片链接:<el-input
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">图片描述:</span>
|
||||
<el-input v-model="selected.describe" />
|
||||
</div>
|
||||
<div class="tips">建议尺寸:{{ selected.size }}</div>
|
||||
<div class="modal-form-item modal-form-link">
|
||||
<span class="modal-label">图片链接:</span>
|
||||
<div class="modal-link-field">
|
||||
<el-input
|
||||
class="outsideUrl"
|
||||
v-model="selected.url"
|
||||
:disabled="!!selected.type && selected.type !== 'link'"
|
||||
@@ -57,26 +63,46 @@
|
||||
>选择链接</el-button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<span>渐变背景色:</span><el-input v-model="selected.fromColor" />
|
||||
<el-color-picker v-if="selected.fromColor" v-model="selected.fromColor" />
|
||||
</div>
|
||||
<div>
|
||||
<span>渐变背景色:</span><el-input v-model="selected.toColor" />
|
||||
<el-color-picker v-if="selected.toColor" v-model="selected.toColor" />
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">渐变背景色:</span>
|
||||
<div class="modal-color-field">
|
||||
<el-input v-model="selected.fromColor" />
|
||||
<el-color-picker
|
||||
v-if="selected.fromColor"
|
||||
v-model="selected.fromColor"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">渐变背景色:</span>
|
||||
<div class="modal-color-field">
|
||||
<el-input v-model="selected.toColor" />
|
||||
<el-color-picker
|
||||
v-if="selected.toColor"
|
||||
v-model="selected.toColor"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-form-item modal-form-exhibition">
|
||||
<div
|
||||
:style="{
|
||||
backgroundImage: `linear-gradient(to right, ${selected.fromColor}, ${selected.toColor})`,
|
||||
}"
|
||||
class="exhibition"
|
||||
></div>
|
||||
<div>
|
||||
选择图片:<el-button size="small" type="primary" @click="handleSelectImg"
|
||||
</div>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">选择图片:</span>
|
||||
<el-button size="small" type="primary" @click="handleSelectImg"
|
||||
>选择图片</el-button
|
||||
>
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 选择商品。链接 -->
|
||||
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
|
||||
@@ -86,6 +112,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -105,14 +132,19 @@ export default {
|
||||
return {
|
||||
options: this.data.options, // 当前类型数据
|
||||
showModal: false, // modal显隐
|
||||
selected: {}, // 已选数据
|
||||
selected: {}, // 弹窗编辑草稿
|
||||
editTarget: null, // 确认后写回的原数据
|
||||
picModelFlag: false, // 图片选择器
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
cloneItem(item) {
|
||||
return JSON.parse(JSON.stringify(item || {}));
|
||||
},
|
||||
// 打开装修modal
|
||||
handleSelectModel(item, type) {
|
||||
this.selected = item;
|
||||
handleSelectModel(item) {
|
||||
this.editTarget = item;
|
||||
this.selected = this.cloneItem(item);
|
||||
this.showModal = true;
|
||||
},
|
||||
handleSelectLink(item, index) {
|
||||
@@ -137,8 +169,22 @@ export default {
|
||||
// 选择图片回调
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (!val?.url) return;
|
||||
this.selected.img = val.url;
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
if (this.editTarget) {
|
||||
Object.assign(this.editTarget, this.cloneItem(this.selected));
|
||||
}
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -148,7 +194,6 @@ export default {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
// margin-top: -10px;
|
||||
.item {
|
||||
width: 393px;
|
||||
height: 170px;
|
||||
@@ -192,12 +237,86 @@ export default {
|
||||
width: 154px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-top-advert {
|
||||
align-items: start;
|
||||
padding: 0 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
padding: 0 20px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.modal-form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.modal-label {
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-form-preview {
|
||||
justify-content: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.modal-form-link {
|
||||
align-items: flex-start;
|
||||
|
||||
.modal-label {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.modal-link-field {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
|
||||
.outsideUrl {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-color-field {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-form-exhibition {
|
||||
padding-left: 112px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.exhibition {
|
||||
width: 300px;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
padding-left: 112px;
|
||||
margin-bottom: 16px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -55,23 +55,23 @@
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
<div>
|
||||
<div class="modal-tab-bar">
|
||||
<div class="modal-tab-bar" v-if="draftOptions">
|
||||
<div>
|
||||
主标题:
|
||||
<el-input style="width: 200px" v-model="data.options.title" />
|
||||
<el-input style="width: 200px" v-model="draftOptions.title" />
|
||||
</div>
|
||||
<el-divider content-position="left">左侧商品部分</el-divider>
|
||||
<div class="flex">
|
||||
<div>图片 :</div>
|
||||
<div>
|
||||
<img class="image" :src="data.options.data.image.src" alt="" />
|
||||
<img class="image" :src="draftOptions.data.image.src" alt="" />
|
||||
<div>
|
||||
<div>推荐尺寸:{{ data.options.data.image.size }}</div>
|
||||
<div>推荐尺寸:{{ draftOptions.data.image.size }}</div>
|
||||
<div class="link-src">
|
||||
链接地址:
|
||||
<el-input
|
||||
style="width: 200px"
|
||||
v-model="data.options.data.image.url"
|
||||
v-model="draftOptions.data.image.url"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
@@ -95,7 +95,7 @@
|
||||
<el-divider content-position="left">中间商品部分</el-divider>
|
||||
<div class="flex column-list">
|
||||
<div
|
||||
v-for="(item, index) in data.options.data.list"
|
||||
v-for="(item, index) in draftOptions.data.list"
|
||||
:key="index"
|
||||
class="draggable"
|
||||
>
|
||||
@@ -129,12 +129,12 @@
|
||||
<div>右侧标题 :</div>
|
||||
<el-input
|
||||
style="width: 200px"
|
||||
v-model="data.options.data.hot.title"
|
||||
v-model="draftOptions.data.hot.title"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex column-list">
|
||||
<div
|
||||
v-for="(item, index) in data.options.data.hot.list"
|
||||
v-for="(item, index) in draftOptions.data.hot.list"
|
||||
:key="index"
|
||||
class="draggable"
|
||||
>
|
||||
@@ -154,6 +154,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 选择商品。链接 -->
|
||||
@@ -169,6 +173,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -183,13 +188,11 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
showModal: false,
|
||||
|
||||
draftOptions: null,
|
||||
picModelFlag: false,
|
||||
selectedData: "", //选中的数据
|
||||
goodsIndex: 0, // 商品索引
|
||||
align: "",
|
||||
defaultCallbackImageType: "",
|
||||
current: "",
|
||||
};
|
||||
},
|
||||
props: {
|
||||
@@ -204,6 +207,9 @@ export default {
|
||||
mounted() {
|
||||
},
|
||||
methods: {
|
||||
cloneOptions(options) {
|
||||
return JSON.parse(JSON.stringify(options || {}));
|
||||
},
|
||||
handleSelectImg(type, index) {
|
||||
this.defaultCallbackImageType = type;
|
||||
this.goodsIndex = index;
|
||||
@@ -232,45 +238,51 @@ export default {
|
||||
// 回显图片
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (!val?.url || !this.draftOptions) return;
|
||||
if (this.defaultCallbackImageType == "image") {
|
||||
this.data.options.data.image.src = val.url;
|
||||
this.draftOptions.data.image.src = val.url;
|
||||
} else {
|
||||
this.data.options.data[this.defaultCallbackImageType][
|
||||
this.draftOptions.data[this.defaultCallbackImageType][
|
||||
this.goodsIndex
|
||||
].img = val.url;
|
||||
}
|
||||
},
|
||||
// 选择商品回调
|
||||
selectedGoodsData(val) {
|
||||
this.data.options.data.hot.list[this.goodsIndex].img = val[0].thumbnail;
|
||||
this.data.options.data.hot.list[this.goodsIndex].title = val[0].goodsName;
|
||||
this.data.options.data.hot.list[this.goodsIndex].price = val[0].price;
|
||||
this.data.options.data.hot.list[this.goodsIndex].url =
|
||||
this.$filters.formatLinkType(val[0]);
|
||||
|
||||
console.log(val, this.selectedData, this.goodsIndex);
|
||||
if (!val?.length || !this.draftOptions) return;
|
||||
const item = this.draftOptions.data.hot.list[this.goodsIndex];
|
||||
item.img = val[0].thumbnail;
|
||||
item.title = val[0].goodsName;
|
||||
item.price = val[0].price;
|
||||
item.url = this.$filters.formatLinkType(val[0]);
|
||||
},
|
||||
// 选择链接回调
|
||||
selectedLink(val) {
|
||||
console.log(val,this.selectedData)
|
||||
if (!this.draftOptions) return;
|
||||
if (this.selectedData == "image") {
|
||||
this.data.options.data.image.url =
|
||||
this.$filters.formatLinkType(val);
|
||||
this.draftOptions.data.image.url = this.$filters.formatLinkType(val);
|
||||
} else {
|
||||
console.log(this.data.options.data.list,this.goodsIndex)
|
||||
this.data.options.data.list[
|
||||
this.goodsIndex
|
||||
].url = this.$filters.formatLinkType(val);
|
||||
this.draftOptions.data.list[this.goodsIndex].url =
|
||||
this.$filters.formatLinkType(val);
|
||||
}
|
||||
},
|
||||
/*
|
||||
* 点击不同模块进行编辑
|
||||
* 判断也很简单,就是第一个第二个模块进行判断
|
||||
*
|
||||
* */
|
||||
handleSelectModel() {
|
||||
this.draftOptions = this.cloneOptions(this.data.options);
|
||||
this.showModal = true;
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.draftOptions = null;
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
if (this.draftOptions) {
|
||||
const saved = this.cloneOptions(this.draftOptions);
|
||||
this.data.options.title = saved.title;
|
||||
this.data.options.data = saved.data;
|
||||
}
|
||||
this.draftOptions = null;
|
||||
this.showModal = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<div>
|
||||
<el-button
|
||||
size="small"
|
||||
@click.stop="handleSelectModel(data.options.list)"
|
||||
@click.stop="handleSelectModel"
|
||||
>编辑</el-button
|
||||
>
|
||||
</div>
|
||||
@@ -54,16 +54,16 @@
|
||||
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
<div class="modal-tab-bar">
|
||||
<div class="modal-tab-bar" v-if="draftOptions">
|
||||
<div class="tab-bar">
|
||||
标题
|
||||
<el-input style="width: 300px" v-model="data.options.title" />
|
||||
<el-input style="width: 300px" v-model="draftOptions.title" />
|
||||
</div>
|
||||
<div class="tab-bar" v-if="data.options.labels[tabCurrentlyIndex]">
|
||||
<div class="tab-bar" v-if="draftOptions.labels[tabCurrentlyIndex]">
|
||||
标签
|
||||
<el-input
|
||||
style="width: 300px"
|
||||
v-model="data.options.labels[tabCurrentlyIndex].label"
|
||||
v-model="draftOptions.labels[tabCurrentlyIndex].label"
|
||||
/>
|
||||
</div>
|
||||
<el-button @click="handleTabsAdd" size="small" class="mb_10">增加</el-button>
|
||||
@@ -73,7 +73,7 @@
|
||||
@tab-click="handleClickTab"
|
||||
>
|
||||
<el-tab-pane
|
||||
v-for="(tab,tabIndex) in data.options.labels"
|
||||
v-for="(tab,tabIndex) in draftOptions.labels"
|
||||
:key="tabIndex"
|
||||
:label="tab.label"
|
||||
:name="tab.___index + ''"
|
||||
@@ -86,7 +86,7 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="(item, index) in data.options.list.filter((subset) => {
|
||||
v-for="(item, index) in draftOptions.list.filter((subset) => {
|
||||
return subset.___index == tabCurrentlyIndex;
|
||||
})"
|
||||
:key="index"
|
||||
@@ -112,6 +112,10 @@
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 选择商品。链接 -->
|
||||
@@ -139,8 +143,7 @@ export default {
|
||||
tabIndex: 0,
|
||||
current: 0,
|
||||
showModal: false,
|
||||
selected: {}, // 已选数据
|
||||
picModelFlag: false,
|
||||
draftOptions: null,
|
||||
tabCurrentlyIndex: 0, // 选项卡索引
|
||||
};
|
||||
},
|
||||
@@ -148,89 +151,111 @@ export default {
|
||||
this.tabIndex = this.data.options.labels[0].___index
|
||||
},
|
||||
methods: {
|
||||
cloneOptions(options) {
|
||||
return JSON.parse(JSON.stringify(options || {}));
|
||||
},
|
||||
/**
|
||||
* 算出最大的index 然后索引叠加
|
||||
*/
|
||||
handleTabsAdd() {
|
||||
let findAllIndex = this.data.options.labels.map((item) => {
|
||||
return item.___index;
|
||||
});
|
||||
let max = Math.max.apply(null, findAllIndex);
|
||||
if (!this.draftOptions) return;
|
||||
const findAllIndex = this.draftOptions.labels.map((item) => item.___index);
|
||||
const max = Math.max.apply(null, findAllIndex);
|
||||
|
||||
this.data.options.labels.push({
|
||||
this.draftOptions.labels.push({
|
||||
label: "标签" + (max + 1),
|
||||
___index: max + 1,
|
||||
});
|
||||
},
|
||||
// 删除标签
|
||||
handleContextMenuDelete(item, index) {
|
||||
// 删除标签下关联的商品
|
||||
this.data.options.list.forEach((lab,currently)=>{
|
||||
if(lab.___index == item.___index){
|
||||
this.data.options.list.splice(currently,1)
|
||||
}
|
||||
})
|
||||
// 删除当前标签
|
||||
this.data.options.labels.splice(index,1)
|
||||
if (!this.draftOptions) return;
|
||||
this.draftOptions.list = this.draftOptions.list.filter(
|
||||
(lab) => lab.___index != item.___index
|
||||
);
|
||||
this.draftOptions.labels.splice(index, 1);
|
||||
},
|
||||
// 删除商品
|
||||
delGoods(val) {
|
||||
this.data.options.list.forEach((item, i) => {
|
||||
if (!this.draftOptions) return;
|
||||
this.draftOptions.list.forEach((item, i) => {
|
||||
if (
|
||||
item.title == val.title &&
|
||||
item.___index == this.tabCurrentlyIndex
|
||||
) {
|
||||
this.data.options.list.splice(i, 1);
|
||||
this.draftOptions.list.splice(i, 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
// 切换选项卡
|
||||
handleClickTab(name) {
|
||||
console.log(name)
|
||||
this.tabCurrentlyIndex = name;
|
||||
this.tabCurrentlyIndex = name.paneName ?? name;
|
||||
},
|
||||
// 添加当前选项卡中的商品
|
||||
addCurrentGoods() {
|
||||
|
||||
this.$refs.liliDialog.clearGoodsSelected();
|
||||
this.$refs.liliDialog.open("goods");
|
||||
},
|
||||
// 编辑模块
|
||||
handleSelectModel(item) {
|
||||
console.log(item);
|
||||
this.selected = item;
|
||||
handleSelectModel() {
|
||||
this.draftOptions = this.cloneOptions({
|
||||
title: this.data.options.title,
|
||||
labels: this.data.options.labels,
|
||||
list: this.data.options.list,
|
||||
});
|
||||
this.tabCurrentlyIndex = this.draftOptions.labels[0]?.___index ?? 0;
|
||||
this.tabIndex = String(this.tabCurrentlyIndex);
|
||||
this.showModal = true;
|
||||
},
|
||||
// 选择商品回调
|
||||
selectedGoodsData(val) {
|
||||
if (val.length) {
|
||||
if (!val?.length || !this.draftOptions) return;
|
||||
val.forEach((item) => {
|
||||
const pushGoodsDetail = {
|
||||
this.draftOptions.list.push({
|
||||
img: item.thumbnail,
|
||||
price: item.price,
|
||||
title: item.goodsName,
|
||||
desc: "",
|
||||
url: `/goodsDetail?skuId=${item.id}&goodsId=${item.goodsId}`,
|
||||
___index: this.tabCurrentlyIndex,
|
||||
};
|
||||
this.data.options.list.push(pushGoodsDetail);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 选择链接回调
|
||||
selectedLink(val) {
|
||||
this.selected[this.current].url =
|
||||
this.$filters.formatLinkType(val);
|
||||
this.selected[this.current].type =
|
||||
if (!this.draftOptions?.list?.length) return;
|
||||
const item = this.draftOptions.list[this.current];
|
||||
if (!item) return;
|
||||
item.url = this.$filters.formatLinkType(val);
|
||||
item.type =
|
||||
val.___type === "other" && val.url === "" ? "link" : "other";
|
||||
|
||||
console.log(this.selected[this.current]);
|
||||
},
|
||||
handleSelectLink(index) {
|
||||
// 调起选择链接弹窗
|
||||
this.$refs.liliDialog.open("link");
|
||||
this.current = index;
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.draftOptions = null;
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
if (this.draftOptions) {
|
||||
const saved = this.cloneOptions(this.draftOptions);
|
||||
this.data.options.title = saved.title;
|
||||
this.data.options.labels.splice(
|
||||
0,
|
||||
this.data.options.labels.length,
|
||||
...saved.labels
|
||||
);
|
||||
this.data.options.list.splice(
|
||||
0,
|
||||
this.data.options.list.length,
|
||||
...saved.list
|
||||
);
|
||||
}
|
||||
this.draftOptions = null;
|
||||
this.showModal = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -138,6 +138,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 选择商品。链接 -->
|
||||
@@ -153,6 +157,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -169,7 +174,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
showModal: false,
|
||||
current: "", //当前选择的模块
|
||||
current: null, // 当前编辑的模块草稿
|
||||
picModelFlag: false,
|
||||
selectedData: "", //选中的数据
|
||||
goodsIndex: 0, // 商品索引
|
||||
@@ -190,6 +195,9 @@ export default {
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
cloneModule(module) {
|
||||
return JSON.parse(JSON.stringify(module || {}));
|
||||
},
|
||||
handleSelectImg(type, index) {
|
||||
this.defaultCallbackImageType = type;
|
||||
this.goodsIndex = index;
|
||||
@@ -217,54 +225,49 @@ export default {
|
||||
// 回显图片
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (!val?.url || !this.current) return;
|
||||
if (this.defaultCallbackImageType == "default") {
|
||||
console.log(this.current.data.image);
|
||||
this.current.data.image.src = val.url;
|
||||
} else {
|
||||
console.log(this.goodsIndex, this.data.options[this.align].data.list);
|
||||
this.data.options[this.align].data.list[this.goodsIndex].img = val.url;
|
||||
|
||||
// this.data.options[this.align].data[this.selectedData][this.goodsIndex].url = val.img
|
||||
this.current.data.list[this.goodsIndex].img = val.url;
|
||||
}
|
||||
},
|
||||
// 选择商品回调
|
||||
selectedGoodsData(val) {
|
||||
console.log(val);
|
||||
this.$nextTick(() => {
|
||||
this.data.options[this.align].data.list[this.goodsIndex].img =
|
||||
val[0].thumbnail;
|
||||
this.data.options[this.align].data.list[this.goodsIndex].title =
|
||||
val[0].goodsName;
|
||||
this.data.options[this.align].data.list[this.goodsIndex].price =
|
||||
val[0].price;
|
||||
this.data.options[this.align].data.list[this.goodsIndex].url =
|
||||
val[0].url;
|
||||
});
|
||||
console.log(this.data.options[this.align].data.list[this.goodsIndex]);
|
||||
this.$forceUpdate();
|
||||
if (!val?.length || !this.current) return;
|
||||
const item = this.current.data.list[this.goodsIndex];
|
||||
item.img = val[0].thumbnail;
|
||||
item.title = val[0].goodsName;
|
||||
item.price = val[0].price;
|
||||
item.url = val[0].url;
|
||||
},
|
||||
// 选择链接回调
|
||||
selectedLink(val) {
|
||||
if (!this.current) return;
|
||||
const formattedUrl = this.$filters.formatLinkType(val);
|
||||
if (this.selectedData != "list") {
|
||||
this.data.options[this.align].data[this.selectedData].url = this.$filters.formatLinkType(val);
|
||||
console.log(this.data.options[this.align].data[this.selectedData])
|
||||
this.current.data[this.selectedData].url = formattedUrl;
|
||||
}
|
||||
if (this.selectedData == "list") {
|
||||
this.data.options[this.align].data[this.selectedData][this.goodsIndex]
|
||||
.url = this.$filters.formatLinkType(val);
|
||||
this.current.data.list[this.goodsIndex].url = formattedUrl;
|
||||
}
|
||||
},
|
||||
/*
|
||||
* 点击不同模块进行编辑
|
||||
* 判断也很简单,就是第一个第二个模块进行判断
|
||||
*
|
||||
* */
|
||||
handleSelectModel(align) {
|
||||
this.align = align;
|
||||
this.current = this.data.options[align];
|
||||
console.log(this.data.options[align]);
|
||||
this.current = this.cloneModule(this.data.options[align]);
|
||||
this.showModal = true;
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.current = null;
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
if (this.current && this.align) {
|
||||
this.data.options[this.align] = this.cloneModule(this.current);
|
||||
}
|
||||
this.current = null;
|
||||
this.showModal = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -121,13 +121,13 @@
|
||||
<el-dialog
|
||||
v-model="showModal"
|
||||
title="装修"
|
||||
|
||||
width="800"
|
||||
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="modal-top-advert">
|
||||
<div>
|
||||
<div class="modal-form-item modal-form-preview">
|
||||
<img
|
||||
class="show-image"
|
||||
width="160"
|
||||
@@ -145,13 +145,19 @@
|
||||
alt
|
||||
/>
|
||||
</div>
|
||||
<div><span>图片主标题:</span><el-input v-model="selected.name" /></div>
|
||||
<div><span>图片描述:</span><el-input v-model="selected.describe" /></div>
|
||||
<div class="tips">
|
||||
建议尺寸:<span>{{ selected.size }}</span>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">图片主标题:</span>
|
||||
<el-input v-model="selected.name" />
|
||||
</div>
|
||||
<div>
|
||||
图片链接:<el-input
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">图片描述:</span>
|
||||
<el-input v-model="selected.describe" />
|
||||
</div>
|
||||
<div class="tips">建议尺寸:{{ selected.size }}</div>
|
||||
<div class="modal-form-item modal-form-link">
|
||||
<span class="modal-label">图片链接:</span>
|
||||
<div class="modal-link-field">
|
||||
<el-input
|
||||
class="outsideUrl"
|
||||
v-model="selected.url"
|
||||
:disabled="!!selected.type && selected.type !== 'link'"
|
||||
@@ -161,49 +167,65 @@
|
||||
>选择链接</el-button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
<div class="modal-form-item modal-form-actions">
|
||||
<el-button size="small" type="primary" @click="handleSelectImg"
|
||||
>选择图片</el-button
|
||||
>
|
||||
|
||||
>
|
||||
<el-button size="small" type="primary" @click="handleSelectGoods('')"
|
||||
>选择商品</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 装修标题 -->
|
||||
<el-dialog
|
||||
v-model="showModal1"
|
||||
title="装修"
|
||||
|
||||
width="800"
|
||||
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="modal-top-advert">
|
||||
<div><span>主标题:</span><el-input v-model="selected.title" /></div>
|
||||
<div><span>副标题:</span><el-input v-model="selected.secondTitle" /></div>
|
||||
<div>
|
||||
<span
|
||||
>副标题链接:<el-input
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">主标题:</span>
|
||||
<el-input v-model="selected.title" />
|
||||
</div>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">副标题:</span>
|
||||
<el-input v-model="selected.secondTitle" />
|
||||
</div>
|
||||
<div class="modal-form-item modal-form-link">
|
||||
<span class="modal-label">副标题链接:</span>
|
||||
<div class="modal-link-field">
|
||||
<el-input
|
||||
class="outsideUrl"
|
||||
v-model="selected.url"
|
||||
:disabled="!!selected.type && selected.type !== 'link'"
|
||||
placeholder="https://" /></span
|
||||
><el-button
|
||||
size="small"
|
||||
class="ml_10"
|
||||
type="primary"
|
||||
@click="handleSelectLink"
|
||||
placeholder="https://"
|
||||
/>
|
||||
<el-button size="small" type="primary" @click="handleSelectLink"
|
||||
>选择链接</el-button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<span>背景色:</span
|
||||
><el-color-picker v-if="selected.bgColor" v-model="selected.bgColor" />
|
||||
</div>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">背景色:</span>
|
||||
<div class="modal-color-field">
|
||||
<el-input v-model="selected.bgColor" />
|
||||
<el-color-picker v-if="selected.bgColor" v-model="selected.bgColor" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal1">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal1">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 选择商品。链接 -->
|
||||
<liliDialog
|
||||
@@ -217,6 +239,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -239,15 +262,19 @@ export default {
|
||||
options: this.data.options, // 当前数据
|
||||
showModal: false, // modal显隐
|
||||
showModal1: false, // modal显隐
|
||||
selected: {}, // 已选数据
|
||||
selected: {}, // 弹窗编辑草稿
|
||||
editTarget: null, // 确认后写回的原数据
|
||||
picModelFlag: false, // 选择图片modal
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
cloneItem(item) {
|
||||
return JSON.parse(JSON.stringify(item || {}));
|
||||
},
|
||||
// 装修modal
|
||||
handleSelectModel(item, type) {
|
||||
this.selected = item;
|
||||
console.warn(item);
|
||||
this.editTarget = item;
|
||||
this.selected = this.cloneItem(item);
|
||||
if (type) {
|
||||
this.showModal1 = true;
|
||||
} else {
|
||||
@@ -259,9 +286,10 @@ export default {
|
||||
this.$refs.liliDialog.open("link");
|
||||
},
|
||||
handleSelectGoods(item) {
|
||||
// 调起选择商品
|
||||
console.warn(item);
|
||||
if (item) this.selected = item;
|
||||
if (item) {
|
||||
this.editTarget = item;
|
||||
this.selected = this.cloneItem(item);
|
||||
}
|
||||
this.$refs.liliDialog.open("goods", "single");
|
||||
setTimeout(() => {
|
||||
this.$refs.liliDialog.goodsData = [this.selected];
|
||||
@@ -269,18 +297,24 @@ export default {
|
||||
},
|
||||
// 选择链接回调
|
||||
selectedLink(val) {
|
||||
if (!this.selected) return;
|
||||
this.selected.url = this.$filters.formatLinkType(val);
|
||||
this.selected.type =
|
||||
val.___type === "other" && val.url === "" ? "link" : "other";
|
||||
},
|
||||
// 选择商品回调
|
||||
selectedGoodsData(val) {
|
||||
let goods = val[0];
|
||||
console.log(this.selected);
|
||||
if (!val?.length || !this.selected) return;
|
||||
const goods = val[0];
|
||||
this.selected.img = goods.thumbnail;
|
||||
this.selected.price = goods.price;
|
||||
this.selected.name = goods.goodsName;
|
||||
this.selected.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
|
||||
if (this.editTarget && !this.showModal && !this.showModal1) {
|
||||
Object.assign(this.editTarget, this.cloneItem(this.selected));
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
}
|
||||
},
|
||||
handleSelectImg() {
|
||||
// 选择图片
|
||||
@@ -294,8 +328,35 @@ export default {
|
||||
// 选择图片回显
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (!val?.url) return;
|
||||
this.selected.img = val.url;
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
if (this.editTarget) {
|
||||
Object.assign(this.editTarget, this.cloneItem(this.selected));
|
||||
}
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal = false;
|
||||
},
|
||||
handleCancelModal1() {
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal1 = false;
|
||||
},
|
||||
handleConfirmModal1() {
|
||||
if (this.editTarget) {
|
||||
Object.assign(this.editTarget, this.cloneItem(this.selected));
|
||||
}
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal1 = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -573,7 +634,78 @@ export default {
|
||||
}
|
||||
}
|
||||
.modal-top-advert {
|
||||
align-items: start;
|
||||
padding: 0 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
padding: 0 20px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.modal-form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.modal-label {
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-form-preview {
|
||||
justify-content: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.modal-form-link {
|
||||
align-items: flex-start;
|
||||
|
||||
.modal-label {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.modal-link-field {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
|
||||
.outsideUrl {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-form-actions {
|
||||
padding-left: 112px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.modal-color-field {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
padding-left: 112px;
|
||||
margin-bottom: 16px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
<template>
|
||||
<div class="not-enough">
|
||||
<ul class="nav-bar setup-content">
|
||||
<div class="nav-bar setup-content">
|
||||
<ul class="nav-list">
|
||||
<li v-for="(item, index) in conData.options.navList" :class="currentIndex===index?'curr':''" @click="changeCurr(index)" :key="index">
|
||||
<p>{{item.title}}</p>
|
||||
<p>{{item.desc}}</p>
|
||||
</li>
|
||||
<div class="setup-box" style="width:100px;left:1100px;">
|
||||
</ul>
|
||||
<div class="setup-box nav-setup-box">
|
||||
<div>
|
||||
<el-button size="small" @click.stop="handleSelectModel">编辑</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="content" v-if="showContent">
|
||||
<div v-for="(item, index) in conData.options.list[currentIndex]" :key="index" class="setup-content">
|
||||
<img :src="item.img" width="210" height="210" :alt="item.name">
|
||||
<p>{{item.name}}</p>
|
||||
<p>
|
||||
<span>{{ $filters.unitPrice(item.price, '¥') }}</span>
|
||||
<!-- <span>{{ $filters.unitPrice(item.price, '¥') }}</span> -->
|
||||
</p>
|
||||
<div class="setup-box">
|
||||
<div>
|
||||
@@ -29,12 +30,12 @@
|
||||
<el-dialog
|
||||
v-model="showModal"
|
||||
title="装修"
|
||||
|
||||
width="800"
|
||||
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
<div class="modal-tab-bar">
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@close="handleCancelModal">
|
||||
<div class="modal-tab-bar" v-if="draftNavList.length">
|
||||
<el-button type="primary" size='small' @click="handleAddNav">添加分类</el-button>
|
||||
<table cellspacing="0">
|
||||
<thead>
|
||||
@@ -45,7 +46,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(item, index) in conData.options.navList" :key="index">
|
||||
<tr v-for="(item, index) in draftNavList" :key="index">
|
||||
<td><el-input v-model="item.title" /></td>
|
||||
<td><el-input v-model="item.desc" /></td>
|
||||
<td v-if="index!=0">
|
||||
@@ -55,8 +56,40 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-model="showGoodsModal"
|
||||
title="装修"
|
||||
width="600"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@close="handleCancelGoodsModal">
|
||||
<div class="modal-top-advert">
|
||||
<div class="modal-form-item modal-form-preview" v-if="selected.img">
|
||||
<img class="show-image" width="210" height="210" :src="selected.img" alt />
|
||||
</div>
|
||||
<div class="modal-form-item" v-if="selected.name">
|
||||
<span class="modal-label">商品名称:</span>
|
||||
<span>{{ selected.name }}</span>
|
||||
</div>
|
||||
<div class="modal-form-item" v-if="selected.price">
|
||||
<span class="modal-label">商品价格:</span>
|
||||
<span>{{ $filters.unitPrice(selected.price, '¥') }}</span>
|
||||
</div>
|
||||
<div class="modal-form-item modal-form-actions">
|
||||
<el-button size="small" type="primary" @click="handleOpenGoodsPicker">选择商品</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelGoodsModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmGoodsModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 选择商品。链接 -->
|
||||
<liliDialog
|
||||
ref="liliDialog"
|
||||
@selectedGoodsData="selectedGoodsData"
|
||||
@@ -73,11 +106,15 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex:0, // 当前商品index
|
||||
conData:this.data, // 当前数据
|
||||
selected:{}, // 已选数据
|
||||
showModal:false, // modal显隐
|
||||
showContent:true, // 选择后刷新数据用
|
||||
currentIndex:0,
|
||||
conData:this.data,
|
||||
selected:{},
|
||||
editTarget: null,
|
||||
showModal:false,
|
||||
showGoodsModal: false,
|
||||
showContent:true,
|
||||
draftNavList: [],
|
||||
draftGoodsList: [],
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
@@ -89,41 +126,46 @@ export default {
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
// tab点击切换
|
||||
cloneList(list) {
|
||||
return JSON.parse(JSON.stringify(list || []));
|
||||
},
|
||||
cloneItem(item) {
|
||||
return JSON.parse(JSON.stringify(item || {}));
|
||||
},
|
||||
changeCurr(index){
|
||||
this.currentIndex = index;
|
||||
},
|
||||
// 编辑
|
||||
handleSelectModel (item,type) {
|
||||
this.selected = item;
|
||||
this.showModal = true
|
||||
handleSelectModel () {
|
||||
this.draftNavList = this.cloneList(this.conData.options.navList);
|
||||
this.draftGoodsList = this.cloneList(this.conData.options.list);
|
||||
this.showModal = true;
|
||||
},
|
||||
handleSelectGoods(item) { // 调起选择商品弹窗
|
||||
if(item) this.selected = item;
|
||||
this.$refs.liliDialog.open('goods', 'single')
|
||||
handleSelectGoods(item) {
|
||||
this.editTarget = item;
|
||||
this.selected = this.cloneItem(item);
|
||||
this.showGoodsModal = true;
|
||||
},
|
||||
handleOpenGoodsPicker() {
|
||||
this.$refs.liliDialog.open('goods', 'single');
|
||||
setTimeout(() => {
|
||||
this.$refs.liliDialog.goodsData = [this.selected]
|
||||
this.$refs.liliDialog.goodsData = [this.selected];
|
||||
}, 500);
|
||||
},
|
||||
// 选择商品回调
|
||||
selectedGoodsData(val){
|
||||
console.log(val)
|
||||
let goods = val[0]
|
||||
this.selected.img = goods.thumbnail
|
||||
this.selected.price = goods.price
|
||||
this.selected.name = goods.goodsName
|
||||
this.selected.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`
|
||||
if (!val?.length) return;
|
||||
const goods = val[0];
|
||||
this.selected.img = goods.thumbnail;
|
||||
this.selected.price = goods.price;
|
||||
this.selected.name = goods.goodsName;
|
||||
this.selected.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
|
||||
},
|
||||
handleDelNav(index){ // 删除导航
|
||||
this.conData.options.navList.splice(index,1)
|
||||
this.conData.options.list.splice(index,1)
|
||||
handleDelNav(index){
|
||||
this.draftNavList.splice(index,1);
|
||||
this.draftGoodsList.splice(index,1);
|
||||
},
|
||||
handleAddNav(){ // 添加导航
|
||||
this.conData.options.navList.push(
|
||||
{title:'',desc:''}
|
||||
)
|
||||
this.conData.options.list.push(
|
||||
[{ img:'', name:'', price:0, url:'' },
|
||||
handleAddNav(){
|
||||
this.draftNavList.push({ title:'', desc:'' });
|
||||
this.draftGoodsList.push([
|
||||
{ img:'', name:'', price:0, url:'' },
|
||||
{ img:'', name:'', price:0, url:'' },
|
||||
{ img:'', name:'', price:0, url:'' },
|
||||
@@ -133,27 +175,66 @@ export default {
|
||||
{ img:'', name:'', price:0, url:'' },
|
||||
{ img:'', name:'', price:0, url:'' },
|
||||
{ img:'', name:'', price:0, url:'' },
|
||||
],
|
||||
)
|
||||
this.showContent = false
|
||||
{ img:'', name:'', price:0, url:'' },
|
||||
]);
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.draftNavList = [];
|
||||
this.draftGoodsList = [];
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
this.conData.options.navList = this.cloneList(this.draftNavList);
|
||||
this.conData.options.list = this.cloneList(this.draftGoodsList);
|
||||
this.draftNavList = [];
|
||||
this.draftGoodsList = [];
|
||||
this.showContent = false;
|
||||
this.$nextTick(() => {
|
||||
this.showContent = true;
|
||||
})
|
||||
});
|
||||
this.showModal = false;
|
||||
},
|
||||
handleCancelGoodsModal() {
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showGoodsModal = false;
|
||||
},
|
||||
handleConfirmGoodsModal() {
|
||||
if (this.editTarget) {
|
||||
Object.assign(this.editTarget, this.cloneItem(this.selected));
|
||||
}
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showGoodsModal = false;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import './setup-box.scss';
|
||||
.not-enough {
|
||||
width: 100%;
|
||||
}
|
||||
.nav-bar{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
background-color: rgb(218, 217, 217);
|
||||
height: 60px;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
.nav-setup-box {
|
||||
left: auto;
|
||||
right: 0;
|
||||
width: 100px;
|
||||
}
|
||||
.nav-list {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
li{
|
||||
padding: 0 30px;
|
||||
text-align: center;
|
||||
@@ -161,11 +242,15 @@ export default {
|
||||
font-size: 16px;
|
||||
border-radius: 50px;
|
||||
padding: 0 7px;
|
||||
margin: 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
p:nth-child(2){
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
margin: 2px 0 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
&:hover{
|
||||
@@ -180,11 +265,9 @@ export default {
|
||||
li:last-of-type{
|
||||
border: none;
|
||||
}
|
||||
|
||||
.curr{
|
||||
p:nth-child(1){
|
||||
background-color: $theme_color;
|
||||
|
||||
color: #fff;
|
||||
}
|
||||
p:nth-child(2){
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div>
|
||||
<el-button
|
||||
size="small"
|
||||
@click.stop="handleSelectModel(data.options.list)"
|
||||
@click.stop="handleSelectModel"
|
||||
>编辑</el-button
|
||||
>
|
||||
</div>
|
||||
@@ -22,7 +22,7 @@
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
<div class="modal-tab-bar">
|
||||
<div v-for="(item,index) in data.options.list" :key="index">
|
||||
<div v-for="(item,index) in draftList" :key="index">
|
||||
<img :src="item.img" class="three-column-img">
|
||||
<div>推荐尺寸:{{item.size}}</div>
|
||||
<el-button
|
||||
@@ -42,6 +42,10 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 选择商品。链接 -->
|
||||
<liliDialog
|
||||
@@ -55,6 +59,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -75,37 +80,41 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
showModal:false,
|
||||
selected: {}, // 已选数据
|
||||
draftList: [],
|
||||
picModelFlag:false,
|
||||
current:0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
cloneList(list) {
|
||||
return JSON.parse(JSON.stringify(list || []));
|
||||
},
|
||||
// 回显图片
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
this.selected[this.current].img = val.url;
|
||||
console.log(this.selected)
|
||||
if (!val?.url) return;
|
||||
this.draftList[this.current].img = val.url;
|
||||
},
|
||||
// 编辑模块
|
||||
handleSelectModel(item) {
|
||||
this.selected = item;
|
||||
handleSelectModel() {
|
||||
this.draftList = this.cloneList(this.data.options.list);
|
||||
this.showModal = true;
|
||||
|
||||
},
|
||||
// 选择商品回调
|
||||
selectedGoodsData(val) {
|
||||
console.log(val);
|
||||
let goods = val[0];
|
||||
this.selected.img = goods.thumbnail;
|
||||
this.selected.price = goods.price;
|
||||
this.selected.name = goods.goodsName;
|
||||
this.selected.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
|
||||
const goods = val[0];
|
||||
if (!goods) return;
|
||||
const item = this.draftList[this.current];
|
||||
item.img = goods.thumbnail;
|
||||
item.price = goods.price;
|
||||
item.name = goods.goodsName;
|
||||
item.url = `/goodsDetail?skuId=${goods.id}&goodsId=${goods.goodsId}`;
|
||||
},
|
||||
// 选择链接回调
|
||||
selectedLink(val) {
|
||||
this.selected.url = this.$filters.formatLinkType(val);
|
||||
this.selected.type =
|
||||
const item = this.draftList[this.current];
|
||||
item.url = this.$filters.formatLinkType(val);
|
||||
item.type =
|
||||
val.___type === "other" && val.url === "" ? "link" : "other";
|
||||
},
|
||||
handleSelectLink(index) {
|
||||
@@ -122,7 +131,17 @@ export default {
|
||||
this.$refs.ossManage.selectImage = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.draftList = [];
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
const saved = this.cloneList(this.draftList);
|
||||
this.data.options.list.splice(0, this.data.options.list.length, ...saved);
|
||||
this.draftList = [];
|
||||
this.showModal = false;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<div>
|
||||
<el-button
|
||||
size="small"
|
||||
@click.stop="handleSelectModel(data.options.list)"
|
||||
@click.stop="handleSelectModel"
|
||||
>编辑</el-button
|
||||
>
|
||||
</div>
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
<div class="modal-tab-bar">
|
||||
<div class="modal-tab-bar" v-if="draftList">
|
||||
<div class="flex flex-a-c">
|
||||
<el-button class="add-goods" @click="addCurrentGoods">
|
||||
添加商品
|
||||
@@ -42,7 +42,7 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-for="(item, index) in data.options.list"
|
||||
v-for="(item, index) in draftList"
|
||||
:key="index"
|
||||
class="draggable"
|
||||
>
|
||||
@@ -65,6 +65,10 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 选择商品。链接 -->
|
||||
@@ -88,61 +92,67 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
flag:false,
|
||||
tabIndex:0,
|
||||
current: 0,
|
||||
showModal: false,
|
||||
selected: {}, // 已选数据
|
||||
picModelFlag: false,
|
||||
draftList: [],
|
||||
};
|
||||
},
|
||||
mounted(){
|
||||
|
||||
},
|
||||
methods: {
|
||||
cloneList(list) {
|
||||
return JSON.parse(JSON.stringify(list || []));
|
||||
},
|
||||
// 删除商品
|
||||
delGoods(val, i) {
|
||||
this.data.options.list.splice(i, 1);
|
||||
this.draftList.splice(i, 1);
|
||||
},
|
||||
// 添加当前选项卡中的商品
|
||||
addCurrentGoods() {
|
||||
this.$refs.liliDialog.open("goods");
|
||||
},
|
||||
// 编辑模块
|
||||
handleSelectModel(item) {
|
||||
console.log(item);
|
||||
this.selected = item;
|
||||
handleSelectModel() {
|
||||
this.draftList = this.cloneList(this.data.options.list);
|
||||
this.showModal = true;
|
||||
},
|
||||
// 选择商品回调
|
||||
selectedGoodsData(val) {
|
||||
if (val.length) {
|
||||
if (!val?.length || !this.draftList) return;
|
||||
val.forEach((item) => {
|
||||
const pushGoodsDetail = {
|
||||
this.draftList.push({
|
||||
img: item.thumbnail,
|
||||
price: item.price,
|
||||
title: item.goodsName,
|
||||
desc: "",
|
||||
url: `/goodsDetail?skuId=${item.id}&goodsId=${item.goodsId}`,
|
||||
};
|
||||
this.data.options.list.push(pushGoodsDetail);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 选择链接回调
|
||||
selectedLink(val) {
|
||||
this.selected[this.current].url =
|
||||
this.$filters.formatLinkType(val);
|
||||
this.selected[this.current].type =
|
||||
if (!this.draftList?.length) return;
|
||||
const item = this.draftList[this.current];
|
||||
item.url = this.$filters.formatLinkType(val);
|
||||
item.type =
|
||||
val.___type === "other" && val.url === "" ? "link" : "other";
|
||||
|
||||
console.log(this.selected[this.current]);
|
||||
},
|
||||
handleSelectLink(index) {
|
||||
// 调起选择链接弹窗
|
||||
this.$refs.liliDialog.open("link");
|
||||
this.current = index;
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.draftList = [];
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
const saved = this.cloneList(this.draftList);
|
||||
this.data.options.list.splice(0, this.data.options.list.length, ...saved);
|
||||
this.draftList = [];
|
||||
this.showModal = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -101,13 +101,13 @@
|
||||
<el-dialog
|
||||
v-model="showModal"
|
||||
title="装修"
|
||||
|
||||
width="800"
|
||||
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="modal-top-advert">
|
||||
<div>
|
||||
<div class="modal-form-item modal-form-preview">
|
||||
<img
|
||||
class="show-image"
|
||||
width="160"
|
||||
@@ -133,67 +133,86 @@
|
||||
alt
|
||||
/>
|
||||
</div>
|
||||
<div><span>图片主标题:</span><el-input v-model="selected.name" /></div>
|
||||
<div><span>图片描述:</span><el-input v-model="selected.describe" /></div>
|
||||
<div class="tips">
|
||||
建议尺寸:<span>{{ selected.size }}</span>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">图片主标题:</span>
|
||||
<el-input v-model="selected.name" />
|
||||
</div>
|
||||
<div>
|
||||
图片链接:<el-input
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">图片描述:</span>
|
||||
<el-input v-model="selected.describe" />
|
||||
</div>
|
||||
<div class="tips">建议尺寸:{{ selected.size }}</div>
|
||||
<div class="modal-form-item modal-form-link">
|
||||
<span class="modal-label">图片链接:</span>
|
||||
<div class="modal-link-field">
|
||||
<el-input
|
||||
class="outsideUrl"
|
||||
v-model="selected.url"
|
||||
:disabled="!!selected.type && selected.type !== 'link'"
|
||||
placeholder="https://"
|
||||
/>
|
||||
<el-button
|
||||
size="small"
|
||||
class="ml_10"
|
||||
type="primary"
|
||||
@click="handleSelectLink"
|
||||
<el-button size="small" type="primary" @click="handleSelectLink"
|
||||
>选择链接</el-button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
<div class="modal-form-item modal-form-actions">
|
||||
<el-button size="small" type="primary" @click="handleSelectImg"
|
||||
>选择图片</el-button
|
||||
>
|
||||
>
|
||||
<el-button size="small" type="primary" @click="handleSelectGoods"
|
||||
>选择商品</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-model="showModal1"
|
||||
title="装修"
|
||||
|
||||
width="800"
|
||||
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body destroy-on-close>
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="modal-top-advert">
|
||||
<div><span>主标题:</span><el-input v-model="selected.title" /></div>
|
||||
<div><span>副标题:</span><el-input v-model="selected.secondTitle" /></div>
|
||||
<div>
|
||||
<span
|
||||
>副标题链接:<el-input
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">主标题:</span>
|
||||
<el-input v-model="selected.title" />
|
||||
</div>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">副标题:</span>
|
||||
<el-input v-model="selected.secondTitle" />
|
||||
</div>
|
||||
<div class="modal-form-item modal-form-link">
|
||||
<span class="modal-label">副标题链接:</span>
|
||||
<div class="modal-link-field">
|
||||
<el-input
|
||||
class="outsideUrl"
|
||||
v-model="selected.url"
|
||||
:disabled="!!selected.type && selected.type !== 'link'"
|
||||
placeholder="https://" /></span
|
||||
><el-button
|
||||
size="small"
|
||||
class="ml_10"
|
||||
type="primary"
|
||||
@click="handleSelectLink"
|
||||
placeholder="https://"
|
||||
/>
|
||||
<el-button size="small" type="primary" @click="handleSelectLink"
|
||||
>选择链接</el-button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<span>背景色:</span><el-input v-model="selected.bgColor" />
|
||||
</div>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">背景色:</span>
|
||||
<div class="modal-color-field">
|
||||
<el-input v-model="selected.bgColor" />
|
||||
<el-color-picker v-if="selected.bgColor" v-model="selected.bgColor" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal1">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal1">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 选择商品。链接 -->
|
||||
<liliDialog
|
||||
@@ -207,6 +226,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -230,14 +250,19 @@ export default {
|
||||
msgRight: this.data.options.contentRight, // 右侧数据
|
||||
showModal: false, // modal显隐
|
||||
showModal1: false, // modal显隐
|
||||
selected: {}, // 已选数据
|
||||
selected: {}, // 弹窗编辑草稿
|
||||
editTarget: null, // 确认后写回的原数据
|
||||
picModelFlag: false, // 图片选择
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
cloneItem(item) {
|
||||
return JSON.parse(JSON.stringify(item || {}));
|
||||
},
|
||||
// 编辑
|
||||
handleSelectModel(item, type) {
|
||||
this.selected = item;
|
||||
this.editTarget = item;
|
||||
this.selected = this.cloneItem(item);
|
||||
if (type) {
|
||||
this.showModal1 = true;
|
||||
} else {
|
||||
@@ -279,8 +304,35 @@ export default {
|
||||
// 选择图片回调
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (!val?.url) return;
|
||||
this.selected.img = val.url;
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
if (this.editTarget) {
|
||||
Object.assign(this.editTarget, this.cloneItem(this.selected));
|
||||
}
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal = false;
|
||||
},
|
||||
handleCancelModal1() {
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal1 = false;
|
||||
},
|
||||
handleConfirmModal1() {
|
||||
if (this.editTarget) {
|
||||
Object.assign(this.editTarget, this.cloneItem(this.selected));
|
||||
}
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal1 = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -446,7 +498,78 @@ export default {
|
||||
}
|
||||
|
||||
.modal-top-advert {
|
||||
align-items: start;
|
||||
padding: 0 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
padding: 0 20px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.modal-form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.modal-label {
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-form-preview {
|
||||
justify-content: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.modal-form-link {
|
||||
align-items: flex-start;
|
||||
|
||||
.modal-label {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.modal-link-field {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
|
||||
.outsideUrl {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-form-actions {
|
||||
padding-left: 112px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.modal-color-field {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
padding-left: 112px;
|
||||
margin-bottom: 16px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -203,8 +203,8 @@ export default {
|
||||
}
|
||||
|
||||
.section {
|
||||
width: 1000px;
|
||||
// background: #efefef;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
.seckill-list {
|
||||
|
||||
@@ -203,8 +203,8 @@ export default {
|
||||
}
|
||||
|
||||
.section {
|
||||
width: 1000px;
|
||||
// background: #efefef;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
.seckill-list {
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
z-index: 99;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.ivu-btn{
|
||||
.ivu-btn,
|
||||
.el-button{
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
@@ -47,16 +48,3 @@
|
||||
background-color: aliceblue;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-top-advert{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
>*{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ivu-input-wrapper{
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
@@ -173,7 +173,7 @@ export default {
|
||||
overflow-y: auto;
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
margin-top: 60px;
|
||||
margin-top: 80px;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
box-shadow: 1px 1px 10px #999;
|
||||
|
||||
@@ -165,6 +165,7 @@ export default {
|
||||
}, // 图片选择器回显
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (!val?.url) return;
|
||||
this.advertising[0].img = val.url;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -156,6 +156,7 @@ export default {
|
||||
// 图片选择器回显
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (!val?.url) return;
|
||||
this.advertising[0].img = val.url;
|
||||
},
|
||||
// 点击选择图片
|
||||
|
||||
@@ -498,11 +498,23 @@
|
||||
@selectedGoodsData="selectedGoodsData"
|
||||
></liliDialog>
|
||||
|
||||
<el-dialog width="800px" title="选择分类" v-model="enableSelectCategory" append-to-body destroy-on-close>
|
||||
<el-dialog
|
||||
width="800px"
|
||||
title="选择分类"
|
||||
v-model="enableSelectCategory"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
@close="handleCancelCategoryModal"
|
||||
>
|
||||
<categoryTemplate
|
||||
v-if="enableSelectCategory"
|
||||
@selected="confirmCategory"
|
||||
@selected="onCategorySelected"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelCategoryModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmCategoryModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<hotzone ref="hotzone" @changeZone="changeZone"></hotzone>
|
||||
@@ -542,6 +554,7 @@ export default {
|
||||
selectedLinks: "", // 已选链接
|
||||
modelList: "", // 装修列表
|
||||
enableSelectCategory: false, //商品是否绑定分类
|
||||
pendingCategory: null, // 选择分类弹窗草稿
|
||||
goodsSelectedIndex: 0, //绑定商品分类的索引
|
||||
};
|
||||
},
|
||||
@@ -553,7 +566,21 @@ export default {
|
||||
},
|
||||
props: ["res"],
|
||||
methods: {
|
||||
// 选择分类
|
||||
// 选择分类(弹窗内暂存,确定后写回)
|
||||
onCategorySelected(val) {
|
||||
this.pendingCategory = val;
|
||||
},
|
||||
handleCancelCategoryModal() {
|
||||
this.pendingCategory = null;
|
||||
this.enableSelectCategory = false;
|
||||
},
|
||||
handleConfirmCategoryModal() {
|
||||
if (this.pendingCategory?.length) {
|
||||
this.confirmCategory(this.pendingCategory);
|
||||
}
|
||||
this.pendingCategory = null;
|
||||
this.enableSelectCategory = false;
|
||||
},
|
||||
confirmCategory(val) {
|
||||
let data = {
|
||||
...this.res.options.list[0].titleWay[this.goodsSelectedIndex],
|
||||
@@ -687,6 +714,7 @@ export default {
|
||||
},
|
||||
// 绑定分类
|
||||
bindGoodsCategory(index, key) {
|
||||
this.pendingCategory = null;
|
||||
this.enableSelectCategory = true;
|
||||
this.goodsSelectedIndex = index;
|
||||
},
|
||||
@@ -771,6 +799,7 @@ export default {
|
||||
// 图片选择器回显
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (!val?.url) return;
|
||||
this.selectedGoods.img = val.url;
|
||||
},
|
||||
// 点击选择图片
|
||||
|
||||
@@ -18,22 +18,39 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="获取方式" prop="getType">
|
||||
<el-select v-model="searchForm.getType" placeholder="请选择" clearable style="width: 240px">
|
||||
<el-option label="免费获取" value="FREE" />
|
||||
<el-option label="活动获取" value="ACTIVITY" />
|
||||
<el-select
|
||||
v-model="searchForm.getType"
|
||||
placeholder="请选择"
|
||||
:clearable="!isGetTypeFilterLocked"
|
||||
:disabled="isGetTypeFilterLocked"
|
||||
teleported
|
||||
popper-class="coupon-filter-popper"
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in getTypeFilterOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动状态" prop="promotionStatus">
|
||||
<el-select
|
||||
v-model="searchForm.promotionStatus"
|
||||
placeholder="请选择"
|
||||
clearable
|
||||
:clearable="!isPromotionStatusFilterLocked"
|
||||
:disabled="isPromotionStatusFilterLocked"
|
||||
teleported
|
||||
popper-class="coupon-filter-popper"
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option label="未开始" value="NEW" />
|
||||
<el-option label="已开始/上架" value="START" />
|
||||
<el-option label="已结束/下架" value="END" />
|
||||
<el-option label="紧急关闭/作废" value="CLOSE" />
|
||||
<el-option
|
||||
v-for="item in promotionStatusFilterOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间">
|
||||
@@ -41,6 +58,8 @@
|
||||
v-model="selectDate"
|
||||
type="daterange"
|
||||
clearable
|
||||
teleported
|
||||
popper-class="coupon-filter-popper"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
style="width: 240px"
|
||||
@@ -218,6 +237,8 @@ export default {
|
||||
sort: "create_time",
|
||||
order: "desc",
|
||||
getType: "",
|
||||
promotionStatus: "",
|
||||
couponName: "",
|
||||
},
|
||||
selectList: [],
|
||||
selectCount: 0,
|
||||
@@ -229,6 +250,36 @@ export default {
|
||||
isSyncingSelection: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
getTypeFilterOptions() {
|
||||
const all = [
|
||||
{ label: "免费获取", value: "FREE" },
|
||||
{ label: "活动获取", value: "ACTIVITY" },
|
||||
];
|
||||
if (this.getType) {
|
||||
return all.filter((item) => item.value === this.getType);
|
||||
}
|
||||
return all;
|
||||
},
|
||||
promotionStatusFilterOptions() {
|
||||
const all = [
|
||||
{ label: "未开始", value: "NEW" },
|
||||
{ label: "已开始/上架", value: "START" },
|
||||
{ label: "已结束/下架", value: "END" },
|
||||
{ label: "紧急关闭/作废", value: "CLOSE" },
|
||||
];
|
||||
if (this.promotionStatus) {
|
||||
return all.filter((item) => item.value === this.promotionStatus);
|
||||
}
|
||||
return all;
|
||||
},
|
||||
isGetTypeFilterLocked() {
|
||||
return !!this.getType;
|
||||
},
|
||||
isPromotionStatusFilterLocked() {
|
||||
return !!this.promotionStatus;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
$route(to) {
|
||||
if (to.fullPath == "/promotions/manager-coupon") {
|
||||
@@ -341,9 +392,11 @@ export default {
|
||||
}
|
||||
this.selectList = nextList;
|
||||
this.selectCount = nextList.length;
|
||||
this.$nextTick(() => {
|
||||
this.$nextTick(() => {
|
||||
this.isSyncingSelection = false;
|
||||
});
|
||||
});
|
||||
},
|
||||
check() {
|
||||
this.$emit("selected", this.selectList);
|
||||
@@ -398,9 +451,9 @@ export default {
|
||||
}
|
||||
getPlatformCouponList(this.searchForm)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
if (res && res.success && res.result) {
|
||||
this.data = res.result.records || [];
|
||||
this.total = res.result.total || 0;
|
||||
this.$nextTick(() => {
|
||||
if (this.selectedList.length) {
|
||||
this.syncTableSelection(this.selectedList);
|
||||
@@ -408,6 +461,7 @@ export default {
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
@@ -523,3 +577,9 @@ export default {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.coupon-filter-popper {
|
||||
z-index: 4000 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -366,28 +366,31 @@ export default {
|
||||
padding-top: 1px;
|
||||
}
|
||||
.gift-card-validity-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.gift-card-validity-group :deep(.el-radio) {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
}
|
||||
.gift-card-validity-group :deep(.el-radio:first-child) {
|
||||
margin-top: 0;
|
||||
}
|
||||
.gift-card-validity-group :deep(.el-radio) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
margin-right: 0;
|
||||
margin-bottom: 10px;
|
||||
line-height: 32px;
|
||||
min-height: 32px;
|
||||
height: auto;
|
||||
}
|
||||
.gift-card-validity-group :deep(.el-radio:last-child) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.gift-card-validity-group :deep(.el-radio__label) {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
line-height: 32px;
|
||||
}
|
||||
.gift-card-validity-input-gap {
|
||||
width: 168px;
|
||||
margin: 0 10px;
|
||||
|
||||
@@ -3,14 +3,19 @@
|
||||
<el-card>
|
||||
<el-form :model="liveForm" ref="liveForm" :rules="liveRulesForm" label-width="120px">
|
||||
<el-form-item label="直播标题" prop="name">
|
||||
<div class="form-field-block">
|
||||
<el-input disabled v-model="liveForm.name" style="width:460px"></el-input>
|
||||
<div class="tips">直播间名字,最短3个汉字,最长17个汉字,1个汉字相当于2个字符</div>
|
||||
<div class="form-tip">直播间名字,最短3个汉字,最长17个汉字,1个汉字相当于2个字符</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="主播昵称" prop="anchorName">
|
||||
<div class="form-field-block">
|
||||
<el-input disabled v-model="liveForm.anchorName" style="width:360px"></el-input>
|
||||
<div class="tips">主播昵称,最短2个汉字,最长15个汉字,1个汉字相当于2个字符</div>
|
||||
<div class="form-tip">主播昵称,最短2个汉字,最长15个汉字,1个汉字相当于2个字符</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="直播时间" prop="startTime">
|
||||
<div class="form-field-block">
|
||||
<el-date-picker
|
||||
disabled
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
@@ -22,47 +27,57 @@
|
||||
placeholder="直播计划开始时间-直播计划结束时间"
|
||||
style="width: 300px"
|
||||
/>
|
||||
<div class="tips">直播开播时间需要在当前时间的10分钟后 并且 开始时间不能在 6 个月后</div>
|
||||
<div class="form-tip">直播开播时间需要在当前时间的10分钟后 并且 开始时间不能在 6 个月后</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="主播微信号" prop="anchorWechat">
|
||||
<div class="form-field-block">
|
||||
<el-input disabled v-model="liveForm.anchorWechat" style="width:360px" placeholder="主播微信号"></el-input>
|
||||
<div class="tips">主播微信号,如果未实名认证,需要先前往“小程序直播”小程序进行<a target="_black" href="https://res.wx.qq.com/op_res/9rSix1dhHfK4rR049JL0PHJ7TpOvkuZ3mE0z7Ou_Etvjf-w1J_jVX0rZqeStLfwh">实名验证</a></div>
|
||||
<div class="form-tip">主播微信号,如果未实名认证,需要先前往“小程序直播”小程序进行<a target="_black" href="https://res.wx.qq.com/op_res/9rSix1dhHfK4rR049JL0PHJ7TpOvkuZ3mE0z7Ou_Etvjf-w1J_jVX0rZqeStLfwh">实名验证</a></div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="分享卡片封面" prop="feedsImg">
|
||||
<div class="form-field-block">
|
||||
<div class="upload-list" v-if="liveForm.feedsImg">
|
||||
<img :src="liveForm.feedsImg">
|
||||
<div class="upload-list-cover" @click="handleView(liveForm.feedsImg)">
|
||||
<span class="view-icon">查看</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips">
|
||||
<div class="form-tip">
|
||||
直播间分享图,图片规则:建议像素800*640,大小不超过1M;
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="直播间背景墙" prop="coverImg">
|
||||
<div class="form-field-block">
|
||||
<div class="upload-list" v-if="liveForm.coverImg">
|
||||
<img :src="liveForm.coverImg">
|
||||
<div class="upload-list-cover" @click="handleView(liveForm.coverImg)">
|
||||
<span class="view-icon">查看</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips"> 直播间背景图,图片规则:建议像素1080*1920,大小不超过1M</div>
|
||||
<div class="form-tip"> 直播间背景图,图片规则:建议像素1080*1920,大小不超过1M</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="直播间分享图" prop="shareImg">
|
||||
<div class="form-field-block">
|
||||
<div class="upload-list" v-if="liveForm.shareImg">
|
||||
<img :src="liveForm.shareImg">
|
||||
<div class="upload-list-cover" @click="handleView(liveForm.shareImg)">
|
||||
<span class="view-icon">查看</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips"> 直播间分享图,图片规则:建议像素800*640,大小不超过1M</div>
|
||||
<div class="form-tip"> 直播间分享图,图片规则:建议像素800*640,大小不超过1M</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品" v-if="$route.query.id">
|
||||
<div class="form-field-block">
|
||||
<el-table class="goods-table" border :data="liveData" style="width: 100%">
|
||||
<el-table-column label="商品" min-width="200">
|
||||
<template #default="{ row, $index }">
|
||||
@@ -91,9 +106,10 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="tips">
|
||||
<div class="form-tip">
|
||||
直播间商品中前两个商品将自动被选为封面,伴随直播间在直播列表中显示
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
@@ -198,13 +214,21 @@ export default {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
.tips {
|
||||
.form-field-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
.form-tip {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.goods-table {
|
||||
width: 1000px;
|
||||
margin: 10px 0;
|
||||
margin: 10px 0 0;
|
||||
}
|
||||
.upload-list {
|
||||
display: inline-block;
|
||||
|
||||
@@ -99,10 +99,10 @@ export default {
|
||||
content: "更新后店铺以及用户地区绑定数据将全部错乱",
|
||||
onOk: () => {
|
||||
this.asyncLoading = true;
|
||||
let closeCountdown = null;
|
||||
let messageInstance = null;
|
||||
const showCountdown = () => {
|
||||
if (closeCountdown) closeCountdown();
|
||||
closeCountdown = ElMessage.info({
|
||||
if (messageInstance) messageInstance.close();
|
||||
messageInstance = ElMessage.info({
|
||||
message: `地区数据将在 ${this.num} 秒后更新`,
|
||||
duration: 0,
|
||||
showClose: true,
|
||||
@@ -115,7 +115,7 @@ export default {
|
||||
}, 1000);
|
||||
setTimeout(() => {
|
||||
clearInterval(number);
|
||||
if (closeCountdown) closeCountdown();
|
||||
if (messageInstance) messageInstance.close();
|
||||
ElMessage.closeAll();
|
||||
asyncRegion().then(() => {
|
||||
this.asyncLoading = false;
|
||||
|
||||
@@ -59,13 +59,12 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="店铺logo" class="storeLogo">
|
||||
<div class="store-logo-block">
|
||||
<el-avatar
|
||||
v-if="shopForm.storeLogo"
|
||||
shape="square"
|
||||
:size="100"
|
||||
:src="shopForm.storeLogo"
|
||||
/>
|
||||
<div>
|
||||
<el-button @click="handleCLickImg('storeLogo')" type="primary"
|
||||
>选择图片</el-button
|
||||
>
|
||||
@@ -187,13 +186,12 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="营业执照电子版" prop="licencePhoto">
|
||||
<div class="store-logo-block">
|
||||
<el-avatar
|
||||
v-if="shopForm.licencePhoto"
|
||||
shape="square"
|
||||
:size="100"
|
||||
:src="shopForm.licencePhoto"
|
||||
/>
|
||||
<div>
|
||||
<el-button @click="handleCLickImg('licencePhoto')" type="primary"
|
||||
>选择图片</el-button
|
||||
>
|
||||
@@ -208,6 +206,8 @@
|
||||
<el-input v-model="shopForm.legalId" clearable style="width: 200px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="法人身份证照片" prop="legalPhoto">
|
||||
<div class="legal-photo-block">
|
||||
<div class="legal-photo-list">
|
||||
<el-avatar
|
||||
class="legal-photo"
|
||||
shape="square"
|
||||
@@ -216,13 +216,15 @@
|
||||
:src="shopForm.legalPhoto[0]"
|
||||
/>
|
||||
<el-avatar
|
||||
class="ml_10 legal-photo"
|
||||
class="legal-photo"
|
||||
shape="square"
|
||||
:size="100"
|
||||
@click="handleCLickImg('legalPhoto', 1)"
|
||||
:src="shopForm.legalPhoto[1]"
|
||||
/>
|
||||
<span>点击图片上传身份证正反面,要求身份证清晰,四角无缺漏</span>
|
||||
</div>
|
||||
<div class="form-tip">点击图片上传身份证正反面,要求身份证清晰,四角无缺漏</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider content-position="left">结算银行信息</el-divider>
|
||||
@@ -867,4 +869,26 @@ export default {
|
||||
height: 100px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.store-logo-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
.legal-photo-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
.legal-photo-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.form-tip {
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -24,12 +24,11 @@
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
:data="data"
|
||||
lazy
|
||||
:load="loadNode"
|
||||
:props="treeProps"
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
highlight-current
|
||||
default-expand-all
|
||||
:check-strictly="!strict"
|
||||
:current-node-key="currentNodeKey"
|
||||
@node-click="onNodeClick"
|
||||
@@ -109,7 +108,6 @@
|
||||
<script>
|
||||
import {
|
||||
initDepartment,
|
||||
loadDepartment,
|
||||
addDepartment,
|
||||
editDepartment,
|
||||
deleteDepartment,
|
||||
@@ -176,23 +174,20 @@ export default {
|
||||
initDepartment().then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = this.bubbleSort(res.result);
|
||||
const list = Array.isArray(res.result) ? res.result : [];
|
||||
this.data = this.bubbleSort(this.normalizeDepartmentTree(list));
|
||||
}
|
||||
});
|
||||
},
|
||||
loadNode(node, resolve) {
|
||||
const id = node.data?.id;
|
||||
if (id === undefined || id === null) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
loadDepartment(id).then((res) => {
|
||||
this.loadingEdit = false;
|
||||
if (res.success) {
|
||||
resolve(res.result || []);
|
||||
normalizeDepartmentTree(list) {
|
||||
return list.map((item) => {
|
||||
const node = { ...item };
|
||||
if (Array.isArray(node.children) && node.children.length > 0) {
|
||||
node.children = this.normalizeDepartmentTree(node.children);
|
||||
} else {
|
||||
resolve([]);
|
||||
delete node.children;
|
||||
}
|
||||
return node;
|
||||
});
|
||||
},
|
||||
onNodeClick(data) {
|
||||
@@ -235,6 +230,7 @@ export default {
|
||||
this.selectCount = checkedNodes.length;
|
||||
},
|
||||
bubbleSort(array) {
|
||||
if (!Array.isArray(array)) return [];
|
||||
const len = array.length;
|
||||
if (len < 2) return array;
|
||||
for (let i = 0; i < len; i++) {
|
||||
|
||||
@@ -77,7 +77,7 @@ export default {
|
||||
selectDate: null,
|
||||
searchForm: {
|
||||
type: 1,
|
||||
key: "",
|
||||
searchKey: "",
|
||||
operatorName: "",
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
@@ -114,15 +114,23 @@ export default {
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
if (this.selectDate && this.selectDate.length === 2) {
|
||||
this.searchForm.startDate = this.selectDate[0];
|
||||
this.searchForm.endDate = this.selectDate[1];
|
||||
}
|
||||
this.getLogList();
|
||||
},
|
||||
getLogList() {
|
||||
this.loading = true;
|
||||
getLogListData(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
if (res && res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
} else {
|
||||
this.data = [];
|
||||
this.total = 0;
|
||||
this.$Message.error((res && res.message) || "日志查询失败");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -135,8 +135,10 @@
|
||||
v-model="menuModalVisible"
|
||||
:title="modalTitle"
|
||||
width="500px"
|
||||
align-center
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
top="30px"
|
||||
class="menu-manage-dialog"
|
||||
>
|
||||
<el-form ref="formAdd" :model="formAdd" label-width="100px" :rules="formValidate">
|
||||
<div v-if="showParent">
|
||||
@@ -557,3 +559,10 @@ export default {
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.menu-manage-dialog .el-dialog__body {
|
||||
max-height: calc(100vh - 220px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -135,8 +135,10 @@
|
||||
v-model="menuModalVisible"
|
||||
:title="modalTitle"
|
||||
width="500px"
|
||||
align-center
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
top="30px"
|
||||
class="menu-manage-dialog"
|
||||
>
|
||||
<el-form ref="formAdd" :model="formAdd" label-width="100px" :rules="formValidate">
|
||||
<div v-if="showParent">
|
||||
@@ -557,3 +559,10 @@ export default {
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.menu-manage-dialog .el-dialog__body {
|
||||
max-height: calc(100vh - 220px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
484
manager/src/views/sys/message/messageTemplate.vue
Normal file
484
manager/src/views/sys/message/messageTemplate.vue
Normal file
@@ -0,0 +1,484 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<el-card>
|
||||
<div class="toolbar">
|
||||
<div class="toolbar-title">消息模板管理</div>
|
||||
<div>
|
||||
<el-button size="small" style="margin-right: 8px" @click="reloadCurrent">刷新</el-button>
|
||||
<el-button size="small" style="margin-right: 8px" :loading="syncOaLoading" @click="syncOaTemplates">
|
||||
同步服务号模板
|
||||
</el-button>
|
||||
<el-button size="small" :loading="syncMpLoading" @click="syncMpTemplates">同步小程序模板</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="会员消息模板" name="member">
|
||||
<el-alert
|
||||
type="info"
|
||||
show-icon
|
||||
:closable="false"
|
||||
style="margin-bottom: 10px"
|
||||
title="支持维护站内信、微信服务号消息、微信小程序订阅消息开关。未匹配模板的渠道会显示禁用。"
|
||||
/>
|
||||
<el-table v-loading="loading" border :data="memberRows" style="width: 100%">
|
||||
<el-table-column prop="index" label="序号" width="80" align="center" />
|
||||
<el-table-column prop="noticeNode" label="模板应用场景" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="站内信" width="110" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
:model-value="isOpen(row.noticeStatus)"
|
||||
@change="(v) => toggleNoticeChannel(v, row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="微信服务号消息" width="140" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
:model-value="isOpen(row.oaStatus)"
|
||||
:disabled="!row.oaId"
|
||||
@change="(v) => toggleOaChannel(v, row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="微信小程序订阅消息" width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
:model-value="isOpen(row.mpStatus)"
|
||||
:disabled="!row.mpId"
|
||||
@change="(v) => toggleMpChannel(v, row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="邮箱" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
:model-value="isOpen(row.emailStatus)"
|
||||
:disabled="!row.emailContent"
|
||||
@change="(v) => toggleEmailChannel(v, row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="400" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="ops">
|
||||
<a class="link-text" @click="openNoticeModal(row)">站内信</a>
|
||||
<span class="op-split">|</span>
|
||||
<a
|
||||
:class="row.oaId ? 'link-text' : 'link-disabled'"
|
||||
@click="row.oaId && openOaModal(row)"
|
||||
>
|
||||
微信服务号消息
|
||||
</a>
|
||||
<span class="op-split">|</span>
|
||||
<a
|
||||
:class="row.mpId ? 'link-text' : 'link-disabled'"
|
||||
@click="row.mpId && openMpModal(row)"
|
||||
>
|
||||
微信小程序订阅消息
|
||||
</a>
|
||||
<span class="op-split">|</span>
|
||||
<a class="link-text" @click="openEmailModal(row)">邮箱</a>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="mt_10" style="display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
v-model:current-page="searchForm.pageNumber"
|
||||
v-model:page-size="searchForm.pageSize"
|
||||
:total="total"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
size="small"
|
||||
@current-change="loadMemberPage"
|
||||
@size-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="商户消息模板" name="store">
|
||||
<el-alert type="info" :closable="false" title="商户消息模板待扩展,后续可复用会员模板能力。" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="平台消息模板" name="platform">
|
||||
<el-alert type="info" :closable="false" title="平台消息模板待扩展,后续可复用会员模板能力。" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="邮箱消息模板" name="email">
|
||||
<el-alert type="info" :closable="false" title="邮箱消息模板待扩展,后续可按场景映射邮箱模板。" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="noticeModalVisible" title="站内信模板" width="700px">
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="模板应用场景">
|
||||
<el-input :model-value="currentRow.noticeNode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="启用">
|
||||
<el-switch
|
||||
:model-value="isOpen(currentRow.noticeStatus)"
|
||||
@change="(v) => toggleNoticeChannel(v, currentRow)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容">
|
||||
<el-input :model-value="noticeDetailText" type="textarea" :autosize="{ minRows: 4, maxRows: 8 }" readonly />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="noticeModalVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="oaModalVisible" title="微信服务号消息模板" width="700px">
|
||||
<el-form label-width="140px">
|
||||
<el-form-item label="模板应用场景">
|
||||
<el-input :model-value="currentRow.noticeNode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="启用">
|
||||
<el-switch
|
||||
:model-value="isOpen(currentRow.oaStatus)"
|
||||
:disabled="!currentRow.oaId"
|
||||
@change="(v) => toggleOaChannel(v, currentRow)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板名称">
|
||||
<el-input :model-value="currentRow.oaName || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="微信模板ID">
|
||||
<el-input :model-value="currentRow.oaCode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容">
|
||||
<el-input
|
||||
:model-value="currentRow.oaContent || '-'"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4, maxRows: 8 }"
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-alert v-if="!currentRow.oaId" type="warning" :closable="false" title="当前场景未匹配到微信服务号模板。" />
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="oaModalVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="emailModalVisible" title="邮箱消息模板" width="700px">
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="模板应用场景">
|
||||
<el-input :model-value="currentRow.noticeNode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="启用">
|
||||
<el-switch
|
||||
:model-value="isOpen(currentRow.emailStatus)"
|
||||
@change="(v) => toggleEmailChannel(v, currentRow)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容">
|
||||
<el-input :model-value="emailDetailText" type="textarea" :autosize="{ minRows: 4, maxRows: 8 }" readonly />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="emailModalVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="mpModalVisible" title="微信小程序订阅消息模板" width="700px">
|
||||
<el-form label-width="150px">
|
||||
<el-form-item label="模板应用场景">
|
||||
<el-input :model-value="currentRow.noticeNode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="启用">
|
||||
<el-switch
|
||||
:model-value="isOpen(currentRow.mpStatus)"
|
||||
:disabled="!currentRow.mpId"
|
||||
@change="(v) => toggleMpChannel(v, currentRow)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板名称">
|
||||
<el-input :model-value="currentRow.mpName || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="公共模板库ID">
|
||||
<el-input :model-value="currentRow.mpTemplateId || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="订阅消息模板ID">
|
||||
<el-input :model-value="currentRow.mpCode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容">
|
||||
<el-input
|
||||
:model-value="currentRow.mpContent || '-'"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4, maxRows: 8 }"
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-alert v-if="!currentRow.mpId" type="warning" :closable="false" title="当前场景未匹配到微信小程序模板。" />
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="mpModalVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Setting from "@/api/setting.js";
|
||||
|
||||
export default {
|
||||
name: "messageTemplate",
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
activeTab: "member",
|
||||
syncOaLoading: false,
|
||||
syncMpLoading: false,
|
||||
total: 0,
|
||||
searchForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
},
|
||||
memberRows: [],
|
||||
currentRow: {},
|
||||
noticeDetailText: "",
|
||||
noticeModalVisible: false,
|
||||
oaModalVisible: false,
|
||||
mpModalVisible: false,
|
||||
emailModalVisible: false,
|
||||
emailDetailText: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
isOpen(status) {
|
||||
return String(status || "").toUpperCase() === "OPEN";
|
||||
},
|
||||
wechatEnableToOpenClose(enable) {
|
||||
if (enable === true || enable === "true" || enable === 1) return "OPEN";
|
||||
return "CLOSE";
|
||||
},
|
||||
toOpenClose(flag) {
|
||||
return flag ? "OPEN" : "CLOSE";
|
||||
},
|
||||
safeText(v) {
|
||||
return v === undefined || v === null ? "" : String(v);
|
||||
},
|
||||
pickByKeys(obj, keys) {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const val = obj ? obj[keys[i]] : "";
|
||||
if (val !== undefined && val !== null && val !== "") return val;
|
||||
}
|
||||
return "";
|
||||
},
|
||||
formatOaContent(item) {
|
||||
if (!item) return "";
|
||||
const first = this.pickByKeys(item, ["first", "title", "name"]);
|
||||
const remark = this.pickByKeys(item, ["remark", "content"]);
|
||||
const keywords = Array.isArray(item.keywords)
|
||||
? item.keywords.map((k) => this.pickByKeys(k, ["name", "value", "label"])).filter(Boolean).join(" / ")
|
||||
: this.safeText(item.keywordsText || "");
|
||||
return [first, keywords, remark].filter(Boolean).join("\n");
|
||||
},
|
||||
formatMpContent(item) {
|
||||
if (!item) return "";
|
||||
const keywordsText = this.safeText(item.keywordsText);
|
||||
if (keywordsText) return keywordsText;
|
||||
if (Array.isArray(item.keywords)) {
|
||||
return item.keywords.map((k) => this.pickByKeys(k, ["name", "value", "label"])).filter(Boolean).join(" / ");
|
||||
}
|
||||
return this.safeText(item.content);
|
||||
},
|
||||
async loadMemberPage() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const res = await API_Setting.getMessageTemplateAggregatePage(this.searchForm);
|
||||
if (!(res && res.success && res.result)) {
|
||||
this.memberRows = [];
|
||||
this.total = 0;
|
||||
this.$Message.error((res && res.message) || "加载消息模板失败");
|
||||
return;
|
||||
}
|
||||
const records = res.result.records || [];
|
||||
this.total = res.result.total || 0;
|
||||
this.memberRows = records.map((agg, idx) => {
|
||||
const item = { ...(agg.notice || {}) };
|
||||
const oa = agg.wechatOa;
|
||||
const mp = agg.wechatMp;
|
||||
return {
|
||||
...item,
|
||||
emailStatus: item.emailStatus || "CLOSE",
|
||||
emailContent: item.emailContent || "",
|
||||
index: (this.searchForm.pageNumber - 1) * this.searchForm.pageSize + idx + 1,
|
||||
oaId: oa ? oa.id : "",
|
||||
oaName: oa ? this.pickByKeys(oa, ["name", "templateName", "title"]) : "",
|
||||
oaCode: oa ? this.pickByKeys(oa, ["code", "templateId"]) : "",
|
||||
oaStatus: oa ? this.wechatEnableToOpenClose(oa.enable) : "",
|
||||
oaRaw: oa || null,
|
||||
oaContent: this.formatOaContent(oa),
|
||||
mpId: mp ? mp.id : "",
|
||||
mpName: mp ? this.pickByKeys(mp, ["name", "templateName", "title"]) : "",
|
||||
mpTemplateId: mp ? this.pickByKeys(mp, ["templateId"]) : "",
|
||||
mpCode: mp ? this.pickByKeys(mp, ["code"]) : "",
|
||||
mpStatus: mp ? this.wechatEnableToOpenClose(mp.enable) : "",
|
||||
mpRaw: mp || null,
|
||||
mpContent: this.formatMpContent(mp),
|
||||
};
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
reloadCurrent() {
|
||||
if (this.activeTab === "member") this.loadMemberPage();
|
||||
},
|
||||
async syncOaTemplates() {
|
||||
this.syncOaLoading = true;
|
||||
try {
|
||||
const res = await API_Setting.wechatMessageSync();
|
||||
if (res && res.success) {
|
||||
await this.loadMemberPage();
|
||||
this.$Message.success("服务号模板同步成功");
|
||||
} else {
|
||||
this.$Message.error((res && res.message) || "服务号模板同步失败");
|
||||
}
|
||||
} finally {
|
||||
this.syncOaLoading = false;
|
||||
}
|
||||
},
|
||||
async syncMpTemplates() {
|
||||
this.syncMpLoading = true;
|
||||
try {
|
||||
const res = await API_Setting.wechatMPMessageSync();
|
||||
if (res && res.success) {
|
||||
await this.loadMemberPage();
|
||||
this.$Message.success("小程序模板同步成功");
|
||||
} else {
|
||||
this.$Message.error((res && res.message) || "小程序模板同步失败");
|
||||
}
|
||||
} finally {
|
||||
this.syncMpLoading = false;
|
||||
}
|
||||
},
|
||||
changePageSize() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.loadMemberPage();
|
||||
},
|
||||
async openNoticeModal(row) {
|
||||
this.currentRow = { ...row };
|
||||
this.noticeDetailText = row.noticeContent || "";
|
||||
this.noticeModalVisible = true;
|
||||
const res = await API_Setting.getNoticeMessageDetail(row.id);
|
||||
if (res && res.success && res.result) {
|
||||
const d = res.result;
|
||||
this.noticeDetailText = [d.noticeTitle, d.noticeContent].filter(Boolean).join("\n");
|
||||
}
|
||||
},
|
||||
openOaModal(row) {
|
||||
this.currentRow = { ...row };
|
||||
this.oaModalVisible = true;
|
||||
},
|
||||
openMpModal(row) {
|
||||
this.currentRow = { ...row };
|
||||
this.mpModalVisible = true;
|
||||
},
|
||||
async openEmailModal(row) {
|
||||
this.currentRow = { ...row };
|
||||
const fallback = row.emailContent || row.noticeContent || "";
|
||||
this.emailDetailText = row.noticeTitle ? [row.noticeTitle, fallback].filter(Boolean).join("\n") : fallback;
|
||||
this.emailModalVisible = true;
|
||||
const res = await API_Setting.getNoticeMessageDetail(row.id);
|
||||
if (res && res.success && res.result) {
|
||||
const d = res.result;
|
||||
if (d.emailContent) {
|
||||
this.emailDetailText = d.emailContent;
|
||||
} else {
|
||||
this.emailDetailText = [d.noticeTitle, d.noticeContent].filter(Boolean).join("\n");
|
||||
}
|
||||
}
|
||||
},
|
||||
updateRowStatus(row, key, val) {
|
||||
const idx = this.memberRows.findIndex((x) => x.id === row.id);
|
||||
if (idx >= 0) this.memberRows[idx][key] = val;
|
||||
if (this.currentRow && this.currentRow.id === row.id) this.currentRow[key] = val;
|
||||
},
|
||||
async toggleNoticeChannel(v, row) {
|
||||
const old = row.noticeStatus;
|
||||
this.updateRowStatus(row, "noticeStatus", this.toOpenClose(v));
|
||||
const res = await API_Setting.updateMessageStatus(row.id, this.toOpenClose(v));
|
||||
if (!(res && res.success)) {
|
||||
this.updateRowStatus(row, "noticeStatus", old);
|
||||
this.$Message.error((res && res.message) || "站内信开关更新失败");
|
||||
} else {
|
||||
this.$Message.success("站内信开关更新成功");
|
||||
}
|
||||
},
|
||||
async toggleOaChannel(v, row) {
|
||||
if (!row.oaId) return;
|
||||
const old = row.oaStatus;
|
||||
this.updateRowStatus(row, "oaStatus", this.toOpenClose(v));
|
||||
const params = { id: row.oaId, enable: v };
|
||||
try {
|
||||
const res = await API_Setting.editWechatMessageTemplate(row.oaId, params);
|
||||
if (!(res && res.success)) {
|
||||
this.updateRowStatus(row, "oaStatus", old);
|
||||
this.$Message.error((res && res.message) || "服务号开关更新失败");
|
||||
} else {
|
||||
this.$Message.success("服务号开关更新成功");
|
||||
}
|
||||
} catch (e) {
|
||||
this.updateRowStatus(row, "oaStatus", old);
|
||||
this.$Message.error((e && e.message) || "服务号开关更新失败");
|
||||
}
|
||||
},
|
||||
async toggleMpChannel(v, row) {
|
||||
if (!row.mpId) return;
|
||||
const old = row.mpStatus;
|
||||
this.updateRowStatus(row, "mpStatus", this.toOpenClose(v));
|
||||
const params = { id: row.mpId, enable: v };
|
||||
const res = await API_Setting.editWechatMPMessageTemplate(row.mpId, params);
|
||||
if (!(res && res.success)) {
|
||||
this.updateRowStatus(row, "mpStatus", old);
|
||||
this.$Message.error((res && res.message) || "小程序开关更新失败");
|
||||
} else {
|
||||
this.$Message.success("小程序开关更新成功");
|
||||
}
|
||||
},
|
||||
async toggleEmailChannel(v, row) {
|
||||
const old = row.emailStatus || "CLOSE";
|
||||
this.updateRowStatus(row, "emailStatus", this.toOpenClose(v));
|
||||
const res = await API_Setting.updateNoticeMessageEmailStatus(row.id, this.toOpenClose(v));
|
||||
if (!(res && res.success)) {
|
||||
this.updateRowStatus(row, "emailStatus", old);
|
||||
this.$Message.error((res && res.message) || "邮箱开关更新失败");
|
||||
} else {
|
||||
this.$Message.success("邮箱开关更新成功");
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.loadMemberPage();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.toolbar-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
.ops a {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
.link-disabled {
|
||||
color: #c0c4cc;
|
||||
cursor: not-allowed;
|
||||
text-decoration: none;
|
||||
}
|
||||
.op-split {
|
||||
display: inline-block;
|
||||
margin: 0 8px;
|
||||
color: #dcdfe6;
|
||||
}
|
||||
</style>
|
||||
@@ -57,7 +57,7 @@
|
||||
<div v-if="row" class="ops">
|
||||
<a class="link-text" @click="detail(row)">详细</a>
|
||||
<span class="op-split">|</span>
|
||||
<a class="link-text" @click="delete(row.id)">删除</a>
|
||||
<a class="link-text" @click="removeMessage(row.id)">删除</a>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -207,16 +207,21 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="memberShow" label="选择会员" prop="scopeType">
|
||||
<div class="member-select-wrap">
|
||||
<el-button type="primary" plain @click="addVip">选择会员</el-button>
|
||||
<div v-if="messageSendForm.messageClient == 'member'" style="margin-top: 24px">
|
||||
<el-table border :data="selectedMember" style="width: 100%">
|
||||
<el-table-column prop="nickName" label="用户名称" min-width="120" />
|
||||
<el-table-column label="手机号" min-width="120">
|
||||
<el-table
|
||||
v-if="messageSendForm.messageClient == 'member'"
|
||||
border
|
||||
:data="selectedMember"
|
||||
class="member-select-table"
|
||||
>
|
||||
<el-table-column prop="nickName" label="用户名称" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="手机号" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ row.mobile || "暂未填写" }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="50" align="center">
|
||||
<el-table-column label="操作" width="80" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<a v-if="row" class="link-text" @click="delUser($index)">删除</a>
|
||||
</template>
|
||||
@@ -235,9 +240,14 @@
|
||||
<userList
|
||||
v-if="checkUserList"
|
||||
ref="memberLayout"
|
||||
:selectedMember="true"
|
||||
:selectedList="selectedMember"
|
||||
@callback="callbackSelectUser"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="cancelMemberSelect">取消</el-button>
|
||||
<el-button type="primary" @click="confirmMemberSelect">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
@@ -359,6 +369,7 @@ export default {
|
||||
return {
|
||||
activeTab: "MESSAGE",
|
||||
checkUserList: false,
|
||||
memberSelectSnapshot: [],
|
||||
selectedMember: [],
|
||||
loading: true,
|
||||
modalVisible: false,
|
||||
@@ -455,10 +466,17 @@ export default {
|
||||
this.loading = false;
|
||||
},
|
||||
addVip() {
|
||||
this.memberSelectSnapshot = JSON.parse(JSON.stringify(this.selectedMember));
|
||||
this.checkUserList = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.memberLayout.selectedMember = true;
|
||||
});
|
||||
},
|
||||
cancelMemberSelect() {
|
||||
this.selectedMember = JSON.parse(JSON.stringify(this.memberSelectSnapshot));
|
||||
this.reSelectMember();
|
||||
this.checkUserList = false;
|
||||
},
|
||||
confirmMemberSelect() {
|
||||
this.reSelectMember();
|
||||
this.checkUserList = false;
|
||||
},
|
||||
paneChange(v) {
|
||||
if (v == "SETTING") {
|
||||
@@ -526,7 +544,7 @@ export default {
|
||||
return shop ? shop.storeName : "";
|
||||
});
|
||||
},
|
||||
delete(id) {
|
||||
removeMessage(id) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认删除此站内信 ?",
|
||||
@@ -545,6 +563,7 @@ export default {
|
||||
this.messageModalTitle = "发送站内信";
|
||||
this.shopShow = false;
|
||||
this.memberShow = false;
|
||||
this.selectedMember = [];
|
||||
this.messageSendForm = {
|
||||
messageRange: "ALL",
|
||||
messageClient: "member",
|
||||
@@ -719,4 +738,11 @@ export default {
|
||||
margin: 0 8px;
|
||||
color: #dcdfe6;
|
||||
}
|
||||
.member-select-wrap {
|
||||
width: 100%;
|
||||
}
|
||||
.member-select-table {
|
||||
width: 100%;
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -83,15 +83,27 @@ methodItem h4 {
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
.choose-member-item {
|
||||
width: 100%;
|
||||
|
||||
.el-form-item__content {
|
||||
margin-left: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.choose-member {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-width: 580px;
|
||||
height: 400px;
|
||||
border: 1px solid #eee;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.source-member {
|
||||
width: 50%;
|
||||
flex: 3;
|
||||
min-width: 0;
|
||||
border-right: 1px solid #eee;
|
||||
padding: 10px;
|
||||
}
|
||||
@@ -116,7 +128,8 @@ methodItem h4 {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.traget-member {
|
||||
width: 50%;
|
||||
flex: 2;
|
||||
min-width: 0;
|
||||
padding: 10px;
|
||||
}
|
||||
.scroll-card {
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
<el-dialog
|
||||
v-model="sendSmsModal"
|
||||
:title="sendSmsModalTitle"
|
||||
width="900px"
|
||||
width="1100px"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
>
|
||||
@@ -234,7 +234,7 @@
|
||||
<el-radio value="2">自定义选择</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="customSms">
|
||||
<el-form-item v-if="customSms" label-width="0" class="choose-member-item">
|
||||
<div class="choose-member">
|
||||
<div class="source-member">
|
||||
<el-input
|
||||
|
||||
@@ -161,6 +161,9 @@
|
||||
box-sizing: border-box;
|
||||
margin: 0 13px 8px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.card {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
@@ -172,12 +175,19 @@
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.checkbox {
|
||||
.card-checkbox {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
z-index: 1000;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
|
||||
:deep(.el-checkbox__label) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.preview {
|
||||
width: 100%;
|
||||
@@ -226,35 +236,6 @@
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
/* Checkbox默认的样式 */
|
||||
.check-box {
|
||||
.ivu-checkbox {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
/* 覆盖iView默认的Checkbox样式 */
|
||||
.ivu-checkbox-wrapper {
|
||||
/*font-size: 16px; !* 修改字体大小 *!*/
|
||||
/*color: #495060; !* 修改文本颜色 *!*/
|
||||
/* 添加其他需要的样式 */
|
||||
}
|
||||
.ivu-checkbox-inner {
|
||||
/*width: 20px; !* 修改选框大小 *!*/
|
||||
/*height: 20px;*/
|
||||
/*border-color: #dcdee2; !* 修改边框颜色 *!*/
|
||||
/* 添加其他需要的样式 */
|
||||
}
|
||||
/* 当Checkbox被选中时的样式 */
|
||||
.ivu-checkbox-checked .ivu-checkbox-inner {
|
||||
/*background-color: #2db7f5; !* 修改选中时的背景颜色 *!*/
|
||||
}
|
||||
/* 当Checkbox不可用时的样式 */
|
||||
.ivu-checkbox-disabled .ivu-checkbox-inner {
|
||||
/*background-color: #e9e9e9; !* 修改禁用状态下的背景颜色 *!*/
|
||||
}
|
||||
|
||||
.demo-tree-render .ivu-tree-title{
|
||||
width: 94%;
|
||||
|
||||
@@ -35,6 +35,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.oss-select-footer {
|
||||
margin-top: 16px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ededed;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tab-empty {
|
||||
padding: 48px 0;
|
||||
color: #999;
|
||||
@@ -59,6 +68,10 @@
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.oss-manage-date-popper {
|
||||
z-index: 4000 !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
<template>
|
||||
<div class="search">
|
||||
@@ -86,6 +99,8 @@
|
||||
<el-date-picker
|
||||
v-model="selectDate"
|
||||
clearable
|
||||
teleported
|
||||
popper-class="oss-manage-date-popper"
|
||||
value-format="YYYY-MM-DD"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
@@ -165,12 +180,17 @@
|
||||
<el-checkbox-group v-model="selectedOss" @change="selectOssChange">
|
||||
<div class="img-box">
|
||||
<div v-for="(item, index) in data" :key="index" class="img-item">
|
||||
<el-checkbox :value="item.id + ',' + item.url" class="check-box">
|
||||
<div
|
||||
class="card"
|
||||
:class="{ 'custom-checkbox-card-checked': selectedOss.includes(item.id + ',' + item.url) }"
|
||||
@mouseenter="onMouseOver(item, index)"
|
||||
@mouseleave="onMouseOut(item, index)"
|
||||
>
|
||||
<el-checkbox
|
||||
:value="item.id + ',' + item.url"
|
||||
class="card-checkbox"
|
||||
@click.stop
|
||||
/>
|
||||
<img :src="item.url" alt="" />
|
||||
<div v-if="item.isShowPreview" class="preview">
|
||||
<div @click.prevent="download(item)">
|
||||
@@ -190,14 +210,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-checkbox>
|
||||
<div>
|
||||
<el-tooltip :content="item.name" placement="bottom">
|
||||
<div class="text">{{ item.name }}</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div class="page-box">
|
||||
@@ -210,6 +227,10 @@
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="isComponent && selectImage" class="oss-select-footer">
|
||||
<el-button @click="handleSelectCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleSelectConfirm">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -488,6 +509,10 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
maxSelect: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -954,8 +979,8 @@ export default {
|
||||
if (val) this.selectImage = val
|
||||
},
|
||||
selectedOss(val) {
|
||||
if (val && val.length) {
|
||||
this.$emit("callback", {url: val[val.length - 1].split(',')[1]});
|
||||
if (val && val.length && !(this.isComponent && this.selectImage)) {
|
||||
this.$emit("callback", { url: val[val.length - 1].split(",")[1] });
|
||||
}
|
||||
},
|
||||
// 初始化监听 是否清空所选图片
|
||||
@@ -1062,6 +1087,11 @@ export default {
|
||||
},
|
||||
// 复选框值改变时触发
|
||||
selectOssChange(e) {
|
||||
if (this.maxSelect === 1 && e.length > 1) {
|
||||
const last = e[e.length - 1];
|
||||
this.selectedOss = [last];
|
||||
e = [last];
|
||||
}
|
||||
if (e) {
|
||||
this.selectList = e.map(item => {
|
||||
return {id: item.split(',')[0]}
|
||||
@@ -1291,6 +1321,18 @@ export default {
|
||||
selectedParams(val) {
|
||||
this.$emit("callback", val);
|
||||
},
|
||||
handleSelectConfirm() {
|
||||
if (!this.selectedOss.length) {
|
||||
this.$Message.warning("请选择图片");
|
||||
return;
|
||||
}
|
||||
const last = this.selectedOss[this.selectedOss.length - 1];
|
||||
this.$emit("callback", { url: last.split(",")[1] });
|
||||
},
|
||||
handleSelectCancel() {
|
||||
this.selectedOss = [];
|
||||
this.$emit("callback", { url: "" });
|
||||
},
|
||||
// 初始化数据
|
||||
init() {
|
||||
this.accessToken = {
|
||||
|
||||
@@ -74,9 +74,10 @@
|
||||
v-model="permModalVisible"
|
||||
:title="modalTitle"
|
||||
width="500px"
|
||||
align-center
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
class="permModal"
|
||||
top="30px"
|
||||
class="permModal role-perm-dialog"
|
||||
>
|
||||
<div v-loading="treeLoading" style="position: relative; max-height: 560px; overflow: auto">
|
||||
<el-tree
|
||||
@@ -115,7 +116,14 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="selectIsSuperModel" title="选择菜单权限" width="800px">
|
||||
<el-dialog
|
||||
v-model="selectIsSuperModel"
|
||||
title="选择菜单权限"
|
||||
width="800px"
|
||||
align-center
|
||||
append-to-body
|
||||
class="role-perm-dialog"
|
||||
>
|
||||
<div class="btns">
|
||||
<el-button type="primary" class="btn-item" @click="setRole()">一键选中·数据权限</el-button>
|
||||
<el-button class="btn-item" @click="setRole('onlyView')">一键选中·查看权限</el-button>
|
||||
@@ -295,23 +303,30 @@ export default {
|
||||
addRole() {
|
||||
this.modalType = 0;
|
||||
this.modalTitle = "添加角色";
|
||||
this.$refs.roleForm?.resetFields();
|
||||
delete this.roleForm.id;
|
||||
this.roleForm = {
|
||||
name: "",
|
||||
description: "",
|
||||
};
|
||||
this.roleModalVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.roleForm?.resetFields();
|
||||
this.$refs.roleForm?.clearValidate();
|
||||
});
|
||||
},
|
||||
edit(v) {
|
||||
this.modalType = 1;
|
||||
this.modalTitle = "编辑角色";
|
||||
this.$refs.roleForm?.resetFields();
|
||||
for (let attr in v) {
|
||||
if (v[attr] == null) {
|
||||
v[attr] = "";
|
||||
}
|
||||
}
|
||||
let str = JSON.stringify(v);
|
||||
let roleInfo = JSON.parse(str);
|
||||
const roleInfo = JSON.parse(JSON.stringify(v));
|
||||
this.roleForm = roleInfo;
|
||||
this.roleModalVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.roleForm?.clearValidate();
|
||||
});
|
||||
},
|
||||
remove(v) {
|
||||
this.$Modal.confirm({
|
||||
@@ -553,3 +568,10 @@ export default {
|
||||
margin-right: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.role-perm-dialog .el-dialog__body {
|
||||
max-height: calc(100vh - 220px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,19 +7,19 @@
|
||||
<div class="form-list">
|
||||
<el-form
|
||||
ref="formValidate"
|
||||
label-width="120px"
|
||||
label-width="140px"
|
||||
label-position="right"
|
||||
:model="formValidate"
|
||||
:rules="ruleValidate"
|
||||
>
|
||||
<el-form-item label="买家PC端域名" prop="pc">
|
||||
<el-input v-model="formValidate.pc" class="w200" />
|
||||
<el-input v-model="formValidate.pc" />
|
||||
</el-form-item>
|
||||
<el-form-item label="买家WAP端域名" prop="wap">
|
||||
<el-input v-model="formValidate.wap" class="w200" />
|
||||
<el-input v-model="formValidate.wap" />
|
||||
</el-form-item>
|
||||
<el-form-item label="登录回调域名" prop="callbackUrl">
|
||||
<el-input maxlength="300" v-model="formValidate.callbackUrl" class="w200" />
|
||||
<el-input maxlength="300" v-model="formValidate.callbackUrl" />
|
||||
</el-form-item>
|
||||
<el-form-item label="操作">
|
||||
<el-button @click="setupSetting">保存设置</el-button>
|
||||
@@ -52,10 +52,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, this.formValidate).then((res) => {
|
||||
@@ -67,8 +68,8 @@ export default {
|
||||
});
|
||||
},
|
||||
init() {
|
||||
this.res = JSON.parse(this.res);
|
||||
this.formValidate = { ...this.res };
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
this.formValidate = { ...setting };
|
||||
Object.keys(this.formValidate).forEach((item) => {
|
||||
if (item.indexOf("pId") < 0) {
|
||||
this.ruleValidate[item] = [
|
||||
@@ -112,12 +113,21 @@ export default {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.row {
|
||||
width: 600px;
|
||||
width: 100%;
|
||||
max-width: 720px;
|
||||
margin-right: 10px;
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
:deep(.el-input) {
|
||||
width: 480px !important;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
width: 480px;
|
||||
}
|
||||
|
||||
.label-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -135,4 +145,8 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -44,6 +44,12 @@
|
||||
<script>
|
||||
import { setSetting } from "@/api/index";
|
||||
import { handleSubmit } from "../setting/validate";
|
||||
|
||||
const DEFAULT_QQ_CONNECT_ITEMS = [
|
||||
{ clientType: "PC", appId: "", appKey: "" },
|
||||
{ clientType: "H5", appId: "", appKey: "" },
|
||||
];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -63,10 +69,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, {
|
||||
@@ -81,17 +88,15 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
this.formValidate = JSON.parse(this.res).qqConnectSettingItemList;
|
||||
Object.keys(this.formValidate).forEach((item) => {
|
||||
this.ruleValidate[item] = [
|
||||
{
|
||||
required: true,
|
||||
message: "请填写必填项",
|
||||
trigger: "blur",
|
||||
},
|
||||
];
|
||||
});
|
||||
init() {
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
const items = setting.qqConnectSettingItemList;
|
||||
this.formValidate =
|
||||
Array.isArray(items) && items.length ? items : DEFAULT_QQ_CONNECT_ITEMS;
|
||||
this.ruleValidate = {
|
||||
appId: [{ required: true, message: "请填写必填项", trigger: "blur" }],
|
||||
appKey: [{ required: true, message: "请填写必填项", trigger: "blur" }],
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -45,6 +45,13 @@
|
||||
import { setSetting } from "@/api/index";
|
||||
import { handleSubmit } from "../setting/validate";
|
||||
|
||||
const DEFAULT_WECHAT_CONNECT_ITEMS = [
|
||||
{ clientType: "PC", appId: "", appSecret: "" },
|
||||
{ clientType: "H5", appId: "", appSecret: "" },
|
||||
{ clientType: "APP", appId: "", appSecret: "" },
|
||||
{ clientType: "WECHAT_MP", appId: "", appSecret: "" },
|
||||
];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -64,10 +71,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, {
|
||||
@@ -82,17 +90,15 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
this.formValidate = JSON.parse(this.res).wechatConnectSettingItems;
|
||||
Object.keys(this.formValidate).forEach((item) => {
|
||||
this.ruleValidate[item] = [
|
||||
{
|
||||
required: true,
|
||||
message: "请填写必填项",
|
||||
trigger: "blur",
|
||||
},
|
||||
];
|
||||
});
|
||||
init() {
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
const items = setting.wechatConnectSettingItems;
|
||||
this.formValidate =
|
||||
Array.isArray(items) && items.length ? items : DEFAULT_WECHAT_CONNECT_ITEMS;
|
||||
this.ruleValidate = {
|
||||
appId: [{ required: true, message: "请填写必填项", trigger: "blur" }],
|
||||
appSecret: [{ required: true, message: "请填写必填项", trigger: "blur" }],
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -49,10 +49,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
let that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 保存设置
|
||||
setupSetting() {
|
||||
@@ -66,9 +67,8 @@ export default {
|
||||
},
|
||||
// 实例化数据
|
||||
init() {
|
||||
this.res = JSON.parse(this.res);
|
||||
|
||||
this.formValidate = { ...this.res };
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
this.formValidate = { ...setting };
|
||||
Object.keys(this.formValidate).forEach((item) => {
|
||||
this.ruleValidate[item] = [
|
||||
{
|
||||
|
||||
@@ -41,6 +41,14 @@
|
||||
import { setSetting } from "@/api/index";
|
||||
import { handleSubmit } from "../setting/validate";
|
||||
import { getPaymentSupportForm } from "@/api/setting";
|
||||
|
||||
const DEFAULT_PAYMENT_SUPPORT_ITEMS = [
|
||||
{ client: "PC", supports: [] },
|
||||
{ client: "H5", supports: [] },
|
||||
{ client: "APP", supports: [] },
|
||||
{ client: "WECHAT_MP", supports: [] },
|
||||
];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -51,7 +59,7 @@ export default {
|
||||
WECHAT_MP: "小程序端",
|
||||
PC: "PC端",
|
||||
},
|
||||
formValidate: {},
|
||||
formValidate: [],
|
||||
payWay: {
|
||||
ALIPAY: "支付宝支付",
|
||||
WECHAT: "微信支付",
|
||||
@@ -67,10 +75,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
handleChangePayType(val) {
|
||||
this.$Modal.confirm({
|
||||
@@ -97,13 +106,17 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
this.formValidate = JSON.parse(this.res).paymentSupportItems;
|
||||
init() {
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
const items = setting.paymentSupportItems;
|
||||
this.formValidate =
|
||||
Array.isArray(items) && items.length ? items : DEFAULT_PAYMENT_SUPPORT_ITEMS;
|
||||
this.checkSupport = JSON.parse(JSON.stringify(this.formValidate));
|
||||
console.log(this.formValidate);
|
||||
|
||||
await getPaymentSupportForm().then((res) => {
|
||||
getPaymentSupportForm().then((res) => {
|
||||
if (res.success && res.result) {
|
||||
this.supportForm = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -74,10 +74,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
let that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 保存设置
|
||||
setupSetting() {
|
||||
@@ -91,9 +92,8 @@ export default {
|
||||
},
|
||||
// 实例化数据
|
||||
init() {
|
||||
this.res = JSON.parse(this.res);
|
||||
|
||||
this.formValidate = { ...this.res };
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
this.formValidate = { ...setting };
|
||||
Object.keys(this.formValidate).forEach((item) => {
|
||||
if (item.indexOf("pId") < 0) {
|
||||
this.ruleValidate[item] = [
|
||||
|
||||
@@ -96,7 +96,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
handleSubmit,
|
||||
picModelFlag: false,
|
||||
formValidate: {
|
||||
buyerSideLogo: "",
|
||||
@@ -126,10 +125,11 @@ export default {
|
||||
});
|
||||
},
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
|
||||
@@ -50,18 +50,20 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="label-btns">
|
||||
<el-button type="primary" @click="submit('formValidate')">保存</el-button>
|
||||
<div class="es-buttons">
|
||||
<div class="label-btns goods-setting-btns">
|
||||
<div class="goods-setting-action-row">
|
||||
<el-button type="success" @click="createIndex()">重新生成所有商品索引</el-button>
|
||||
<el-button type="info" @click="deleteDownGoods()">删除ES中下架的商品</el-button>
|
||||
<el-button type="warning" @click="generateCache()">生成所有商品的缓存</el-button>
|
||||
<el-button type="danger" @click="deleteNotExistIndex()">删除不存在的索引</el-button>
|
||||
</div>
|
||||
<div class="progress-item" v-if="showProgress">
|
||||
<el-progress :percentage="progressVal" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="goods-setting-save-row">
|
||||
<el-button type="primary" @click="submit('formValidate')">保存</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
@@ -207,7 +209,27 @@ export default {
|
||||
.label-item {
|
||||
display: flex;
|
||||
}
|
||||
.goods-setting-btns {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
margin-left: 150px;
|
||||
}
|
||||
.goods-setting-action-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.goods-setting-action-row .progress-item {
|
||||
flex: 0 0 240px;
|
||||
min-width: 200px;
|
||||
}
|
||||
.goods-setting-action-row .progress-item :deep(.el-progress) {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.el-input){
|
||||
width: 100px !important;
|
||||
width: 180px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -33,10 +33,11 @@ export default {
|
||||
methods: {
|
||||
// 保存
|
||||
submit(name) {
|
||||
let that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting()
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 保存设置
|
||||
setupSetting() {
|
||||
|
||||
@@ -71,10 +71,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, this.formValidate).then((res) => {
|
||||
|
||||
@@ -63,10 +63,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, this.formValidate).then((res) => {
|
||||
@@ -115,12 +116,12 @@ export default {
|
||||
}
|
||||
|
||||
.el-input {
|
||||
width: 100px;
|
||||
width: 180px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
:deep(.el-input){
|
||||
width: 100px !important;
|
||||
width: 180px !important;
|
||||
}
|
||||
|
||||
.desc {
|
||||
|
||||
@@ -120,10 +120,11 @@ export default {
|
||||
methods: {
|
||||
// 保存
|
||||
submit(name) {
|
||||
let that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting()
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 保存设置
|
||||
setupSetting() {
|
||||
|
||||
@@ -69,10 +69,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, this.formValidate).then((res) => {
|
||||
@@ -140,27 +141,27 @@ export default {
|
||||
display: flex;
|
||||
|
||||
> .el-input-number {
|
||||
width: 100px;
|
||||
width: 120px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
> .el-input-number:nth-last-of-type(1) {
|
||||
width: 150px;
|
||||
width: 180px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
> .el-input {
|
||||
width: 100px;
|
||||
width: 180px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-input){
|
||||
width: 70px !important;
|
||||
width: 180px !important;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
width: 70px;
|
||||
width: 180px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,10 +115,11 @@ export default {
|
||||
methods: {
|
||||
// 保存
|
||||
submit(name) {
|
||||
let that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting()
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 保存设置
|
||||
setupSetting() {
|
||||
|
||||
@@ -44,10 +44,11 @@ export default {
|
||||
props: ["res", "type"],
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, this.formValidate).then((res) => {
|
||||
|
||||
@@ -1,23 +1,28 @@
|
||||
//表单中必填
|
||||
export function validateRequired(rule, value, callback) {
|
||||
if (value != void 0 || value != null) {
|
||||
if (value !== undefined && value !== null && value !== "") {
|
||||
callback();
|
||||
} else {
|
||||
return callback(new Error("必填项不能为空"));
|
||||
callback(new Error("必填项不能为空"));
|
||||
}
|
||||
}
|
||||
|
||||
// 验证必填项
|
||||
// 验证必填项(Element Plus 表单校验为异步,返回 Promise)
|
||||
export function handleSubmit(that, name) {
|
||||
let flag = false;
|
||||
that.$refs[name].validate(valid => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const form = that.$refs[name];
|
||||
if (!form) {
|
||||
that.$Message.error("表单未就绪,请稍后重试");
|
||||
reject(new Error("form ref missing"));
|
||||
return;
|
||||
}
|
||||
form.validate((valid) => {
|
||||
if (valid) {
|
||||
flag = true;
|
||||
return flag;
|
||||
resolve(true);
|
||||
} else {
|
||||
that.$Message.error("请正确填写内容!");
|
||||
return flag;
|
||||
reject(new Error("validation failed"));
|
||||
}
|
||||
});
|
||||
return flag
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
:name="tabItem.type"
|
||||
>
|
||||
<component
|
||||
v-if="settingData"
|
||||
v-if="settingData && selected === tabItem.type"
|
||||
:is="templateSetting[tabItem.type]"
|
||||
:res="settingData"
|
||||
:type="selected"
|
||||
:type="tabItem.type"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@@ -130,6 +130,8 @@ export default {
|
||||
getSetting(name).then((res) => {
|
||||
if (res.result) {
|
||||
this.settingData = JSON.stringify(res.result);
|
||||
} else {
|
||||
this.settingData = "{}";
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -94,9 +94,11 @@
|
||||
v-model="userModalVisible"
|
||||
:title="modalTitle"
|
||||
width="500px"
|
||||
align-center
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
top="30px"
|
||||
destroy-on-close
|
||||
class="user-manage-dialog"
|
||||
>
|
||||
<el-form ref="form" :model="form" label-width="70px" :rules="formValidate">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
@@ -106,7 +108,7 @@
|
||||
<el-input v-model="form.nickName" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="modalType == 0" label="密码" prop="password" :error="errorPass">
|
||||
<el-input v-model="form.password" type="password" show-password autocomplete="off" />
|
||||
<el-input v-model="form.password" type="password" show-password autocomplete="new-password" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" />
|
||||
@@ -326,7 +328,6 @@ export default {
|
||||
add() {
|
||||
this.modalType = 0;
|
||||
this.modalTitle = "添加用户";
|
||||
this.$refs.form?.resetFields();
|
||||
this.form = {
|
||||
username: "",
|
||||
mobile: "",
|
||||
@@ -336,20 +337,23 @@ export default {
|
||||
departmentId: 0,
|
||||
departmentTitle: "",
|
||||
};
|
||||
this.$refs.depTree.setData("", "");
|
||||
this.userModalVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form?.resetFields();
|
||||
this.$refs.depTree?.setData("", "");
|
||||
});
|
||||
},
|
||||
edit(v) {
|
||||
this.form = JSON.parse(JSON.stringify(v));
|
||||
this.modalType = 1;
|
||||
this.modalTitle = "编辑用户";
|
||||
this.$refs.form?.resetFields();
|
||||
for (let attr in this.form) {
|
||||
if (this.form[attr] == null) {
|
||||
this.form[attr] = "";
|
||||
}
|
||||
}
|
||||
this.$refs.depTree.setData(this.form.departmentId, this.form.departmentTitle);
|
||||
const departmentId = this.form.departmentId;
|
||||
const departmentTitle = this.form.departmentTitle;
|
||||
let selectRolesId = [];
|
||||
if (this.form.roles) {
|
||||
this.form.roles.forEach(function (e) {
|
||||
@@ -358,6 +362,10 @@ export default {
|
||||
}
|
||||
this.form.roles = selectRolesId;
|
||||
this.userModalVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form?.resetFields();
|
||||
this.$refs.depTree?.setData(departmentId, departmentTitle);
|
||||
});
|
||||
},
|
||||
enable(v) {
|
||||
let params = { status: true };
|
||||
@@ -462,3 +470,36 @@ export default {
|
||||
color: #dcdee2;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.user-manage-dialog {
|
||||
.el-dialog__body {
|
||||
max-height: calc(100vh - 220px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.el-input__wrapper {
|
||||
background-color: #fff !important;
|
||||
box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
|
||||
|
||||
&.is-focus {
|
||||
box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-input__inner {
|
||||
background-color: transparent !important;
|
||||
|
||||
&:-webkit-autofill,
|
||||
&:-webkit-autofill:hover,
|
||||
&:-webkit-autofill:focus,
|
||||
&:-webkit-autofill:active {
|
||||
-webkit-box-shadow: 0 0 0 1000px #fff inset !important;
|
||||
box-shadow: 0 0 0 1000px #fff inset !important;
|
||||
-webkit-text-fill-color: #606266 !important;
|
||||
caret-color: #606266;
|
||||
transition: background-color 99999s ease-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
.width_1200 {
|
||||
width: 1200px;
|
||||
}
|
||||
.width_1200_auto {
|
||||
width: 1200px;
|
||||
max-width: 1200px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.width_800 {
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/* Element Plus 主题覆盖(对齐原 iView 主色) */
|
||||
:root {
|
||||
--el-color-primary: #f31947;
|
||||
--el-color-success: #67c23a;
|
||||
--el-color-warning: #fa6419;
|
||||
--el-color-danger: #ff3c2a;
|
||||
// --el-color-primary: #f31947;
|
||||
// --el-color-success: #67c23a;
|
||||
// --el-color-warning: #fa6419;
|
||||
// --el-color-danger: #ff3c2a;
|
||||
--el-font-size-extra-small: 12px;
|
||||
--el-font-size-small: 13px;
|
||||
--el-font-size-base: 14px;
|
||||
--el-font-size-large: 16px;
|
||||
}
|
||||
|
||||
.el-button--primary {
|
||||
--el-button-bg-color: #f31947;
|
||||
--el-button-border-color: #f31947;
|
||||
--el-button-hover-bg-color: #ff4d6d;
|
||||
--el-button-hover-border-color: #ff4d6d;
|
||||
}
|
||||
// .el-button--primary {
|
||||
// --el-button-bg-color: #f31947;
|
||||
// --el-button-border-color: #f31947;
|
||||
// --el-button-hover-bg-color: #ff4d6d;
|
||||
// --el-button-hover-border-color: #ff4d6d;
|
||||
// }
|
||||
|
||||
.el-table--border {
|
||||
.el-table__cell {
|
||||
|
||||
@@ -120,9 +120,14 @@ export default {
|
||||
this.dateList.forEach((res) => {
|
||||
res.selected = false;
|
||||
});
|
||||
this.selectedWay.year = this.month.split("-")[0];
|
||||
this.selectedWay.month = this.month.split("-")[1];
|
||||
this.selectedWay.searchType = "";
|
||||
const parts = String(this.month).split("-");
|
||||
this.selectedWay = {
|
||||
...this.selectedWay,
|
||||
year: parts[0],
|
||||
month: parts[1],
|
||||
searchType: "",
|
||||
storeId: this.storeId,
|
||||
};
|
||||
this.$emit("selected", this.selectedWay);
|
||||
} else {
|
||||
const current =
|
||||
@@ -145,8 +150,8 @@ export default {
|
||||
item.storeId = this.storeId;
|
||||
this.month = "";
|
||||
if (item.searchType === "") {
|
||||
const currentDate = this.originDateList[currentIndex].searchType;
|
||||
item.searchType = currentDate || "LAST_SEVEN";
|
||||
const origin = this.originDateList[currentIndex];
|
||||
item.searchType = (origin && origin.searchType) || "LAST_SEVEN";
|
||||
}
|
||||
this.selectedWay = item;
|
||||
this.selectedWay.year = new Date().getFullYear();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
v-model="category"
|
||||
:options="skuList"
|
||||
placeholder="请选择商品分类"
|
||||
popper-class="goods-dialog-cascader-popper"
|
||||
style="width: 250px"
|
||||
clearable
|
||||
/>
|
||||
@@ -265,3 +266,8 @@ export default {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.goods-dialog-cascader-popper {
|
||||
z-index: 10001 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -372,7 +372,7 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="partDeliveryModal" title="分包裹发货" width="760px">
|
||||
<el-dialog v-model="partDeliveryModal" title="分包裹发货" width="1200px">
|
||||
<el-form ref="partDeliveryForm" :model="partDeliveryForm" label-width="100px" :rules="partDeliveryRules">
|
||||
<el-form-item label="物流公司" prop="logisticsId">
|
||||
<el-select v-model="partDeliveryForm.logisticsId" placeholder="请选择物流公司" filterable style="width: 260px">
|
||||
@@ -387,29 +387,65 @@
|
||||
<el-form-item label="物流单号" prop="logisticsNo">
|
||||
<el-input v-model="partDeliveryForm.logisticsNo" placeholder="请输入物流单号" style="width: 260px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="发货商品" prop="partDeliveryDTOList">
|
||||
<div class="delivery-item-group">
|
||||
<div v-for="item in deliverableOrderItems" :key="getOrderItemId(item)" class="delivery-item">
|
||||
<el-checkbox
|
||||
:model-value="isPartDeliveryItemSelected(item)"
|
||||
@change="(checked) => togglePartDeliveryItem(item, checked)"
|
||||
<el-form-item label-width="0" prop="partDeliveryDTOList" class="part-delivery-goods-item">
|
||||
<div v-if="deliverableOrderItems.length" class="part-delivery-table-wrap">
|
||||
<el-table
|
||||
ref="partDeliveryTable"
|
||||
border
|
||||
:data="deliverableOrderItems"
|
||||
style="width: 100%"
|
||||
@selection-change="handlePartDeliverySelectionChange"
|
||||
>
|
||||
<span class="delivery-item-name">{{ item.goodsName }}</span>
|
||||
<span class="delivery-item-num">订单数量 x{{ item.num }}</span>
|
||||
</el-checkbox>
|
||||
<el-table-column type="selection" width="55" :selectable="isPartDeliveryRowSelectable" />
|
||||
<el-table-column label="商品" min-width="420">
|
||||
<template #default="{ row }">
|
||||
<div class="part-delivery-goods">
|
||||
<img :src="row.image" class="part-delivery-goods-img" alt="" />
|
||||
<div class="part-delivery-goods-info">
|
||||
<div class="part-delivery-goods-name">{{ row.goodsName }}</div>
|
||||
<div
|
||||
v-for="(specValue, specKey) in parseOrderItemSpecs(row.specs)"
|
||||
:key="specKey"
|
||||
class="part-delivery-goods-spec"
|
||||
>
|
||||
<span v-if="specKey !== 'images'">{{ specKey }}:{{ specValue }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单价" min-width="110" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ $filters.unitPrice(row.unitPrice || 0, "¥") }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" min-width="140" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
v-model="partDeliveryForm.deliveryNumMap[getOrderItemId(item)]"
|
||||
:disabled="!isPartDeliveryItemSelected(item)"
|
||||
v-model="partDeliveryForm.deliveryNumMap[getOrderItemId(row)]"
|
||||
:min="1"
|
||||
:max="getMaxDeliveryNum(item)"
|
||||
:max="getRemainingDeliveryNum(row)"
|
||||
:precision="0"
|
||||
controls-position="right"
|
||||
size="small"
|
||||
class="delivery-num-input"
|
||||
size="default"
|
||||
class="part-delivery-num-input"
|
||||
@change="(val) => handlePartDeliveryNumChange(row, val)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="已发包裹" min-width="110" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ getShippedPackageNum(row) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="小计" min-width="110" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ $filters.unitPrice(getPartDeliverySubtotal(row), "¥") }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!deliverableOrderItems.length" class="delivery-empty">暂无可发货商品</div>
|
||||
<div v-else class="delivery-empty">暂无可发货商品</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div v-if="orderPackages.length" class="package-list">
|
||||
@@ -637,7 +673,10 @@ export default {
|
||||
);
|
||||
},
|
||||
deliverableOrderItems() {
|
||||
return (this.data || []).filter((item) => this.getOrderItemId(item));
|
||||
return (this.data || []).filter((item) => {
|
||||
if (!this.getOrderItemId(item)) return false;
|
||||
return this.getRemainingDeliveryNum(item) > 0;
|
||||
});
|
||||
},
|
||||
canOrderTake() {
|
||||
if (this.allowOperation.take) return true;
|
||||
@@ -679,29 +718,133 @@ export default {
|
||||
getLogisticsName(item) {
|
||||
return item && (item.logisticsName || item.name || item.logisticsCompany || item.logisticsId || item.id);
|
||||
},
|
||||
getMaxDeliveryNum(item) {
|
||||
const num = Number(item && item.num);
|
||||
return Number.isFinite(num) && num > 0 ? num : 999999;
|
||||
parseOrderItemSpecs(specs) {
|
||||
if (!specs) return {};
|
||||
try {
|
||||
return JSON.parse(specs);
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
getShippedPackageNum(item) {
|
||||
if (item != null && item.deliverNumber != null && item.deliverNumber !== "") {
|
||||
const direct = Number(item.deliverNumber);
|
||||
if (Number.isFinite(direct)) return direct;
|
||||
}
|
||||
const orderItemId = this.getOrderItemId(item);
|
||||
if (!orderItemId || !this.orderPackages.length) return 0;
|
||||
let total = 0;
|
||||
this.orderPackages.forEach((pkg) => {
|
||||
(pkg.orderPackageItemList || []).forEach((pkgItem) => {
|
||||
if (this.isPackageItemMatch(item, pkgItem)) {
|
||||
total += Number(pkgItem.deliverNumber ?? pkgItem.num ?? 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
return total;
|
||||
},
|
||||
isPackageItemMatch(orderItem, pkgItem) {
|
||||
const orderKeys = [
|
||||
this.getOrderItemId(orderItem),
|
||||
orderItem?.sn,
|
||||
orderItem?.id,
|
||||
orderItem?.orderItemId,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.map(String);
|
||||
const pkgKeys = [
|
||||
pkgItem.orderItemSn,
|
||||
pkgItem.orderItemId,
|
||||
pkgItem.orderItemsId,
|
||||
pkgItem.id,
|
||||
pkgItem.sn,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.map(String);
|
||||
return pkgKeys.some((key) => orderKeys.includes(key));
|
||||
},
|
||||
getRemainingDeliveryNum(item) {
|
||||
const total = Number(item && item.num) || 0;
|
||||
return Math.max(total - this.getShippedPackageNum(item), 0);
|
||||
},
|
||||
getPartDeliverySubtotal(row) {
|
||||
const id = this.getOrderItemId(row);
|
||||
const qty = Number(this.partDeliveryForm.deliveryNumMap[id]) || 0;
|
||||
const unitPrice = Number(row.unitPrice) || 0;
|
||||
return unitPrice * qty;
|
||||
},
|
||||
initPartDeliveryNumMap() {
|
||||
const map = {};
|
||||
this.deliverableOrderItems.forEach((item) => {
|
||||
const id = this.getOrderItemId(item);
|
||||
if (id) {
|
||||
map[id] = this.getRemainingDeliveryNum(item);
|
||||
}
|
||||
});
|
||||
this.partDeliveryForm.deliveryNumMap = map;
|
||||
},
|
||||
refreshPartDeliveryAfterSubmit() {
|
||||
this.loading = true;
|
||||
return Promise.all([
|
||||
API_Order.getOrderDetail(this.sn).then((res) => {
|
||||
if (res.success) {
|
||||
this.orderInfo = res.result;
|
||||
this.allowOperation = res.result.allowOperationVO;
|
||||
this.data = res.result.orderItems;
|
||||
this.typeList = JSON.parse(
|
||||
JSON.stringify(res.result.order.priceDetailDTO.discountPriceDetail)
|
||||
);
|
||||
this.getContentPrice();
|
||||
this.getOrderPrice();
|
||||
}
|
||||
}),
|
||||
this.getOrderPackages(),
|
||||
]).finally(() => {
|
||||
this.loading = false;
|
||||
this.partDeliveryForm.logisticsNo = "";
|
||||
this.partDeliveryForm.logisticsId = "";
|
||||
this.partDeliveryForm.selectedOrderItemIds = [];
|
||||
this.initPartDeliveryNumMap();
|
||||
this.$nextTick(() => {
|
||||
this.$refs.partDeliveryTable?.clearSelection();
|
||||
this.$refs.partDeliveryForm?.clearValidate();
|
||||
});
|
||||
});
|
||||
},
|
||||
handlePartDeliveryNumChange(row, value) {
|
||||
const id = this.getOrderItemId(row);
|
||||
if (!id) return;
|
||||
const num = Number(value);
|
||||
if (!Number.isFinite(num) || num < 1) return;
|
||||
if (!this.partDeliveryForm.selectedOrderItemIds.includes(id)) {
|
||||
this.partDeliveryForm.selectedOrderItemIds = [
|
||||
...this.partDeliveryForm.selectedOrderItemIds,
|
||||
id,
|
||||
];
|
||||
this.$nextTick(() => {
|
||||
this.$refs.partDeliveryTable?.toggleRowSelection(row, true);
|
||||
});
|
||||
}
|
||||
},
|
||||
isPartDeliveryRowSelectable(row) {
|
||||
return this.getRemainingDeliveryNum(row) > 0;
|
||||
},
|
||||
handlePartDeliverySelectionChange(selection) {
|
||||
const selectedIds = [];
|
||||
selection.forEach((item) => {
|
||||
const id = this.getOrderItemId(item);
|
||||
if (!id) return;
|
||||
selectedIds.push(id);
|
||||
if (this.partDeliveryForm.deliveryNumMap[id] == null) {
|
||||
this.partDeliveryForm.deliveryNumMap[id] = this.getRemainingDeliveryNum(item);
|
||||
}
|
||||
});
|
||||
this.partDeliveryForm.selectedOrderItemIds = selectedIds;
|
||||
},
|
||||
isPartDeliveryItemSelected(item) {
|
||||
const id = this.getOrderItemId(item);
|
||||
return !!id && this.partDeliveryForm.selectedOrderItemIds.includes(id);
|
||||
},
|
||||
togglePartDeliveryItem(item, checked) {
|
||||
const id = this.getOrderItemId(item);
|
||||
if (!id) return;
|
||||
if (checked) {
|
||||
if (!this.partDeliveryForm.selectedOrderItemIds.includes(id)) {
|
||||
this.partDeliveryForm.selectedOrderItemIds.push(id);
|
||||
}
|
||||
if (!this.partDeliveryForm.deliveryNumMap[id]) {
|
||||
this.partDeliveryForm.deliveryNumMap[id] = this.getMaxDeliveryNum(item);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.partDeliveryForm.selectedOrderItemIds = this.partDeliveryForm.selectedOrderItemIds.filter((itemId) => itemId !== id);
|
||||
delete this.partDeliveryForm.deliveryNumMap[id];
|
||||
},
|
||||
buildPartDeliveryDTOList() {
|
||||
return this.partDeliveryForm.selectedOrderItemIds
|
||||
.map((orderItemId) => ({
|
||||
@@ -721,6 +864,9 @@ export default {
|
||||
if (this.$refs.partDeliveryForm) {
|
||||
this.$refs.partDeliveryForm.clearValidate();
|
||||
}
|
||||
if (this.$refs.partDeliveryTable) {
|
||||
this.$refs.partDeliveryTable.clearSelection();
|
||||
}
|
||||
});
|
||||
},
|
||||
openPartDelivery() {
|
||||
@@ -737,10 +883,11 @@ export default {
|
||||
});
|
||||
},
|
||||
getOrderPackages() {
|
||||
API_Order.getPackage(this.sn).then((res) => {
|
||||
return API_Order.getPackage(this.sn).then((res) => {
|
||||
if (res.success) {
|
||||
this.orderPackages = Array.isArray(res.result) ? res.result : [];
|
||||
}
|
||||
this.initPartDeliveryNumMap();
|
||||
});
|
||||
},
|
||||
submitPartDelivery() {
|
||||
@@ -761,8 +908,7 @@ export default {
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("发货成功");
|
||||
this.partDeliveryModal = false;
|
||||
this.getDataList();
|
||||
this.refreshPartDeliveryAfterSubmit();
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
@@ -965,43 +1111,70 @@ export default {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.delivery-item-group {
|
||||
width: 100%;
|
||||
.delivery-empty {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.delivery-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.part-delivery-goods-item :deep(.el-form-item__content) {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.part-delivery-table-wrap {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin: 0 0 8px 0;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #dcdfe6;
|
||||
min-height: 360px;
|
||||
max-height: 520px;
|
||||
overflow: auto;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
|
||||
:deep(.el-table__cell) {
|
||||
padding: 18px 0;
|
||||
}
|
||||
|
||||
:deep(.el-table__header .el-table__cell) {
|
||||
padding: 14px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
:deep(.el-table__body .el-table__cell) {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.part-delivery-goods {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 8px 0;
|
||||
min-height: 88px;
|
||||
}
|
||||
|
||||
.part-delivery-goods-img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
flex-shrink: 0;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.delivery-item-name {
|
||||
display: inline-block;
|
||||
max-width: 420px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
.part-delivery-goods-info {
|
||||
margin-left: 16px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.delivery-item-num {
|
||||
margin-left: 12px;
|
||||
.part-delivery-goods-name {
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.part-delivery-goods-spec {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.delivery-num-input {
|
||||
width: 120px;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.delivery-empty {
|
||||
color: #999;
|
||||
.part-delivery-num-input {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.package-list {
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="店铺承担比例" prop="storeCommission">
|
||||
<div class="form-field-block">
|
||||
<el-input
|
||||
:disabled="disabled"
|
||||
v-model="form.storeCommission"
|
||||
@@ -71,22 +72,26 @@
|
||||
>
|
||||
<template #append>%</template>
|
||||
</el-input>
|
||||
<span class="describe">店铺承担比例,输入0-100之间数值</span>
|
||||
<div class="form-tip">店铺承担比例,输入0-100之间数值</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="发放数量" prop="publishNum" v-if="form.getType === 'FREE'">
|
||||
<div class="form-field-block">
|
||||
<el-input
|
||||
:disabled="disabled"
|
||||
v-model="form.publishNum"
|
||||
placeholder="发放数量"
|
||||
style="width: 260px"
|
||||
/>
|
||||
<div class="tips">如果发放数量为0时,则代表不限制发放数量</div>
|
||||
<div class="form-tip">如果发放数量为0时,则代表不限制发放数量</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="领取数量限制"
|
||||
prop="couponLimitNum"
|
||||
v-if="form.getType === 'FREE'"
|
||||
>
|
||||
<div class="form-field-block">
|
||||
<el-input
|
||||
:disabled="disabled"
|
||||
v-model="form.couponLimitNum"
|
||||
@@ -94,7 +99,8 @@
|
||||
clearable
|
||||
style="width: 260px"
|
||||
/>
|
||||
<div class="tips">如果领取数量为0时,则代表不限制领取数量</div>
|
||||
<div class="form-tip">如果领取数量为0时,则代表不限制领取数量</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="范围描述" prop="description">
|
||||
<el-input
|
||||
@@ -591,6 +597,20 @@ h4 {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.form-field-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
margin-top: 4px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.effectiveDays {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
@@ -599,8 +619,4 @@ h4 {
|
||||
margin: 0 4px;
|
||||
}
|
||||
}
|
||||
.tips {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间" prop="rangeTime">
|
||||
<el-date-picker
|
||||
class="full-discount-range-picker"
|
||||
type="datetimerange"
|
||||
v-model="form.rangeTime"
|
||||
:disabled="fieldDisabled"
|
||||
@@ -24,7 +25,6 @@
|
||||
end-placeholder="结束时间"
|
||||
placeholder="请选择"
|
||||
:disabled-date="options.disabledDate"
|
||||
style="width: 320px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动描述" prop="description">
|
||||
@@ -505,4 +505,11 @@ h4 {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
:deep(.full-discount-range-picker.el-date-editor--datetimerange) {
|
||||
width: 380px;
|
||||
max-width: 380px;
|
||||
flex-grow: 0;
|
||||
--el-date-editor-width: 380px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
<div class="tips">主播昵称,最短2个汉字,最长15个汉字,1个汉字相当于2个字符</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="直播时间" prop="startTime">
|
||||
<div class="form-field-block">
|
||||
<el-date-picker
|
||||
class="live-time-picker"
|
||||
:disabled="liveStatus != 'NEW'"
|
||||
v-model="times"
|
||||
type="datetimerange"
|
||||
@@ -23,12 +25,12 @@
|
||||
:disabled-date="disabledDate"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
style="width: 360px"
|
||||
@change="handleChangeTime"
|
||||
/>
|
||||
<div class="tips">
|
||||
直播开播时间需要在当前时间的10分钟后并且,开始时间不能在6个月后,直播计划结束时间(开播时间和结束时间间隔不得短于30分钟,不得超过24小时)
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="主播微信号" prop="anchorWechat">
|
||||
<el-input
|
||||
@@ -285,6 +287,25 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-form-item__content) {
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.form-field-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.live-time-picker.el-date-editor--datetimerange) {
|
||||
width: 360px;
|
||||
max-width: 360px;
|
||||
flex-grow: 0;
|
||||
--el-date-editor-width: 360px;
|
||||
}
|
||||
|
||||
.action {
|
||||
display: flex;
|
||||
}
|
||||
@@ -306,7 +327,15 @@ export default {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
:deep(.el-form-item__content > .tips) {
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
|
||||
.tips {
|
||||
width: 100%;
|
||||
max-width: 460px;
|
||||
margin-top: 6px;
|
||||
line-height: 1.6;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -3,15 +3,21 @@
|
||||
<el-card>
|
||||
<el-form :model="liveForm" ref="liveForm" :rules="liveRulesForm" label-width="120px">
|
||||
<el-form-item label="直播标题" prop="name">
|
||||
<div class="form-field-block">
|
||||
<el-input disabled v-model="liveForm.name" style="width:460px"></el-input>
|
||||
<div class="tips">直播间名字,最短3个汉字,最长17个汉字,1个汉字相当于2个字符</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="主播昵称" prop="anchorName">
|
||||
<div class="form-field-block">
|
||||
<el-input disabled v-model="liveForm.anchorName" style="width:360px"></el-input>
|
||||
<div class="tips">主播昵称,最短2个汉字,最长15个汉字,1个汉字相当于2个字符</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="直播时间" prop="startTime">
|
||||
<div class="form-field-block">
|
||||
<el-date-picker
|
||||
class="live-time-picker"
|
||||
disabled
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
type="datetimerange"
|
||||
@@ -20,17 +26,20 @@
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
placeholder="直播计划开始时间-直播计划结束时间"
|
||||
style="width: 300px"
|
||||
/>
|
||||
<div class="tips">直播开播时间需要在当前时间的10分钟后 并且 开始时间不能在 6 个月后</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="主播微信号" prop="anchorWechat">
|
||||
<div class="form-field-block">
|
||||
<el-input disabled v-model="liveForm.anchorWechat" style="width:360px" placeholder="主播微信号"></el-input>
|
||||
<div class="tips">主播微信号,如果未实名认证,需要先前往“小程序直播”小程序进行<a target="_black" href="https://res.wx.qq.com/op_res/9rSix1dhHfK4rR049JL0PHJ7TpOvkuZ3mE0z7Ou_Etvjf-w1J_jVX0rZqeStLfwh">实名验证</a></div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="分享卡片封面" prop="feedsImg">
|
||||
<div class="form-field-block">
|
||||
<div class="upload-list" v-if="liveForm.feedsImg">
|
||||
<img :src="liveForm.feedsImg">
|
||||
<div class="upload-list-cover" @click="handleView(liveForm.feedsImg)">
|
||||
@@ -40,9 +49,11 @@
|
||||
<div class="tips">
|
||||
直播间分享图,图片规则:建议像素800*640,大小不超过1M;
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="直播间背景墙" prop="coverImg">
|
||||
<div class="form-field-block">
|
||||
<div class="upload-list" v-if="liveForm.coverImg">
|
||||
<img :src="liveForm.coverImg">
|
||||
<div class="upload-list-cover" @click="handleView(liveForm.coverImg)">
|
||||
@@ -50,9 +61,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips"> 直播间背景图,图片规则:建议像素1080*1920,大小不超过1M</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="直播间分享图" prop="shareImg">
|
||||
<div class="form-field-block">
|
||||
<div class="upload-list" v-if="liveForm.shareImg">
|
||||
<img :src="liveForm.shareImg">
|
||||
<div class="upload-list-cover" @click="handleView(liveForm.shareImg)">
|
||||
@@ -60,9 +73,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="tips"> 直播间分享图,图片规则:建议像素800*640,大小不超过1M</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品" v-if="$route.query.id">
|
||||
<div class="form-field-block">
|
||||
<el-table class="goods-table" border :data="liveData" style="width: 100%">
|
||||
<el-table-column label="商品" min-width="200">
|
||||
<template #default="{ row, $index }">
|
||||
@@ -94,6 +109,7 @@
|
||||
<div class="tips">
|
||||
直播间商品中前两个商品将自动被选为封面,伴随直播间在直播列表中显示
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
@@ -173,6 +189,25 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-form-item__content) {
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.form-field-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:deep(.live-time-picker.el-date-editor--datetimerange) {
|
||||
width: 360px;
|
||||
max-width: 360px;
|
||||
flex-grow: 0;
|
||||
--el-date-editor-width: 360px;
|
||||
}
|
||||
|
||||
.action {
|
||||
display: flex;
|
||||
:deep(.el-button) {
|
||||
@@ -197,7 +232,15 @@ export default {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
:deep(.el-form-item__content > .tips) {
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
|
||||
.tips {
|
||||
width: 100%;
|
||||
max-width: 460px;
|
||||
margin-top: 6px;
|
||||
line-height: 1.6;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<el-card>
|
||||
<el-form ref="form" :model="form" label-width="130px" :rules="formValidate">
|
||||
<el-form-item label="活动名称" prop="promotionName">
|
||||
<div class="form-field-block">
|
||||
<el-input
|
||||
v-model="form.promotionName"
|
||||
clearable
|
||||
@@ -13,32 +14,40 @@
|
||||
<div class="form-tip">
|
||||
活动名称将显示在店铺拼团活动列表中,供商家管理使用,最多输入25个字符
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间" prop="rangeTime">
|
||||
<div class="form-field-block">
|
||||
<el-date-picker
|
||||
v-model="form.rangeTime"
|
||||
class="pintuan-range-picker"
|
||||
type="datetimerange"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
start-placeholder="开始时间"
|
||||
end-placeholder="结束时间"
|
||||
placeholder="请选择"
|
||||
:disabled-date="options.disabledDate"
|
||||
style="width: 360px"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="成团人数" prop="requiredNum">
|
||||
<div class="form-field-block">
|
||||
<el-input v-model="form.requiredNum" style="width: 260px" placeholder="请输入成团人数">
|
||||
<template #append>人</template>
|
||||
</el-input>
|
||||
<span class="form-tip inline-tip">成团人数最少为2人,最多不超过10人。</span>
|
||||
<div class="form-tip">成团人数最少为2人,最多不超过10人。</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="限购数量" prop="limitNum">
|
||||
<div class="form-field-block">
|
||||
<el-input v-model="form.limitNum" type="number" style="width: 260px" placeholder="请输入限购数量">
|
||||
<template #append>件/人</template>
|
||||
</el-input>
|
||||
<span class="form-tip inline-tip">若设置为0,则为不限制购买数量。</span>
|
||||
<div class="form-tip">若设置为0,则为不限制购买数量。</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="虚拟成团" prop="fictitious">
|
||||
<div class="form-field-block">
|
||||
<el-radio-group v-model="form.fictitious">
|
||||
<el-radio-button :value="1">开启</el-radio-button>
|
||||
<el-radio-button :value="0">关闭</el-radio-button>
|
||||
@@ -46,8 +55,10 @@
|
||||
<div class="form-tip">
|
||||
开启虚拟成团后,24小时内人数未满的团,系统将会模拟匿名买家凑满人数,使该团成团。您只需要对真实拼团买家发货。建议合理开启,以提高成团率。
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="拼团规则" prop="pintuanRule">
|
||||
<div class="form-field-block">
|
||||
<el-input
|
||||
v-model="form.pintuanRule"
|
||||
type="textarea"
|
||||
@@ -58,6 +69,7 @@
|
||||
placeholder="请输入拼团规则"
|
||||
/>
|
||||
<div class="form-tip">拼团规则字数不能超过255字,将在WAP拼团详情页中显示</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="closeCurrentPage">返回</el-button>
|
||||
@@ -180,16 +192,31 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.new-pintuan {
|
||||
:deep(.el-form-item__label) {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
:deep(.pintuan-range-picker.el-date-editor--datetimerange) {
|
||||
width: 400px;
|
||||
max-width: 100%;
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-field-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
color: #cccccc;
|
||||
color: #666666;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.inline-tip {
|
||||
display: inline-block;
|
||||
margin-top: 0;
|
||||
margin-left: 8px;
|
||||
width: 100%;
|
||||
max-width: 720px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -208,11 +208,28 @@ export default {
|
||||
getPintuanGoodsList(params).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success && res.result) {
|
||||
this.goodsData = res.result.records || [];
|
||||
const serverRecords = res.result.records || [];
|
||||
this.goodsData = this.readonly
|
||||
? serverRecords
|
||||
: this.mergeGoodsData(serverRecords);
|
||||
this.total = res.result.total || 0;
|
||||
}
|
||||
});
|
||||
},
|
||||
mergeGoodsData(serverRecords) {
|
||||
const localMap = new Map(this.goodsData.map((item) => [item.skuId, item]));
|
||||
const serverSkuIds = new Set(serverRecords.map((item) => item.skuId));
|
||||
|
||||
const merged = serverRecords.map((serverItem) => {
|
||||
const local = localMap.get(serverItem.skuId);
|
||||
return local ? { ...serverItem, price: local.price } : serverItem;
|
||||
});
|
||||
|
||||
const unsavedItems = this.goodsData.filter(
|
||||
(item) => item.skuId && !serverSkuIds.has(item.skuId)
|
||||
);
|
||||
return [...merged, ...unsavedItems];
|
||||
},
|
||||
openSkuList() {
|
||||
const data = JSON.parse(JSON.stringify(this.goodsData));
|
||||
data.forEach((e) => {
|
||||
|
||||
@@ -215,7 +215,7 @@ export const modelData = [
|
||||
bgImg: {
|
||||
img: require('@/assets/nav/decorate.png'),
|
||||
url: '',
|
||||
size: "1300*586"
|
||||
size: "1300*585"
|
||||
},
|
||||
classification: [{
|
||||
img: require('@/assets/nav/decorate2.jpeg'),
|
||||
|
||||
@@ -136,6 +136,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -264,6 +265,7 @@ export default {
|
||||
@import "./modelList/setup-box.scss";
|
||||
.model-form {
|
||||
width: 1500px;
|
||||
max-width: 100%;
|
||||
}
|
||||
.model-content {
|
||||
width: 1200px;
|
||||
@@ -273,6 +275,8 @@ export default {
|
||||
}
|
||||
.model-form-list {
|
||||
min-height: 500px;
|
||||
padding-right: 110px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.top-fixed-advert {
|
||||
display: flex;
|
||||
|
||||
@@ -14,12 +14,11 @@
|
||||
</template>
|
||||
<!-- 热门广告 -->
|
||||
<template v-if="element.type == 'hotAdvert'">
|
||||
<div class="setup-content">
|
||||
<div class="hot-advert">
|
||||
<div class="hot-advert-banner setup-content">
|
||||
<img
|
||||
style="display: block"
|
||||
:src="element.options.list[0].img"
|
||||
@click="$router.push(element.options.list[0].url)"
|
||||
width="1200"
|
||||
alt=""
|
||||
/>
|
||||
<div class="setup-box">
|
||||
@@ -40,7 +39,7 @@
|
||||
class="setup-content"
|
||||
:key="index"
|
||||
>
|
||||
<img :src="item.img" width="230" height="190" alt="" />
|
||||
<img :src="item.img" alt="" />
|
||||
<div class="setup-box">
|
||||
<div>
|
||||
<el-button size="small" @click.stop="handleSelectModel(item)"
|
||||
@@ -51,6 +50,7 @@
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 限时秒杀 待完善 -->
|
||||
<template v-if="element.type == 'seckill'">
|
||||
@@ -107,15 +107,15 @@
|
||||
</template>
|
||||
<!-- 好货推荐 -->
|
||||
<template v-if="element.type == 'recommend'">
|
||||
<recommend :data="element"></recommend>
|
||||
<recommend :data="element" class="mb_20 width_1200_auto"></recommend>
|
||||
</template>
|
||||
<!-- 新品排行 -->
|
||||
<template v-if="element.type == 'newGoodsSort'">
|
||||
<new-goods-sort :data="element"></new-goods-sort>
|
||||
<new-goods-sort :data="element" class="mb_20 width_1200_auto"></new-goods-sort>
|
||||
</template>
|
||||
<!-- 首页广告 -->
|
||||
<template v-if="element.type == 'firstAdvert'">
|
||||
<first-page-advert :data="element"></first-page-advert>
|
||||
<first-page-advert :data="element" class="mb_20 width_1200_auto"></first-page-advert>
|
||||
</template>
|
||||
<!-- 商品模块 -->
|
||||
<template v-if="element.type == 'goodsType'">
|
||||
@@ -142,7 +142,7 @@
|
||||
<div class="horizontal-advert setup-content">
|
||||
<img
|
||||
v-if="element.options.img"
|
||||
width="1200"
|
||||
class="banner-ad-img"
|
||||
:src="element.options.img"
|
||||
alt=""
|
||||
/>
|
||||
@@ -162,7 +162,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="element.type == 'notEnough'">
|
||||
<not-enough :data="element"></not-enough>
|
||||
<not-enough :data="element" class="mb_20 width_1200_auto"></not-enough>
|
||||
</template>
|
||||
<div class="del-btn">
|
||||
<el-button size="small" type="danger" @click="handleModelDelete">删除</el-button>
|
||||
@@ -176,13 +176,13 @@
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="modal-top-advert">
|
||||
<div>
|
||||
<div class="modal-form-item modal-form-preview">
|
||||
<!-- 热门广告两种图片尺寸 -->
|
||||
<img
|
||||
class="show-image"
|
||||
width="600"
|
||||
height="40"
|
||||
v-if="selected.size && selected.size.indexOf('1200') >= 0"
|
||||
v-if="selected.size && selected.size.indexOf('1200') >= 0 && selected.img"
|
||||
:src="selected.img"
|
||||
alt
|
||||
/>
|
||||
@@ -198,7 +198,7 @@
|
||||
<img
|
||||
class="show-image"
|
||||
width="600"
|
||||
height="300"
|
||||
height="270"
|
||||
v-if="selected.size && selected.size.indexOf('1300') >= 0"
|
||||
:src="selected.img"
|
||||
alt
|
||||
@@ -220,11 +220,11 @@
|
||||
alt
|
||||
/>
|
||||
</div>
|
||||
<div class="tips">
|
||||
建议尺寸:<span>{{ selected.size }}</span>
|
||||
</div>
|
||||
<div>
|
||||
图片链接:<el-input
|
||||
<div class="tips">建议尺寸:{{ selected.size }}</div>
|
||||
<div class="modal-form-item modal-form-link">
|
||||
<span class="modal-label">图片链接:</span>
|
||||
<div class="modal-link-field">
|
||||
<el-input
|
||||
class="outsideUrl"
|
||||
v-model="selected.url"
|
||||
:disabled="!!selected.type && selected.type !== 'link'"
|
||||
@@ -234,12 +234,18 @@
|
||||
>选择链接</el-button
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
选择图片:<el-button size="small" type="primary" @click="handleSelectImg"
|
||||
</div>
|
||||
<div class="modal-form-item">
|
||||
<span class="modal-label">选择图片:</span>
|
||||
<el-button size="small" type="primary" @click="handleSelectImg"
|
||||
>选择图片</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleCancelModal">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirmModal">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 选择商品。链接 -->
|
||||
<liliDialog ref="liliDialog" @selectedLink="selectedLink"></liliDialog>
|
||||
@@ -249,6 +255,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
@@ -296,14 +303,19 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
showModal: false, // modal显隐
|
||||
selected: {}, // 已选数据
|
||||
selected: {}, // 弹窗编辑草稿
|
||||
editTarget: null, // 确定后写回的原数据
|
||||
picModelFlag: false, // 图片选择器
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
cloneItem(item) {
|
||||
return JSON.parse(JSON.stringify(item || {}));
|
||||
},
|
||||
// 编辑模块
|
||||
handleSelectModel(item) {
|
||||
this.selected = item;
|
||||
this.editTarget = item;
|
||||
this.selected = this.cloneItem(item);
|
||||
this.showModal = true;
|
||||
},
|
||||
// 删除模块
|
||||
@@ -341,8 +353,22 @@ export default {
|
||||
// 回显图片
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
if (!val?.url) return;
|
||||
this.selected.img = val.url;
|
||||
},
|
||||
handleCancelModal() {
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal = false;
|
||||
},
|
||||
handleConfirmModal() {
|
||||
if (this.editTarget) {
|
||||
Object.assign(this.editTarget, this.cloneItem(this.selected));
|
||||
}
|
||||
this.editTarget = null;
|
||||
this.selected = {};
|
||||
this.showModal = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -364,30 +390,68 @@ export default {
|
||||
position: absolute;
|
||||
right: -100px;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
&:hover {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
/** 横幅广告 */
|
||||
.horizontal-advert {
|
||||
width: 1200px;
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
overflow: hidden;
|
||||
line-height: 0;
|
||||
|
||||
.banner-ad-img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 166px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.default-con {
|
||||
height: 100px;
|
||||
padding-top: 30px;
|
||||
text-align: center;
|
||||
background: #ddd;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
/** 热门广告 */
|
||||
.hot-advert {
|
||||
width: 1200px;
|
||||
margin-right: -110px;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
|
||||
.hot-advert-banner {
|
||||
line-height: 0;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
.advert-list {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 5px 0;
|
||||
list-style: none;
|
||||
box-sizing: border-box;
|
||||
background: $theme_color;
|
||||
height: 200px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 3px 10px;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
> li {
|
||||
flex: 0 0 calc((100% - 40px) / 5);
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 190px;
|
||||
cursor: pointer;
|
||||
border-radius: 10px;
|
||||
transition: all 150ms ease-in-out;
|
||||
@@ -414,11 +478,11 @@ export default {
|
||||
}
|
||||
.discountAdvert {
|
||||
width: 1300px;
|
||||
height: 566px;
|
||||
height: 585px;
|
||||
margin-left: -100px;
|
||||
box-sizing: border-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1300px 566px;
|
||||
background-size: 1300px 585px;
|
||||
position: relative;
|
||||
> div {
|
||||
padding-left: 295px;
|
||||
@@ -428,11 +492,14 @@ export default {
|
||||
&:nth-child(1) img {
|
||||
margin: 10px 10px 0 0;
|
||||
}
|
||||
&:nth-child(2) img {
|
||||
&:nth-child(2) {
|
||||
margin-top: 10px;
|
||||
img {
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 首页品牌 */
|
||||
.brand {
|
||||
.brand-view {
|
||||
@@ -535,11 +602,61 @@ export default {
|
||||
/** 装修模态框 内部样式start */
|
||||
.modal-top-advert {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
> * {
|
||||
margin-bottom: 10px;
|
||||
align-items: stretch;
|
||||
padding: 0 20px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.modal-form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.modal-label {
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-form-preview {
|
||||
justify-content: center;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.modal-form-link {
|
||||
align-items: flex-start;
|
||||
|
||||
.modal-label {
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.modal-link-field {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
|
||||
.outsideUrl {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tips {
|
||||
padding-left: 112px;
|
||||
margin-bottom: 16px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
@callback="callbackSelected"
|
||||
:is-component="true"
|
||||
:initialize="picModelFlag"
|
||||
:max-select="1"
|
||||
ref="ossManage"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user