feat:增加后端接口

This commit is contained in:
2025-06-24 23:34:00 +08:00
parent 69c0bfa4c7
commit 71c107f2e5
17 changed files with 141 additions and 191 deletions

View File

@@ -1,5 +1,6 @@
import { cloudService } from './index' import { cloudService } from './index'
import type { IFoodQuery, IFoodRecipe, IFoodRecord, IFoodStats } from '@/types/food' import type { IFoodQuery, IFoodRecipe, IFoodRecord, IFoodStats } from '@/types/food'
import type { IStatsChart } from 'vue3-common/types'
export const addFoodRecipeApi = (foodRecipe: IFoodRecipe): Promise<boolean> => export const addFoodRecipeApi = (foodRecipe: IFoodRecipe): Promise<boolean> =>
cloudService({ cloudService({
@@ -21,13 +22,20 @@ export const deleteFoodRecipeApi = (id: number): Promise<boolean> =>
method: 'DELETE' method: 'DELETE'
}) })
export const queryFoodRecipeByIdApi = (id: number): Promise<any> => export const queryFoodRecipeByIdApi = (id: number): Promise<IFoodRecipe> =>
cloudService({ cloudService({
url: `/food-service/food/recipe/${id}`, url: `/food-service/food/recipe/${id}`,
method: 'get' method: 'get'
}) })
export const queryFoodRecipeApi = (currentPage: number, pageSize: number, export const queryFoodRecipeApi = (query: IFoodQuery): Promise<IFoodRecipe[]> =>
cloudService({
url: '/food-service/food/recipe',
method: 'get',
params: { ...query }
})
export const queryFoodRecipeByPageApi = (currentPage: number, pageSize: number,
query: IFoodQuery): Promise<any> => query: IFoodQuery): Promise<any> =>
cloudService({ cloudService({
url: '/food-service/food/recipe/page', url: '/food-service/food/recipe/page',
@@ -79,3 +87,21 @@ export const queryFoodStatsApi = (): Promise<IFoodStats> =>
url: '/food-service/food/stats', url: '/food-service/food/stats',
method: 'get' method: 'get'
}) })
export const queryFoodRecordStatsApi = (): Promise<IStatsChart[]> =>
cloudService({
url: '/food-service/food/stats/record',
method: 'get'
})
export const queryFoodCategoryStatsApi = (): Promise<IStatsChart[]> =>
cloudService({
url: '/food-service/food/stats/category',
method: 'get'
})
export const queryFoodRankStatsApi = (): Promise<IStatsChart[]> =>
cloudService({
url: '/food-service/food/stats/rank',
method: 'get'
})

View File

