-
-
-
-
-
-
-
-
-
- 还没有轮播图,点击下方按钮添加。
-
- 新增轮播
-
-
-
- 还没有友情链接,点击下方按钮添加。
-
- 新增友情链接
-
-
-
- 企业荣誉
- 用于首页“荣誉资质”模块(honor)。
-
- 新增荣誉
+
-
合作伙伴/成功案例
-
用于首页“典型案例/合作伙伴”模块(partner)。
-
-
-
新增合作伙伴
-
-
-
-
- 对应 /console/v1/feedback 的类型选项,ID 需与后端保持一致,仅建议修改名称与描述。
-
- 还没有反馈类型,点击下方按钮添加。
-
- 新增反馈类型
-
-
-
-
- 对应前台右侧悬浮工具条(电话咨询/在线客服/提交工单等),结构与模板中的 side_floating_window 一致。
-
- 还没有侧边浮窗,点击下方按钮添加。
-
- 新增浮窗
-
+
+
-
-
- 用于暂未在 UI 中开放的配置项(如复杂导航结构 header_nav/footer_nav 等)。如非必要,建议优先使用上方表单编辑。
-
-
-
- 同步当前配置
- 应用 JSON
-
-
+
+
+
+ 还没有轮播图,点击下方按钮添加。
+
+
+ 新增轮播
+
+
+
+ 企业荣誉
+
+ 用于首页“荣誉资质”模块(honor)。
+
+
+ 新增荣誉
+
+ 合作伙伴/成功案例
+
+ 用于首页“典型案例/合作伙伴”模块(partner)。
+
+
+ 新增合作伙伴
+
+
+
+
+
+
+ 控制站点顶部导航栏及其下拉菜单结构。第一个导航项用作 Logo 点击跳转地址。
+
+
+
+ 一级导航
+
+ 还没有自定义导航,请点击下方按钮新增。
+
+
+
+
+
+
下拉子菜单
+
+ 还没有子菜单,点击下方按钮新增。
+
+
+
+ 新增子菜单
+
+
+
+ 新增一级导航
+
+
+
+
+
+
+
+ 控制首页底部多列链接(如【热门产品】【客户支持】等),结构与模板中的
+ footer_nav 一致。
+
+
+ 还没有底部栏目,点击下方按钮新增。
+
+
+
+
+
栏目链接
+
+ 还没有链接,点击下方按钮新增。
+
+
+
+ 新增链接
+
+
+
+ 新增栏目
+
+
+
+
+
+ 还没有友情链接,点击下方按钮添加。
+
+
+ 新增友情链接
+
+
+
+
+
+
+ 用于暂未在 UI 中开放的配置项(如复杂导航结构 header_nav/footer_nav 等)。如非必要,建议优先使用上方表单编辑。
+
+
+
+ 同步当前配置
+ 应用 JSON
+
+
+
+
- 重新加载
- 保存全部配置
-
- {{ showAdvanced ? '隐藏高级 JSON' : '显示高级 JSON' }}
-
+ 重新加载
+
+ 保存全部配置
+
+
+ {{ showAdvanced ? "隐藏高级 JSON" : "显示高级 JSON" }}
+
@@ -325,6 +701,7 @@
enterprise_mailbox: "",
enterprise_qrcode: "",
official_website_logo: "",
+ online_customer_service_link: "",
icp_info: "",
icp_info_link: "",
public_security_network_preparation: "",
@@ -355,6 +732,11 @@
fullConfig: createDefaultConfig(),
advancedText: "",
showAdvanced: false,
+ activeTab: "basic",
+ uploadUrl: `${host}/${adminPath}/v1/upload`,
+ uploadHeaders: {
+ Authorization: "Bearer " + localStorage.getItem("backJwt"),
+ },
};
},
computed: {
@@ -364,11 +746,34 @@
}
return this.fullConfig.banner;
},
+ headerNavList() {
+ if (!Array.isArray(this.fullConfig.header_nav)) {
+ this.fullConfig.header_nav = [];
+ }
+ if (this.fullConfig.header_nav.length === 0) {
+ this.fullConfig.header_nav.push({
+ name: "首页",
+ file_address: "index.html",
+ blank: false,
+ children: [],
+ });
+ }
+ return this.fullConfig.header_nav;
+ },
+ homeNav() {
+ return this.headerNavList[0];
+ },
+ footerNavList() {
+ if (!Array.isArray(this.fullConfig.footer_nav)) {
+ this.fullConfig.footer_nav = [];
+ }
+ return this.fullConfig.footer_nav;
+ },
},
methods: {
normalizeConfig(data = {}) {
const defaults = createDefaultConfig();
- return {
+ const merged = {
...defaults,
...data,
seo: {
@@ -380,31 +785,95 @@
...(data.site_config || {}),
},
banner: Array.isArray(data.banner) ? data.banner : [],
- header_nav: Array.isArray(data.header_nav) ? data.header_nav : [],
+ header_nav:
+ Array.isArray(data.header_nav) && data.header_nav.length
+ ? data.header_nav
+ : [],
footer_nav: Array.isArray(data.footer_nav) ? data.footer_nav : [],
friendly_link: Array.isArray(data.friendly_link) ? data.friendly_link : [],
- side:
- Array.isArray(data.side)
- ? data.side
- : Array.isArray(data.side_floating_window)
- ? data.side_floating_window
- : [],
+ side: Array.isArray(data.side)
+ ? data.side
+ : Array.isArray(data.side_floating_window)
+ ? data.side_floating_window
+ : [],
feedback_type: Array.isArray(data.feedback_type)
? data.feedback_type
: Array.isArray(data.site_config && data.site_config.feedback_type)
- ? data.site_config.feedback_type
- : [],
+ ? data.site_config.feedback_type
+ : [],
honor: Array.isArray(data.honor)
? data.honor
: Array.isArray(data.site_config && data.site_config.honor)
- ? data.site_config.honor
- : [],
+ ? data.site_config.honor
+ : [],
partner: Array.isArray(data.partner)
? data.partner
: Array.isArray(data.site_config && data.site_config.partner)
- ? data.site_config.partner
- : [],
+ ? data.site_config.partner
+ : [],
};
+
+ if (!Array.isArray(merged.header_nav) || merged.header_nav.length === 0) {
+ merged.header_nav = [
+ {
+ name: "首页",
+ file_address: "index.html",
+ blank: false,
+ children: [],
+ },
+ ];
+ }
+
+ return merged;
+ },
+ uploadFormatResponse(res) {
+ if (!res || res.status !== 200) {
+ return { error: "上传失败" };
+ }
+ return res;
+ },
+ handleUpload(path, ctx) {
+ try {
+ const resp = ctx && ctx.file && ctx.file.response;
+ const data = resp && resp.data ? resp.data : resp;
+ if (!data) {
+ return showMessage(this, "error", "上传失败:未获取到响应数据");
+ }
+ let url = data.url || data.save_name || "";
+ if (!url) {
+ return showMessage(this, "error", "上传失败:未获取到文件地址");
+ }
+ if (!/^https?:\/\//i.test(url) && url.charAt(0) !== "/") {
+ url = "/" + url;
+ }
+ this.setConfigByPath(path, url);
+ } catch (e) {
+ showMessage(this, "error", "上传处理异常:" + e.message);
+ }
+ },
+ setConfigByPath(path, value) {
+ if (!Array.isArray(path) || !path.length) return;
+ let target = this.fullConfig;
+ for (let i = 0; i < path.length - 1; i++) {
+ const key = path[i];
+ if (typeof key === "number") {
+ if (!Array.isArray(target)) return;
+ target = target[key];
+ } else {
+ if (!target[key]) {
+ this.$set(target, key, {});
+ }
+ target = target[key];
+ }
+ if (!target) return;
+ }
+ const lastKey = path[path.length - 1];
+ if (typeof lastKey === "number") {
+ if (!Array.isArray(target)) return;
+ this.$set(target, lastKey, value);
+ } else {
+ this.$set(target, lastKey, value);
+ }
},
loadConfig() {
this.loading = true;
@@ -424,7 +893,7 @@
});
},
syncJson() {
- this.advancedText = JSON.stringify(this.fullConfig, null, 2);
+ this.advancedText = JSON.stringify(this.fullConfig, null, 2);
},
applyAdvanced() {
if (!this.advancedText.trim()) {
@@ -516,6 +985,85 @@
removeSide(index) {
this.fullConfig.side.splice(index, 1);
},
+ getHeaderChildren(item) {
+ if (!item) return [];
+ if (!Array.isArray(item.children)) {
+ this.$set(item, "children", []);
+ }
+ return item.children;
+ },
+ addHeaderNav() {
+ if (!Array.isArray(this.fullConfig.header_nav)) {
+ this.fullConfig.header_nav = [];
+ }
+ this.fullConfig.header_nav.push({
+ name: "",
+ file_address: "",
+ blank: false,
+ children: [],
+ });
+ },
+ removeHeaderNav(index) {
+ if (index === 0) {
+ return;
+ }
+ this.headerNavList.splice(index, 1);
+ },
+ addHeaderNavChild(index) {
+ const item = this.headerNavList[index];
+ if (!item) return;
+ if (!Array.isArray(item.children)) {
+ this.$set(item, "children", []);
+ }
+ item.children.push({
+ name: "",
+ file_address: "",
+ blank: false,
+ icon: "",
+ description: "",
+ });
+ },
+ removeHeaderNavChild(index, childIndex) {
+ const item = this.headerNavList[index];
+ if (!item || !Array.isArray(item.children)) return;
+ item.children.splice(childIndex, 1);
+ },
+ getFooterChildren(group) {
+ if (!group) return [];
+ if (!Array.isArray(group.children)) {
+ this.$set(group, "children", []);
+ }
+ return group.children;
+ },
+ addFooterNav() {
+ if (!Array.isArray(this.fullConfig.footer_nav)) {
+ this.fullConfig.footer_nav = [];
+ }
+ this.fullConfig.footer_nav.push({
+ name: "",
+ children: [],
+ });
+ },
+ removeFooterNav(index) {
+ this.footerNavList.splice(index, 1);
+ },
+ addFooterNavChild(index) {
+ const group = this.footerNavList[index];
+ if (!group) return;
+ if (!Array.isArray(group.children)) {
+ this.$set(group, "children", []);
+ }
+ group.children.push({
+ name: "",
+ url: "",
+ blank: false,
+ });
+ },
+ removeFooterNavChild(index, childIndex) {
+ const group = this.footerNavList[index];
+ if (!group || !Array.isArray(group.children)) return;
+ group.children.splice(childIndex, 1);
+ },
saveConfig() {
this.saving = true;
const payload = {
@@ -536,6 +1084,15 @@
this.saving = false;
});
},
+ toggleAdvanced() {
+ this.showAdvanced = !this.showAdvanced;
+ if (this.showAdvanced) {
+ this.syncJson();
+ this.activeTab = "advanced";
+ } else if (this.activeTab === "advanced") {
+ this.activeTab = "basic";
+ }
+ },
},
mounted() {
this.loadConfig();
@@ -543,3 +1100,4 @@
});
})();
+
diff --git a/plugins/addon/theme_configurator/template/admin/theme.css b/plugins/addon/theme_configurator/template/admin/theme.css
index e964046..a487c5c 100644
--- a/plugins/addon/theme_configurator/template/admin/theme.css
+++ b/plugins/addon/theme_configurator/template/admin/theme.css
@@ -97,6 +97,11 @@
margin-top: 20px;
}
+.upload-row {
+ display: flex;
+ align-items: center;
+}
+
.mt-10 {
margin-top: 10px;
}