This commit is contained in:
fengchuanhn@gmail.com
2026-05-21 17:19:30 +08:00
parent 5e17e68329
commit eba781d15d
2 changed files with 119 additions and 6 deletions

113
src/api/oemAppBranding.js Normal file
View File

@@ -0,0 +1,113 @@
import { apiRequest } from "./client.js";
/** 品牌静态资源基址(与 pythonbackend 根目录 images 挂载的 /images 一致) */
const MEDIA_BASE =
import.meta.env.VITE_MEDIA_BASE_URL || "http://127.0.0.1:8001";
/**
* @param {string} token
* @param {RequestInit} [options]
*/
function oemRequest(token, path, options = {}) {
return apiRequest(path, {
...options,
headers: {
Authorization: `Bearer ${token}`,
...options.headers,
},
});
}
function emptyBrandingForm() {
return {
softwareName: "",
logo: "",
contactWechat: "",
contactQq: "",
wechatQr: "",
qqQr: "",
};
}
/**
* 库内路径 images/xxx → 可访问 URL预览用
* @param {string | null | undefined} path
*/
export function brandingImageUrl(path) {
if (!path?.trim()) return "";
const value = path.trim();
if (value.startsWith("data:image/") || value.startsWith("http")) return value;
const normalized = value.replace(/\\/g, "/").replace(/^\//, "");
if (normalized.startsWith("images/")) {
return `${MEDIA_BASE}/${normalized}`;
}
return `${MEDIA_BASE}/images/${normalized}`;
}
/** 提交前:新上传保留 data URL已有文件只提交 images/ 相对路径 */
function toStoredImageValue(value) {
if (!value?.trim()) return null;
const v = value.trim();
if (v.startsWith("data:image/")) return v;
const match = v.match(/\/images\/(.+?)(?:\?.*)?$/);
if (match) return `images/${match[1]}`;
if (v.startsWith("images/")) return v;
return v;
}
/** API 载荷 → 表单 */
function toForm(data) {
if (!data) return emptyBrandingForm();
return {
softwareName: data.software_name ?? "",
logo: brandingImageUrl(data.logo_path),
contactWechat: data.wechat ?? "",
contactQq: data.qq ?? "",
wechatQr: brandingImageUrl(data.wechat_qrcode),
qqQr: brandingImageUrl(data.qq_qrcode),
};
}
/** 表单 → API 载荷 */
function toPayload(form) {
return {
software_name: String(form.softwareName ?? "").trim(),
logo_path: toStoredImageValue(form.logo),
wechat: form.contactWechat?.trim() || null,
qq: form.contactQq?.trim() || null,
wechat_qrcode: toStoredImageValue(form.wechatQr),
qq_qrcode: toStoredImageValue(form.qqQr),
};
}
/**
* 加载默认 OEMid=1软件配置
* @param {string} token
*/
export async function loadOemAppBrandingApi(token) {
const res = await oemRequest(token, "/oem/oem-branding");
if (!res.ok) {
return { ok: false, message: res.message || "加载软件配置失败" };
}
return { ok: true, data: { form: toForm(res.data), oemId: res.data?.id ?? 1 } };
}
/**
* 保存默认 OEMid=1软件配置
* @param {string} token
* @param {ReturnType<typeof emptyBrandingForm>} form
*/
export async function saveOemAppBrandingApi(token, form) {
const res = await oemRequest(token, "/oem/oem-branding", {
method: "PATCH",
body: JSON.stringify(toPayload(form)),
});
if (!res.ok) {
return { ok: false, message: res.message || "保存软件配置失败" };
}
return {
ok: true,
message: res.message || "软件配置已保存",
data: { form: toForm(res.data), oemId: res.data?.id ?? 1 },
};
}

View File

@@ -1,11 +1,11 @@
<script setup> <script setup>
import { onMounted, ref } from "vue"; import { onMounted, ref } from "vue";
import { useAuthStore } from "../../stores/auth.js"; import { useAuthStore } from "../../stores/auth.js";
import AdminImageUpload from "../../components/admin/AdminImageUpload.vue"; import AdminImageUpload from "../../components/oem/OemImageUpload.vue";
import { import {
loadAdminAppBrandingApi, loadOemAppBrandingApi,
saveAdminAppBrandingApi, saveOemAppBrandingApi,
} from "../../api/adminAppBranding.js"; } from "../../api/oemAppBranding.js";
const auth = useAuthStore(); const auth = useAuthStore();
@@ -33,7 +33,7 @@ function onImageError(message) {
async function loadSettings() { async function loadSettings() {
loading.value = true; loading.value = true;
feedback.value = { severity: "", message: "" }; feedback.value = { severity: "", message: "" };
const res = await loadAdminAppBrandingApi(auth.token); const res = await loadOemAppBrandingApi(auth.token);
loading.value = false; loading.value = false;
if (!res.ok) { if (!res.ok) {
@@ -47,7 +47,7 @@ async function loadSettings() {
async function saveSettings() { async function saveSettings() {
saving.value = true; saving.value = true;
feedback.value = { severity: "", message: "" }; feedback.value = { severity: "", message: "" };
const res = await saveAdminAppBrandingApi(auth.token, form.value); const res = await saveOemAppBrandingApi(auth.token, form.value);
saving.value = false; saving.value = false;
if (!res.ok) { if (!res.ok) {