mirror of
				https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
				synced 2025-11-04 16:23:41 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			176 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { create } from "zustand";
 | 
						|
import { persist } from "zustand/middleware";
 | 
						|
import Fuse from "fuse.js";
 | 
						|
import { getLang } from "../locales";
 | 
						|
import { StoreKey } from "../constant";
 | 
						|
 | 
						|
export interface Prompt {
 | 
						|
  id?: number;
 | 
						|
  isUser?: boolean;
 | 
						|
  title: string;
 | 
						|
  content: string;
 | 
						|
}
 | 
						|
 | 
						|
export interface PromptStore {
 | 
						|
  counter: number;
 | 
						|
  latestId: number;
 | 
						|
  prompts: Record<number, Prompt>;
 | 
						|
 | 
						|
  add: (prompt: Prompt) => number;
 | 
						|
  get: (id: number) => Prompt | undefined;
 | 
						|
  remove: (id: number) => void;
 | 
						|
  search: (text: string) => Prompt[];
 | 
						|
  update: (id: number, updater: (prompt: Prompt) => void) => void;
 | 
						|
 | 
						|
  getUserPrompts: () => Prompt[];
 | 
						|
}
 | 
						|
 | 
						|
export const SearchService = {
 | 
						|
  ready: false,
 | 
						|
  builtinEngine: new Fuse<Prompt>([], { keys: ["title"] }),
 | 
						|
  userEngine: new Fuse<Prompt>([], { keys: ["title"] }),
 | 
						|
  count: {
 | 
						|
    builtin: 0,
 | 
						|
  },
 | 
						|
  allPrompts: [] as Prompt[],
 | 
						|
  builtinPrompts: [] as Prompt[],
 | 
						|
 | 
						|
  init(builtinPrompts: Prompt[], userPrompts: Prompt[]) {
 | 
						|
    if (this.ready) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    this.allPrompts = userPrompts.concat(builtinPrompts);
 | 
						|
    this.builtinPrompts = builtinPrompts.slice();
 | 
						|
    this.builtinEngine.setCollection(builtinPrompts);
 | 
						|
    this.userEngine.setCollection(userPrompts);
 | 
						|
    this.ready = true;
 | 
						|
  },
 | 
						|
 | 
						|
  remove(id: number) {
 | 
						|
    this.userEngine.remove((doc) => doc.id === id);
 | 
						|
  },
 | 
						|
 | 
						|
  add(prompt: Prompt) {
 | 
						|
    this.userEngine.add(prompt);
 | 
						|
  },
 | 
						|
 | 
						|
  search(text: string) {
 | 
						|
    const userResults = this.userEngine.search(text);
 | 
						|
    const builtinResults = this.builtinEngine.search(text);
 | 
						|
    return userResults.concat(builtinResults).map((v) => v.item);
 | 
						|
  },
 | 
						|
};
 | 
						|
 | 
						|
export const usePromptStore = create<PromptStore>()(
 | 
						|
  persist(
 | 
						|
    (set, get) => ({
 | 
						|
      counter: 0,
 | 
						|
      latestId: 0,
 | 
						|
      prompts: {},
 | 
						|
 | 
						|
      add(prompt) {
 | 
						|
        const prompts = get().prompts;
 | 
						|
        prompt.id = get().latestId + 1;
 | 
						|
        prompt.isUser = true;
 | 
						|
        prompts[prompt.id] = prompt;
 | 
						|
 | 
						|
        set(() => ({
 | 
						|
          latestId: prompt.id!,
 | 
						|
          prompts: prompts,
 | 
						|
        }));
 | 
						|
 | 
						|
        return prompt.id!;
 | 
						|
      },
 | 
						|
 | 
						|
      get(id) {
 | 
						|
        const targetPrompt = get().prompts[id];
 | 
						|
 | 
						|
        if (!targetPrompt) {
 | 
						|
          return SearchService.builtinPrompts.find((v) => v.id === id);
 | 
						|
        }
 | 
						|
 | 
						|
        return targetPrompt;
 | 
						|
      },
 | 
						|
 | 
						|
      remove(id) {
 | 
						|
        const prompts = get().prompts;
 | 
						|
        delete prompts[id];
 | 
						|
        SearchService.remove(id);
 | 
						|
 | 
						|
        set(() => ({
 | 
						|
          prompts,
 | 
						|
          counter: get().counter + 1,
 | 
						|
        }));
 | 
						|
      },
 | 
						|
 | 
						|
      getUserPrompts() {
 | 
						|
        const userPrompts = Object.values(get().prompts ?? {});
 | 
						|
        userPrompts.sort((a, b) => (b.id && a.id ? b.id - a.id : 0));
 | 
						|
        return userPrompts;
 | 
						|
      },
 | 
						|
 | 
						|
      update(id: number, updater) {
 | 
						|
        const prompt = get().prompts[id] ?? {
 | 
						|
          title: "",
 | 
						|
          content: "",
 | 
						|
          id,
 | 
						|
        };
 | 
						|
 | 
						|
        SearchService.remove(id);
 | 
						|
        updater(prompt);
 | 
						|
        const prompts = get().prompts;
 | 
						|
        prompts[id] = prompt;
 | 
						|
        set(() => ({ prompts }));
 | 
						|
        SearchService.add(prompt);
 | 
						|
      },
 | 
						|
 | 
						|
      search(text) {
 | 
						|
        if (text.length === 0) {
 | 
						|
          // return all rompts
 | 
						|
          return SearchService.allPrompts.concat([...get().getUserPrompts()]);
 | 
						|
        }
 | 
						|
        return SearchService.search(text) as Prompt[];
 | 
						|
      },
 | 
						|
    }),
 | 
						|
    {
 | 
						|
      name: StoreKey.Prompt,
 | 
						|
      version: 1,
 | 
						|
      onRehydrateStorage(state) {
 | 
						|
        const PROMPT_URL = "./prompts.json";
 | 
						|
 | 
						|
        type PromptList = Array<[string, string]>;
 | 
						|
 | 
						|
        fetch(PROMPT_URL)
 | 
						|
          .then((res) => res.json())
 | 
						|
          .then((res) => {
 | 
						|
            let fetchPrompts = [res.en, res.cn];
 | 
						|
            if (getLang() === "cn") {
 | 
						|
              fetchPrompts = fetchPrompts.reverse();
 | 
						|
            }
 | 
						|
            const builtinPrompts = fetchPrompts.map(
 | 
						|
              (promptList: PromptList) => {
 | 
						|
                return promptList.map(
 | 
						|
                  ([title, content]) =>
 | 
						|
                    ({
 | 
						|
                      id: Math.random(),
 | 
						|
                      title,
 | 
						|
                      content,
 | 
						|
                    } as Prompt),
 | 
						|
                );
 | 
						|
              },
 | 
						|
            );
 | 
						|
 | 
						|
            const userPrompts =
 | 
						|
              usePromptStore.getState().getUserPrompts() ?? [];
 | 
						|
 | 
						|
            const allPromptsForSearch = builtinPrompts
 | 
						|
              .reduce((pre, cur) => pre.concat(cur), [])
 | 
						|
              .filter((v) => !!v.title && !!v.content);
 | 
						|
            SearchService.count.builtin = res.en.length + res.cn.length;
 | 
						|
            SearchService.init(allPromptsForSearch, userPrompts);
 | 
						|
          });
 | 
						|
      },
 | 
						|
    },
 | 
						|
  ),
 | 
						|
);
 |