1
0
mirror of synced 2025-11-06 04:20:50 +08:00

feat: refactor more ui with app

This commit is contained in:
YunYouJun
2025-10-06 18:43:58 +08:00
parent 30a92d0eb2
commit cf58e820c9
16 changed files with 255 additions and 101 deletions

View File

@@ -1,35 +1,50 @@
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
const props = defineProps({
isVisible: Boolean,
})
const rStore = useRecipeStore()
const { displayedRecipe } = storeToRefs(rStore)
/**
* Show basket button if there are recipes in the basket
* scroll into view
*/
const showBasketBtn = computed(() => {
return displayedRecipe.value.length !== rStore.recipesLength && props.isVisible
})
function recipePanelScrollIntoView() {
const panel = recipePanelRef.value as HTMLElement
if (panel) {
panel.scrollIntoView({ behavior: 'smooth', block: 'start' })
}
}
</script>
<template>
<button
v-show="showBasketBtn"
class="rounded rounded-full inline-flex cursor-pointer shadow items-center justify-center fixed z-9 hover:shadow-md"
bg="green-50 dark:green-900" w="10" h="10"
bottom="22"
right="4"
text="green-600 dark:green-300"
>
<span v-if="displayedRecipe.length > 0">
<div i-mdi-bowl-mix-outline />
</span>
<span v-else>
<div i-mdi-bowl-outline />
</span>
</button>
<ion-fab slot="fixed" horizontal="end" vertical="bottom">
<!-- <button
v-show="showBasketBtn"
class="rounded rounded-full inline-flex cursor-pointer shadow items-center justify-center fixed z-9 hover:shadow-md"
bg="green-50 dark:green-900" w="10" h="10"
bottom="22"
right="4"
text="green-600 dark:green-300"
>
</button> -->
<ion-fab-button size="small">
<!-- <ion-icon :icon="add" /> -->
<span v-if="displayedRecipe.length > 0">
<div i-mdi-bowl-mix-outline />
</span>
<span v-else>
<div i-mdi-bowl-outline />
</span>
</ion-fab-button>
<ion-fab-list side="top">
<ion-fab-button @click="rStore.reset">
<ion-icon :icon="ioniconsTrashOutline" />
</ion-fab-button>
<ion-fab-button @click="recipePanelScrollIntoView">
<ion-icon :icon="ioniconsListOutline" />
</ion-fab-button>
</ion-fab-list>
</ion-fab>
</template>

View File

