feat(setting): 添加店铺H5和小程序二维码展示功能

This commit is contained in:
pikachu1995@126.com
2026-08-26 10:59:52 +08:00
parent 404492b7a3
commit ebcc0075ce
4 changed files with 229 additions and 1 deletions

View File

@@ -64,6 +64,14 @@
<el-form-item label="wap站点地址" prop="staticPageWapAddress">
<el-input v-model="formValidate.staticPageWapAddress" />
</el-form-item>
<el-form-item label="展示店铺H5地址" prop="showStoreH5Address">
<el-switch v-model="formValidate.showStoreH5Address" active-text="开" inactive-text="关" />
<span class="desc">开启后商家后台顶栏展示 H5 店铺首页二维码需先填写上方wap站点地址</span>
</el-form-item>
<el-form-item label="展示店铺小程序地址" prop="showStoreMpAddress">
<el-switch v-model="formValidate.showStoreMpAddress" active-text="开" inactive-text="关" />
<span class="desc">开启后商家后台顶栏展示小程序店铺首页码需先配置微信小程序且小程序已发布店铺页</span>
</el-form-item>
<div class="label-btns">
<el-button type="primary" @click="submit('formValidate')">保存</el-button>
</div>
@@ -106,6 +114,8 @@ export default {
siteName: "",
staticPageAddress: "",
staticPageWapAddress: "",
showStoreH5Address: false,
showStoreMpAddress: false,
},
selected: "",
ruleValidate: {},
@@ -150,8 +160,16 @@ export default {
},
init() {
this.result = JSON.parse(this.res);
this.formValidate = { ...this.result };
this.formValidate = {
...this.formValidate,
...this.result,
showStoreH5Address: this.result.showStoreH5Address === true,
showStoreMpAddress: this.result.showStoreMpAddress === true,
};
Object.keys(this.result).forEach((item) => {
if (item === "showStoreH5Address" || item === "showStoreMpAddress") {
return;
}
this.ruleValidate[item] = [
{
required: true,

View File

@@ -55,6 +55,11 @@ export const userInfo = params => {
export const userMsg = params => {
return getRequest('/settings/storeSettings', params)
}
/** 当前店铺首页小程序码 */
export const getStoreMpQrcode = () => {
return getRequest("/settings/storeSettings/mp-qrcode");
};
//验证短信验证码
export const validateCode = params => {
return postRequestWithNoToken("/passport/login/resetByMobile", params);

View File

@@ -20,6 +20,7 @@
align="middle"
class="user-dropdown-innercon"
>
<store-qrcode />
<ul class="nav-list">
<li class="nav-item" @click="im">
<el-tooltip content="联系客服" placement="bottom">
@@ -84,6 +85,7 @@ import shrinkableMenu from "./main-components/shrinkable-menu/shrinkable-menu.vu
import tagsPageOpened from "./main-components/tags-page-opened.vue";
import circleLoading from "@/views/my-components/lili/circle-loading.vue";
import configDrawer from "@/views/main-components/config-drawer.vue";
import storeQrcode from "@/views/main-components/store-qrcode.vue";
import Cookies from "js-cookie";
import util from "@/libs/util.js";
import { logout } from "@/api/index";
@@ -100,6 +102,7 @@ export default {
tagsPageOpened,
circleLoading,
configDrawer,
storeQrcode,
},
data() {
return {

View File

@@ -0,0 +1,202 @@
<template>
<div v-if="storeId && (showH5 || showMp)" class="store-qr-group">
<el-popover v-if="showH5" trigger="hover" placement="bottom" :width="220">
<template #reference>
<div class="store-qr-thumb">
<vue-qr v-if="h5Url" :text="h5Url" :margin="0" color-dark="#000" color-light="#fff" :size="40" />
<el-icon v-else class="store-qr-empty"><Picture /></el-icon>
<span>H5</span>
</div>
</template>
<div class="store-qr-panel">
<vue-qr v-if="h5Url" :text="h5Url" :margin="0" color-dark="#000" color-light="#fff" :size="160" />
<div v-else class="store-qr-tip">请先在系统设置中填写 wap 站点地址</div>
<div class="store-qr-title">H5 店铺首页</div>
<el-button v-if="h5Url" size="small" @click="copyText(h5Url)">复制链接</el-button>
</div>
</el-popover>
<el-popover v-if="showMp" trigger="hover" placement="bottom" :width="220">
<template #reference>
<div class="store-qr-thumb">
<img v-if="mpQrSrc" :src="mpQrSrc" width="40" height="40" alt="小程序码" />
<el-icon v-else class="store-qr-empty"><Picture /></el-icon>
<span>小程序</span>
</div>
</template>
<div class="store-qr-panel">
<img v-if="mpQrSrc" :src="mpQrSrc" width="160" height="160" alt="小程序码" />
<div v-else class="store-qr-tip">{{ mpError || "小程序码生成中..." }}</div>
<div class="store-qr-title">小程序店铺首页</div>
<el-button v-if="mpQrSrc" size="small" @click="downloadMp">下载二维码</el-button>
</div>
</el-popover>
</div>
</template>
<script>
import Cookies from "js-cookie";
import vueQr from "vue-qr";
import { Picture } from "@element-plus/icons-vue";
import { getStoreMpQrcode } from "@/api/index";
import { getBaseSite } from "@/api/common.js";
export default {
name: "store-qrcode",
components: { "vue-qr": vueQr, Picture },
data() {
return {
storeId: "",
wapUrl: "",
showH5: false,
showMp: false,
mpQrcode: "",
mpError: "",
};
},
computed: {
h5Url() {
if (!this.storeId || !this.wapUrl) return "";
return `${String(this.wapUrl).replace(/\/$/, "")}/pages/product/shopPage?id=${this.storeId}`;
},
mpQrSrc() {
return this.mpQrcode ? `data:image/png;base64,${this.mpQrcode}` : "";
},
},
mounted() {
this.initStore();
this.loadSiteSetting();
},
methods: {
initStore() {
try {
const userInfo = JSON.parse(Cookies.get("userInfoSeller") || "{}") || {};
this.storeId = userInfo.id || userInfo.storeId || "";
} catch (e) {
this.storeId = "";
}
},
parseSettingValue(raw) {
if (!raw) return {};
if (typeof raw === "object") return raw;
try {
return JSON.parse(raw);
} catch (e) {
return {};
}
},
loadSiteSetting() {
getBaseSite()
.then((res) => {
if (!res || !res.success || !res.result) return;
const data = this.parseSettingValue(res.result.settingValue || res.result);
this.showH5 = data.showStoreH5Address === true;
this.showMp = data.showStoreMpAddress === true;
this.wapUrl =
data.staticPageWapAddress ||
(typeof window !== "undefined" && window.BASE && window.BASE.WAP_URL) ||
"";
if (this.showMp) {
this.loadMpQrcode();
}
})
.catch(() => {
this.showH5 = false;
this.showMp = false;
});
},
loadMpQrcode() {
if (!this.storeId) return;
getStoreMpQrcode()
.then((res) => {
if (res && res.success && res.result) {
if (String(res.result).startsWith("eyJ")) {
this.mpError = "请先配置微信小程序";
return;
}
this.mpQrcode = res.result;
this.mpError = "";
} else {
this.mpError = (res && res.message) || "小程序码生成失败";
}
})
.catch(() => {
this.mpError = "请先配置微信小程序";
});
},
copyText(text) {
if (!text) return;
const textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand("copy");
this.$Message.success("复制成功");
} catch (e) {
this.$Message.error("复制失败");
}
document.body.removeChild(textArea);
},
downloadMp() {
if (!this.mpQrSrc) return;
const link = document.createElement("a");
link.href = this.mpQrSrc;
link.download = "店铺小程序码.png";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
},
};
</script>
<style scoped lang="scss">
.store-qr-group {
display: inline-flex;
align-items: center;
gap: 12px;
margin-right: 16px;
}
.store-qr-thumb {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
line-height: 1.2;
span {
margin-top: 2px;
font-size: 12px;
color: #666;
}
}
.store-qr-empty {
width: 40px;
height: 40px;
font-size: 22px;
color: #ccc;
}
.store-qr-panel {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 4px 0;
}
.store-qr-title {
font-size: 13px;
color: #333;
}
.store-qr-tip {
width: 160px;
min-height: 80px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-size: 12px;
color: #999;
}
</style>