feat:更新美食和旅游模块

This commit is contained in:
2026-02-09 23:16:19 +08:00
parent 45342fb55c
commit 1b8bd5a7e2
18 changed files with 179 additions and 41 deletions

View File

@@ -6,7 +6,7 @@
<el-table :data="foodStore.currentFoodRecipe.materialList" <el-table :data="foodStore.currentFoodRecipe.materialList"
border stripe class="material-table"> border stripe class="material-table">
<el-table-column prop="type" label="类型" align="center" min-width="10%"/> <el-table-column prop="type" label="类型" align="center" min-width="15%"/>
<el-table-column prop="name" label="名称" align="center" min-width="20%"/> <el-table-column prop="name" label="名称" align="center" min-width="20%"/>
<el-table-column prop="amount" label="分量" align="center" min-width="20%"/> <el-table-column prop="amount" label="分量" align="center" min-width="20%"/>
<el-table-column label="操作" align="center" width="100"> <el-table-column label="操作" align="center" width="100">

View File

@@ -1,18 +1,17 @@
<template> <template>
<div class="life-record-card card-item"> <div class="life-record-card card-item">
<el-carousel v-if="props.travelItem?.recordList.length > 0" <el-image v-if="props.travelItem?.recordList.length > 0"
arrow="always" @change="changeTravelEvent"> :src="AListUrl + props.travelItem?.recordList[0].imageList[0]"
<el-carousel-item v-for="(item, index) in props.travelItem?.recordList" :key="index"> :preview-src-list="previewImageList"
<el-image :src="AListUrl + item.imageList[0]" :initial-index="0"
fit="contain" alt="暂无图片"> show-progress
fit="contain" alt="暂无成果">
<template #error> <template #error>
<div class="image-slot"> <div class="image-slot">
<span>暂无图片</span> <span>暂无图片</span>
</div> </div>
</template> </template>
</el-image> </el-image>
</el-carousel-item>
</el-carousel>
<el-empty v-else description="暂无记录"/> <el-empty v-else description="暂无记录"/>
@@ -65,7 +64,7 @@
import { Edit, MoreFilled, DeleteFilled } from '@element-plus/icons-vue' import { Edit, MoreFilled, DeleteFilled } from '@element-plus/icons-vue'
import { useTravelStore } from '@/store/travel.ts' import { useTravelStore } from '@/store/travel.ts'
import { useAppStore } from '@/store/app.ts' import { useAppStore } from '@/store/app.ts'
import { defineProps, PropType, reactive } from 'vue' import { computed, defineProps, PropType, reactive } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { formatDate } from 'vue3-common/utils/dateUtil' import { formatDate } from 'vue3-common/utils/dateUtil'
import { ITravelSpot } from '@/types/travel.ts' import { ITravelSpot } from '@/types/travel.ts'
@@ -88,6 +87,11 @@ const props = defineProps({
} }
}) })
const previewImageList = computed(() => {
return props.travelItem.recordList.flatMap((record) =>
record.imageList.map((item) => `${AListUrl}${item}`))
})
const editClick = async () => { const editClick = async () => {
const id = props.travelItem?.id const id = props.travelItem?.id
travelStore.travelSpotApiType = 'UPDATE' travelStore.travelSpotApiType = 'UPDATE'

View File

@@ -31,6 +31,11 @@
<i class="fa-solid fa-utensils"></i> <i class="fa-solid fa-utensils"></i>
<span>菜谱</span> <span>菜谱</span>
</router-link> </router-link>
<router-link v-if="path.includes('food')" to="/food/timeline"
@click="routerClick()" class="item">
<i class="fa-solid fa-timeline"></i>
<span>时间轴</span>
</router-link>
<router-link v-if="path.includes('food')" to="/food/record" <router-link v-if="path.includes('food')" to="/food/record"
@click="routerClick()" class="item"> @click="routerClick()" class="item">
<i class="fa-solid fa-calendar-days"></i> <i class="fa-solid fa-calendar-days"></i>

View File

@@ -98,7 +98,7 @@
margin-left: 1vw; margin-left: 1vw;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; // justify-content: space-between;
gap: 1vh; gap: 1vh;
min-height: 28vh; min-height: 28vh;

View File

@@ -223,4 +223,11 @@ $tabBar-height: 70px;
border-radius: 10px; border-radius: 10px;
// box-shadow: 3px 3px 3px #CFCFCF; // box-shadow: 3px 3px 3px #CFCFCF;
} }
.form-item {
padding: 10px;
background-color: var(--color-card-bg);
border: 1px solid var(--color-border-bg);
border-radius: 10px;
}
} }

View File

