init local code

This commit is contained in:
chenxing
2026-09-07 09:11:37 +08:00
commit a3a75c3680
112 changed files with 24837 additions and 0 deletions
+244
View File
@@ -0,0 +1,244 @@
import { Method } from "alova";
import { alovaInstance } from "@/utils/alova/alova-iview";
import conf from "@/assets/config/host.config";
import { IObj } from "@/types/Basics";
import {
ArticleEditVo,
ArticlePageItem,
ArticlePageQuery,
ArticleSaveRequest,
AttachmentVo,
AuthUserInfo,
BannerVo,
CategoryTreeNode,
DeleteRequest,
LinkVo,
PageResult,
SchoolCard,
SchoolOption,
SiteVo,
ThemeVo,
} from "@/types/cms";
/**
* CMS 管理端 API(手写 class 风格,同 Notice front 约定)。
* baseURL = conf.serviceHost(dev 为空串走 vite 代理;生产 = 源 + /cms 上下文)。
*/
const AUTH = "/api/auth";
const BASE = "/api/base";
const SCHOOL = "/api/school";
const SITE = "/api/site";
const CATEGORY = "/api/category";
const ARTICLE = "/api/article";
const ATTACHMENT = "/api/attachment";
const BANNER = "/api/banner";
const LINK = "/api/link";
const THEME = "/api/theme";
/** GET(query 参数) */
function get<T>(url: string, params?: IObj): Method {
return alovaInstance.Get<T>(url, { params });
}
/** POST JSON(@RequestBody) */
function postJSON<T>(url: string, data?: unknown): Method {
return alovaInstance.Post<T>(url, data, {
headers: { "Content-Type": "application/json;charset=UTF-8" },
});
}
/** 上传地址(wangEditor customUpload / Upload 组件 action 直链,不经 alova) */
export function uploadUrl(): string {
return `${conf.isMock ? "" : conf.serviceHost}/api/attachment/upload`;
}
/** 门户预览基地址({serviceHost}/portal/{siteCode}) */
export function portalBase(siteCode: string): string {
return `${conf.isMock ? "" : conf.serviceHost}/portal/${siteCode}`;
}
class AuthApi {
/** 登录态:用户 + 可管理站点 + 是否超管 */
getUser() {
return get<AuthUserInfo>(`${AUTH}/user`);
}
}
/** 平台代理域(Notice BaseApiController 同款契约) */
class BaseApi {
/** 当前登录用户信息(CAS 会话注入,头像/姓名用于 layout) */
getUserInfo() {
return get<any>(`${BASE}/GetUserInfo`);
}
/** 当前用户已授权的模块列表(左侧菜单树) */
getUserMod() {
return get<any[]>(`${BASE}/GetUserMod`);
}
}
class SchoolApi {
/** 学校工作台列表(学校卡片 = 顶层站点聚合,docs/09 §3.3) */
list() {
return get<SchoolCard[]>(`${SCHOOL}/list`);
}
/** UserBase 学校选项(添加学校绑定用,仅超管;平台不可达为空数组) */
options() {
return get<SchoolOption[]>(`${SCHOOL}/options`);
}
}
class SiteApi {
list() {
return get<SiteVo[]>(`${SITE}/list`);
}
/** 入参对齐 SiteSaveRequest(themeParams 服务端合并进 config_json.theme_params,方案 §5.3) */
save(data: Partial<SiteVo> & { themeParams?: Record<string, string> }) {
return postJSON<SiteVo>(`${SITE}/save`, data);
}
}
class CategoryApi {
tree(siteId: number) {
return get<CategoryTreeNode[]>(`${CATEGORY}/tree`, { siteId });
}
save(data: Partial<CategoryTreeNode>) {
return postJSON<CategoryTreeNode>(`${CATEGORY}/save`, data);
}
delete(data: DeleteRequest) {
return postJSON<void>(`${CATEGORY}/delete`, data);
}
/** 子栏目排序(UserBase SortChildren 同语义:按传入顺序落库 sortNo=1..n) */
sort(data: { siteId: number; parentId: number; ids: number[] }) {
return postJSON<void>(`${CATEGORY}/sort`, data);
}
}
class ArticleApi {
page(query: ArticlePageQuery) {
return get<PageResult<ArticlePageItem>>(`${ARTICLE}/page`, { ...query });
}
/** 编辑回显 */
get(siteId: number, id: number) {
return get<ArticleEditVo>(`${ARTICLE}/get`, { siteId, id });
}
/** 保存草稿(content 服务端 jsoup 清洗) */
save(data: ArticleSaveRequest) {
return postJSON<number>(`${ARTICLE}/save`, data);
}
/** 发布(publishTime 为未来时间即定时发布) */
publish(siteId: number, id: number) {
return postJSON<void>(`${ARTICLE}/publish/${id}`, undefined, {
params: { siteId },
});
}
offline(siteId: number, id: number) {
return postJSON<void>(`${ARTICLE}/offline/${id}`, undefined, {
params: { siteId },
});
}
topmost(siteId: number, id: number, enable: boolean) {
return postJSON<void>(`${ARTICLE}/topmost/${id}`, undefined, {
params: { siteId, enable },
});
}
delete(data: DeleteRequest) {
return postJSON<void>(`${ARTICLE}/delete`, data);
}
}
class AttachmentApi {
page(siteId: number, orphanOnly: boolean, page: number, pageSize: number) {
return get<PageResult<AttachmentVo> & { orphanCount: number }>(`${ATTACHMENT}/page`, {
siteId,
orphanOnly,
page,
pageSize,
});
}
delete(data: DeleteRequest) {
return postJSON<void>(`${ATTACHMENT}/delete`, data);
}
}
class BannerApi {
list(siteId: number, position?: string) {
return get<BannerVo[]>(`${BANNER}/list`, { siteId, position });
}
save(data: Partial<BannerVo>) {
return postJSON<BannerVo>(`${BANNER}/save`, data);
}
delete(data: DeleteRequest) {
return postJSON<void>(`${BANNER}/delete`, data);
}
}
class LinkApi {
list(siteId: number) {
return get<LinkVo[]>(`${LINK}/list`, { siteId });
}
save(data: Partial<LinkVo>) {
return postJSON<LinkVo>(`${LINK}/save`, data);
}
delete(data: DeleteRequest) {
return postJSON<void>(`${LINK}/delete`, data);
}
}
class ThemeApi {
/** 可用主题列表(含 params schema,建站向导/站点编辑共用,方案 §5.2) */
list() {
return get<ThemeVo[]>(`${THEME}/list`);
}
}
/** 主题预览 iframe URL(方案 §5.5:/api/theme/preview,CAS 会话同源,参数 p_ 前缀) */
export function themePreviewUrl(siteCode: string, theme: string, themeParams: Record<string, string> = {}): string {
const params = new URLSearchParams({ siteCode, theme, page: "home" });
Object.keys(themeParams).forEach(k => params.set(`p_${k}`, themeParams[k]));
return `${conf.isMock ? "" : conf.serviceHost}/api/theme/preview?${params.toString()}`;
}
export const authApi = new AuthApi();
export const baseApi = new BaseApi();
export const schoolApi = new SchoolApi();
export const siteApi = new SiteApi();
export const categoryApi = new CategoryApi();
export const articleApi = new ArticleApi();
export const attachmentApi = new AttachmentApi();
export const bannerApi = new BannerApi();
export const linkApi = new LinkApi();
export const themeApi = new ThemeApi();
export default {
authApi,
baseApi,
schoolApi,
siteApi,
categoryApi,
articleApi,
attachmentApi,
bannerApi,
linkApi,
themeApi,
uploadUrl,
portalBase,
themePreviewUrl,
};