@@ -19,7 +19,6 @@ const { playAnimation } = useEmojiAnimation(recipeBtnRef)
const { proxy } = useScriptGoogleTagManager()
const recipePanelRef = ref()
const { isVisible, show } = useInvisibleElement(recipePanelRef)
// 监听食材变化,自动检测相克
watch(curStuff, (newIngredients) => {
@@ -59,7 +58,14 @@ function toggleStuff(item: StuffItem, category = '', _e?: Event) {
</h2>
<!-- 食物相克警告提示 -->
<Transition name="incompatible-warning">
<ion-toast
class="incompatible-warning-toast"
:message="warningMessage"
:is-open="hasWarning"
position="top"
:icon="ioniconsWarningOutline"
animated
>
<div
v-if="hasWarning"
class="incompatible-warning-box"
@@ -84,7 +90,7 @@ function toggleStuff(item: StuffItem, category = '', _e?: Event) {
</div>
</div>
</div>
</Transition>
</ion-toast>
<div>
<h2 opacity="90" text="base" font="bold" p="1">
@@ -155,9 +161,20 @@ function toggleStuff(item: StuffItem, category = '', _e?: Event) {
</div>
</div>
<Transition>
<BasketButton ref="recipeBtnRef" :is-visible="isVisible" @click="show" />
</Transition>
<RecipePanel ref="recipePanelRef" />
</div>
<Transition>
<BasketButton ref="recipeBtnRef" />
</Transition>
</template>
<style>
ion-toast.incompatible-warning-toast {
/* --background: #f4f4fa; */
--box-shadow: 3px 3px 10px 0 rgba(0, 0, 0, 0.2);
/* --color: #4b4a50; */
--background: rgba(254, 202, 202, 0.95);
--color: #7f1d1d;
}
</style>

View File

@@ -5,24 +5,24 @@ const { random, randomRecipes } = useRandomRecipe(count)
<template>
<div inline-flex m="y-3">
<button btn p-2 rounded-full @click="dec()">
<div i-carbon-subtract />
</button>
<div font="mono" w="15" m-auto inline-block>
<ion-button shape="round" @click="dec()">
<ion-icon slot="icon-only" :icon="ioniconsRemoveOutline" />
</ion-button>
<div font="mono" class="w-15 text-center text-2xl" m-auto>
{{ count }}
</div>
<button btn p-2 rounded-full @click="inc()">
<div i-carbon-add />
</button>
<ion-button shape="round" @click="inc()">
<ion-icon slot="icon-only" :icon="ioniconsAddOutline" />
</ion-button>
</div>
<button cursor-pointer class="text-sm text-white leading-6 font-semibold px-3 py-1.5 rounded-md border-none bg-blue-600 inline-flex inline-flex shadow-sm items-center justify-center focus-visible:outline-2 focus-visible:outline-blue-600 focus-visible:outline-offset-2 focus-visible:outline hover:bg-blue-500" @click="random">
<ion-button @click="random">
<div class="transition" hover="text-blue-500" i-ri-refresh-line mr-1 inline-flex />
<div>随机一下</div>
</button>
</ion-button>
<div v-show="randomRecipes.length > 0">
<div m="t-8" flex="~ col">
<div m="t-4" flex="~ col">
<template v-for="recipe, i in randomRecipes" :key="i">
<DishTag v-if="recipe" :dish="recipe" />
</template>

View File

@@ -1,5 +1,6 @@
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { recipePanelRef } from '~/composables/global'
const rStore = useRecipeStore()
@@ -12,15 +13,16 @@ const showTooltip = computed(() => !selectedStuff.value.length && !curTool.value
<template>
<div
class="recipe-panel shadow transition relative hover:shadow-md"
m="x-2 y-4" p="2"
ref="recipePanelRef"
class="recipe-panel relative shadow transition hover:shadow-md" m="x-2 y-4"
p="2"
bg="gray-400/8"
>
<RecipePanelTitle />
<ToggleMode />
<button right-4 top-4 absolute @click="showSearchInput = !showSearchInput">
<button absolute right-4 top-4 @click="showSearchInput = !showSearchInput">
<div v-if="!showSearchInput" i-ri-search-line />
<div v-else i-ri-search-fill />
</button>
@@ -36,7 +38,7 @@ const showTooltip = computed(() => !selectedStuff.value.length && !curTool.value
<div
v-else-if="rStore.isSearching"
text-xl p-6 flex items-center justify-center relative
relative flex items-center justify-center p-6 text-xl
>
<div class="magnifying-glass" i-ri-search-line inline-flex />
</div>

View File

@@ -0,0 +1,65 @@
<script lang="ts" setup>
import { isClient } from '@vueuse/core'
import pkg from '~/../package.json'
import { icp } from '../constants'
const displayICP = ref(true)
const commitSha = (import.meta.env.VITE_COMMIT_REF || '').slice(0, 7)
const date = import.meta.env.VITE_APP_BUILD_DATE
const buildDate = (new Date(date)).toLocaleDateString()
onBeforeMount(() => {
if (isClient)
displayICP.value = ['cook.yunyoujun.cn', 'localhost', '127.0.0.1'].includes(window.location.hostname)
})
</script>
<template>
<ion-list :inset="true">
<ion-item>
<ion-label>当前版本</ion-label>
<ion-text>v{{ pkg.version }}</ion-text>
</ion-item>
<ion-item>
<ion-label>构建时间</ion-label>
<ion-text>{{ buildDate }}</ion-text>
</ion-item>
<ion-item v-if="commitSha" :href="`https://github.com/YunYouJun/cook/commit/${commitSha}`" target="_blank">
<ion-label>Commit Hash</ion-label>
<ion-text>{{ commitSha }}</ion-text>
</ion-item>
<ion-item v-if="displayICP" href="https://beian.miit.gov.cn/" target="_blank">
<ion-label>备案号</ion-label>
<ion-text>{{ icp }}</ion-text>
</ion-item>
</ion-list>
<ion-list :inset="true">
<ion-item href="https://www.bilibili.com/blackboard/dynamic/306882" target="_blank">
<ion-label>数据来源</ion-label>
<ion-text class="inline-flex items-center justify-center">
<div class="inline-flex" i-ri-bilibili-line />
<span m="l-1" class="inline-flex">哔哩哔哩</span>
</ion-text>
</ion-item>
<ion-item href="https://github.com/YunYouJun/cook" target="_blank">
<ion-label>开源代码</ion-label>
<ion-text class="inline-flex items-center justify-center">
<div class="inline-flex" i-ri-github-line />
<span m="l-1" class="inline-flex">GitHub</span>
</ion-text>
</ion-item>
<ion-item href="https://www.yunyoujun.cn" target="_blank">
<ion-label>项目作者</ion-label>
<ion-text class="inline-flex items-center justify-center">
云游君
</ion-text>
</ion-item>
</ion-list>
</template>

View File

@@ -0,0 +1 @@
export const recipePanelRef = ref()

View File

@@ -4,6 +4,8 @@ import { isClient, useElementBounding } from '@vueuse/core'
/**
* trigger show invisible element
* @param target
*
* @deprecated use scrollIntoView instead
*/
export function useInvisibleElement(target: MaybeComputedElementRef<HTMLElement>) {
const { top } = useElementBounding(target)

View File

@@ -4,4 +4,6 @@ export const appDescription = '好的,今天我们来做菜!'
export const namespace = 'cook'
export const lastDbUpdated = '2023-11-11 19:51:02'
export const icp = '苏ICP备17038157号'
export * from './links'

View File

@@ -7,6 +7,8 @@ export const links = {
* 兔小巢反馈
*/
feedback: 'https://support.qq.com/product/507827',
githubIssue: 'https://github.com/YunYouJun/cook/issues',
githubDiscussions: 'https://github.com/YunYouJun/cook/discussions',
/**
* changelog

View File

@@ -1,6 +1,6 @@
foodA,foodB,reason
番茄,黄瓜,黄瓜中含有维生素C分解酶会破坏番茄中的维生素C营养流失严重
牛奶,韭菜,牛奶与韭菜同食会影响钙的吸收,降低营养价值
土豆,番茄,土豆会产生大量的盐酸,番茄在较强的酸性环境中会产生不溶于水的沉淀
白萝卜,胡萝卜,白萝卜中的维生素C会被胡萝卜中的抗坏血酸酵素破坏
芹菜,黄瓜,芹菜中的维生素C会被黄瓜中的维生素C分解酶破坏
番茄,黄瓜,黄瓜中含有维生素C分解酶会破坏番茄中的维生素C营养流失严重
牛奶,韭菜,牛奶与韭菜同食会影响钙的吸收,降低营养价值
土豆,番茄,土豆会产生大量的盐酸,番茄在较强的酸性环境中会产生不溶于水的沉淀
白萝卜,胡萝卜,白萝卜中的维生素C会被胡萝卜中的抗坏血酸酵素破坏
芹菜,黄瓜,芹菜中的维生素C会被黄瓜中的维生素C分解酶破坏
1 foodA foodB reason
2 番茄 黄瓜 黄瓜中含有维生素C分解酶,会破坏番茄中的维生素C,营养流失严重 黄瓜中含有维生素C分解酶,会破坏番茄中的维生素C,营养流失严重。
3 牛奶 韭菜 牛奶与韭菜同食会影响钙的吸收,降低营养价值 牛奶与韭菜同食会影响钙的吸收,降低营养价值。
4 土豆 番茄 土豆会产生大量的盐酸,番茄在较强的酸性环境中会产生不溶于水的沉淀 土豆会产生大量的盐酸,番茄在较强的酸性环境中会产生不溶于水的沉淀。
5 白萝卜 胡萝卜 白萝卜中的维生素C会被胡萝卜中的抗坏血酸酵素破坏 白萝卜中的维生素C会被胡萝卜中的抗坏血酸酵素破坏。
6 芹菜 黄瓜 芹菜中的维生素C会被黄瓜中的维生素C分解酶破坏 芹菜中的维生素C会被黄瓜中的维生素C分解酶破坏。

View File

@@ -1,5 +1,16 @@
<template>
<div>
关于
</div>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button default-href="/my" />
</ion-buttons>
<ion-title>关于</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<TheAboutList />
</ion-content>
</ion-page>
</template>

View File

@@ -1,15 +1,20 @@
<script setup lang="ts">
// help
</script>
<template>
<div>
<div class="w-full">
<CommonHeader>
帮助
</CommonHeader>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button default-href="/my" />
</ion-buttons>
<ion-title>帮助</ion-title>
</ion-toolbar>
</ion-header>
<InstallPwa />
<FeedbackActions />
<div class="mx-auto p-2 rounded-2xl max-w-md w-full" text-left>
<ion-content class="w-full">
<div class="mx-auto max-w-md w-full rounded-2xl p-2" text-left>
<FAQItem title="未来计划?">
计划增加新功能如自定义菜谱与使用其他用户分享的菜谱
</FAQItem>
@@ -96,7 +101,7 @@
小玩具们
</a>
<a py-4 inline-flex href="https://cdn.yunyoujun.cn/img/about/white-qrcode-and-search.jpg" target="_blank">
<a inline-flex py-4 href="https://cdn.yunyoujun.cn/img/about/white-qrcode-and-search.jpg" target="_blank">
<img src="https://cdn.yunyoujun.cn/img/about/white-qrcode-and-search.jpg">
</a>
</div>
@@ -108,7 +113,7 @@
感谢以下小伙伴为本项目提供的数据支持和 QA
</p>
<ul text-sm mt-2 text-left>
<ul mt-2 text-left text-sm>
<li>
<a href="https://weibo.com/runny" target="_blank">Runny</a>
</li>
@@ -135,7 +140,7 @@
</div>
</FAQItem>
</div>
</div>
<BaseFooter mt-4 />
</div>
<BaseFooter mt-4 />
</ion-content>
</ion-page>
</template>

View File

@@ -7,6 +7,8 @@ useHead({
title: '食用手册',
})
const ionContentRef = ref<HTMLElement>()
const rStore = useRecipeStore()
</script>
@@ -30,7 +32,7 @@ const rStore = useRecipeStore()
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="text-center">
<ion-content ref="ionContentRef" class="text-center">
<ChooseFood />
<SimpleCopyright />
</ion-content>

View File

@@ -8,44 +8,72 @@ definePageMeta({
<template>
<ion-page>
<CommonHeader>
我的
</CommonHeader>
<ion-header>
<ion-toolbar>
<ion-title>我的</ion-title>
</ion-toolbar>
</ion-header>
<div
class="mx-auto max-w-md w-full"
px-2
text-left
>
<div mt-2 gap="3" grid="~ cols-3">
<YlfIconItem to="/recipes/history" icon="i-ri-history-line" label="历史记录" />
<YlfIconItem to="/recipes/collect" icon="i-ri-star-line" label="我的收藏" />
<YlfIconItem to="/cookbooks" icon="i-ri-article-line" label="自定义菜谱" />
</div>
<ion-content>
<!-- TODO -->
<!-- <ion-list :inset="true">
<ion-item router-link="/recipes/history">
<ion-icon slot="start" :icon="ioniconsTimeOutline" />
<ion-label>历史记录</ion-label>
</ion-item>
<ion-item router-link="/recipes/collect">
<ion-icon slot="start" :icon="ioniconsStarOutline" />
<ion-label>我的收藏</ion-label>
</ion-item>
<ion-item router-link="/cookbooks">
<ion-icon slot="start" :icon="ioniconsBookOutline" />
<ion-label>自定义菜谱</ion-label>
</ion-item>
</ion-list> -->
<YlfForm>
<YlfFormItem icon="i-ri-feedback-line" label="立即反馈" :to="links.feedback" target="_blank" />
<YlfFormItem icon="i-ri-mail-send-line" label="立即投稿" :to="links.contribute" target="_blank" />
</YlfForm>
<ion-list :inset="true">
<ion-item :href="links.githubIssue" target="_blank">
<ion-icon slot="start" :icon="ioniconsChatbubbleEllipsesOutline" />
<ion-label>问题反馈</ion-label>
</ion-item>
<ion-item :href="links.githubDiscussions" target="_blank">
<ion-icon slot="start" :icon="ioniconsChatbubblesOutline" />
<ion-label>参与讨论</ion-label>
</ion-item>
<ion-item :href="links.contribute" target="_blank">
<ion-icon slot="start" :icon="ioniconsMailOutline" />
<ion-label>菜谱投稿</ion-label>
</ion-item>
</ion-list>
<YlfForm>
<YlfFormItem icon="i-ri-file-history-line" label="更新日志" :to="links.changelog" target="_blank" />
</YlfForm>
<ion-list :inset="true">
<ion-item :href="links.changelog" target="_blank">
<ion-icon slot="start" :icon="ioniconsDocumentTextOutline" />
<ion-label>更新日志</ion-label>
</ion-item>
</ion-list>
<YlfForm>
<YlfFormItem icon="i-ri-settings-line" label="设置" to="/settings" />
</YlfForm>
<ion-list :inset="true">
<ion-item router-link="/settings">
<ion-icon slot="start" :icon="ioniconsSettingsOutline" />
<ion-label>设置</ion-label>
</ion-item>
</ion-list>
<ion-list :inset="true">
<ion-item router-link="/help">
<ion-icon slot="start" :icon="ioniconsHelpCircleOutline" />
<ion-label>帮助</ion-label>
</ion-item>
<ion-item router-link="/about">
<ion-icon slot="start" :icon="ioniconsInformationCircleOutline" />
<ion-label>关于</ion-label>
</ion-item>
</ion-list>
<!-- <YlfForm>
<YlfFormItem icon="i-ri-article-line" label="自定义菜谱 TODO" to="/cookbooks/" />
</YlfForm> -->
<YlfForm>
<YlfFormItem icon="i-ri-question-line" label="帮助" to="/help" />
<YlfFormItem icon="i-ri-information-line" label="关于" to="/help" />
</YlfForm>
</div>
<BaseFooter mt-4 />
</ion-content>
</ion-page>
</template>

View File

@@ -17,8 +17,10 @@ useHead({
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content flex flex-grow flex-col items-center justify-center>
<RandomRecipe />
<ion-content>
<div class="flex flex-grow flex-col items-center justify-center">
<RandomRecipe />
</div>
</ion-content>
</ion-page>
</template>

View File

@@ -117,7 +117,7 @@ export default defineNuxtConfig({
css: {
core: true,
basic: true,
utilities: true,
// utilities: true,
},
},