diff --git a/src/data/i18n.ts b/src/data/i18n.ts index c85141d..2dc01fe 100644 --- a/src/data/i18n.ts +++ b/src/data/i18n.ts @@ -116,6 +116,18 @@ const i18ns: I18n[] = [ "tips": "请选择模式" } }, + { + id: "b4b7c9f5d8cc5466e9424d7538ff0176", + namespace: "new-demo-p-frontend-essay-details", + language: "zh-CN", + module: "new-demo", + position: "src/pages/frontend/essay/details", + data: { + "like": "点赞", + "liked": "已点赞", + "unlike": "取消点赞" + } + }, { id: "aa6631e469935d0fb5c556e96dcc4379", namespace: "new-demo-p-frontend-home", @@ -622,7 +634,9 @@ const i18ns: I18n[] = [ "publish": "发布", "withdraw": "撤回", "setTop": "置顶", - "cancelTop": "取消置顶" + "cancelTop": "取消置顶", + "like": "点赞", + "unlike": "取消点赞" }, "v": { "iState": { @@ -747,6 +761,20 @@ const i18ns: I18n[] = [ } } }, + { + id: "b9691c35f8511fb42aa59cbcc8645610", + namespace: "like", + language: "zh-CN", + module: "", + position: "oak-app-domain/Like", + data: { + "name": "点赞记录", + "attr": { + "essay": "文章", + "user": "用户" + } + } + }, { id: "f3c966c0e1deb4ca4c10e10117143849", namespace: "livestream", diff --git a/src/entities/Essay.ts b/src/entities/Essay.ts index 3580c95..c4cea4d 100644 --- a/src/entities/Essay.ts +++ b/src/entities/Essay.ts @@ -35,7 +35,10 @@ export const IActionDef: ActionDef = { // 用户行为操作 export type CommonAction = 'setTop' | 'cancelTop'; -type Action = IAction | CommonAction; +// 点赞操作 +export type LikeAction = 'like' | 'unlike'; + +type Action = IAction | CommonAction | LikeAction; export const entityDesc: EntityDesc< Schema, @@ -65,6 +68,8 @@ export const entityDesc: EntityDesc< withdraw: '撤回', setTop: '置顶', cancelTop: '取消置顶', + like: '点赞', + unlike: '取消点赞', }, v: { iState: { diff --git a/src/entities/Like.ts b/src/entities/Like.ts new file mode 100644 index 0000000..6f76f3f --- /dev/null +++ b/src/entities/Like.ts @@ -0,0 +1,22 @@ +import { EntityDesc, EntityShape } from 'oak-domain/lib/types'; +import { Schema as Essay } from './Essay'; +import { Schema as User } from 'oak-general-business/lib/entities/User'; + +// Like.ts +// 关联文章和用户,表示点赞记录 +export interface Schema extends EntityShape { + essay: Essay; + user: User; +} + +export const entityDesc: EntityDesc = { + locales: { + zh_CN: { + name: '点赞记录', + attr: { + essay: '文章', + user: '用户', + }, + }, + }, +}; diff --git a/src/pages/frontend/essay/details/index.ts b/src/pages/frontend/essay/details/index.ts index c3e494a..c8a0adf 100644 --- a/src/pages/frontend/essay/details/index.ts +++ b/src/pages/frontend/essay/details/index.ts @@ -5,6 +5,10 @@ export default OakComponent({ isList: false, projection: essayProjection, formData({ data }) { + const isLiked = data?.like$essay?.some(item => { + return item.user.id === this.features.token.getUserId(); + }) + const likeNums = data?.like$essay?.length || 0; const fileIndex = data?.extraFile$entity?.findIndex( (item) => item.tag1 === 'cover' ); @@ -16,11 +20,15 @@ export default OakComponent({ item: data, // 获取封面的url地址 cover: url, + isLiked, + likeNums }; } return { item: data, cover: '', + isLiked, + likeNums }; }, }); diff --git a/src/pages/frontend/essay/details/locales/zh_CN.json b/src/pages/frontend/essay/details/locales/zh_CN.json new file mode 100644 index 0000000..b6f1b2b --- /dev/null +++ b/src/pages/frontend/essay/details/locales/zh_CN.json @@ -0,0 +1,5 @@ +{ + "like": "点赞", + "liked": "已点赞", + "unlike": "取消点赞" +} \ No newline at end of file diff --git a/src/pages/frontend/essay/details/styles.module.less b/src/pages/frontend/essay/details/styles.module.less index c0d4e4b..b6be99c 100644 --- a/src/pages/frontend/essay/details/styles.module.less +++ b/src/pages/frontend/essay/details/styles.module.less @@ -3,6 +3,22 @@ display: flex; flex-direction: column; + .back { + font-size: 14px; + } + + .nums { + font-size: 14px; + color: #666; + } + + .likes { + display: flex; + flex-direction: row; + align-items: center; + gap: 10px; + } + .top { position: relative; width: 100%; diff --git a/src/pages/frontend/essay/details/web.pc.tsx b/src/pages/frontend/essay/details/web.pc.tsx index e3078f6..2c89226 100644 --- a/src/pages/frontend/essay/details/web.pc.tsx +++ b/src/pages/frontend/essay/details/web.pc.tsx @@ -6,6 +6,7 @@ import MdViewer from '@project/components/common/byteMD/MdViewer'; import FrontendFooter from '@project/components/frontend/home/FrontendFooter'; import { Button } from 'antd'; import { VerticalAlignTopOutlined } from '@ant-design/icons'; +import OakIcon from 'oak-frontend-base/es/components/icon'; const EssayDetails = ( props: WebComponentProps< @@ -15,11 +16,14 @@ const EssayDetails = ( { item: RowWithActions; cover: string; + isLiked: boolean; + likeNums: number; } > ) => { - const { item, cover } = props.data; + const { item, cover, isLiked, likeNums } = props.data; const [showScrollTop, setShowScrollTop] = useState(false); + const { t, update, execute } = props.methods; useEffect(() => { const handleScroll = () => { @@ -74,6 +78,32 @@ const EssayDetails = ( > 返回 + +
+ {isLiked ? ( + + ) : ( + + )} +
{likeNums}
+
diff --git a/src/triggers/essay.ts b/src/triggers/essay.ts index 194010a..14885ab 100644 --- a/src/triggers/essay.ts +++ b/src/triggers/essay.ts @@ -2,6 +2,7 @@ import { EntityDict } from '@oak-app-domain'; import { Trigger } from 'oak-domain/lib/types'; import { BackendRuntimeContext } from '../context/BackendRuntimeContext'; import assert from 'assert'; +import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid'; const triggers: Trigger[] = [ { @@ -52,6 +53,57 @@ const triggers: Trigger[] = [ return 1; }, }, + // 调用like的action的时候,创建点赞的记录 + { + name: "调用like的action的时候,创建点赞的记录", + entity: "essay", + action: "like", + when: "before", + fn: async ({ operation }, context, option) => { + const { filter } = operation; + assert(filter && filter.id, "filter is required"); + const eId = filter.id; + const userId = context.getCurrentUserId(); + // 创建点赞记录 + const opres = await context.operate("like", { + id: await generateNewIdAsync(), + action: "create", + data: { + id: await generateNewIdAsync(), + essayId: eId as string, + userId, + } + }, option) + + return opres.like?.create || 0; + } + }, + // 调用unlike的action的时候,移除点赞的记录 + { + name: "调用unlike的action的时候,移除点赞的记录", + entity: "essay", + action: "unlike", + when: "before", + fn: async ({ operation }, context, option) => { + const { filter, data } = operation; + assert(filter && filter.id, "filter is required"); + const eId = filter.id; + const userId = context.getCurrentUserId(); + // 创建点赞记录 + const opres = await context.operate("like", { + id: await generateNewIdAsync(), + action: "remove", + data: { + }, + filter: { + essayId: eId as string, + userId, + } + }, option) + + return opres.like?.remove || 0; + } + } ]; export default triggers; diff --git a/src/utils/projection.ts b/src/utils/projection.ts index 96b030a..d1bd1c7 100644 --- a/src/utils/projection.ts +++ b/src/utils/projection.ts @@ -81,6 +81,18 @@ export const essayProjection: EntityDict['essay']['Selection']['data'] = { }, count: 1, }, + // 点赞相关的记录 + like$essay: { + $entity: "like", + data: { + id: 1, + user: { + id: 1, + name: 1, + nickname: 1, + } + } + } }; export const categoryProjection: EntityDict['category']['Selection']['data'] = {