mirror of
https://github.com/coaidev/coai.git
synced 2025-05-31 19:00:22 +09:00
feat: support custom footer and hide when logged in
This commit is contained in:
parent
780a55a109
commit
3a6eed9ec4
@ -18,6 +18,8 @@ export type SiteInfo = {
|
|||||||
buy_link: string;
|
buy_link: string;
|
||||||
mail: boolean;
|
mail: boolean;
|
||||||
contact: string;
|
contact: string;
|
||||||
|
footer: string;
|
||||||
|
auth_footer: boolean;
|
||||||
article: string[];
|
article: string[];
|
||||||
generation: string[];
|
generation: string[];
|
||||||
};
|
};
|
||||||
@ -36,6 +38,8 @@ export async function getSiteInfo(): Promise<SiteInfo> {
|
|||||||
announcement: "",
|
announcement: "",
|
||||||
buy_link: "",
|
buy_link: "",
|
||||||
contact: "",
|
contact: "",
|
||||||
|
footer: "",
|
||||||
|
auth_footer: false,
|
||||||
mail: false,
|
mail: false,
|
||||||
article: [],
|
article: [],
|
||||||
generation: [],
|
generation: [],
|
||||||
|
@ -35,6 +35,8 @@ export type SiteState = {
|
|||||||
buy_link: string;
|
buy_link: string;
|
||||||
announcement: string;
|
announcement: string;
|
||||||
contact: string;
|
contact: string;
|
||||||
|
footer: string;
|
||||||
|
auth_footer: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CommonState = {
|
export type CommonState = {
|
||||||
@ -119,6 +121,8 @@ export const initialSystemState: SystemProps = {
|
|||||||
buy_link: "",
|
buy_link: "",
|
||||||
announcement: "",
|
announcement: "",
|
||||||
contact: "",
|
contact: "",
|
||||||
|
footer: "",
|
||||||
|
auth_footer: false,
|
||||||
},
|
},
|
||||||
mail: {
|
mail: {
|
||||||
host: "",
|
host: "",
|
||||||
|
@ -11,25 +11,36 @@ import {
|
|||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog.tsx";
|
} from "@/components/ui/dialog.tsx";
|
||||||
import { getLanguage } from "@/i18n.ts";
|
|
||||||
import { selectAuthenticated } from "@/store/auth.ts";
|
import { selectAuthenticated } from "@/store/auth.ts";
|
||||||
import { appLogo } from "@/conf/env.ts";
|
import { appLogo } from "@/conf/env.ts";
|
||||||
import {
|
import {
|
||||||
infoArticleSelector,
|
infoArticleSelector,
|
||||||
|
infoAuthFooterSelector,
|
||||||
infoContactSelector,
|
infoContactSelector,
|
||||||
|
infoFooterSelector,
|
||||||
infoGenerationSelector,
|
infoGenerationSelector,
|
||||||
} from "@/store/info.ts";
|
} from "@/store/info.ts";
|
||||||
import Markdown from "@/components/Markdown.tsx";
|
import Markdown from "@/components/Markdown.tsx";
|
||||||
import { hitGroup } from "@/utils/groups.ts";
|
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() {
|
function ChatSpace() {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const contact = useSelector(infoContactSelector);
|
const contact = useSelector(infoContactSelector);
|
||||||
|
|
||||||
const cn = getLanguage() === "cn";
|
|
||||||
const auth = useSelector(selectAuthenticated);
|
|
||||||
|
|
||||||
const generationGroup = useSelector(infoGenerationSelector);
|
const generationGroup = useSelector(infoGenerationSelector);
|
||||||
const generation = hitGroup(generationGroup);
|
const generation = hitGroup(generationGroup);
|
||||||
|
|
||||||
@ -84,18 +95,7 @@ function ChatSpace() {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
<div className={`space-footer`}>
|
<div className={`space-footer`}>
|
||||||
{cn && !auth && (
|
<Footer />
|
||||||
<p>
|
|
||||||
请您遵守
|
|
||||||
<a
|
|
||||||
href={`http://www.cac.gov.cn/2023-07/13/c_1690898327029107.htm`}
|
|
||||||
target={`_blank`}
|
|
||||||
>
|
|
||||||
《生成式人工智能服务管理暂行办法》
|
|
||||||
</a>
|
|
||||||
法规使用
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -3,6 +3,8 @@ import { EventCommitter } from "@/events/struct.ts";
|
|||||||
export type InfoForm = {
|
export type InfoForm = {
|
||||||
mail: boolean;
|
mail: boolean;
|
||||||
contact: string;
|
contact: string;
|
||||||
|
footer: string;
|
||||||
|
auth_footer: boolean;
|
||||||
article: string[];
|
article: string[];
|
||||||
generation: string[];
|
generation: string[];
|
||||||
};
|
};
|
||||||
|
@ -664,6 +664,9 @@
|
|||||||
"announcementPlaceholder": "请输入站点公告 (支持 Markdown / HTML 格式)",
|
"announcementPlaceholder": "请输入站点公告 (支持 Markdown / HTML 格式)",
|
||||||
"contact": "联系信息",
|
"contact": "联系信息",
|
||||||
"contactPlaceholder": "请输入联系信息 (支持 Markdown / HTML 格式)",
|
"contactPlaceholder": "请输入联系信息 (支持 Markdown / HTML 格式)",
|
||||||
|
"footer": "页脚信息",
|
||||||
|
"footerPlaceholder": "请输入页脚信息 (支持 Markdown / HTML 格式)",
|
||||||
|
"authFooter": "登录后隐藏页脚",
|
||||||
"article": "批量文章生成功能分组",
|
"article": "批量文章生成功能分组",
|
||||||
"articleTip": "批量文章生成功能分组,勾选后当前用户组可使用批量文章生成功能",
|
"articleTip": "批量文章生成功能分组,勾选后当前用户组可使用批量文章生成功能",
|
||||||
"generate": "AI 项目生成器分组",
|
"generate": "AI 项目生成器分组",
|
||||||
|
@ -522,6 +522,30 @@ function Site({ data, dispatch, onChange }: CompProps<SiteState>) {
|
|||||||
placeholder={t("admin.system.contactPlaceholder")}
|
placeholder={t("admin.system.contactPlaceholder")}
|
||||||
/>
|
/>
|
||||||
</ParagraphItem>
|
</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>
|
<ParagraphFooter>
|
||||||
<div className={`grow`} />
|
<div className={`grow`} />
|
||||||
<Button
|
<Button
|
||||||
|
@ -17,6 +17,8 @@ export const infoSlice = createSlice({
|
|||||||
contact: getMemory("contact"),
|
contact: getMemory("contact"),
|
||||||
article: getArrayMemory("article"),
|
article: getArrayMemory("article"),
|
||||||
generation: getArrayMemory("generation"),
|
generation: getArrayMemory("generation"),
|
||||||
|
footer: getMemory("footer"),
|
||||||
|
auth_footer: getBooleanMemory("auth_footer", false),
|
||||||
} as InfoForm,
|
} as InfoForm,
|
||||||
reducers: {
|
reducers: {
|
||||||
setForm: (state, action) => {
|
setForm: (state, action) => {
|
||||||
@ -25,11 +27,15 @@ export const infoSlice = createSlice({
|
|||||||
state.contact = form.contact ?? "";
|
state.contact = form.contact ?? "";
|
||||||
state.article = form.article ?? [];
|
state.article = form.article ?? [];
|
||||||
state.generation = form.generation ?? [];
|
state.generation = form.generation ?? [];
|
||||||
|
state.footer = form.footer ?? "";
|
||||||
|
state.auth_footer = form.auth_footer ?? false;
|
||||||
|
|
||||||
setBooleanMemory("mail", state.mail);
|
setBooleanMemory("mail", state.mail);
|
||||||
setMemory("contact", state.contact);
|
setMemory("contact", state.contact);
|
||||||
setArrayMemory("article", state.article);
|
setArrayMemory("article", state.article);
|
||||||
setArrayMemory("generation", state.generation);
|
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;
|
state.info.article;
|
||||||
export const infoGenerationSelector = (state: RootState): string[] =>
|
export const infoGenerationSelector = (state: RootState): string[] =>
|
||||||
state.info.generation;
|
state.info.generation;
|
||||||
|
export const infoFooterSelector = (state: RootState): string =>
|
||||||
|
state.info.footer;
|
||||||
|
export const infoAuthFooterSelector = (state: RootState): boolean =>
|
||||||
|
state.info.auth_footer;
|
||||||
|
@ -16,6 +16,8 @@ type ApiInfo struct {
|
|||||||
Announcement string `json:"announcement"`
|
Announcement string `json:"announcement"`
|
||||||
BuyLink string `json:"buy_link"`
|
BuyLink string `json:"buy_link"`
|
||||||
Contact string `json:"contact"`
|
Contact string `json:"contact"`
|
||||||
|
Footer string `json:"footer"`
|
||||||
|
AuthFooter bool `json:"auth_footer"`
|
||||||
Mail bool `json:"mail"`
|
Mail bool `json:"mail"`
|
||||||
Article []string `json:"article"`
|
Article []string `json:"article"`
|
||||||
Generation []string `json:"generation"`
|
Generation []string `json:"generation"`
|
||||||
@ -34,6 +36,8 @@ type siteState struct {
|
|||||||
BuyLink string `json:"buy_link" mapstructure:"buylink"`
|
BuyLink string `json:"buy_link" mapstructure:"buylink"`
|
||||||
Announcement string `json:"announcement" mapstructure:"announcement"`
|
Announcement string `json:"announcement" mapstructure:"announcement"`
|
||||||
Contact string `json:"contact" mapstructure:"contact"`
|
Contact string `json:"contact" mapstructure:"contact"`
|
||||||
|
Footer string `json:"footer" mapstructure:"footer"`
|
||||||
|
AuthFooter bool `json:"auth_footer" mapstructure:"authfooter"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type whiteList struct {
|
type whiteList struct {
|
||||||
@ -108,6 +112,8 @@ func (c *SystemConfig) AsInfo() ApiInfo {
|
|||||||
Docs: c.General.Docs,
|
Docs: c.General.Docs,
|
||||||
Announcement: c.Site.Announcement,
|
Announcement: c.Site.Announcement,
|
||||||
Contact: c.Site.Contact,
|
Contact: c.Site.Contact,
|
||||||
|
Footer: c.Site.Footer,
|
||||||
|
AuthFooter: c.Site.AuthFooter,
|
||||||
BuyLink: c.Site.BuyLink,
|
BuyLink: c.Site.BuyLink,
|
||||||
Mail: c.IsMailValid(),
|
Mail: c.IsMailValid(),
|
||||||
Article: c.Common.Article,
|
Article: c.Common.Article,
|
||||||
|
@ -42,7 +42,6 @@ func PreflightCache(cache *redis.Client, hash string, buffer *utils.Buffer, hook
|
|||||||
|
|
||||||
buf, err := utils.UnmarshalString[utils.Buffer](raw)
|
buf, err := utils.UnmarshalString[utils.Buffer](raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
|
||||||
return idx, false, nil
|
return idx, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user