feat: support custom footer and hide when logged in

This commit is contained in:
Zhang Minghan 2024-02-13 20:32:22 +08:00
parent 780a55a109
commit 3a6eed9ec4
9 changed files with 69 additions and 17 deletions

View File

@ -18,6 +18,8 @@ export type SiteInfo = {
buy_link: string;
mail: boolean;
contact: string;
footer: string;
auth_footer: boolean;
article: string[];
generation: string[];
};
@ -36,6 +38,8 @@ export async function getSiteInfo(): Promise<SiteInfo> {
announcement: "",
buy_link: "",
contact: "",
footer: "",
auth_footer: false,
mail: false,
article: [],
generation: [],

View File

@ -35,6 +35,8 @@ export type SiteState = {
buy_link: string;
announcement: string;
contact: string;
footer: string;
auth_footer: boolean;
};
export type CommonState = {
@ -119,6 +121,8 @@ export const initialSystemState: SystemProps = {
buy_link: "",
announcement: "",
contact: "",
footer: "",
auth_footer: false,
},
mail: {
host: "",

View File

@ -11,25 +11,36 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog.tsx";
import { getLanguage } from "@/i18n.ts";
import { selectAuthenticated } from "@/store/auth.ts";
import { appLogo } from "@/conf/env.ts";
import {
infoArticleSelector,
infoAuthFooterSelector,
infoContactSelector,
infoFooterSelector,
infoGenerationSelector,
} from "@/store/info.ts";
import Markdown from "@/components/Markdown.tsx";
import { hitGroup } from "@/utils/groups.ts";
function Footer() {
const auth = useSelector(selectAuthenticated);
const footer = useSelector(infoFooterSelector);
const auth_footer = useSelector(infoAuthFooterSelector);
if (auth && auth_footer) {
// hide footer
return null;
}
return footer.length > 0 && <Markdown acceptHtml={true}>{footer}</Markdown>;
}
function ChatSpace() {
const [open, setOpen] = useState(false);
const { t } = useTranslation();
const contact = useSelector(infoContactSelector);
const cn = getLanguage() === "cn";
const auth = useSelector(selectAuthenticated);
const generationGroup = useSelector(infoGenerationSelector);
const generation = hitGroup(generationGroup);
@ -84,18 +95,7 @@ function ChatSpace() {
</DialogContent>
</Dialog>
<div className={`space-footer`}>
{cn && !auth && (
<p>
<a
href={`http://www.cac.gov.cn/2023-07/13/c_1690898327029107.htm`}
target={`_blank`}
>
</a>
使
</p>
)}
<Footer />
</div>
</div>
);

View File

@ -3,6 +3,8 @@ import { EventCommitter } from "@/events/struct.ts";
export type InfoForm = {
mail: boolean;
contact: string;
footer: string;
auth_footer: boolean;
article: string[];
generation: string[];
};

View File

@ -664,6 +664,9 @@
"announcementPlaceholder": "请输入站点公告 (支持 Markdown / HTML 格式)",
"contact": "联系信息",
"contactPlaceholder": "请输入联系信息 (支持 Markdown / HTML 格式)",
"footer": "页脚信息",
"footerPlaceholder": "请输入页脚信息 (支持 Markdown / HTML 格式)",
"authFooter": "登录后隐藏页脚",
"article": "批量文章生成功能分组",
"articleTip": "批量文章生成功能分组,勾选后当前用户组可使用批量文章生成功能",
"generate": "AI 项目生成器分组",

View File

@ -522,6 +522,30 @@ function Site({ data, dispatch, onChange }: CompProps<SiteState>) {
placeholder={t("admin.system.contactPlaceholder")}
/>
</ParagraphItem>
<ParagraphSpace />
<ParagraphItem rowLayout={true}>
<Label>{t("admin.system.footer")}</Label>
<Textarea
value={data.footer}
rows={6}
onChange={(e) =>
dispatch({
type: "update:site.footer",
value: e.target.value,
})
}
placeholder={t("admin.system.footerPlaceholder")}
/>
</ParagraphItem>
<ParagraphItem>
<Label>{t("admin.system.authFooter")}</Label>
<Switch
checked={data.auth_footer}
onCheckedChange={(value) => {
dispatch({ type: "update:site.auth_footer", value });
}}
/>
</ParagraphItem>
<ParagraphFooter>
<div className={`grow`} />
<Button

View File

@ -17,6 +17,8 @@ export const infoSlice = createSlice({
contact: getMemory("contact"),
article: getArrayMemory("article"),
generation: getArrayMemory("generation"),
footer: getMemory("footer"),
auth_footer: getBooleanMemory("auth_footer", false),
} as InfoForm,
reducers: {
setForm: (state, action) => {
@ -25,11 +27,15 @@ export const infoSlice = createSlice({
state.contact = form.contact ?? "";
state.article = form.article ?? [];
state.generation = form.generation ?? [];
state.footer = form.footer ?? "";
state.auth_footer = form.auth_footer ?? false;
setBooleanMemory("mail", state.mail);
setMemory("contact", state.contact);
setArrayMemory("article", state.article);
setArrayMemory("generation", state.generation);
setMemory("footer", state.footer);
setBooleanMemory("auth_footer", state.auth_footer);
},
},
});
@ -46,3 +52,7 @@ export const infoArticleSelector = (state: RootState): string[] =>
state.info.article;
export const infoGenerationSelector = (state: RootState): string[] =>
state.info.generation;
export const infoFooterSelector = (state: RootState): string =>
state.info.footer;
export const infoAuthFooterSelector = (state: RootState): boolean =>
state.info.auth_footer;

View File

@ -16,6 +16,8 @@ type ApiInfo struct {
Announcement string `json:"announcement"`
BuyLink string `json:"buy_link"`
Contact string `json:"contact"`
Footer string `json:"footer"`
AuthFooter bool `json:"auth_footer"`
Mail bool `json:"mail"`
Article []string `json:"article"`
Generation []string `json:"generation"`
@ -34,6 +36,8 @@ type siteState struct {
BuyLink string `json:"buy_link" mapstructure:"buylink"`
Announcement string `json:"announcement" mapstructure:"announcement"`
Contact string `json:"contact" mapstructure:"contact"`
Footer string `json:"footer" mapstructure:"footer"`
AuthFooter bool `json:"auth_footer" mapstructure:"authfooter"`
}
type whiteList struct {
@ -108,6 +112,8 @@ func (c *SystemConfig) AsInfo() ApiInfo {
Docs: c.General.Docs,
Announcement: c.Site.Announcement,
Contact: c.Site.Contact,
Footer: c.Site.Footer,
AuthFooter: c.Site.AuthFooter,
BuyLink: c.Site.BuyLink,
Mail: c.IsMailValid(),
Article: c.Common.Article,

View File

@ -42,7 +42,6 @@ func PreflightCache(cache *redis.Client, hash string, buffer *utils.Buffer, hook
buf, err := utils.UnmarshalString[utils.Buffer](raw)
if err != nil {
fmt.Println(err)
return idx, false, nil
}