feat: basic interactive & tags
This commit is contained in:
7
src/components.d.ts
vendored
7
src/components.d.ts
vendored
@@ -1,17 +1,22 @@
|
||||
// generated by unplugin-vue-components
|
||||
// We suggest you to commit this file into source control
|
||||
// Read more: https://github.com/vuejs/vue-next/pull/3399
|
||||
import '@vue/runtime-core'
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
BaseFooter: typeof import('./components/BaseFooter.vue')['default']
|
||||
ChooseFood: typeof import('./components/ChooseFood.vue')['default']
|
||||
Counter: typeof import('./components/Counter.vue')['default']
|
||||
DishTag: typeof import('./components/DishTag.vue')['default']
|
||||
MeatTag: typeof import('./components/MeatTag.vue')['default']
|
||||
Menu: typeof import('./components/Menu.vue')['default']
|
||||
README: typeof import('./components/README.md')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
StapleTag: typeof import('./components/StapleTag.vue')['default']
|
||||
VegetableTag: typeof import('./components/VegetableTag.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
export { }
|
||||
export {}
|
||||
|
||||
@@ -1,11 +1,80 @@
|
||||
<script lang="ts" setup>
|
||||
import MeatTag from './MeatTag.vue'
|
||||
import StapleTag from './StapleTag.vue'
|
||||
import DishTag from './DishTag.vue'
|
||||
import { meat, staple, vegetable } from '~/data/foot'
|
||||
import recipeData from '~/data/recipe.json'
|
||||
import type { Recipe } from '~/types'
|
||||
import { useRecipeStore } from '~/stores/recipe'
|
||||
const recipe = ref(recipeData as Recipe)
|
||||
|
||||
const rStore = useRecipeStore()
|
||||
|
||||
const displayedRecipe = computed(() => {
|
||||
return recipe.value.filter((item) => {
|
||||
return Array.from(rStore.curStuff).some(stuff => item.stuff.includes(stuff))
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div m="y-4">
|
||||
<h2 text="xl" font="bold" p="1">
|
||||
🥬 蔬菜区
|
||||
</h2>
|
||||
<VegetableTag
|
||||
v-for="item, i in vegetable" :key="i"
|
||||
:active="rStore.curStuff.has(item.name)"
|
||||
@click="rStore.toggleStuff(item.name)"
|
||||
>
|
||||
<span v-if="item.emoji">{{ item.emoji }}</span>
|
||||
<img v-else-if="item.image" class="inline-flex" w="3" :src="item.image">
|
||||
<span m="l-1">
|
||||
{{
|
||||
item.name
|
||||
}}
|
||||
</span>
|
||||
</VegetableTag>
|
||||
</div>
|
||||
<div m="y-4">
|
||||
<h2 text="xl" font="bold" p="1">
|
||||
🥩 荤菜区
|
||||
</h2>
|
||||
<MeatTag
|
||||
v-for="item, i in meat" :key="i"
|
||||
:active="rStore.curStuff.has(item.name)"
|
||||
@click="rStore.toggleStuff(item.name)"
|
||||
>
|
||||
<span>{{ item.emoji }}</span>
|
||||
<span m="l-1">
|
||||
{{
|
||||
item.name
|
||||
}}
|
||||
</span>
|
||||
</MeatTag>
|
||||
</div>
|
||||
<div m="y-4">
|
||||
<h2 text="xl" font="bold" p="1">
|
||||
🍚 主食区
|
||||
</h2>
|
||||
<StapleTag
|
||||
v-for="item, i in staple" :key="i"
|
||||
:active="rStore.curStuff.has(item.name)"
|
||||
@click="rStore.toggleStuff(item.name)"
|
||||
>
|
||||
<span>{{ item.emoji }}</span>
|
||||
<span m="l-1">
|
||||
{{
|
||||
item.name
|
||||
}}
|
||||
</span>
|
||||
</StapleTag>
|
||||
</div>
|
||||
<hr p="2" opacity="10">
|
||||
<div>
|
||||
<span v-for="item, i in recipe" :key="i" class="tag">{{ item.name }}</span>
|
||||
<h2 text="xl" font="bold" p="1">
|
||||
📄 菜谱
|
||||
</h2>
|
||||
<DishTag v-for="item, i in displayedRecipe" :key="i" :dish="item" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
16
src/components/DishTag.vue
Normal file
16
src/components/DishTag.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<script lang="ts" setup>
|
||||
import type { RecipeItem } from '~/types'
|
||||
defineProps<{
|
||||
dish: RecipeItem
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a
|
||||
:href="dish.link" target="_blank" class="tag rounded" p="x-2"
|
||||
border="~ blue-200 dark:blue-800"
|
||||
bg="blue-300 opacity-20"
|
||||
>
|
||||
<span text="sm blue-700 dark:blue-200">{{ dish.name }}</span>
|
||||
</a>
|
||||
</template>
|
||||
16
src/components/MeatTag.vue
Normal file
16
src/components/MeatTag.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
active: boolean
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span
|
||||
class="tag rounded" p="x-2"
|
||||
border="~ red-200 dark:red-800"
|
||||
:bg="active ? 'red-500 opacity-90' : 'red-300 opacity-20'"
|
||||
:text="active ? 'red-100' : 'red-800 dark:red-200'"
|
||||
>
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
@@ -3,7 +3,7 @@ import { toggleDark } from '~/composables'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav text-xl mt-6>
|
||||
<nav text-xl p="t-6">
|
||||
<RouterLink class="icon-btn mx-2" to="/" title="首页">
|
||||
<div i-ri-home-2-line />
|
||||
</RouterLink>
|
||||
|
||||
15
src/components/StapleTag.vue
Normal file
15
src/components/StapleTag.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
active: boolean
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span
|
||||
class="tag rounded" p="x-2" border="~ yellow-200 dark:yellow-800"
|
||||
:bg="active ? 'yellow-500 dark:yellow-600 opacity-100' : 'yellow-300 opacity-20'"
|
||||
:text="active ? 'yellow-100' : 'yellow-800 dark:yellow-200'"
|
||||
>
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
16
src/components/VegetableTag.vue
Normal file
16
src/components/VegetableTag.vue
Normal file
@@ -0,0 +1,16 @@
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
active: boolean
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span
|
||||
class="tag rounded" p="x-2"
|
||||
border="~ green-200 dark:green-800"
|
||||
:bg="active ? 'green-600 opacity-90' : 'green-300 opacity-20'"
|
||||
:text="active ? 'green-100' : 'green-800 dark:green-200'"
|
||||
>
|
||||
<slot />
|
||||
</span>
|
||||
</template>
|
||||
141
src/data/foot.ts
Normal file
141
src/data/foot.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
export interface StuffItem {
|
||||
/**
|
||||
* 食材名称
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* 例如:🥔
|
||||
*/
|
||||
emoji: string
|
||||
/**
|
||||
* 图片链接
|
||||
*/
|
||||
image?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* 素菜
|
||||
*/
|
||||
export const vegetable: StuffItem[] = [
|
||||
{
|
||||
name: '土豆',
|
||||
emoji: '🥔',
|
||||
},
|
||||
{
|
||||
name: '胡萝卜',
|
||||
emoji: '🥕',
|
||||
},
|
||||
{
|
||||
name: '花菜',
|
||||
emoji: '🥦',
|
||||
},
|
||||
{
|
||||
name: '白萝卜',
|
||||
emoji: '🥣',
|
||||
},
|
||||
{
|
||||
name: '西葫芦',
|
||||
emoji: '🥒',
|
||||
},
|
||||
{
|
||||
name: '番茄',
|
||||
emoji: '🍅',
|
||||
},
|
||||
{
|
||||
name: '芹菜',
|
||||
emoji: '🥬',
|
||||
},
|
||||
{
|
||||
name: '黄瓜',
|
||||
emoji: '🥒',
|
||||
},
|
||||
{
|
||||
name: '洋葱',
|
||||
emoji: '🧅',
|
||||
},
|
||||
{
|
||||
name: '莴笋',
|
||||
emoji: '🥗',
|
||||
},
|
||||
{
|
||||
name: '菌菇',
|
||||
emoji: '🍄',
|
||||
},
|
||||
{
|
||||
name: '茄子',
|
||||
emoji: '🍆',
|
||||
},
|
||||
{
|
||||
name: '豆腐',
|
||||
emoji: '🍲',
|
||||
},
|
||||
{
|
||||
name: '包菜',
|
||||
emoji: '',
|
||||
image: '/images/cabbage-dog.jpg',
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
* 荤菜
|
||||
*/
|
||||
export const meat: StuffItem[] = [
|
||||
{
|
||||
name: '午餐肉',
|
||||
emoji: '🥓',
|
||||
},
|
||||
{
|
||||
name: '香肠',
|
||||
emoji: '🌭',
|
||||
},
|
||||
{
|
||||
name: '鸡翅',
|
||||
emoji: '🐤',
|
||||
},
|
||||
{
|
||||
name: '猪肉',
|
||||
emoji: '🐷',
|
||||
},
|
||||
{
|
||||
name: '鸡蛋',
|
||||
emoji: '🥚',
|
||||
},
|
||||
{
|
||||
name: '虾',
|
||||
emoji: '🦐',
|
||||
},
|
||||
{
|
||||
name: '牛肉',
|
||||
emoji: '🐮',
|
||||
},
|
||||
{
|
||||
name: '鸡胸肉',
|
||||
emoji: '💪',
|
||||
},
|
||||
{
|
||||
name: '骨头',
|
||||
emoji: '🦴',
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
* 主食
|
||||
*/
|
||||
export const staple: StuffItem[] = [
|
||||
{
|
||||
name: '面条',
|
||||
emoji: '🍝',
|
||||
},
|
||||
{
|
||||
name: '面包',
|
||||
emoji: '🍞',
|
||||
},
|
||||
{
|
||||
name: '米饭',
|
||||
emoji: '🍚',
|
||||
},
|
||||
{
|
||||
name: '方便面',
|
||||
emoji: '🍜',
|
||||
},
|
||||
]
|
||||
20
src/stores/recipe.ts
Normal file
20
src/stores/recipe.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { acceptHMRUpdate, defineStore } from 'pinia'
|
||||
|
||||
export const useRecipeStore = defineStore('recipe', () => {
|
||||
const curStuff = ref(new Set<string>())
|
||||
|
||||
function toggleStuff(name: string) {
|
||||
if (curStuff.value.has(name))
|
||||
curStuff.value.delete(name)
|
||||
else
|
||||
curStuff.value.add(name)
|
||||
}
|
||||
|
||||
return {
|
||||
curStuff,
|
||||
toggleStuff,
|
||||
}
|
||||
})
|
||||
|
||||
if (import.meta.hot)
|
||||
import.meta.hot.accept(acceptHMRUpdate(useRecipeStore, import.meta.hot))
|
||||
@@ -10,5 +10,5 @@ a {
|
||||
.tag {
|
||||
margin: 4px;
|
||||
padding: 2px 4px;
|
||||
border: 1px solid var(--c-text);
|
||||
// border: 1px solid var(--c-text);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user