@@ -89,15 +89,6 @@ const props = defineProps({
justify-self: flex-end; justify-self: flex-end;
} }
.card-item__extra span:nth-child(1) {
font-size: 1rem;
}
.card-item__extra span:nth-child(2) {
font-size: 0.9rem;
color: #A9A9A9;
}
hr { hr {
height: 1px; height: 1px;
background-color: #cccccc; background-color: #cccccc;

View File

@@ -44,10 +44,6 @@
</div> </div>
<div v-if="props.foodItem?.recordList.length > 0" class="info-list"> <div v-if="props.foodItem?.recordList.length > 0" class="info-list">
<div class="info-item">
<i class="fa-solid fa-flag"></i>
{{ props.foodItem.recordList[foodCardInfo.currentFoodIndex].person}}
</div>
<div class="info-item"> <div class="info-item">
<i class="fa-regular fa-calendar-check"></i> <i class="fa-regular fa-calendar-check"></i>
{{ formatDate(props.foodItem.recordList[foodCardInfo.currentFoodIndex].date) }} {{ formatDate(props.foodItem.recordList[foodCardInfo.currentFoodIndex].date) }}
@@ -73,7 +69,6 @@ import { formatDate } from 'vue3-common/utils/dateUtil'
import { deepCopyObject } from 'vue3-common/utils/dataUtil' import { deepCopyObject } from 'vue3-common/utils/dataUtil'
import { commonElMessageBox } from 'vue3-common/utils/elUtil' import { commonElMessageBox } from 'vue3-common/utils/elUtil'
import { serviceFileRootPath } from '@/utils' import { serviceFileRootPath } from '@/utils'
import { isMobile } from 'vue3-common/utils/layoutUtil'
const router = useRouter() const router = useRouter()
const foodStore = useFoodStore() const foodStore = useFoodStore()
@@ -116,7 +111,7 @@ const viewFoodRecipeClick = async () => {
const deleteFoodRecipeClick = () => { const deleteFoodRecipeClick = () => {
foodStore.foodRecipeApiType = 'DELETE' foodStore.foodRecipeApiType = 'DELETE'
commonElMessageBox(`请确认是否删除该菜谱: ${props.foodItem?.name}?`).then(() => { commonElMessageBox(`请确认是否删除该菜谱: ${props.foodItem?.name}?`).then(() => {
foodStore.handleFoodRecipeApi(props.foodItem?.id as number) foodStore.handleFoodRecipeApi(props.foodItem)
}) })
} }

View File

@@ -20,7 +20,10 @@ const calendarRef = ref()
const foodStore = useFoodStore() const foodStore = useFoodStore()
const appStore = useAppStore() const appStore = useAppStore()
onMounted(() => { onMounted(async () => {
foodStore.queryDateType = 'month'
await foodStore.refreshInfo()
const { month } = foodStore.queryRecord const { month } = foodStore.queryRecord
calendarRef.value.move(new Date(month)) calendarRef.value.move(new Date(month))
}) })

View File

@@ -6,15 +6,13 @@
<div class="daily-list"> <div class="daily-list">
<daily-card v-for="(item, index) in dailyItemInfo.itemList" <daily-card v-for="(item, index) in dailyItemInfo.itemList"
:key="index" @click="selectFoodRecordClick(item)" :key="index" :title="item.name" :content="item.category">
:title="item.name" :content="item.category">
<template #icon> <template #icon>
<el-avatar>{{ item.category.charAt(0) }}</el-avatar> <el-avatar>{{ item.category.charAt(0) }}</el-avatar>
</template> </template>
<template #extra> <template #extra>
<span>{{ item.person }}</span> <el-button type="primary" :icon="CaretRight" circle @click="selectFoodRecordClick(item)"/>
<span>{{ item.date }}</span>
</template> </template>
</daily-card> </daily-card>
</div> </div>
@@ -22,6 +20,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { CaretRight } from '@element-plus/icons-vue'
import DailySummary from '@/components/DailySummary.vue' import DailySummary from '@/components/DailySummary.vue'
import DailyCard from '@/components/DailyCard.vue' import DailyCard from '@/components/DailyCard.vue'
import { defineProps, onMounted, reactive, watch } from 'vue' import { defineProps, onMounted, reactive, watch } from 'vue'
@@ -83,11 +82,11 @@ const getFoodDailyByDate = (date: string) => {
* @param foodRecord 美食记录 * @param foodRecord 美食记录
*/ */
const selectFoodRecordClick = async (foodRecord: IFoodRecord) => { const selectFoodRecordClick = async (foodRecord: IFoodRecord) => {
foodStore.foodRecordApiType = 'UPDATE' // foodStore.foodRecordApiType = 'UPDATE'
appStore.isShowMobileBack = true // appStore.isShowMobileBack = true
foodStore.currentFoodRecord = foodRecord // foodStore.currentFoodRecord = foodRecord
await router.push({ name: 'MobileHomeFoodRecordForm' }) // await router.push({ name: 'MobileHomeFoodRecordForm' })
} }
</script> </script>
@@ -95,13 +94,13 @@ const selectFoodRecordClick = async (foodRecord: IFoodRecord) => {
.food-daily-item { .food-daily-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 1vh; gap: 10px;
padding: 1vh 0.5vw; padding: 5px;
.daily-list { .daily-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 1vh; gap: 10px;
overflow: auto; overflow: auto;
} }
} }

View File

@@ -3,7 +3,7 @@
<div class="query-item card-item"> <div class="query-item card-item">
<span>分类</span> <span>分类</span>
<el-segmented v-model="foodStore.queryRecipe.category" <el-segmented v-model="foodStore.queryRecipe.category"
:options="foodCategoryList" :options="queryCategoryList"
@change="queryFoodSegmented"/> @change="queryFoodSegmented"/>
</div> </div>
@@ -25,29 +25,41 @@ import FoodCard from '@/components/Food/FoodCard.vue'
import ArriveBottom from '@/components/ArriveButton.vue' import ArriveBottom from '@/components/ArriveButton.vue'
import { useFoodStore } from '@/store/food.ts' import { useFoodStore } from '@/store/food.ts'
import { onBeforeUnmount, onMounted, ref } from 'vue' import { onBeforeUnmount, onMounted, ref } from 'vue'
import type { ICategory } from '@/types'
const foodRecipeRef = ref() const foodRecipeRef = ref()
const foodStore = useFoodStore() const foodStore = useFoodStore()
const foodCategoryList = [{ const queryCategoryList = ref([] as ICategory[])
label: '全部',
value: ''
},
{
label: '家常菜',
value: '家常菜'
}]
onMounted(async () => { onMounted(async () => {
foodRecipeRef.value.addEventListener('scroll', handleScroll) await foodStore.queryFoodCategory()
initCategoryList()
// foodStore.foodRecipeList = []
await foodStore.refreshInfo()
// foodRecipeRef.value.addEventListener('scroll', handleScroll)
}) })
onBeforeUnmount(() => { onBeforeUnmount(() => {
foodRecipeRef.value.removeEventListener('scroll', handleScroll) // foodRecipeRef.value.removeEventListener('scroll', handleScroll)
}) })
const initCategoryList = () => {
queryCategoryList.value = []
queryCategoryList.value.push({
label: '全部',
value: ''
})
foodStore.foodCategoryList.forEach((item) => {
queryCategoryList.value.push({
label: item,
value: item
})
})
}
const queryFoodSegmented = async () => { const queryFoodSegmented = async () => {
foodStore.pageInfo.currentPage = 1 // foodStore.pageInfo.currentPage = 1
foodStore.foodRecipeList = [] foodStore.foodRecipeList = []
await foodStore.queryFoodRecipeList() await foodStore.queryFoodRecipeList()
} }
@@ -70,6 +82,7 @@ const handleScroll = () => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
overflow: auto;
.query-item { .query-item {
padding: 5px 10px; padding: 5px 10px;

View File

@@ -12,7 +12,7 @@
:key="index" :timestamp="formatDate(item.date)" placement="top"> :key="index" :timestamp="formatDate(item.date)" placement="top">
<div class="timeline-info card-item"> <div class="timeline-info card-item">
<span>{{ item.name }}</span> <span>{{ item.name }}</span>
<el-image :src="item.imageUrl" <el-image :src="serviceFileRootPath + item.imageUrl"
fit="contain" alt="暂无成果"> fit="contain" alt="暂无成果">
<template #error> <template #error>
<div class="image-slot"> <div class="image-slot">
@@ -24,30 +24,26 @@
</el-timeline-item> </el-timeline-item>
</el-timeline> </el-timeline>
<el-empty v-else description="暂无记"/> <el-empty v-else description="暂无记"/>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useFoodStore } from '@/store/food.ts' import { useFoodStore } from '@/store/food.ts'
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import { formatDate, getCurrentYear, getStartEndDate } from 'vue3-common/utils/dateUtil' import { formatDate } from 'vue3-common/utils/dateUtil'
import { serviceFileRootPath } from '@/utils' import { serviceFileRootPath } from '@/utils'
const currentYear = ref(new Date()) const currentYear = ref(new Date())
const foodStore = useFoodStore() const foodStore = useFoodStore()
onMounted(async () => { onMounted(async () => {
const dateInfo = getStartEndDate(getCurrentYear(), 'year') foodStore.queryDateType = 'year'
foodStore.queryDateList[0] = dateInfo[0]
foodStore.queryDateList[1] = dateInfo[1]
await foodStore.refreshInfo() await foodStore.refreshInfo()
}) })
const changeDateEvent = async (value: Date) => { const changeDateEvent = async (value: Date) => {
const dateInfo = getStartEndDate(value, 'year') foodStore.queryRecord.year = String(value.getFullYear())
foodStore.queryDateList[0] = dateInfo[0]
foodStore.queryDateList[1] = dateInfo[1]
await foodStore.refreshInfo() await foodStore.refreshInfo()
} }
</script> </script>
@@ -69,6 +65,10 @@ const changeDateEvent = async (value: Date) => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
.el-image {
height: 300px;
}
} }
} }
} }

