feat:更新美食和旅游模块
This commit is contained in:
@@ -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">
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统计信息
|
* 统计信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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">
|
||||||
|
|||||||
@@ -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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
107
src/views/food/timeline.vue
Normal 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>
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
|||||||
title: '菜谱',
|
title: '菜谱',
|
||||||
icon: ''
|
icon: ''
|
||||||
},
|
},
|
||||||
|
'/food/timeline': {
|
||||||
|
title: '时间轴',
|
||||||
|
icon: ''
|
||||||
|
},
|
||||||
'/food/record': {
|
'/food/record': {
|
||||||
title: '记录',
|
title: '记录',
|
||||||
icon: ''
|
icon: ''
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user