fix: useStorage in ssr & extract random

This commit is contained in:
YunYouJun
2023-07-30 16:31:37 +08:00
parent 033d6adbe6
commit 5164279311
13 changed files with 147 additions and 148 deletions

View File

@@ -31,9 +31,9 @@
- [居家菜谱投稿](https://docs.qq.com/form/page/DWk9GWW9oTmlXZU9V) - [居家菜谱投稿](https://docs.qq.com/form/page/DWk9GWW9oTmlXZU9V)
- [反馈建议分享-兔小巢](https://support.qq.com/products/507827) - [反馈建议分享-兔小巢](https://support.qq.com/products/507827)
<!-- ### Features --> ### Features
<!-- 本项目支持 PWA使用浏览器打开时可将其添加到主屏幕以获得近原生 APP 的体验。 --> 本项目支持 PWA使用浏览器打开时可将其添加到主屏幕以获得近原生 APP 的体验。
## 开发 ## 开发

View File

@@ -52,11 +52,5 @@ const buildDate = (new Date(Number.parseInt(now) * 1000)).toLocaleDateString()
云乐坊工作室 云乐坊工作室
</a> </a>
</div> </div>
<!-- 欢迎赞助 -->
<!-- <div m="t-2" opacity="80" class="footer-support flex justify-center items-center">
<span>本网站由</span><a class="footer-support-logo" href="https://www.upyun.com" target="blank" title="又拍云">
<img m="x-1" width="50" src="https://cdn.yunyoujun.cn/img/logo/upyun-logo.png" alt="又拍云">
</a><span>提供 CDN 加速</span>
</div> -->
</div> </div>
</template> </template>

View File

@@ -1,5 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import recipes from '~/data/recipe.json'
defineProps({ defineProps({
isVisible: Boolean, isVisible: Boolean,
@@ -11,7 +12,7 @@ const { displayedRecipe } = storeToRefs(rStore)
<template> <template>
<button <button
v-show="displayedRecipe.length !== rStore.recipes.length && isVisible" v-show="displayedRecipe.length !== recipes.length && isVisible"
class="fixed z-9 inline-flex cursor-pointer items-center justify-center rounded rounded-full shadow hover:shadow-md" class="fixed z-9 inline-flex cursor-pointer items-center justify-center rounded rounded-full shadow hover:shadow-md"
bg="green-50 dark:green-900" w="10" h="10" bg="green-50 dark:green-900" w="10" h="10"
bottom="18" right="4" bottom="18" right="4"

View File

@@ -13,8 +13,8 @@ const recipeBtn = ref<HTMLButtonElement>()
const { playAnimation } = useEmojiAnimation(recipeBtn) const { playAnimation } = useEmojiAnimation(recipeBtn)
const gtm = useGtm() const gtm = useGtm()
const recipePanel = ref() const recipePanelRef = ref()
const { isVisible, show } = useInvisibleElement(recipePanel) const { isVisible, show } = useInvisibleElement(recipePanelRef)
function toggleStuff(item: StuffItem, category = '', _e?: Event) { function toggleStuff(item: StuffItem, category = '', _e?: Event) {
rStore.toggleStuff(item.name) rStore.toggleStuff(item.name)
@@ -36,6 +36,7 @@ function toggleStuff(item: StuffItem, category = '', _e?: Event) {
</script> </script>
<template> <template>
<div>
<h2 m="t-4" text="xl" font="bold" p="1"> <h2 m="t-4" text="xl" font="bold" p="1">
🥘 先选一下食材 🥘 先选一下食材
</h2> </h2>
@@ -52,11 +53,7 @@ function toggleStuff(item: StuffItem, category = '', _e?: Event) {
<span v-else-if="item.image" class="inline-flex"> <span v-else-if="item.image" class="inline-flex">
<img class="inline-flex" w="2" h="2" width="10" height="10" :src="item.image" :alt="item.name"> <img class="inline-flex" w="2" h="2" width="10" height="10" :src="item.image" :alt="item.name">
</span> </span>
<span class="inline-flex" m="l-1"> <span class="inline-flex" m="l-1">{{ item.name }}</span>
{{
item.name
}}
</span>
</VegetableTag> </VegetableTag>
</div> </div>
<div m="y-4"> <div m="y-4">
@@ -69,11 +66,7 @@ function toggleStuff(item: StuffItem, category = '', _e?: Event) {
@click="toggleStuff(item, 'meat')" @click="toggleStuff(item, 'meat')"
> >
<span>{{ item.emoji }}</span> <span>{{ item.emoji }}</span>
<span m="l-1"> <span m="l-1">{{ item.name }}</span>
{{
item.name
}}
</span>
</MeatTag> </MeatTag>
</div> </div>
<div m="y-4"> <div m="y-4">
@@ -86,11 +79,7 @@ function toggleStuff(item: StuffItem, category = '', _e?: Event) {
@click="toggleStuff(item, 'staple')" @click="toggleStuff(item, 'staple')"
> >
<span>{{ item.emoji }}</span> <span>{{ item.emoji }}</span>
<span m="l-1"> <span m="l-1">{{ item.name }}</span>
{{
item.name
}}
</span>
</StapleTag> </StapleTag>
</div> </div>
<div m="t-4"> <div m="t-4">
@@ -102,20 +91,21 @@ function toggleStuff(item: StuffItem, category = '', _e?: Event) {
:active="curTool === item.name" :active="curTool === item.name"
@click="rStore.clickTool(item)" @click="rStore.clickTool(item)"
> >
<span v-if="item.emoji" class="inline-flex">{{ item.emoji }}</span> <span v-if="item.emoji" class="inline-flex">
{{ item.emoji }}
</span>
<span v-else-if="item.icon" class="inline-flex"> <span v-else-if="item.icon" class="inline-flex">
<div :class="item.icon" /> <div :class="item.icon" />
</span> </span>
<span class="inline-flex" m="l-1"> <span class="inline-flex" m="l-1">{{ item.label || item.name }}</span>
{{
item.label || item.name
}}
</span>
</ToolTag> </ToolTag>
</div> </div>
<Transition> <Transition>
<BasketButton ref="recipeBtn" :is-visible="isVisible" @click="show" /> <BasketButton ref="recipeBtn" :is-visible="isVisible" @click="show" />
</Transition> </Transition>
<RecipePanel ref="recipePanel" /> <div ref="recipePanelRef">
<RecipePanel />
</div>
</div>
</template> </template>

View File

@@ -1,12 +1,15 @@
<script lang="ts" setup> <script lang="ts" setup>
const rStore = useRecipeStore() const { random, randomRecipe } = useRandomRecipe()
</script> </script>
<template> <template>
<div v-show="randomRecipe">
<div class="inline-flex items-center justify-center"> <div class="inline-flex items-center justify-center">
今天吃什么<div class="transition" hover="text-blue-500" i-ri-refresh-line inline-block cursor-pointer @click="rStore.random" /> <div>今天吃什么</div>
<div class="transition" hover="text-blue-500" i-ri-refresh-line inline-block cursor-pointer @click="random" />
</div> </div>
<div m="t-2"> <div m="t-2">
<DishTag :dish="rStore.randomRecipe" /> <DishTag v-if="randomRecipe" :dish="randomRecipe" />
</div>
</div> </div>
</template> </template>

View File

@@ -6,13 +6,17 @@ const rStore = useRecipeStore()
const { displayedRecipe, selectedStuff, curTool } = storeToRefs(rStore) const { displayedRecipe, selectedStuff, curTool } = storeToRefs(rStore)
const showSearchInput = ref(false) const showSearchInput = ref(false)
const showTooltip = computed(() => !selectedStuff.value.length && !curTool.value)
</script> </script>
<template> <template>
<div m="x-2 y-4" p="2" class="recipe-panel relative shadow transition hover:shadow-md" bg="gray-400/8"> <div
<h2 text="xl" font="bold" p="1"> class="recipe-panel relative shadow transition hover:shadow-md"
🍲 来看看组合出的菜谱吧 m="x-2 y-4" p="2"
</h2> bg="gray-400/8"
>
<RecipePanelTitle />
<ToggleMode /> <ToggleMode />
@@ -21,31 +25,34 @@ const showSearchInput = ref(false)
<div v-else i-ri-search-fill /> <div v-else i-ri-search-fill />
</button> </button>
<!-- <Switch /> -->
<div class="cook-recipes" p="2"> <div class="cook-recipes" p="2">
<SearchFoodInput v-if="showSearchInput" /> <SearchFoodInput v-if="showSearchInput" />
<Transition mode="out-in"> <Transition mode="out-in">
<div class="cook-filter-recipes"> <div class="cook-filter-recipes">
<span v-if="!selectedStuff.length && !curTool" text="sm" p="2"> <span v-if="showTooltip" text="sm" p="2">
你要先选食材或工具哦 你要先选食材或工具哦
</span> </span>
<span v-else-if="displayedRecipe.length"> <div v-else-if="displayedRecipe.length">
<DishTag v-for="item, i in displayedRecipe" :key="i" :dish="item" /> <DishTag v-for="item, i in displayedRecipe" :key="i" :dish="item" />
</span> </div>
<span v-else text="sm"> <div v-else text="sm">
还没有完美匹配的菜谱呢 <span>还没有完美匹配的菜谱呢</span>
<br> <br>
大胆尝试一下或者<a href="#" @click="rStore.reset()"> <span>大胆尝试一下或者</span>
<strong>换个组合</strong></a> <a href="#" @click="rStore.reset()">
<strong>换个组合</strong>
</a>
<span></span>
<br> <br>
<span m="t-1">欢迎来 <div m="t-1">
<span>欢迎来</span>
<a class="font-bold text-blue-600 dark:text-blue-400" href="https://docs.qq.com/sheet/DQk1vdkhFV0twQVNS?tab=uykkic" target="_blank">这里</a> <a class="font-bold text-blue-600 dark:text-blue-400" href="https://docs.qq.com/sheet/DQk1vdkhFV0twQVNS?tab=uykkic" target="_blank">这里</a>
反馈新的菜谱 <span>反馈新的菜谱</span>
</span> </div>
</span> </div>
</div> </div>
</Transition> </Transition>

View File

@@ -0,0 +1,5 @@
<template>
<div text="xl" font="bold" p="1">
🍲 来看看组合出的菜谱吧
</div>
</template>

View File

@@ -1,16 +0,0 @@
<script lang="ts" setup>
defineProps<{
frontmatter: {
title: string
}
}>()
</script>
<template>
<div m="t-4" class="m-auto max-w-900px text-left">
<h3 text="center 3xl" font="serif !black">
{{ frontmatter?.title }}
</h3>
<slot class="markdown-body" />
</div>
</template>

19
composables/recipe.ts Normal file
View File

@@ -0,0 +1,19 @@
import recipeData from '~/data/recipe.json'
import type { RecipeItem, Recipes } from '~/types'
export function useRandomRecipe() {
const randomRecipe = ref<RecipeItem>()
function random() {
randomRecipe.value = generateRandomRecipe(recipeData as Recipes)
}
onMounted(() => {
random()
})
return {
random,
randomRecipe,
}
}

View File

@@ -4,18 +4,11 @@ import { computed, ref } from 'vue'
import { useGtm } from '@gtm-support/vue-gtm' import { useGtm } from '@gtm-support/vue-gtm'
import recipeData from '../../data/recipe.json' import recipeData from '../../data/recipe.json'
import type { StuffItem } from '../../data/food' import type { StuffItem } from '../../data/food'
import type { RecipeItem, Recipes } from '~/types' import type { Recipes } from '~/types'
const namespace = 'cook' const namespace = 'cook'
/** const recipes = recipeData as Recipes
* 生成随机菜谱
* @param recipes
* @returns
*/
function generateRandomRecipe(recipes: Recipes) {
return recipes[Math.floor(Math.random() * recipes.length)]
}
/** /**
* survival: 生存模式 * survival: 生存模式
@@ -25,7 +18,6 @@ function generateRandomRecipe(recipes: Recipes) {
export type SearchMode = 'survival' | 'loose' | 'strict' export type SearchMode = 'survival' | 'loose' | 'strict'
export const useRecipeStore = defineStore('recipe', () => { export const useRecipeStore = defineStore('recipe', () => {
const recipes = recipeData as Recipes
const gtm = useGtm() const gtm = useGtm()
/** /**
@@ -37,13 +29,12 @@ export const useRecipeStore = defineStore('recipe', () => {
const curStuff = useStorage(`${namespace}:stuff`, new Set<string>()) const curStuff = useStorage(`${namespace}:stuff`, new Set<string>())
// const curTools = ref(new Set<string>()) // const curTools = ref(new Set<string>())
const curTool = useStorage(`${namespace}:tool`, '') const curTool = useStorage(`${namespace}:tool`, '')
const curMode = useStorage<SearchMode>(`${namespace}:mode`, 'loose')
const selectedStuff = computed(() => Array.from(curStuff.value)) const selectedStuff = computed(() => Array.from(curStuff.value))
// const selectedTools = computed(() => Array.from(curTools.value)) // const selectedTools = computed(() => Array.from(curTools.value))
// const selectedTools = ref('') // const selectedTools = ref('')
const curMode = useStorage<SearchMode>(`${namespace}:mode`, 'loose')
function toggleStuff(name: string) { function toggleStuff(name: string) {
if (!curStuff.value) if (!curStuff.value)
return return
@@ -81,8 +72,6 @@ export const useRecipeStore = defineStore('recipe', () => {
curStuff.value.add(name) curStuff.value.add(name)
} }
const randomRecipe = ref<RecipeItem>(generateRandomRecipe(recipes))
// 默认严格模式 // 默认严格模式
const displayedRecipe = computed(() => { const displayedRecipe = computed(() => {
if (keyword.value) if (keyword.value)
@@ -152,9 +141,6 @@ export const useRecipeStore = defineStore('recipe', () => {
curMode, curMode,
selectedStuff, selectedStuff,
randomRecipe,
random: () => { randomRecipe.value = generateRandomRecipe(recipes) },
clearKeyWord: () => { keyword.value = '' }, clearKeyWord: () => { keyword.value = '' },
toggleStuff, toggleStuff,
toggleTools, toggleTools,

View File

@@ -3,8 +3,8 @@ const rStore = useRecipeStore()
</script> </script>
<template> <template>
<div pt-4> <div>
<div text-4xl> <div pt-4 text-4xl>
<button <button
class="cursor-pointer transition active:text-green-800 hover:(text-green-600)" class="cursor-pointer transition active:text-green-800 hover:(text-green-600)"
title="重置" title="重置"

2
pnpm-lock.yaml generated
View File

@@ -5535,7 +5535,7 @@ packages:
dependencies: dependencies:
debug: 3.2.7 debug: 3.2.7
is-core-module: 2.12.1 is-core-module: 2.12.1
resolve: 1.22.3 resolve: 1.22.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true

10
utils/random.ts Normal file
View File

@@ -0,0 +1,10 @@
import type { Recipes } from '../types'
/**
* 生成随机菜谱
* @param recipes
* @returns
*/
export function generateRandomRecipe(recipes: Recipes) {
return recipes[Math.floor(Math.random() * recipes.length)]
}