feat:增加菜谱收藏功能
This commit is contained in:
@@ -34,6 +34,12 @@ export const queryRecipeByUserApi = (id: number): Promise<IRecipe[]> =>
|
||||
method: 'get'
|
||||
})
|
||||
|
||||
export const queryRecipeUserFavouriteApi = (): Promise<IRecipe[]> =>
|
||||
cloudService({
|
||||
url: '/food-service/food/recipe/user/favourite',
|
||||
method: 'get'
|
||||
})
|
||||
|
||||
export const queryRecipeApi = (query: IFoodQuery): Promise<IRecipe[]> =>
|
||||
cloudService({
|
||||
url: '/food-service/food/recipe',
|
||||
@@ -94,6 +100,18 @@ export const deleteRecipeLikeApi = (id: number): Promise<boolean> =>
|
||||
method: 'delete'
|
||||
})
|
||||
|
||||
export const addRecipeFavouriteApi = (id: number): Promise<boolean> =>
|
||||
cloudService({
|
||||
url: `/food-service/food/recipe/${id}/favourite`,
|
||||
method: 'post'
|
||||
})
|
||||
|
||||
export const deleteRecipeFavouriteApi = (id: number): Promise<boolean> =>
|
||||
cloudService({
|
||||
url: `/food-service/food/recipe/${id}/favourite`,
|
||||
method: 'delete'
|
||||
})
|
||||
|
||||
export const queryRecordApi = (startDate: string, endDate: string): Promise<IRecord[]> =>
|
||||
cloudService({
|
||||
url: '/food-service/food/record',
|
||||
|
||||
@@ -39,21 +39,25 @@
|
||||
|
||||
<div class="bottom-container">
|
||||
<div class="info-list">
|
||||
<div class="info-item category-item">
|
||||
<el-avatar v-if="!isCurrentUser" :src="avatarUrl" :size="20" fit="contain"/>
|
||||
<span v-if="!isCurrentUser" class="user">{{ props.item.username }}</span>
|
||||
|
||||
<div v-if="isCurrentUser" class="info-item category-item">
|
||||
<i class="fa-solid fa-utensils"></i>
|
||||
{{ props.item.category }}
|
||||
</div>
|
||||
<div class="info-item like-item">
|
||||
|
||||
<div v-if="isCurrentUser" class="info-item like-item">
|
||||
<i class="fa-regular fa-thumbs-up"></i>
|
||||
{{ props.item.likeCount }}
|
||||
</div>
|
||||
<div class="info-item comment-item">
|
||||
<div v-if="isCurrentUser" class="info-item comment-item">
|
||||
<i class="fa-regular fa-comment"></i>
|
||||
{{ props.item.commentCount }}
|
||||
</div>
|
||||
<div class="info-item start-item">
|
||||
<div v-if="isCurrentUser" class="info-item start-item">
|
||||
<i class="fa-solid fa-star"></i>
|
||||
0
|
||||
{{ props.item.favouriteCount }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -75,17 +79,18 @@
|
||||
<script setup lang="ts">
|
||||
import { Edit, Collection, DeleteFilled } from '@element-plus/icons-vue'
|
||||
import { useFoodStore } from '@/store/food'
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { computed, defineProps, onMounted, reactive } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import type { IRecipe, IRecord } from '@/types/food.ts'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { formatDate } from 'vue3-common/utils/dateUtil'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import { serviceFileRootPath } from '@/utils'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const foodStore = useFoodStore()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const foodCardInfo = reactive({
|
||||
recommendRate: 0,
|
||||
@@ -103,7 +108,15 @@ onMounted(() => {
|
||||
foodCardInfo.recommendRate = props.item?.recommendRate as number
|
||||
})
|
||||
|
||||
const isCurrentUser = computed(() => route.path.includes('record'))
|
||||
const avatarUrl = computed(() => {
|
||||
if (props.item?.avatar) {
|
||||
return serviceFileRootPath + props.item.avatar
|
||||
} else {
|
||||
return 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
|
||||
}
|
||||
})
|
||||
|
||||
const isCurrentUser = computed(() => props.item?.userId === userStore.getUserId())
|
||||
|
||||
const getRecord = (recordList: IRecord[]) => {
|
||||
return recordList.filter((item) => item.imageUrl)
|
||||
|
||||
@@ -4,25 +4,12 @@ import type {
|
||||
IStats, IRecord, IMoment, IFoodSegment
|
||||
} from '@/types/food'
|
||||
import {
|
||||
addRecipeApi,
|
||||
addRecordApi,
|
||||
deleteRecipeApi,
|
||||
deleteRecordApi,
|
||||
queryFoodNameListApi,
|
||||
queryRecipeByIdApi,
|
||||
queryRecordApi,
|
||||
queryStatsApi,
|
||||
updateRecipeApi,
|
||||
updateRecordApi,
|
||||
queryCategoryApi,
|
||||
queryRecordStatsApi,
|
||||
queryCategoryStatsApi,
|
||||
queryRankStatsApi,
|
||||
queryRecipeApi,
|
||||
queryRecipeByUserApi,
|
||||
deleteRecipeLikeApi,
|
||||
addRecipeLikeApi,
|
||||
addRecipeCommentApi
|
||||
addRecipeApi, addRecordApi, deleteRecipeApi, deleteRecordApi,
|
||||
queryFoodNameListApi, queryRecipeByIdApi, queryRecordApi, queryStatsApi,
|
||||
updateRecipeApi, updateRecordApi, queryCategoryApi, queryRecordStatsApi,
|
||||
queryCategoryStatsApi, queryRankStatsApi,
|
||||
queryRecipeApi, queryRecipeByUserApi, deleteRecipeLikeApi,
|
||||
addRecipeLikeApi, addRecipeCommentApi, addRecipeFavouriteApi, deleteRecipeFavouriteApi, queryRecipeUserFavouriteApi
|
||||
} from '@/apis/food.ts'
|
||||
import type { IDialog, IHandleApi, IStatsChart } from 'vue3-common/types'
|
||||
import { ElMessage } from 'element-plus'
|
||||
@@ -45,11 +32,17 @@ export const useFoodStore = defineStore('food', {
|
||||
category: '',
|
||||
recommendRate: 0,
|
||||
remark: '',
|
||||
isShare: false,
|
||||
username: '',
|
||||
userId: 0,
|
||||
avatar: '',
|
||||
materialList: [],
|
||||
stepList: [],
|
||||
recordList: [],
|
||||
likeCount: 0,
|
||||
likeList: [],
|
||||
favouriteCount: 0,
|
||||
favouriteList: [],
|
||||
commentCount: 0,
|
||||
commentList: []
|
||||
} as IRecipe,
|
||||
@@ -133,6 +126,11 @@ export const useFoodStore = defineStore('food', {
|
||||
this.recipeList = await queryRecipeByUserApi(id)
|
||||
this.isLoading = false
|
||||
},
|
||||
async queryRecipeUserFavourite() {
|
||||
this.isLoading = true
|
||||
this.recipeList = await queryRecipeUserFavouriteApi()
|
||||
this.isLoading = false
|
||||
},
|
||||
async queryRecordList() {
|
||||
const { year, month } = this.queryRecord
|
||||
const date = this.queryDateType === 'year' ? year : month
|
||||
@@ -249,6 +247,14 @@ export const useFoodStore = defineStore('food', {
|
||||
await deleteRecipeLikeApi(id)
|
||||
await this.queryRecipe(this.currentRecipe.id as number)
|
||||
},
|
||||
async addRecipeFavourite(id: number) {
|
||||
await addRecipeFavouriteApi(id)
|
||||
await this.queryRecipe(this.currentRecipe.id as number)
|
||||
},
|
||||
async deleteRecipeFavourite(id: number) {
|
||||
await deleteRecipeFavouriteApi(id)
|
||||
await this.queryRecipe(this.currentRecipe.id as number)
|
||||
},
|
||||
getEmptyRecipe(): IRecipe {
|
||||
return {
|
||||
commentCount: 0,
|
||||
@@ -259,6 +265,7 @@ export const useFoodStore = defineStore('food', {
|
||||
materialList: [],
|
||||
name: '',
|
||||
recommendRate: 0,
|
||||
isShare: false,
|
||||
remark: '',
|
||||
stepList: [],
|
||||
recordList: []
|
||||
|
||||
@@ -53,6 +53,11 @@ $card-image-height: 200px;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.user {
|
||||
// font-size: 0.9rem;
|
||||
color: #9C9C9C;
|
||||
}
|
||||
}
|
||||
|
||||
.category-item {
|
||||
|
||||
@@ -59,6 +59,10 @@ export interface IRecipe {
|
||||
* 备注
|
||||
*/
|
||||
remark: string;
|
||||
isShare: boolean;
|
||||
userId?: number;
|
||||
username?: string;
|
||||
avatar?: string;
|
||||
/**
|
||||
* 食材
|
||||
*/
|
||||
@@ -71,10 +75,12 @@ export interface IRecipe {
|
||||
* 成果
|
||||
*/
|
||||
recordList: IRecord[];
|
||||
likeList: number[];
|
||||
likeCount: number;
|
||||
commentList: IComment[];
|
||||
commentCount: number;
|
||||
likeList?: number[];
|
||||
likeCount?: number;
|
||||
favouriteList?: number[];
|
||||
favouriteCount?: number;
|
||||
commentList?: IComment[];
|
||||
commentCount?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<moment-list />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="菜谱收藏" name="recipe">
|
||||
|
||||
<recipe-list />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="系统设置" name="system">
|
||||
<div class="menu-card card-item">
|
||||
@@ -77,6 +77,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import ProfileCard from '@/components/Profile/ProfileCard.vue'
|
||||
import RecipeList from '@/components/Food/RecipeList.vue'
|
||||
import MomentList from '@/components/Moment/MomentList.vue'
|
||||
import { useUserStore } from '@/store/user.ts'
|
||||
import { useAppStore } from '@/store/app.ts'
|
||||
@@ -113,6 +114,9 @@ const handleClick = async (tab: TabsPaneContext) => {
|
||||
case 'moment':
|
||||
await foodStore.queryMoment(userStore.getUserId())
|
||||
break
|
||||
case 'recipe':
|
||||
await foodStore.queryRecipeUserFavourite()
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
@@ -20,8 +20,14 @@
|
||||
<i class="fa-regular fa-thumbs-up"></i>
|
||||
</el-button>
|
||||
</el-badge>
|
||||
<el-button circle><i class="fa-regular fa-star"></i></el-button>
|
||||
<!-- <el-button circle><i class="fa-regular fa-comment"></i></el-button>-->
|
||||
<el-badge v-if="!isCurrentUser"
|
||||
:value="foodStore.currentRecipe.favouriteList.length" :max="9">
|
||||
<el-button v-if="!isCurrentUser"
|
||||
:type="isFavourite ? 'danger' : 'default'"
|
||||
circle @click="handleFavouriteClick()">
|
||||
<i class="fa-regular fa-star"></i>
|
||||
</el-button>
|
||||
</el-badge>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -49,6 +55,8 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
const isLike = computed(() => foodStore.currentRecipe.likeList.includes(userStore.getUserId()))
|
||||
const isFavourite = computed(() => foodStore.currentRecipe.favouriteList.includes(userStore.getUserId()))
|
||||
const isCurrentUser = computed(() => foodStore.currentRecipe.userId === userStore.getUserId())
|
||||
|
||||
const handleLikeClick = () => {
|
||||
if (isLike.value) {
|
||||
@@ -57,6 +65,14 @@ const handleLikeClick = () => {
|
||||
foodStore.addRecipeLike(foodStore.currentRecipe.id as number)
|
||||
}
|
||||
}
|
||||
|
||||
const handleFavouriteClick = () => {
|
||||
if (isFavourite.value) {
|
||||
foodStore.deleteRecipeFavourite(foodStore.currentRecipe.id as number)
|
||||
} else {
|
||||
foodStore.addRecipeFavourite(foodStore.currentRecipe.id as number)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -22,6 +22,13 @@
|
||||
:colors="foodStore.rateColorList"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="共享">
|
||||
<el-radio-group v-model="foodStore.currentRecipe.isShare">
|
||||
<el-radio :value="false">否</el-radio>
|
||||
<el-radio :value="true">是</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="食材">
|
||||
<food-material-form />
|
||||
</el-form-item>
|
||||
|
||||
Reference in New Issue
Block a user