View File

@@ -9,7 +9,7 @@
</div> </div>
<div class="chart-container card-item"> <div class="chart-container card-item">
<div class="content"> <div class="content">
<span class="title">📊类别统计</span> <span class="title">📊菜谱统计</span>
</div> </div>
<div class="chart" ref="foodCategoryChartRef"/> <div class="chart" ref="foodCategoryChartRef"/>
</div> </div>
@@ -28,22 +28,18 @@
import FoodRank from '@/components/Stats/FoodRank.vue' import FoodRank from '@/components/Stats/FoodRank.vue'
import { onMounted, ref, watch } from 'vue' import { onMounted, ref, watch } from 'vue'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { lineChartOptions, barChartOptions, pieChartOptions } from 'vue3-common/utils/eChartsUtil' import { lineChartOptions, pieChartOptions } from 'vue3-common/utils/eChartsUtil'
import { useFoodStore } from '@/store/food' import { useFoodStore } from '@/store/food'
import { useAppStore } from '@/store/app.ts' import { useAppStore } from '@/store/app.ts'
import type { IStatsChart } from 'vue3-common/types'
import { isMobile } from 'vue3-common/utils/layoutUtil'
const foodStore = useFoodStore() const foodStore = useFoodStore()
const appStore = useAppStore() const appStore = useAppStore()
const foodDailyChartRef = ref<HTMLElement>() const foodDailyChartRef = ref<HTMLElement>()
const foodCategoryChartRef = ref<HTMLElement>() const foodCategoryChartRef = ref<HTMLElement>()
const billRankChartRef = ref<HTMLElement>()
let foodDailyChart: echarts.ECharts let foodDailyChart: echarts.ECharts
let foodCategoryChart: echarts.ECharts let foodCategoryChart: echarts.ECharts
let billRankChart: echarts.ECharts
watch(() => foodStore.isRefresh, () => { watch(() => foodStore.isRefresh, () => {
updateChart() updateChart()
@@ -52,60 +48,19 @@ watch(() => foodStore.isRefresh, () => {
onMounted(() => { onMounted(() => {
foodDailyChart = echarts.init(foodDailyChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null) foodDailyChart = echarts.init(foodDailyChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null)
foodCategoryChart = echarts.init(foodCategoryChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null) foodCategoryChart = echarts.init(foodCategoryChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null)
// billRankChart = echarts.init(billRankChartRef.value as HTMLElement, appStore.isDark ? 'dark' : null)
}) })
const updateChart = () => { const updateChart = () => {
const MAX_CATEGORY_COUNT = 5 const MAX_COUNT = 5
const MAX_RANK_COUNT = 10
// 记录统计图 // 记录统计图
// const dailyXAxis = foodStore.billDateStatsList.map((item) => item.name) const dailyXAxis = foodStore.foodRecordStats.slice(0, MAX_COUNT).map((item) => item.name)
// const dailyYAxis = foodStore.billDateStatsList.map((item) => item.value) const dailyYAxis = foodStore.foodRecordStats.slice(0, MAX_COUNT).map((item) => item.value)
const dailyXAxis = ['2024-01', '2024-02']
const dailyYAxis = ['10', '6']
foodDailyChart.setOption(lineChartOptions('日期', dailyXAxis, '次数(次)', dailyYAxis)) foodDailyChart.setOption(lineChartOptions('日期', dailyXAxis, '次数(次)', dailyYAxis))
//
// // 账本统计图
// const bookXAxis = foodStore.billBookStatsList.map((item) => item.name)
// const bookYAxis = foodStore.billBookStatsList.map((item) => item.value)
// billBookChart.setOption(barChartOptions('账本', bookXAxis, '金额(元)', bookYAxis))
// billBookChart.setOption({
// series: [{
// itemStyle: {
// color: foodStore.billType === 'expensive' ? '#CA6C65' : '#6FBB69'
// },
// markPoint: {
// label: {
// color: '#FFFFFF'
// }
// }
// }]
// })
//
// 类别统计图 // 类别统计图
const foodCategoryList = [ const foodCategoryData = foodStore.foodCategoryStats.slice(0, MAX_COUNT)
{ value: 12, name: '家常菜' }, foodCategoryChart.setOption(pieChartOptions('category', '个', foodCategoryData))
{ value: 10, name: '鲁菜' },
{ value: 8, name: '川菜' },
{ value: 5, name: '淮扬菜' },
{ value: 2, name: '其他' }
]
foodCategoryChart.setOption(pieChartOptions('category', '次', foodCategoryList))
//
// // 排行榜统计图
// const billRankList: IStatsChart[] = []
// const resultList = foodStore.billRecordList.filter((item) => item.type === foodStore.billType)
// resultList.sort((a, b) => b.amount - a.amount).forEach((item) => {
// billRankList.push({
// name: item.content,
// value: item.amount
// })
// })
//
// if (!isMobile()) {
// billRankChart.setOption(pieChartOptions('rank', '元', billRankList.slice(0, MAX_RANK_COUNT)))
// }
} }
</script> </script>
@@ -124,7 +79,7 @@ const updateChart = () => {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
border-bottom: 1px solid #009FA8; border-bottom: 1px solid var(--el-color-primary);
.title { .title {
font-size: 1em; font-size: 1em;

View File

@@ -2,8 +2,8 @@
<div v-for="(item, index) in foodRankList.slice(0, MAX_RANK_COUNT)" <div v-for="(item, index) in foodRankList.slice(0, MAX_RANK_COUNT)"
:key="index" class="rank-item"> :key="index" class="rank-item">
<span class="rank-index">{{ index+1 }}.</span> <span class="rank-index">{{ index+1 }}.</span>
<span class="rank-content">{{ item.value }}</span> <span class="rank-content">{{ item.name }}</span>
<span class="rank-amount">{{ item.count }} </span> <span class="rank-amount">{{ item.value }} </span>
</div> </div>
</template> </template>
@@ -15,19 +15,5 @@ const foodStore = useFoodStore()
const MAX_RANK_COUNT = 10 const MAX_RANK_COUNT = 10
const foodRankList = computed(() => { const foodRankList = computed(() => foodStore.foodRankStats)
return [{
value: '红烧肉',
count: 10
}, {
value: '红烧鱼',
count: 8
}, {
value: '排骨汤',
count: 5
}, {
value: '红烧带鱼',
count: 2
}]
})
</script> </script>

View File

@@ -14,7 +14,7 @@ export const useAppStore = defineStore('ipp', {
isDark: false, isDark: false,
isWebSocket: false, isWebSocket: false,
serverIp: '14.103.235.151', serverIp: '14.103.235.151',
version: 'v1.0.0.2025062303' version: 'v1.0.0.2025062401'
}), }),
actions: { actions: {
initApp() { initApp() {

View File

@@ -83,8 +83,6 @@ export const useAuthStore = defineStore('auth', {
const { email, code: emailCode } = this.emailLoginForm const { email, code: emailCode } = this.emailLoginForm
switch (type) { switch (type) {
case 'common': case 'common':
console.log(username)
console.log(password)
this.homeSession = await loginApi(username, password) this.homeSession = await loginApi(username, password)
break break
case 'phone': case 'phone':

View File

@@ -4,15 +4,23 @@ import type {
IFoodStats, IFoodRecord IFoodStats, IFoodRecord
} from '@/types/food' } from '@/types/food'
import { import {
addFoodRecipeApi, addFoodRecordApi, deleteFoodRecipeApi, deleteFoodRecordApi, addFoodRecipeApi,
queryFoodNameListApi, queryFoodRecipeByIdApi, queryFoodRecipeApi, queryFoodRecordApi, addFoodRecordApi,
queryFoodStatsApi, updateFoodRecipeApi, updateFoodRecordApi, queryFoodCategoryApi deleteFoodRecipeApi,
deleteFoodRecordApi,
queryFoodNameListApi,
queryFoodRecipeByIdApi,
queryFoodRecordApi,
queryFoodStatsApi,
updateFoodRecipeApi,
updateFoodRecordApi,
queryFoodCategoryApi,
queryFoodRecordStatsApi,
queryFoodCategoryStatsApi, queryFoodRankStatsApi, queryFoodRecipeApi
} from '@/apis/food.ts' } from '@/apis/food.ts'
// import { IDateType, ImagePathEnum } from '@/types' import type { IDialog, IHandleApi, IStatsChart } from 'vue3-common/types'
import type { IDialog, IHandleApi } from 'vue3-common/types'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { getCurrentMonth, getCurrentYear, getStartEndDate } from 'vue3-common/utils/dateUtil' import { getCurrentMonth, getCurrentYear, getStartEndDate } from 'vue3-common/utils/dateUtil'
import { isMobile } from 'vue3-common/utils/layoutUtil'
export const useFoodStore = defineStore('food', { export const useFoodStore = defineStore('food', {
state: () => ({ state: () => ({
@@ -44,7 +52,7 @@ export const useFoodStore = defineStore('food', {
year: getCurrentYear(), year: getCurrentYear(),
month: getCurrentMonth() month: getCurrentMonth()
}, },
queryDateType: 'month', queryDateType: 'month' as 'month' | 'year',
queryDateList: [] as string[], queryDateList: [] as string[],
foodRecipeApiType: 'ADD' as IHandleApi, foodRecipeApiType: 'ADD' as IHandleApi,
foodMaterialApiType: 'ADD' as IHandleApi, foodMaterialApiType: 'ADD' as IHandleApi,
@@ -67,7 +75,7 @@ export const useFoodStore = defineStore('food', {
rateColorList: ['#E2DEDC', '#F7BA2A', '#009FA8'], rateColorList: ['#E2DEDC', '#F7BA2A', '#009FA8'],
pageInfo: { pageInfo: {
currentPage: 1, currentPage: 1,
pageSize: 3, pageSize: 2,
totalSize: 1 totalSize: 1
}, },
isScrollEnd: false, isScrollEnd: false,
@@ -77,96 +85,78 @@ export const useFoodStore = defineStore('food', {
categoryCount: 0, categoryCount: 0,
workCount: 0 workCount: 0
} as IFoodStats, } as IFoodStats,
foodRecordStats: [] as IStatsChart[],
foodCategoryStats: [] as IStatsChart[],
foodRankStats: [] as IStatsChart[],
isRefresh: false isRefresh: false
}), }),
actions: { actions: {
async queryFoodRecipeList() { async queryFoodRecipeList() {
const { currentPage, pageSize } = this.pageInfo // const { currentPage, pageSize } = this.pageInfo
const result = await queryFoodRecipeApi(currentPage, pageSize, this.queryRecipe) // const result = await queryFoodRecipeByPageApi(currentPage, pageSize, this.queryRecipe)
this.foodRecipeList.push(...result.records) // this.foodRecipeList.push(...result.records)
this.pageInfo.totalSize = result.total // this.pageInfo.totalSize = result.total
this.foodRecipeList = await queryFoodRecipeApi(this.queryRecipe)
}, },
async queryFoodRecordList() { async queryFoodRecordList() {
const { year, month } = this.queryRecord const { year, month } = this.queryRecord
const date = this.queryDateType === 'year' ? year : month const date = this.queryDateType === 'year' ? year : month
this.queryDateList = getStartEndDate(date, this.queryDateType) this.queryDateList = getStartEndDate(date, this.queryDateType)
this.foodRecordList = await queryFoodRecordApi(this.queryDateList[0], this.queryDateList[1])
const foodRecord: IFoodRecord = {
category: '家常菜',
date: '2025-06-23',
id: 0,
imageUrl: 'https://ts2.tc.mm.bing.net/th/id/OSK.277ab994364a7e09543c78379bab1d05?w=612&h=408&c=7&rs=1&qlt=80&o=6&cdv=1&cb=ircwebp1&pid=16.1',
name: '红烧鱼',
person: '哥哥'
}
const foodRecord2: IFoodRecord = {
category: '家常菜',
date: '2025-06-22',
id: 0,
imageUrl: 'https://ts2.tc.mm.bing.net/th/id/OSK.277ab994364a7e09543c78379bab1d05?w=612&h=408&c=7&rs=1&qlt=80&o=6&cdv=1&cb=ircwebp1&pid=16.1',
name: '红烧鱼',
person: '哥哥'
}
this.foodRecordList = []
this.foodRecordList.push(foodRecord)
this.foodRecordList.push(foodRecord2)
// this.foodRecordList = await queryFoodRecordApi(this.queryDateList[0], this.queryDateList[1])
}, },
async queryFoodNameList() { async queryFoodNameList() {
// this.foodNameList = await queryFoodNameListApi() this.foodNameList = await queryFoodNameListApi()
}, },
async queryFoodRecipe(id: number) { async queryFoodRecipe(id: number) {
// this.currentFoodRecipe = await queryFoodRecipeByIdApi(id) this.currentFoodRecipe = await queryFoodRecipeByIdApi(id)
}, },
async queryFoodStats() { async queryFoodStats() {
// this.foodStats = await queryFoodStatsApi() this.foodStats = await queryFoodStatsApi()
this.foodRecordStats = await queryFoodRecordStatsApi()
this.foodCategoryStats = await queryFoodCategoryStatsApi()
this.foodRankStats = await queryFoodRankStatsApi()
this.isRefresh = !this.isRefresh this.isRefresh = !this.isRefresh
}, },
async queryFoodCategory() { async queryFoodCategory() {
// this.foodCategoryList = await queryFoodCategoryApi() this.foodCategoryList = await queryFoodCategoryApi()
}, },
async handleFoodRecipeApi(foodRecipe: IFoodRecipe) { async handleFoodRecipeApi(foodRecipe: IFoodRecipe) {
switch (this.foodRecipeApiType) { switch (this.foodRecipeApiType) {
case 'ADD': case 'ADD':
// await addFoodRecipeApi(foodRecipe) await addFoodRecipeApi(foodRecipe)
ElMessage.success('新增菜谱成功') ElMessage.success('新增菜谱成功')
break break
case 'UPDATE': case 'UPDATE':
// await updateFoodRecipeApi(foodRecipe.id as number, foodRecipe) await updateFoodRecipeApi(foodRecipe.id as number, foodRecipe)
ElMessage.success('更新菜谱成功') ElMessage.success('更新菜谱成功')
break break
case 'DELETE': case 'DELETE':
// await deleteFoodRecipeApi(foodRecipe.id as number) await deleteFoodRecipeApi(foodRecipe.id as number)
ElMessage.success('删除菜谱成功') ElMessage.success('删除菜谱成功')
break break
default: default:
break break
} }
this.foodRecipeDialog.visible = false
await this.refreshInfo() await this.refreshInfo()
}, },
async handleFoodRecordApi(foodRecord: IFoodRecord) { async handleFoodRecordApi(foodRecord: IFoodRecord) {
switch (this.foodRecordApiType) { switch (this.foodRecordApiType) {
case 'ADD': case 'ADD':
// await addFoodRecordApi(foodRecord) await addFoodRecordApi(foodRecord)
ElMessage.success('新增成果成功') ElMessage.success('新增成果成功')
break break
case 'UPDATE': case 'UPDATE':
// await updateFoodRecordApi(foodRecord.id as number, foodRecord) await updateFoodRecordApi(foodRecord.id as number, foodRecord)
ElMessage.success('更新成果成功') ElMessage.success('更新成果成功')
break break
case 'DELETE': case 'DELETE':
// await deleteFoodRecordApi(foodRecord.id as number) await deleteFoodRecordApi(foodRecord.id as number)
ElMessage.success('删除成果成功') ElMessage.success('删除成果成功')
break break
default: default:
break break
} }
this.foodRecordDialog.visible = false await this.refreshInfo()
if (!isMobile()) {
await this.refreshInfo()
}
}, },
async refreshInfo() { async refreshInfo() {
await this.queryFoodRecipeList() await this.queryFoodRecipeList()
@@ -201,7 +191,6 @@ export const useFoodStore = defineStore('food', {
getEmptyFoodRecord(): IFoodRecord { getEmptyFoodRecord(): IFoodRecord {
return { return {
category: '', category: '',
person: '',
date: '', date: '',
id: 0, id: 0,
imageUrl: '', imageUrl: '',

View File

@@ -25,8 +25,8 @@ export interface IFoodRecord {
id: number; id: number;
name: string; name: string;
category: string; category: string;
person: number;
date: string; date: string;
person: string;
imageUrl: string; imageUrl: string;
} }

4
src/types/index.ts Normal file
View File

@@ -0,0 +1,4 @@
export interface ICategory {
label: string;
value: string;
}

View File

@@ -1,12 +1,12 @@
/** /**
* 文件服务器地址 * 文件服务器地址
*/ */
export const fileServiceUrl = '/home-service/file' export const fileServiceUrl = '/food-service/file'
/** /**
* 服务器文件路径根地址 * 服务器文件路径根地址
*/ */
export const serviceFileRootPath = '/home-service/' export const serviceFileRootPath = '/food-service/'
/** /**
* 获取assets静态资源 * 获取assets静态资源

View File

@@ -1,6 +1,6 @@
<template> <template>
<div class="common-mobile-view food-record"> <div class="common-mobile-view food-record">
<div class="food-query card-item"> <div class="food-segment card-item">
<el-input <el-input
v-model="foodInfo.query" v-model="foodInfo.query"
placeholder="请输入菜谱名称" :prefix-icon="Search" clearable placeholder="请输入菜谱名称" :prefix-icon="Search" clearable
@@ -10,8 +10,7 @@
<div class="query-item"> <div class="query-item">
<span>查看类型</span> <span>查看类型</span>
<el-segmented v-model="foodInfo.recordSegment" <el-segmented v-model="foodInfo.recordSegment"
:options="recordSegmentList" :options="recordSegmentList"/>
@change="changeRecordSegmentEvent()"/>
</div> </div>
</div> </div>
@@ -39,7 +38,7 @@ import FoodDaily from '@/components/Food/FoodDaily.vue'
import FoodTimeline from '@/components/Food/FoodTimeline.vue' import FoodTimeline from '@/components/Food/FoodTimeline.vue'
import DraggableButton from '@/components/DraggableButton.vue' import DraggableButton from '@/components/DraggableButton.vue'
import { Search } from '@element-plus/icons-vue' import { Search } from '@element-plus/icons-vue'
import { onMounted, reactive } from 'vue' import { reactive } from 'vue'
import { useFoodStore } from '@/store/food' import { useFoodStore } from '@/store/food'
import type { IFoodSegment } from '@/types/food' import type { IFoodSegment } from '@/types/food'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
@@ -67,14 +66,6 @@ const recordSegmentList = [{
value: 'timeline' value: 'timeline'
}] }]
onMounted(() => {
foodStore.refreshInfo()
})
const changeRecordSegmentEvent = () => {
foodStore.refreshInfo()
}
const addClick = () => { const addClick = () => {
appStore.isShowMobileBack = true appStore.isShowMobileBack = true
@@ -101,7 +92,7 @@ const addClick = () => {
flex-direction: column; flex-direction: column;
gap: 5px; gap: 5px;
.food-query { .food-segment {
padding: 5px 10px; padding: 5px 10px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@@ -23,7 +23,7 @@ export default defineConfig({
port: 5175, port: 5175,
proxy: { proxy: {
'/food-service': { '/food-service': {
target: 'http://127.0.0.1:8090', target: 'http://127.0.0.1:8100',
changeOrigin: true, changeOrigin: true,
rewrite: (item) => item.replace(/^\/food-service/, '') rewrite: (item) => item.replace(/^\/food-service/, '')
} }