feat:更新图片存储路径
This commit is contained in:
@@ -17,6 +17,10 @@ server {
|
||||
proxy_pass http://host.docker.internal:8081/;
|
||||
}
|
||||
|
||||
location /alist-api/ {
|
||||
proxy_pass http://host.docker.internal:5244/;
|
||||
}
|
||||
|
||||
location /blog-api/ {
|
||||
proxy_pass http://host.docker.internal:8082/;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
arrow="always" @change="changeFoodEvent">
|
||||
<el-carousel-item v-for="(item, index) in getFoodRecord(props.foodItem?.recordList)"
|
||||
:key="index">
|
||||
<el-image :src="serviceFileRootPath + item.imageUrl"
|
||||
<el-image :src="AListPath + item.imageUrl"
|
||||
fit="contain" alt="暂无成果">
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
@@ -26,8 +26,7 @@
|
||||
</div>
|
||||
|
||||
<div class="button-info">
|
||||
<el-button v-if="!isMobile()"
|
||||
type="primary" :icon="Edit" circle :size="'small'"
|
||||
<el-button type="primary" :icon="Edit" circle :size="'small'"
|
||||
@click="editFoodRecipeClick"/>
|
||||
<el-button type="primary" :icon="MoreFilled" circle :size="'small'"
|
||||
@click="viewFoodRecipeClick()" />
|
||||
@@ -70,10 +69,8 @@ import { defineProps, onMounted, PropType, reactive } from 'vue'
|
||||
import { IFoodRecipe, IFoodRecord } from '@/types/food.ts'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { formatDate } from 'vue3-common/utils/dateUtil'
|
||||
import { deepCopyObject } from 'vue3-common/utils/dataUtil'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import { serviceFileRootPath } from '@/utils'
|
||||
import { isMobile } from 'vue3-common/utils/layoutUtil'
|
||||
import { AListPath } from '@/utils'
|
||||
|
||||
const router = useRouter()
|
||||
const foodStore = useFoodStore()
|
||||
@@ -102,11 +99,7 @@ const editFoodRecipeClick = async () => {
|
||||
const id = props.foodItem?.id
|
||||
foodStore.foodRecipeApiType = 'UPDATE'
|
||||
await foodStore.queryFoodRecipe(id as number)
|
||||
foodStore.foodRecipeDialog = {
|
||||
title: '编辑菜谱',
|
||||
visible: true,
|
||||
data: deepCopyObject(foodStore.currentFoodRecipe)
|
||||
}
|
||||
await router.push({ name: 'FoodRecipeForm' })
|
||||
}
|
||||
|
||||
const viewFoodRecipeClick = async () => {
|
||||
@@ -116,7 +109,7 @@ const viewFoodRecipeClick = async () => {
|
||||
const deleteFoodRecipeClick = () => {
|
||||
foodStore.foodRecipeApiType = 'DELETE'
|
||||
commonElMessageBox(`请确认是否删除该菜谱: ${props.foodItem?.name}?`).then(() => {
|
||||
foodStore.handleFoodRecipeApi(props.foodItem?.id as number)
|
||||
foodStore.handleFoodRecipeApi(props.foodItem)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogData.visible" :title="dialogData.title"
|
||||
center @open="openDialogEvent" class="food-dialog">
|
||||
<el-form ref="formRef" :model="dialogData.data"
|
||||
:rules=rules label-width="80px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="美食名称" prop="name">
|
||||
<el-input v-model="dialogData.data.name" autocomplete="off"
|
||||
placeholder="请输入美食名称" clearable
|
||||
show-word-limit maxlength="20">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="美食菜系" prop="category">
|
||||
<el-select v-model="dialogData.data.category">
|
||||
<el-option v-for="(item, index) in foodCategoryList"
|
||||
:key="index" :label="item" :value="item"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="推荐指数" prop="recommendRate">
|
||||
<el-rate v-model="dialogData.data.recommendRate"
|
||||
:colors="foodStore.rateColorList"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="食材">
|
||||
<food-material-form />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item label="步骤">
|
||||
<food-step-form />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="dialogData.data.remark" autocomplete="off"
|
||||
placeholder="请输入备注" clearable
|
||||
show-word-limit maxlength="20">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="cancelClick">取消</el-button>
|
||||
<el-button type="primary" @click="confirmClick">保存</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import FoodMaterialForm from '@/components/Food/Form/FoodMaterialForm.vue'
|
||||
import FoodStepForm from '@/components/Food/Form/FoodStepForm.vue'
|
||||
import { useFoodStore } from '@/store/food.ts'
|
||||
import { FormInstance, FormRules } from 'element-plus'
|
||||
import { computed, nextTick, ref, reactive } from 'vue'
|
||||
import { foodRules } from '@/utils/element/elRules.ts'
|
||||
|
||||
const rules = reactive<FormRules>(foodRules)
|
||||
const formRef = ref<FormInstance>()
|
||||
const foodStore = useFoodStore()
|
||||
|
||||
const foodCategoryList = ['家常菜', '淮扬菜', '鲁菜', '川菜', '粤菜', '闽菜', '浙菜', '湘菜', '徽菜', '其他']
|
||||
|
||||
const dialogData = computed(() => foodStore.foodRecipeDialog)
|
||||
|
||||
/**
|
||||
* 打开对话框事件
|
||||
*/
|
||||
const openDialogEvent = async () => {
|
||||
await nextTick(() => {
|
||||
formRef.value?.clearValidate()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 点击确认按钮
|
||||
*/
|
||||
const confirmClick = () => {
|
||||
formRef.value?.validate().then(() => {
|
||||
foodStore.handleFoodRecipeApi()
|
||||
})
|
||||
}
|
||||
|
||||
const cancelClick = () => {
|
||||
dialogData.value.visible = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.food-dialog {
|
||||
width: 75%;
|
||||
|
||||
.el-dialog__body {
|
||||
height: 65vh;
|
||||
|
||||
.el-button.is-text {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.material-table {
|
||||
height: 45vh;
|
||||
}
|
||||
|
||||
.food-step-table {
|
||||
height: 55vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<el-dialog v-model="foodStore.foodMaterialDialog.visible"
|
||||
:title="foodStore.foodMaterialDialog.title"
|
||||
<el-dialog v-model="foodStore.foodMaterialDialogVisible"
|
||||
:title="foodStore.foodMaterialApiType === 'ADD' ? '新增食材' : '编辑食材'"
|
||||
center @open="openDialogEvent"
|
||||
class="food-material-dialog">
|
||||
<el-form ref="formRef" :model="foodStore.foodMaterialDialog.data"
|
||||
:rules="rules">
|
||||
<el-form ref="formRef" :model="foodStore.currentFoodMaterial"
|
||||
:rules="rules" label-width="auto">
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select
|
||||
v-model="foodStore.foodMaterialDialog.data.type"
|
||||
v-model="foodStore.currentFoodMaterial.type"
|
||||
placeholder="请选择类型">
|
||||
<el-option
|
||||
v-for="(item, index) in foodMaterialTypeList"
|
||||
@@ -17,14 +17,14 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="foodStore.foodMaterialDialog.data.name" autocomplete="off"
|
||||
<el-input v-model="foodStore.currentFoodMaterial.name" autocomplete="off"
|
||||
placeholder="请输入名称" clearable
|
||||
show-word-limit maxlength="20">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="分量" prop="amount">
|
||||
<el-input v-model="foodStore.foodMaterialDialog.data.amount" autocomplete="off"
|
||||
<el-input v-model="foodStore.currentFoodMaterial.amount" autocomplete="off"
|
||||
placeholder="请输入分量(1斤/2勺/适量)" clearable
|
||||
show-word-limit maxlength="20">
|
||||
</el-input>
|
||||
@@ -68,22 +68,22 @@ const confirmClick = () => {
|
||||
formRef.value.validate().then(async () => {
|
||||
if (foodStore.foodMaterialApiType === 'UPDATE') {
|
||||
const { editFoodMaterialIndex: index } = foodStore
|
||||
foodStore.foodRecipeDialog.data.materialList[index] = foodStore.foodMaterialDialog.data
|
||||
foodStore.currentFoodRecipe.materialList[index] = foodStore.currentFoodMaterial
|
||||
} else {
|
||||
foodStore.foodRecipeDialog.data.materialList.push(foodStore.foodMaterialDialog.data)
|
||||
foodStore.currentFoodRecipe.materialList.push(foodStore.currentFoodMaterial)
|
||||
}
|
||||
foodStore.foodMaterialDialog.visible = false
|
||||
foodStore.foodMaterialDialogVisible = false
|
||||
})
|
||||
}
|
||||
|
||||
const cancelClick = () => {
|
||||
foodStore.foodMaterialDialog.visible = false
|
||||
foodStore.foodMaterialDialogVisible = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.food-material-dialog {
|
||||
width: 30%;
|
||||
width: 80%;
|
||||
|
||||
.el-dialog__body {
|
||||
// height: 50vh;
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
<template>
|
||||
<el-table :data="foodStore.foodRecipeDialog.data.materialList"
|
||||
border stripe class="material-table">
|
||||
<el-table-column type="index" align="center" width="90">
|
||||
<template #header>
|
||||
<el-button type="primary" @click="handleAddClick">新增</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="type" label="类型" align="center" min-width="10%"/>
|
||||
<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 label="操作" align="center" width="100">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" text
|
||||
@click="handleEditClick(scope.$index, scope.row)">编辑</el-button>
|
||||
<el-button type="danger" text
|
||||
@click="handleDeleteClick(scope.$index, scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="material-form">
|
||||
<div style="align-self: center;">
|
||||
<el-button type="primary" @click="handleAddClick">新增</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="foodStore.currentFoodRecipe.materialList"
|
||||
border stripe class="material-table">
|
||||
<el-table-column prop="type" label="类型" align="center" min-width="10%"/>
|
||||
<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 label="操作" align="center" width="100">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" text style="margin: 0 10px 0 0;padding: 0;"
|
||||
@click="handleEditClick(scope.$index, scope.row)">编辑</el-button>
|
||||
<el-button type="danger" text style="margin: 0;padding: 0;"
|
||||
@click="handleDeleteClick(scope.$index, scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -30,27 +31,21 @@ const foodStore = useFoodStore()
|
||||
|
||||
const handleAddClick = () => {
|
||||
foodStore.foodMaterialApiType = 'ADD'
|
||||
foodStore.foodMaterialDialog = {
|
||||
title: '新增食材',
|
||||
visible: true,
|
||||
data: foodStore.getEmptyFoodMaterial()
|
||||
}
|
||||
foodStore.currentFoodMaterial = foodStore.getEmptyFoodMaterial()
|
||||
foodStore.foodMaterialDialogVisible = true
|
||||
}
|
||||
|
||||
const handleEditClick = (index: number, material: IFoodMaterial) => {
|
||||
foodStore.editFoodMaterialIndex = index
|
||||
foodStore.foodMaterialApiType = 'UPDATE'
|
||||
foodStore.foodMaterialDialog = {
|
||||
title: '编辑食材',
|
||||
visible: true,
|
||||
data: deepCopyObject(material)
|
||||
}
|
||||
foodStore.currentFoodMaterial = deepCopyObject(material)
|
||||
foodStore.foodMaterialDialogVisible = true
|
||||
}
|
||||
|
||||
const handleDeleteClick = (index: number, material: IFoodMaterial) => {
|
||||
foodStore.foodMaterialApiType = 'DELETE'
|
||||
commonElMessageBox(`确认删除该食材: ${material.name}?`).then(() => {
|
||||
foodStore.foodRecipeDialog.data.materialList.splice(index, 1)
|
||||
foodStore.currentFoodRecipe.materialList.splice(index, 1)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<el-dialog v-model="foodStore.foodStepDialog.visible"
|
||||
:title="foodStore.foodStepDialog.title"
|
||||
<el-dialog v-model="foodStore.foodStepDialogVisible"
|
||||
:title="foodStore.foodStepApiType === 'ADD' ? '新增步骤' : '编辑步骤'"
|
||||
center @open="openDialogEvent"
|
||||
class="food-step-dialog">
|
||||
<el-form ref="formRef" :model="foodStore.foodStepDialog.data"
|
||||
:rules="rules">
|
||||
<el-form ref="formRef" :model="foodStore.currentFoodStep"
|
||||
:rules="rules" label-width="auto">
|
||||
<el-form-item label="内容" prop="content">
|
||||
<el-input v-model="foodStore.foodStepDialog.data.content" autocomplete="off"
|
||||
<el-input v-model="foodStore.currentFoodStep.content" autocomplete="off"
|
||||
placeholder="请输入内容" clearable
|
||||
show-word-limit maxlength="20">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="图片">
|
||||
<upload-image v-model="foodStore.foodStepDialog.data.imageUrl"
|
||||
<upload-image v-model="foodStore.currentFoodStep.imageUrl"
|
||||
:service-url="fileServiceUrl"
|
||||
:image-limit="1"
|
||||
:service-file-root-path="serviceFileRootPath"
|
||||
@@ -60,22 +60,22 @@ const confirmClick = () => {
|
||||
.then(async () => {
|
||||
if (foodStore.foodStepApiType === 'UPDATE') {
|
||||
const { editFoodStepIndex: index } = foodStore
|
||||
foodStore.foodRecipeDialog.data.stepList[index] = foodStore.foodStepDialog.data
|
||||
foodStore.currentFoodRecipe.stepList[index] = foodStore.currentFoodStep
|
||||
} else {
|
||||
foodStore.foodRecipeDialog.data.stepList.push(foodStore.foodStepDialog.data)
|
||||
foodStore.currentFoodRecipe.stepList.push(foodStore.currentFoodStep)
|
||||
}
|
||||
foodStore.foodStepDialog.visible = false
|
||||
foodStore.foodStepDialogVisible = false
|
||||
})
|
||||
}
|
||||
|
||||
const cancelClick = () => {
|
||||
foodStore.foodStepDialog.visible = false
|
||||
foodStore.foodStepDialogVisible = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.food-step-dialog {
|
||||
width: 30%;
|
||||
width: 80%;
|
||||
|
||||
.el-dialog__body {
|
||||
// height: 50vh;
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
<template>
|
||||
<el-table :data="foodStore.foodRecipeDialog.data.stepList"
|
||||
border class="food-step-table">
|
||||
<el-table-column type="index" align="center" width="90">
|
||||
<template #header>
|
||||
<el-button type="primary" @click="handleAddClick">新增</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="content" label="内容" align="center" min-width="20%" />
|
||||
<el-table-column prop="imageUrl" label="图片" align="center" min-width="20%">
|
||||
<template #default="scope">
|
||||
<el-image v-if="scope.row.imageUrl" :src="serviceFileRootPath + scope.row.imageUrl" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<div class="step-form">
|
||||
<div style="align-self: center;">
|
||||
<el-button type="primary" @click="handleAddClick">新增</el-button>
|
||||
</div>
|
||||
|
||||
<el-table-column label="操作" align="center" width="100">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" text
|
||||
@click="handleEditClick(scope.$index, scope.row)">编辑</el-button>
|
||||
<el-button type="danger" text
|
||||
@click="handleDeleteClick(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table :data="foodStore.currentFoodRecipe.stepList"
|
||||
border class="food-step-table">
|
||||
<el-table-column prop="content" label="内容" align="center" min-width="20%" />
|
||||
<el-table-column prop="imageUrl" label="图片" align="center" min-width="20%">
|
||||
<template #default="scope">
|
||||
<el-image v-if="scope.row.imageUrl" :src="serviceFileRootPath + scope.row.imageUrl" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" align="center" width="100">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" text style="margin: 0 10px 0 0;padding: 0;"
|
||||
@click="handleEditClick(scope.$index, scope.row)">编辑</el-button>
|
||||
<el-button type="danger" text style="margin: 0;padding: 0;"
|
||||
@click="handleDeleteClick(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -35,29 +36,22 @@ const foodStore = useFoodStore()
|
||||
|
||||
const handleAddClick = () => {
|
||||
foodStore.foodStepApiType = 'ADD'
|
||||
foodStore.foodStepImageList = []
|
||||
foodStore.foodStepDialog = {
|
||||
title: '新增步骤',
|
||||
visible: true,
|
||||
data: foodStore.getEmptyFoodStep()
|
||||
}
|
||||
foodStore.currentFoodStep = foodStore.getEmptyFoodStep()
|
||||
foodStore.foodStepDialogVisible = true
|
||||
}
|
||||
|
||||
const handleEditClick = (index: number, step: IFoodStep) => {
|
||||
foodStore.editFoodStepIndex = index
|
||||
foodStore.foodStepApiType = 'UPDATE'
|
||||
foodStore.foodStepDialog = {
|
||||
title: '编辑步骤',
|
||||
visible: true,
|
||||
data: deepCopyObject(step)
|
||||
}
|
||||
foodStore.currentFoodStep = deepCopyObject(step)
|
||||
foodStore.foodStepDialogVisible = true
|
||||
}
|
||||
|
||||
const handleDeleteClick = (index: number) => {
|
||||
commonElMessageBox('确认删除该步骤?').then(() => {
|
||||
foodStore.foodStepApiType = 'DELETE'
|
||||
foodStore.foodRecipeDialog.data.stepList.splice(index, 1)
|
||||
foodStore.foodRecipeDialog.data.stepList.forEach((item) => {
|
||||
foodStore.currentFoodRecipe.stepList.splice(index, 1)
|
||||
foodStore.currentFoodRecipe.stepList.forEach((item) => {
|
||||
if (item.sort > index) {
|
||||
item.sort -= 1
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
<!-- 单媒体内容(图片优先于视频) -->
|
||||
<el-image
|
||||
v-if="props.item?.imageUrl"
|
||||
:src="serviceFileRootPath + props.item?.imageUrl"
|
||||
:preview-src-list="[serviceFileRootPath + props.item?.imageUrl]"
|
||||
:src="AListPath + props.item?.imageUrl"
|
||||
:preview-src-list="[AListPath + props.item?.imageUrl]"
|
||||
fit="contain"
|
||||
class="media-content"/>
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
v-if="props.item?.videoUrl"
|
||||
controls
|
||||
class="media-content">
|
||||
<source :src="serviceFileRootPath + props.item?.videoUrl" type="video/mp4">
|
||||
<source :src="AListPath + props.item?.videoUrl" type="video/mp4">
|
||||
</video>
|
||||
|
||||
<!-- 展开/收起按钮 -->
|
||||
@@ -76,7 +76,7 @@ import { deepCopyObject } from 'vue3-common/utils/dataUtil'
|
||||
import { useJournalStore } from '@/store/journal.ts'
|
||||
import { useAppStore } from '@/store/app.ts'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { serviceFileRootPath } from '@/utils'
|
||||
import { AListPath } from '@/utils'
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="life-record-card card-item">
|
||||
<el-image :src="serviceFileRootPath + props.productItem?.imageUrl"
|
||||
:preview-src-list="[serviceFileRootPath + props.productItem?.imageUrl]"
|
||||
<el-image :src="AListPath + props.productItem?.imageUrl"
|
||||
:preview-src-list="[AListPath + props.productItem?.imageUrl]"
|
||||
fit="contain" alt="暂无成果">
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
@@ -70,7 +70,7 @@ import { defineProps, onMounted, PropType } from 'vue'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import { IProduct } from '@/types/product.ts'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { serviceFileRootPath } from '@/utils'
|
||||
import { AListPath } from '@/utils'
|
||||
|
||||
const productStore = useProductStore()
|
||||
const router = useRouter()
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
<el-card class="record-card">
|
||||
<span class="record-content">旅行人:{{ item.persons.join('-') }}</span>
|
||||
<el-image v-for="(image, index) in item.imageList" :key="index"
|
||||
:src="serviceFileRootPath + image"
|
||||
:preview-src-list="[serviceFileRootPath + image]"
|
||||
:src="AListPath + image"
|
||||
:preview-src-list="[AListPath + image]"
|
||||
fit="contain" alt="暂无图片" class="record-image"/>
|
||||
|
||||
<video v-for="(video, index) in item.videoList"
|
||||
:key="index" controls style="width: 60%;min-height: 200px;">
|
||||
<source :src="serviceFileRootPath + video" type="video/mp4">
|
||||
<source :src="AListPath + video" type="video/mp4">
|
||||
您的浏览器不支持 HTML5 视频
|
||||
</video>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<script setup lang="ts">
|
||||
import { SvgIcon } from 'vue3-common'
|
||||
import { useTravelStore } from '@/store/travel.ts'
|
||||
import { serviceFileRootPath } from '@/utils'
|
||||
import { AListPath } from '@/utils'
|
||||
|
||||
const travelStore = useTravelStore()
|
||||
</script>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<el-carousel v-if="props.travelItem?.recordList.length > 0"
|
||||
arrow="always" @change="changeTravelEvent">
|
||||
<el-carousel-item v-for="(item, index) in props.travelItem?.recordList" :key="index">
|
||||
<el-image :src="serviceFileRootPath + item.imageList[0]"
|
||||
<el-image :src="AListPath + item.imageList[0]"
|
||||
fit="contain" alt="暂无图片">
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
@@ -70,7 +70,7 @@ import { useRouter } from 'vue-router'
|
||||
import { formatDate } from 'vue3-common/utils/dateUtil'
|
||||
import { ITravelSpot } from '@/types/travel.ts'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import { serviceFileRootPath } from '@/utils'
|
||||
import { AListPath } from '@/utils'
|
||||
import { parsePerson } from '@/utils/home/travelUtil.ts'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -29,6 +29,16 @@ export const useFoodStore = defineStore('food', {
|
||||
stepList: [],
|
||||
recordList: []
|
||||
} as IFoodRecipe,
|
||||
currentFoodMaterial: {
|
||||
name: '',
|
||||
type: '',
|
||||
amount: ''
|
||||
} as IFoodMaterial,
|
||||
currentFoodStep: {
|
||||
content: '',
|
||||
sort: 0,
|
||||
imageUrl: ''
|
||||
}as IFoodStep,
|
||||
foodRecordList: [] as IFoodRecord[],
|
||||
currentFoodRecord: {
|
||||
id: 0,
|
||||
@@ -49,24 +59,11 @@ export const useFoodStore = defineStore('food', {
|
||||
queryDateType: 'month' as IDateType,
|
||||
queryDateList: [] as string[],
|
||||
foodRecipeApiType: 'ADD' as IHandleApi,
|
||||
foodRecipeDialog: {
|
||||
visible: false,
|
||||
title: '',
|
||||
data: {}
|
||||
} as IDialog<IFoodRecipe>,
|
||||
foodMaterialApiType: 'ADD' as IHandleApi,
|
||||
foodMaterialDialog: {
|
||||
visible: false,
|
||||
title: '',
|
||||
data: {}
|
||||
} as IDialog<IFoodMaterial>,
|
||||
foodMaterialDialogVisible: false,
|
||||
editFoodMaterialIndex: 0,
|
||||
foodStepApiType: 'ADD' as IHandleApi,
|
||||
foodStepDialog: {
|
||||
visible: false,
|
||||
title: '',
|
||||
data: {}
|
||||
} as IDialog<IFoodStep>,
|
||||
foodStepDialogVisible: false,
|
||||
editFoodStepIndex: 0,
|
||||
foodRecordApiType: 'ADD' as IHandleApi,
|
||||
foodRecordDialog: {
|
||||
@@ -123,25 +120,23 @@ export const useFoodStore = defineStore('food', {
|
||||
async queryFoodCategory() {
|
||||
this.foodCategoryList = await queryFoodCategoryApi()
|
||||
},
|
||||
async handleFoodRecipeApi(id?: number) {
|
||||
const { data } = this.foodRecipeDialog
|
||||
async handleFoodRecipeApi(recipe: IFoodRecipe) {
|
||||
switch (this.foodRecipeApiType) {
|
||||
case 'ADD':
|
||||
await addFoodRecipeApi(data)
|
||||
await addFoodRecipeApi(recipe)
|
||||
ElMessage.success('新增菜谱成功')
|
||||
break
|
||||
case 'UPDATE':
|
||||
await updateFoodRecipeApi(data.id as number, data)
|
||||
await updateFoodRecipeApi(recipe.id as number, recipe)
|
||||
ElMessage.success('更新菜谱成功')
|
||||
break
|
||||
case 'DELETE':
|
||||
await deleteFoodRecipeApi(id as number)
|
||||
await deleteFoodRecipeApi(recipe.id as number)
|
||||
ElMessage.success('删除菜谱成功')
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
this.foodRecipeDialog.visible = false
|
||||
await this.refreshInfo()
|
||||
},
|
||||
async handleFoodRecordApi(foodRecord: IFoodRecord) {
|
||||
|
||||
@@ -28,6 +28,8 @@ export const fileServiceUrl = '/home-api/file'
|
||||
*/
|
||||
export const serviceFileRootPath = '/home-api/'
|
||||
|
||||
export const AListPath = '/alist-api/'
|
||||
|
||||
/**
|
||||
* 获取assets静态资源
|
||||
* @param url 路径
|
||||
|
||||
132
src/views/food/recipeForm.vue
Normal file
132
src/views/food/recipeForm.vue
Normal file
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<div class="mobile-food-recipe-form common-mobile-view">
|
||||
<el-form ref="formRef" :model="foodStore.currentFoodRecipe"
|
||||
:rules=rules label-width="80px">
|
||||
<el-steps :active="activeStep" align-center
|
||||
style="margin-bottom: 10px;" >
|
||||
<el-step title="基础信息" />
|
||||
<el-step title="Step 2" />
|
||||
<el-step title="Step 3" />
|
||||
</el-steps>
|
||||
|
||||
<div v-if="activeStep === 0">
|
||||
<el-form-item label="美食名称" prop="name">
|
||||
<el-input v-model="foodStore.currentFoodRecipe.name" autocomplete="off"
|
||||
placeholder="请输入美食名称" clearable
|
||||
show-word-limit maxlength="20">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="美食菜系" prop="category">
|
||||
<el-select v-model="foodStore.currentFoodRecipe.category">
|
||||
<el-option v-for="(item, index) in foodCategoryList"
|
||||
:key="index" :label="item" :value="item"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="推荐指数" prop="recommendRate">
|
||||
<el-rate v-model="foodStore.currentFoodRecipe.recommendRate"
|
||||
:colors="foodStore.rateColorList"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="foodStore.currentFoodRecipe.remark" autocomplete="off"
|
||||
placeholder="请输入备注" clearable
|
||||
show-word-limit maxlength="20">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div v-if="activeStep === 1">
|
||||
<food-material-form />
|
||||
</div>
|
||||
|
||||
<div v-if="activeStep === 2">
|
||||
<food-step-form />
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<div class="button-container">
|
||||
<el-button type="primary" :disabled="activeStep === 0"
|
||||
@click="previewClick">上一步</el-button>
|
||||
<el-button type="primary" :disabled="activeStep === 2"
|
||||
@click="nextClick">下一步</el-button>
|
||||
</div>
|
||||
|
||||
<div class="button-container">
|
||||
<el-button type="primary" @click="confirmClick">确认</el-button>
|
||||
<el-button type="danger" @click="deleteClick">删除</el-button>
|
||||
<el-button type="info" @click="cancelClick">取消</el-button>
|
||||
</div>
|
||||
|
||||
<food-material-dialog />
|
||||
<food-step-dialog />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import FoodMaterialDialog from '@/components/Food/Form/FoodMaterialDialog.vue'
|
||||
import FoodStepDialog from '@/components/Food/Form/FoodStepDialog.vue'
|
||||
import { useFoodStore } from '@/store/food.ts'
|
||||
import { ref, reactive } from 'vue'
|
||||
import { FormRules } from 'element-plus'
|
||||
import { foodRecordRules } from '@/utils/element/elRules.ts'
|
||||
import { commonElMessageBox } from 'vue3-common/utils/elUtil'
|
||||
import FoodMaterialForm from '@/components/Food/Form/FoodMaterialForm.vue'
|
||||
import FoodStepForm from '@/components/Food/Form/FoodStepForm.vue'
|
||||
|
||||
const rules = reactive<FormRules>(foodRecordRules)
|
||||
|
||||
const formRef = ref()
|
||||
const activeStep = ref(0)
|
||||
const foodStore = useFoodStore()
|
||||
|
||||
const foodCategoryList = ['家常菜', '淮扬菜', '鲁菜', '川菜', '粤菜', '闽菜', '浙菜', '湘菜', '徽菜', '其他']
|
||||
|
||||
const previewClick = () => {
|
||||
activeStep.value--
|
||||
}
|
||||
|
||||
const nextClick = () => {
|
||||
activeStep.value++
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击确认按钮
|
||||
*/
|
||||
const confirmClick = () => {
|
||||
formRef.value.validate().then(() => {
|
||||
foodStore.handleFoodRecipeApi(foodStore.currentFoodRecipe)
|
||||
history.back()
|
||||
})
|
||||
}
|
||||
|
||||
const cancelClick = () => {
|
||||
history.back()
|
||||
}
|
||||
|
||||
const deleteClick = () => {
|
||||
commonElMessageBox('是否确认删除该记录?').then(() => {
|
||||
foodStore.foodRecordApiType = 'DELETE'
|
||||
foodStore.handleFoodRecipeApi(foodStore.currentFoodRecipe)
|
||||
history.back()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.mobile-food-recipe-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
|
||||
.button-container {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.material-form, .step-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
}</style>
|
||||
@@ -18,6 +18,10 @@
|
||||
title="账单记录" sub-title="收支一目了然"
|
||||
router="/bill/data" @click="initBillClick"/>
|
||||
|
||||
<module-card icon="iconfont icon-canyin" color="#FF8C32"
|
||||
title="美食记录" sub-title="收录每日餐食"
|
||||
router="/food/recipe"/>
|
||||
|
||||
<module-card icon="iconfont icon-jingdian" color="#FF9966"
|
||||
title="旅行记录" sub-title="足迹遍及四方"
|
||||
router="/travel/spot"/>
|
||||
|
||||
@@ -27,10 +27,36 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
title: '账单设置',
|
||||
icon: ''
|
||||
},
|
||||
'/food': {
|
||||
title: '美食记录',
|
||||
icon: '',
|
||||
order: 2,
|
||||
redirect: '/food/recipe'
|
||||
},
|
||||
'/food/recipe': {
|
||||
title: '菜谱',
|
||||
icon: ''
|
||||
},
|
||||
'/food/record': {
|
||||
title: '记录',
|
||||
icon: ''
|
||||
},
|
||||
'/food/detail/:id': {
|
||||
title: '菜谱内容',
|
||||
icon: ''
|
||||
},
|
||||
'/food/recipeForm': {
|
||||
title: '菜谱表单',
|
||||
icon: ''
|
||||
},
|
||||
'/food/recordForm': {
|
||||
title: '记录表单',
|
||||
icon: ''
|
||||
},
|
||||
'/travel': {
|
||||
title: '旅行记录',
|
||||
icon: '',
|
||||
order: 2,
|
||||
order: 3,
|
||||
redirect: '/travel/spot'
|
||||
},
|
||||
'/travel/spot': {
|
||||
@@ -56,7 +82,7 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
'/health': {
|
||||
title: '运动健康',
|
||||
icon: '',
|
||||
order: 3,
|
||||
order: 4,
|
||||
redirect: '/health/calendar'
|
||||
},
|
||||
'/health/calendar': {
|
||||
@@ -70,7 +96,7 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
'/anniversary': {
|
||||
title: '纪念日',
|
||||
icon: 'home-anniversary',
|
||||
order: 4,
|
||||
order: 5,
|
||||
redirect: '/anniversary/list'
|
||||
},
|
||||
'/anniversary/list': {
|
||||
@@ -88,7 +114,7 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
'/period': {
|
||||
title: '月经记录',
|
||||
icon: 'home-period',
|
||||
order: 5,
|
||||
order: 6,
|
||||
redirect: '/period/calendar'
|
||||
},
|
||||
'/period/calendar': {
|
||||
@@ -106,7 +132,7 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
'/product': {
|
||||
title: '物品记录',
|
||||
icon: 'home-product',
|
||||
order: 6,
|
||||
order: 7,
|
||||
redirect: '/product/list'
|
||||
},
|
||||
'/product/list': {
|
||||
@@ -120,7 +146,7 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
'/journal': {
|
||||
title: '日记',
|
||||
icon: 'home-product',
|
||||
order: 7,
|
||||
order: 8,
|
||||
redirect: '/journal/record'
|
||||
},
|
||||
'/journal/record': {
|
||||
@@ -138,7 +164,7 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
'/kpi': {
|
||||
title: '绩效',
|
||||
icon: 'home-kpi',
|
||||
order: 8,
|
||||
order: 9,
|
||||
redirect: '/kpi/record'
|
||||
},
|
||||
'/kpi/record': {
|
||||
@@ -152,7 +178,7 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
'/asset': {
|
||||
title: '资产',
|
||||
icon: 'home-asset',
|
||||
order: 9,
|
||||
order: 10,
|
||||
redirect: '/asset/list'
|
||||
},
|
||||
'/asset/list': {
|
||||
@@ -166,7 +192,7 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
'/ledger': {
|
||||
title: '账本',
|
||||
icon: 'home-ledger',
|
||||
order: 10,
|
||||
order: 11,
|
||||
redirect: '/ledger/list'
|
||||
},
|
||||
'/ledger/list': {
|
||||
@@ -184,7 +210,7 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
'/password': {
|
||||
title: '密码',
|
||||
icon: 'home-password',
|
||||
order: 11,
|
||||
order: 12,
|
||||
redirect: '/password/list'
|
||||
},
|
||||
'/password/list': {
|
||||
@@ -194,7 +220,7 @@ export const mobileHomeMeta: IRouteMetaConfig = {
|
||||
'/profile': {
|
||||
title: '个人信息',
|
||||
icon: '',
|
||||
order: 12,
|
||||
order: 13,
|
||||
hidden: true,
|
||||
redirect: '/profile/index'
|
||||
},
|
||||
|
||||
@@ -50,6 +50,11 @@ export default defineConfig({
|
||||
target: `http://${API_HOST}:8082`,
|
||||
changeOrigin: true,
|
||||
rewrite: (item) => item.replace(/^\/blog-api/, '')
|
||||
},
|
||||
'/alist-api': {
|
||||
target: 'http://192.168.1.7:5244',
|
||||
changeOrigin: true,
|
||||
rewrite: (item) => item.replace(/^\/alist-api/, '')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user