diff --git a/README.md b/README.md index 1758483..36e2c22 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Gorse Docs -[![Netlify Status](https://api.netlify.com/api/v1/badges/2480ea13-f8c7-4c84-aa77-51f105ac5bbf/deploy-status)](https://app.netlify.com/sites/gorse-io/deploys) Official documents for Gorse recommender system. diff --git a/src/.vuepress/components/WeChatLink.ts b/src/.vuepress/components/WeChatLink.ts index d7bc63f..e32a2e5 100644 --- a/src/.vuepress/components/WeChatLink.ts +++ b/src/.vuepress/components/WeChatLink.ts @@ -1,20 +1,94 @@ -import { type FunctionalComponent, h } from "vue"; - -const TwitterLink: FunctionalComponent = () => - h( - "div", - { class: "vp-nav-item vp-action" }, - h("a", { - class: "vp-action-link", - href: "https://gorse.io/weixin.jpg", - target: "_blank", - rel: "noopener noreferrer", - "aria-label": "wechat", - innerHTML: - '', - }) - ); - -TwitterLink.displayName = "DiscordLink"; - -export default TwitterLink; \ No newline at end of file +import { defineComponent, h, onBeforeUnmount, onMounted, ref } from "vue"; + +export default defineComponent({ + name: "WeChatLink", + setup() { + const containerRef = ref(null); + const showPopup = ref(false); + + const togglePopup = () => { + showPopup.value = !showPopup.value; + }; + + const closePopup = () => { + showPopup.value = false; + }; + + const handleDocumentClick = (event: MouseEvent) => { + const target = event.target; + + if ( + showPopup.value && + target instanceof Node && + containerRef.value && + !containerRef.value.contains(target) + ) { + closePopup(); + } + }; + + onMounted(() => { + document.addEventListener("click", handleDocumentClick); + }); + + onBeforeUnmount(() => { + document.removeEventListener("click", handleDocumentClick); + }); + + return () => + h( + "div", + { + ref: containerRef, + class: "vp-nav-item vp-action wechat-container", + style: { position: "relative" }, + }, + [ + h("a", { + class: "vp-action-link", + href: "#", + "aria-label": "wechat", + onClick: (e: Event) => { + e.preventDefault(); + togglePopup(); + }, + innerHTML: '', + }), + showPopup.value + ? h( + "div", + { + class: "wechat-popup", + style: { + position: "absolute", + top: "100%", + right: "0", + marginTop: "8px", + padding: "16px", + zIndex: "100", + }, + }, + [ + h("img", { + src: "https://gorse.io/weixin.jpg", + alt: "WeChat QR Code", + style: { + width: "150px", + height: "150px", + display: "block", + }, + }), + h( + "div", + { + class: "wechat-popup-text", + }, + "扫码关注公众号" + ), + ] + ) + : null, + ] + ); + }, +}); diff --git a/src/.vuepress/styles/index.scss b/src/.vuepress/styles/index.scss index f6af387..893462a 100644 --- a/src/.vuepress/styles/index.scss +++ b/src/.vuepress/styles/index.scss @@ -1 +1,36 @@ // place your custom styles here + +// WeChat popup styles +.wechat-container { + position: relative; +} + +.wechat-popup { + animation: fadeIn 0.2s ease-in-out; + border: 1px solid var(--vp-c-border); + border-radius: 8px; + background: var(--vp-c-bg); + box-shadow: 0 8px 24px rgb(0 0 0 / 12%); + text-align: center; +} + +.wechat-popup img { + border-radius: 4px; +} + +.wechat-popup-text { + margin-top: 8px; + font-size: 14px; + color: var(--vp-c-text-mute); +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(-8px); + } + to { + opacity: 1; + transform: translateY(0); + } +} diff --git a/src/docs/concepts/data-source.md b/src/docs/concepts/data-source.md index c2c8e2e..79631dd 100644 --- a/src/docs/concepts/data-source.md +++ b/src/docs/concepts/data-source.md @@ -86,6 +86,25 @@ Before inserting feedback into the Gorse recommender system, it is necessary to - **Read Feedback:** The user sees the item. - **Positive feedback:** The user action that is expected to do by the service provider. +### Negative Feedback + +Negative feedback represents explicit user dislike or disinterest in an item. Unlike read feedback (which indicates the user simply viewed an item), negative feedback explicitly tells the recommender system that the user does not want to see similar items in the future. + +Common examples of negative feedback include: +- **Dislike button**: User clicks a "dislike" or "thumbs down" button +- **Not interested**: User selects "not interested" or "hide this" option +- **Explicit removal**: User removes an item from their recommendations + +Negative feedback has the **highest priority** in the recommendation system. When a user gives negative feedback to an item: +- The item will never be recommended to that user again +- Similar items will be deprioritized in recommendations + +To configure negative feedback, add the feedback type to `negative_feedback_types` in the configuration: + +::: warning +Negative feedback should be used sparingly. Only configure truly negative actions as negative feedback. Actions like "skip" or "close" should be treated as read feedback, not negative feedback. +::: + ### Insert Feedback There are two ways to insert feedback into the Gorse recommender system: inserting new feedback and updating existing feedback. Inserting new feedback is done via the `PUT /api/feedback` API, while updating existing feedback is done via the `POST /api/feedback` API. Both APIs accept a list of feedback in JSON format. @@ -162,6 +181,7 @@ There are several configuration options related to data source in Gorse: - `positive_feedback_types`: A list of feedback types that are considered positive feedback. - `read_feedback_types`: A list of feedback types that are considered read feedback. +- `negative_feedback_types`: A list of feedback types that are considered negative feedback. - `positive_feedback_ttl`: Time-to-live for positive feedback in days. After this period, positive feedback will be ignored in recommendations. Default value: `0` (no expiration). - `item_ttl`: Time-to-live for items in days. After this period, items will be automatically hidden from recommendations. Default value: `0` (no expiration). @@ -171,11 +191,12 @@ TTL is used to automatically remove old feedback and items from the recommender ## Example -In the demo project [GitRec](https://gitrec.gorse.io/), the following configuration is used to define positive feedback as "star", "like", and "read" with a value greater than or equal to 3. Read feedback is defined as "read". Both positive feedback and items do not expire. +In the demo project [GitRec](https://gitrec.gorse.io/), the following configuration is used to define positive feedback as "star", "like", and "read" with a value greater than or equal to 3. Read feedback is defined as "read". Negative feedback is defined as "dislike". Both positive feedback and items do not expire. ```toml [recommend.data_source] positive_feedback_types = ["star","like","read>=3"] +negative_feedback_types = ["dislike"] read_feedback_types = ["read"] positive_feedback_ttl = 0 item_ttl = 0 diff --git a/src/docs/config.md b/src/docs/config.md index c7d82b4..7591f8b 100644 --- a/src/docs/config.md +++ b/src/docs/config.md @@ -149,6 +149,7 @@ Configuration for [data source](./concepts/data-source) of recommenders. |---------------------------|--------|---------|-----------------------------------| | `positive_feedback_types` | string | | Types of positive feedback | | `read_feedback_types` | string | | Type of read feedback | +| `negative_feedback_types` | string | | Types of negative feedback | | `positive_feedback_ttl` | string | `0` | Time-to-live of positive feedback | | `item_ttl` | string | `0` | Time-to-live of items | diff --git a/src/zh/docs/concepts/data-source.md b/src/zh/docs/concepts/data-source.md index 0581f89..66b9d4d 100644 --- a/src/zh/docs/concepts/data-source.md +++ b/src/zh/docs/concepts/data-source.md @@ -86,6 +86,23 @@ type Feedback struct { - **已读反馈:** 用户看到物品。 - **积极反馈:** 服务提供商期望用户执行的操作。 +### 负反馈 + +负反馈表示用户对物品的明确不喜欢或不感兴趣。与已读反馈(仅表示用户查看了物品)不同,负反馈明确告诉推荐系统用户将来不想看到类似的物品。 + +常见的负反馈示例包括: +- **不喜欢按钮**:用户点击"不喜欢"或"踩"按钮 +- **不感兴趣**:用户选择"不感兴趣"或"隐藏此内容"选项 +- **明确移除**:用户从推荐中移除物品 + +负反馈在推荐系统中具有**最高优先级**。当用户对物品给出负反馈时: +- 该物品将永远不会再次推荐给该用户 +- 相似物品在推荐中的优先级会降低 + +::: warning +负反馈应谨慎使用。只应将真正负面的操作配置为负反馈。如"跳过"或"关闭"等操作应视为已读反馈,而非负反馈。 +::: + ### 插入反馈 有两种方法可以将反馈插入 Gorse 推荐系统:插入新反馈和更新现有反馈。插入新反馈通过 `PUT /api/feedback` API 完成,而更新现有反馈通过 `POST /api/feedback` API 完成。两个 API 都接受 JSON 格式的反馈列表。 @@ -162,6 +179,7 @@ Gorse 中有几个与数据源相关的配置选项: - `positive_feedback_types`: 被视为积极反馈的反馈类型列表。 - `read_feedback_types`: 被视为已读反馈的反馈类型列表。 +- `negative_feedback_types`: 被视为负反馈的反馈类型列表。 - `positive_feedback_ttl`: 积极反馈的生存时间(天)。在此期限后,积极反馈将在推荐中被忽略。默认值:`0`(无过期)。 - `item_ttl`: 物品的生存时间(天)。在此期限后,物品将自动从推荐中隐藏。默认值:`0`(无过期)。 @@ -171,12 +189,13 @@ TTL 用于自动从推荐系统中删除旧的反馈和物品,以确保推荐 ## 示例 -在演示项目 [GitRec](https://gitrec.gorse.io/) 中,使用以下配置将积极反馈定义为“star”、“like”和值大于或等于 3 的“read”。已读反馈定义为“read”。积极反馈和物品都不会过期。 +在演示项目 [GitRec](https://gitrec.gorse.io/) 中,使用以下配置将积极反馈定义为"star"、"like"和值大于或等于 3 的"read"。已读反馈定义为"read"。负反馈定义为"dislike"。积极反馈和物品都不会过期。 ```toml [recommend.data_source] positive_feedback_types = ["star","like","read>=3"] read_feedback_types = ["read"] +negative_feedback_types = ["dislike"] positive_feedback_ttl = 0 item_ttl = 0 ``` diff --git a/src/zh/docs/config.md b/src/zh/docs/config.md index 9dad4b4..c58b397 100644 --- a/src/zh/docs/config.md +++ b/src/zh/docs/config.md @@ -149,6 +149,7 @@ chhttps://user:password@host[:port]/database?param1=value1&...¶mN=valueN |---------------------------|--------|-----|-----------| | `positive_feedback_types` | string | | 积极反馈的类型 | | `read_feedback_types` | string | | 已读反馈的类型 | +| `negative_feedback_types` | string | | 负反馈的类型 | | `positive_feedback_ttl` | string | `0` | 积极反馈的生存时间 | | `item_ttl` | string | `0` | 物品的生存时间 |