@@ -1,3 +1,16 @@
/**
* 旅行景点
*/
export interface ITravelRecord {
id: number;
name: string;
area: string[];
date: string;
persons: string[];
imageList: string[];
videoList: string[];
}
/** /**
* 景点信息 * 景点信息
*/ */
@@ -16,19 +29,6 @@ export interface ITravelSpot {
recordList: ITravelRecord[]; recordList: ITravelRecord[];
} }
/**
* 旅行景点
*/
export interface ITravelRecord {
id: number;
name: string;
area: string[];
date: string;
persons: string[];
imageList: string[];
videoList: string[];
}
/** /**
* 统计信息 * 统计信息
*/ */

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="mobile-anniversary-detail common-mobile-view"> <div class="mobile-anniversary-detail common-mobile-view">
<el-form ref="formRef" :model="anniversaryStore.currentAnniversary" <el-form ref="formRef" :model="anniversaryStore.currentAnniversary"
:rules="rules" label-width="60px"> :rules="rules" label-position="top" label-width="60px"
class="form-item">
<el-form-item label="标题" prop="title"> <el-form-item label="标题" prop="title">
<el-input v-model="anniversaryStore.currentAnniversary.title" autocomplete="off" <el-input v-model="anniversaryStore.currentAnniversary.title" autocomplete="off"
placeholder="请输入标题" clearable placeholder="请输入标题" clearable

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="mobile-asset-detail common-mobile-view"> <div class="mobile-asset-detail common-mobile-view">
<el-form ref="formRef" :model="assetStore.currentAssetRecord" <el-form ref="formRef" :model="assetStore.currentAssetRecord"
:rules="rules" label-width="auto"> :rules="rules" label-position="top" label-width="auto"
class="form-item">
<el-form-item label="类别" prop="category"> <el-form-item label="类别" prop="category">
<el-radio-group v-model="assetStore.currentAssetRecord.category" <el-radio-group v-model="assetStore.currentAssetRecord.category"
@change="changeCategoryEvent"> @change="changeCategoryEvent">

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="bill-detail-mobile common-mobile-view"> <div class="bill-detail-mobile common-mobile-view">
<el-form ref="formRef" :model="billStore.currentBillRecord" <el-form ref="formRef" :model="billStore.currentBillRecord"
:rules="rules" label-width="80px"> :rules="rules" label-position="top" label-width="80px"
class="form-item">
<el-form-item label="账本类型" prop="bookName"> <el-form-item label="账本类型" prop="bookName">
<el-radio-group v-model="billStore.currentBillRecord.bookName" <el-radio-group v-model="billStore.currentBillRecord.bookName"
@change="changeBillBookNameEvent"> @change="changeBillBookNameEvent">

View File

@@ -1,12 +1,13 @@
<template> <template>
<div class="mobile-food-recipe-form common-mobile-view"> <div class="mobile-food-recipe-form common-mobile-view">
<el-form ref="formRef" :model="foodStore.currentFoodRecipe" <el-form ref="formRef" :model="foodStore.currentFoodRecipe"
:rules=rules label-width="80px"> :rules=rules label-position="top" label-width="80px"
class="form-item">
<el-steps :active="activeStep" align-center <el-steps :active="activeStep" align-center
style="margin-bottom: 10px;" > style="margin-bottom: 10px;" >
<el-step title="基础信息" /> <el-step title="基础信息" />
<el-step title="Step 2" /> <el-step title="食材信息" />
<el-step title="Step 3" /> <el-step title="步骤信息" />
</el-steps> </el-steps>
<div v-if="activeStep === 0"> <div v-if="activeStep === 0">
@@ -104,6 +105,7 @@ const confirmClick = () => {
formRef.value.validate().then(() => { formRef.value.validate().then(() => {
foodStore.handleFoodRecipeApi(foodStore.currentFoodRecipe) foodStore.handleFoodRecipeApi(foodStore.currentFoodRecipe)
history.back() history.back()
appStore.isShowMobileBack = false
}) })
} }

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="mobile-food-record-form common-mobile-view"> <div class="mobile-food-record-form common-mobile-view">
<el-form ref="formRef" :model="foodStore.currentFoodRecord" <el-form ref="formRef" :model="foodStore.currentFoodRecord"
:rules="rules" label-width="80"> :rules="rules" label-position="top" label-width="80"
class="form-item">
<el-form-item label="菜谱名称" prop="name"> <el-form-item label="菜谱名称" prop="name">
<el-select <el-select
v-model="foodStore.currentFoodRecord.name" v-model="foodStore.currentFoodRecord.name"

107
src/views/food/timeline.vue Normal file
View File

