refactor(site-settings): 统一站点配置管理并清理废弃页面

- 新增 useSiteSettings composable 替代各端硬编码的配置引用
- 移除 memberRecycle 和 fictitiousOrderList 废弃页面并增加缓存过滤
- 版权信息改为通过接口动态获取,后台新增版权归属配置字段
- 全局禁止 textarea 拖拽缩放并统一三端样式规则
- 会员列表增加状态 tab 筛选及启用/禁用双向切换功能
- 删除未使用的 getSpecificationList API 方法
This commit is contained in:
pikachu1995@126.com
2026-11-03 09:14:05 +08:00
parent 22f3e9b5e9
commit fb99824a3a
24 changed files with 422 additions and 1274 deletions

View File

@@ -69,10 +69,6 @@ export const saveCategoryBrand = (category_id, params) => {
export const getBrandListData = params => {
return getRequest("/goods/brand/all", params);
};
// 获取所有可用规格
export const getSpecificationList = params => {
return getRequest("/goods/spec/all", params);
};
// 获取店铺分类列表数据
export const getAllList = id => {

View File

@@ -0,0 +1,33 @@
import { computed, onMounted, ref } from "vue";
import { getBaseSite } from "@/api/common.js";
import config from "@/config";
// 同页的页头、页脚共享请求;每次重新进入页面时刷新,避免旧缓存覆盖后台设置。
const settings = ref(null);
let pendingRequest;
export function loadSiteSettings() {
if (!pendingRequest) {
pendingRequest = getBaseSite()
.then((res) => {
if (res.success && res.result?.settingValue) {
settings.value = JSON.parse(res.result.settingValue);
}
return settings.value;
})
.catch(() => settings.value)
.finally(() => { pendingRequest = null; });
}
return pendingRequest;
}
export function useSiteSettings() {
onMounted(loadSiteSettings);
const siteName = computed(() => settings.value?.siteName || config.title);
const companyName = computed(() => settings.value ? settings.value.companyName || "" : config.company?.name || "");
const companyUrl = computed(() => settings.value ? settings.value.companyUrl || "" : config.company?.href || "");
const website = computed(() => settings.value ? settings.value.website || "" : config.website || "");
const icp = computed(() => settings.value ? settings.value.icp || "" : config.icpMessage || "");
const copyrightOwner = computed(() => settings.value?.copyrightOwner?.trim() || siteName.value);
return { settings, siteName, companyName, companyUrl, website, icp, copyrightOwner };
}

View File

@@ -113,9 +113,9 @@
z-index: 4000 !important;
}
/* 全局禁止 textarea 拖拽改变大小 */
/* 全局禁止多行输入框拖动缩放,覆盖组件生成的内联 resize 样式。 */
.el-textarea__inner {
resize: none;
resize: none !important;
}
/* 统一空状态:表格 / 树 / 列表无数据时的展示(未自定义 #empty 插槽的页面均生效) */

View File

@@ -99,15 +99,15 @@
<div class="login-btn"><a @click="$router.push('login')">前往登录</a></div>
</div>
<div class="foot">
<el-row justify="space-around" class="help">
<a class="item" href="https://pickmall.cn/" target="_blank">帮助</a>
<a class="item" href="https://pickmall.cn/" target="_blank">隐私</a>
<a class="item" href="https://pickmall.cn/" target="_blank">条款</a>
<el-row v-if="website" justify="space-around" class="help">
<a class="item" :href="website" target="_blank">帮助</a>
<a class="item" :href="website" target="_blank">隐私</a>
<a class="item" :href="website" target="_blank">条款</a>
</el-row>
<el-row justify="center" class="copyright">
Copyright © {{ year }} - Present
<a href="https://pickmall.cn/" target="_blank" style="margin: 0 5px">{{
siteName
Copyright © {{ year }}
<a :href="website || undefined" target="_blank" style="margin: 0 5px">{{
copyrightOwner
}}</a>
版权所有
</el-row>
@@ -124,7 +124,7 @@ import { md5 } from "@/utils/md5.js";
import * as RegExp from "@/utils/regular.js";
import * as apiLogin from "@/api/index.js";
import { sendSms } from "@/api/common.js";
import util from "@/libs/util.js";
import { useSiteSettings } from "@/composables/useSiteSettings";
import verify from "@/views/my-components/verify";
import { useAppStore } from "@/stores/app";
@@ -146,8 +146,7 @@ const form = reactive({
oncePasd: "",
});
const year = new Date().getFullYear();
// 站点名优先取接口下发缓存,兜底用本地配置
const siteName = util.getSiteName();
const { website, copyrightOwner } = useSiteSettings();
const step = ref(0);
const ruleInline = {
mobile: [

View File

@@ -2,46 +2,30 @@
<div class="foot">
<div class="information footer-bottom">
<div class="icp">
<li v-if="config.icpCard">
<a
:href="
'https://tsm.miit.gov.cn/dxxzsp/xkz/xkzgl/resource/qiyesearch.jsp?num=' +
config.icpCard +
'&type=xuke'
"
target="_blank"
>
{{ config.icpCard }}
</a>
</li>
<li v-if="config.icpMessage" class="footer-bottom">
<li v-if="icp" class="footer-bottom">
<a href="https://beian.miit.gov.cn/" target="_blank">
{{ config.icpMessage }}
{{ icp }}
</a>
</li>
</div>
<a class="company-link" :href="companyUrl" target="_blank">
<a v-if="companyName" class="company-link" :href="companyUrl || undefined" target="_blank">
<img class="zhizhao" :src="zhizhaoImg" alt="" />
{{ companyName }}
</a>
</div>
<div class="copyright">
<p>Copyright © {{ year }} {{ siteName }}</p>
<p>Copyright © {{ year }} {{ copyrightOwner }}</p>
</div>
</div>
</template>
<script setup>
import config from "@/config/index";
import util from "@/libs/util.js";
import { useSiteSettings } from "@/composables/useSiteSettings";
import zhizhaoImg from "@/assets/images/zhizhao.jpg";
const year = new Date().getFullYear();
// 站点名/公司信息优先取接口下发缓存,兜底用本地配置
const siteName = util.getSiteName();
const companyName = localStorage.getItem("sellerCompanyName") || config.company.name;
const companyUrl = localStorage.getItem("sellerCompanyUrl") || config.company.href;
const { companyName, companyUrl, icp, copyrightOwner } = useSiteSettings();
</script>
<style lang="scss" scoped>

View File

@@ -8,27 +8,15 @@
<script setup>
import { onMounted, ref } from "vue";
import { getBaseSite } from "@/api/common.js";
import { loadSiteSettings } from "@/composables/useSiteSettings";
const storeSideLogo = ref(require("@/assets/logo-lilishop.png"));
function init() {
if (
!localStorage.getItem("sellersiteName") ||
!localStorage.getItem("sellerlogoImg") ||
!localStorage.getItem("sellerIconImg") ||
!localStorage.getItem("seller_expiration_time")
) {
getSite();
} else if (new Date() > localStorage.getItem("seller_expiration_time")) {
getSite();
} else {
storeSideLogo.value = localStorage.getItem("sellerlogoImg");
window.document.title = localStorage.getItem("sellersiteName");
applyFavicon(localStorage.getItem("sellerIconImg"));
}
getSite();
}
function applyFavicon(href) {
if (!href) return;
const link =
document.querySelector("link[rel*='icon']") ||
document.createElement("link");
@@ -38,10 +26,9 @@ function applyFavicon(href) {
document.getElementsByTagName("head")[0].appendChild(link);
}
function getSite() {
getBaseSite()
.then((res) => {
if (res.success && res.result.settingValue) {
const data = JSON.parse(res.result.settingValue);
loadSiteSettings()
.then((data) => {
if (data) {
const expirationTime = new Date().setHours(new Date().getHours() + 1);
localStorage.setItem("seller_expiration_time", expirationTime);
localStorage.setItem("sellersiteName", data.siteName);
@@ -49,8 +36,8 @@ function getSite() {
localStorage.setItem("sellerIconImg", data.storeSideIcon);
localStorage.setItem("sellerCompanyName", data.companyName || "");
localStorage.setItem("sellerCompanyUrl", data.companyUrl || "");
storeSideLogo.value = data.storeSideLogo;
window.document.title = data.siteName;
storeSideLogo.value = data.storeSideLogo || storeSideLogo.value;
if (data.siteName) window.document.title = data.siteName;
applyFavicon(data.storeSideIcon);
}
})