@@ -0,0 +1,107 @@
<template>
<div class="mobile-food-timeline common-mobile-view ">
<div class="button-container">
<el-button :icon="CaretLeft" circle
type="primary" size="small"
@click="previousYearClick"/>
<el-date-picker
v-model="foodStore.queryRecord.year"
type="year" placeholder="请选择年份"
:editable="false"
style="width: 100px;"
@change="changeDateEvent"
/>
<el-button :icon="CaretRight" circle
type="primary" size="small"
@click="nextYearClick"/>
</div>
<el-timeline v-if="foodStore.foodRecordList.length > 0">
<el-timeline-item v-for="(item, index) in foodStore.foodRecordList"
:key="index" :timestamp="formatDate(item.date)"
placement="top">
<div class="timeline-info card-item">
<span>{{ item.name }}</span>
<el-image :src="AListUrl + item.imageUrl"
fit="contain" alt="暂无成果">
<template #error>
<div class="image-slot">
<span>暂无图片</span>
</div>
</template>
</el-image>
</div>
</el-timeline-item>
</el-timeline>
<el-empty v-else description="暂无记录"/>
</div>
</template>
<script setup lang="ts">
import { CaretLeft, CaretRight } from '@element-plus/icons-vue'
import { useFoodStore } from '@/store/food.ts'
import { formatDate, getLastDate, getNextDate } from 'vue3-common/utils/dateUtil'
import { AListUrl } from '@/utils'
import { onMounted } from 'vue'
const foodStore = useFoodStore()
onMounted(async () => {
foodStore.queryDateType = 'year'
await foodStore.queryFoodRecordList()
})
const changeDateEvent = async (value: Date) => {
foodStore.queryRecord.year = String(value.getFullYear())
await foodStore.queryFoodRecordList()
}
const previousYearClick = async () => {
const lastYear = getLastDate(foodStore.queryRecord.year, 1, 'years')
foodStore.queryRecord.year = String(new Date(lastYear).getFullYear())
await foodStore.queryFoodRecordList()
}
const nextYearClick = async () => {
const lastYear = getNextDate(foodStore.queryRecord.year, 1, 'years')
foodStore.queryRecord.year = String(new Date(lastYear).getFullYear())
await foodStore.queryFoodRecordList()
}
</script>
<style lang="scss">
.mobile-food-timeline {
display: flex;
flex-direction: column;
.button-container {
align-self: center;
display: flex;
align-items: center;
gap: 10px;
}
.el-timeline {
padding: 10px;
.el-timeline-item__timestamp {
font-weight: bold;
color: #000000;
}
.timeline-info {
padding: 10px;
display: flex;
flex-direction: column;
gap: 10px;
.el-image {
height: 300px;
}
}
}
}
</style>

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="mobile-journal-detail common-mobile-view"> <div class="mobile-journal-detail common-mobile-view">
<el-form ref="formRef" :model="journalStore.currentJournal" <el-form ref="formRef" :model="journalStore.currentJournal"
:rules="rules" label-width="60px"> :rules="rules" label-position="top" label-width="60px"
class="form-item">
<el-form-item label="日期" prop="date"> <el-form-item label="日期" prop="date">
<el-date-picker <el-date-picker
v-model="journalStore.currentJournal.date" v-model="journalStore.currentJournal.date"

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="mobile-ledger-detail common-mobile-view"> <div class="mobile-ledger-detail common-mobile-view">
<el-form ref="formRef" :model="ledgerStore.currentLedgerRecord" <el-form ref="formRef" :model="ledgerStore.currentLedgerRecord"
:rules="rules" label-width="auto"> :rules="rules" label-position="top" label-width="auto"
class="form-item">
<el-form-item label="账本" prop="book"> <el-form-item label="账本" prop="book">
<el-input v-model="ledgerStore.currentLedgerRecord.book" <el-input v-model="ledgerStore.currentLedgerRecord.book"
placeholder="请输入账本名称" clearable placeholder="请输入账本名称" clearable

View File

@@ -37,6 +37,10 @@ export const mobileHomeMeta: IRouteMetaConfig = {
title: '菜谱', title: '菜谱',
icon: '' icon: ''
}, },
'/food/timeline': {
title: '时间轴',
icon: ''
},
'/food/record': { '/food/record': {
title: '记录', title: '记录',
icon: '' icon: ''

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="mobile-product-detail common-mobile-view"> <div class="mobile-product-detail common-mobile-view">
<el-form ref="formRef" :model="productStore.currentProduct" <el-form ref="formRef" :model="productStore.currentProduct"
:rules="rules" label-width="80px"> :rules="rules" label-position="top" label-width="80px"
class="form-item">
<el-form-item label="物品名称" prop="name"> <el-form-item label="物品名称" prop="name">
<el-input v-model="productStore.currentProduct.name" autocomplete="off" <el-input v-model="productStore.currentProduct.name" autocomplete="off"
placeholder="请输入物品名称" clearable placeholder="请输入物品名称" clearable

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="mobile-travel-record-form common-mobile-view"> <div class="mobile-travel-record-form common-mobile-view">
<el-form ref="formRef" :model="travelStore.currentTravelRecord" <el-form ref="formRef" :model="travelStore.currentTravelRecord"
:rules="rules" label-width="80"> :rules="rules" label-position="top" label-width="auto"
class="form-item">
<el-form-item label="景点名称" prop="name"> <el-form-item label="景点名称" prop="name">
<el-select <el-select
v-model="travelStore.currentTravelRecord.name" v-model="travelStore.currentTravelRecord.name"

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="mobile-travel-spot-form common-mobile-view"> <div class="mobile-travel-spot-form common-mobile-view">
<el-form ref="formRef" :model="travelStore.currentTravelSpot" <el-form ref="formRef" :model="travelStore.currentTravelSpot"
:rules=rules label-width="100px"> :rules=rules label-position="top" label-width="auto"
class="form-item">
<el-form-item label="景点名称" prop="name"> <el-form-item label="景点名称" prop="name">
<el-input <el-input
v-model="travelStore.currentTravelSpot.name" v-model="travelStore.currentTravelSpot.name"