feat: use indexDB instead of array filter
This commit is contained in:
7
app.vue
7
app.vue
@@ -2,9 +2,7 @@
|
|||||||
import { installPrompt } from './utils/pwa'
|
import { installPrompt } from './utils/pwa'
|
||||||
import { appName } from '~/constants'
|
import { appName } from '~/constants'
|
||||||
|
|
||||||
// https://github.com/vueuse/head
|
// https://nuxt.com/docs/api/composables/use-head
|
||||||
// you can use this to manipulate the document head in any components,
|
|
||||||
// they will be rendered correctly in the html results with vite-ssg
|
|
||||||
useHead({
|
useHead({
|
||||||
title: appName,
|
title: appName,
|
||||||
meta: [
|
meta: [
|
||||||
@@ -15,8 +13,11 @@ useHead({
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const indexedDB = useIndexedDB()
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
installPrompt()
|
installPrompt()
|
||||||
|
indexedDB.init()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import recipes from '~/data/recipe.json'
|
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
isVisible: Boolean,
|
isVisible: Boolean,
|
||||||
})
|
})
|
||||||
|
|
||||||
const rStore = useRecipeStore()
|
const rStore = useRecipeStore()
|
||||||
const { displayedRecipe } = storeToRefs(rStore)
|
const { displayedRecipe } = storeToRefs(rStore)
|
||||||
|
|
||||||
|
const showBasketBtn = computed(async () => {
|
||||||
|
return displayedRecipe.value.length !== rStore.recipesLength && props.isVisible
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
v-show="displayedRecipe.length !== recipes.length && isVisible"
|
v-show="showBasketBtn"
|
||||||
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"
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ const rStore = useRecipeStore()
|
|||||||
const { curTool } = storeToRefs(rStore)
|
const { curTool } = storeToRefs(rStore)
|
||||||
const curStuff = computed(() => rStore.selectedStuff)
|
const curStuff = computed(() => rStore.selectedStuff)
|
||||||
|
|
||||||
const recipeBtn = ref<HTMLButtonElement>()
|
const recipeBtnRef = ref<HTMLButtonElement>()
|
||||||
const { playAnimation } = useEmojiAnimation(recipeBtn)
|
const { playAnimation } = useEmojiAnimation(recipeBtnRef)
|
||||||
|
|
||||||
const gtm = useGtm()
|
const gtm = useGtm()
|
||||||
const recipePanelRef = ref()
|
const recipePanelRef = ref()
|
||||||
@@ -44,65 +44,73 @@ function toggleStuff(item: StuffItem, category = '', _e?: Event) {
|
|||||||
<h2 opacity="90" text="base" font="bold" p="1">
|
<h2 opacity="90" text="base" font="bold" p="1">
|
||||||
🥬 菜菜们
|
🥬 菜菜们
|
||||||
</h2>
|
</h2>
|
||||||
<VegetableTag
|
<div>
|
||||||
v-for="item, i in vegetable" :key="i"
|
<VegetableTag
|
||||||
:active="curStuff.includes(item.name)"
|
v-for="item, i in vegetable" :key="i"
|
||||||
@click="toggleStuff(item, 'vegetable')"
|
:active="curStuff.includes(item.name)"
|
||||||
>
|
@click="toggleStuff(item, 'vegetable')"
|
||||||
<span v-if="item.emoji" class="inline-flex">{{ item.emoji }}</span>
|
>
|
||||||
<span v-else-if="item.image" class="inline-flex">
|
<span v-if="item.emoji" class="inline-flex">{{ item.emoji }}</span>
|
||||||
<img class="inline-flex" w="2" h="2" width="10" height="10" :src="item.image" :alt="item.name">
|
<span v-else-if="item.image" class="inline-flex">
|
||||||
</span>
|
<img class="inline-flex" w="2" h="2" width="10" height="10" :src="item.image" :alt="item.name">
|
||||||
<span class="inline-flex" m="l-1">{{ item.name }}</span>
|
</span>
|
||||||
</VegetableTag>
|
<span class="inline-flex" m="l-1">{{ item.name }}</span>
|
||||||
|
</VegetableTag>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div m="y-4">
|
<div m="y-4">
|
||||||
<h2 opacity="90" text="base" font="bold" p="1">
|
<h2 opacity="90" text="base" font="bold" p="1">
|
||||||
🥩 肉肉们
|
🥩 肉肉们
|
||||||
</h2>
|
</h2>
|
||||||
<MeatTag
|
<div>
|
||||||
v-for="item, i in meat" :key="i"
|
<MeatTag
|
||||||
:active="curStuff.includes(item.name)"
|
v-for="item, i in meat" :key="i"
|
||||||
@click="toggleStuff(item, 'meat')"
|
:active="curStuff.includes(item.name)"
|
||||||
>
|
@click="toggleStuff(item, 'meat')"
|
||||||
<span>{{ item.emoji }}</span>
|
>
|
||||||
<span m="l-1">{{ item.name }}</span>
|
<span>{{ item.emoji }}</span>
|
||||||
</MeatTag>
|
<span m="l-1">{{ item.name }}</span>
|
||||||
|
</MeatTag>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div m="y-4">
|
<div m="y-4">
|
||||||
<h2 opacity="90" text="base" font="bold" p="1">
|
<h2 opacity="90" text="base" font="bold" p="1">
|
||||||
🍚 主食也要一起下锅吗?(不选也行)
|
🍚 主食也要一起下锅吗?(不选也行)
|
||||||
</h2>
|
</h2>
|
||||||
<StapleTag
|
<div>
|
||||||
v-for="item, i in staple" :key="i"
|
<StapleTag
|
||||||
:active="curStuff.includes(item.name)"
|
v-for="item, i in staple" :key="i"
|
||||||
@click="toggleStuff(item, 'staple')"
|
:active="curStuff.includes(item.name)"
|
||||||
>
|
@click="toggleStuff(item, 'staple')"
|
||||||
<span>{{ item.emoji }}</span>
|
>
|
||||||
<span m="l-1">{{ item.name }}</span>
|
<span>{{ item.emoji }}</span>
|
||||||
</StapleTag>
|
<span m="l-1">{{ item.name }}</span>
|
||||||
|
</StapleTag>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div m="t-4">
|
<div m="t-4">
|
||||||
<h2 text="xl" font="bold" p="1">
|
<h2 text="xl" font="bold" p="1">
|
||||||
🍳 再选一下厨具
|
🍳 再选一下厨具
|
||||||
</h2>
|
</h2>
|
||||||
<ToolTag
|
<div>
|
||||||
v-for="item, i in tools" :key="i"
|
<ToolTag
|
||||||
:active="curTool === item.name"
|
v-for="item, i in tools" :key="i"
|
||||||
@click="rStore.clickTool(item)"
|
:active="curTool === item.name"
|
||||||
>
|
@click="rStore.clickTool(item)"
|
||||||
<span v-if="item.emoji" class="inline-flex">
|
>
|
||||||
{{ item.emoji }}
|
<span v-if="item.emoji" class="inline-flex">
|
||||||
</span>
|
{{ item.emoji }}
|
||||||
<span v-else-if="item.icon" class="inline-flex">
|
</span>
|
||||||
<div :class="item.icon" />
|
<span v-else-if="item.icon" class="inline-flex">
|
||||||
</span>
|
<div :class="item.icon" />
|
||||||
<span class="inline-flex" m="l-1">{{ item.label || item.name }}</span>
|
</span>
|
||||||
</ToolTag>
|
<span class="inline-flex" m="l-1">{{ item.label || item.name }}</span>
|
||||||
|
</ToolTag>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Transition>
|
<Transition>
|
||||||
<BasketButton ref="recipeBtn" :is-visible="isVisible" @click="show" />
|
<BasketButton ref="recipeBtnRef" :is-visible="isVisible" @click="show" />
|
||||||
</Transition>
|
</Transition>
|
||||||
<RecipePanel ref="recipePanelRef" />
|
<RecipePanel ref="recipePanelRef" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ const showTooltip = computed(() => !selectedStuff.value.length && !curTool.value
|
|||||||
你要先选食材或工具哦~
|
你要先选食材或工具哦~
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div v-else-if="displayedRecipe.length">
|
<div v-else-if="rStore.displayedRecipe.length">
|
||||||
<DishTag v-for="item, i in displayedRecipe" :key="i" :dish="item" />
|
<DishTag v-for="item, i in rStore.displayedRecipe" :key="i" :dish="item" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else text="sm">
|
<div v-else text="sm">
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ onMounted(() => {
|
|||||||
p="x4 y2"
|
p="x4 y2"
|
||||||
w="full"
|
w="full"
|
||||||
text="center"
|
text="center"
|
||||||
bg="transparent"
|
bg="white dark:dark-800"
|
||||||
border="~ rounded gray-200 dark:gray-700"
|
border="~ rounded gray-200 dark:gray-700"
|
||||||
class="focus:dark:gray-500"
|
class="focus:dark:gray-500"
|
||||||
>
|
>
|
||||||
|
|||||||
18
composables/db.ts
Normal file
18
composables/db.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { useStorage } from '@vueuse/core'
|
||||||
|
import { lastDbUpdated, namespace } from '~/constants'
|
||||||
|
|
||||||
|
export function useIndexedDB() {
|
||||||
|
const dbUpdated = useStorage(`${namespace}:lastDbUpdated`, lastDbUpdated)
|
||||||
|
|
||||||
|
return {
|
||||||
|
// db,
|
||||||
|
// initDb,
|
||||||
|
init: async () => {
|
||||||
|
const count = await db.recipes.count()
|
||||||
|
if (!count || dbUpdated.value !== lastDbUpdated) {
|
||||||
|
dbUpdated.value = lastDbUpdated
|
||||||
|
initDb()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,14 +2,11 @@ import { acceptHMRUpdate, defineStore } from 'pinia'
|
|||||||
import { useStorage } from '@vueuse/core'
|
import { useStorage } from '@vueuse/core'
|
||||||
import { computed, ref } from 'vue'
|
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 type { RecipeItem } from 'types'
|
||||||
import type { StuffItem } from '../../data/food'
|
import type { StuffItem } from '../../data/food'
|
||||||
import type { Recipes } from '~/types'
|
|
||||||
|
|
||||||
const namespace = 'cook'
|
const namespace = 'cook'
|
||||||
|
|
||||||
const recipes = recipeData as Recipes
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* survival: 生存模式
|
* survival: 生存模式
|
||||||
* strict: 严格
|
* strict: 严格
|
||||||
@@ -72,22 +69,27 @@ export const useRecipeStore = defineStore('recipe', () => {
|
|||||||
curStuff.value.add(name)
|
curStuff.value.add(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 默认严格模式
|
/**
|
||||||
const displayedRecipe = computed(() => {
|
* 搜索菜谱
|
||||||
if (keyword.value)
|
* @returns
|
||||||
return recipes.filter(item => item.name.includes(keyword.value))
|
*/
|
||||||
|
async function searchRecipes() {
|
||||||
|
if (keyword.value) {
|
||||||
|
const result = await db.recipes.filter(item => item.name.includes(keyword.value)).toArray()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
if (curMode.value === 'strict') {
|
if (curMode.value === 'strict') {
|
||||||
return recipes.filter((item) => {
|
return await db.recipes.filter((item) => {
|
||||||
const stuffFlag = selectedStuff.value.every(stuff => item.stuff.includes(stuff))
|
const stuffFlag = selectedStuff.value.every(stuff => item.stuff.includes(stuff))
|
||||||
const toolFlag = item.tools?.includes(curTool.value)
|
const toolFlag = item.tools.includes(curTool.value)
|
||||||
return curTool.value ? (stuffFlag && toolFlag) : stuffFlag
|
return curTool.value ? (stuffFlag && toolFlag) : stuffFlag
|
||||||
})
|
}).toArray()
|
||||||
}
|
}
|
||||||
else if (curMode.value === 'loose') {
|
else if (curMode.value === 'loose') {
|
||||||
return recipes.filter((item) => {
|
return await db.recipes.filter((item) => {
|
||||||
const stuffFlag = selectedStuff.value.some(stuff => item.stuff.includes(stuff))
|
const stuffFlag = selectedStuff.value.some(stuff => item.stuff.includes(stuff))
|
||||||
const toolFlag = item.tools?.includes(curTool.value)
|
const toolFlag = Boolean(item.tools?.includes(curTool.value))
|
||||||
|
|
||||||
// 同时存在 厨具和材料,则同时判断
|
// 同时存在 厨具和材料,则同时判断
|
||||||
if (curTool.value && selectedStuff.value.length) {
|
if (curTool.value && selectedStuff.value.length) {
|
||||||
@@ -101,16 +103,22 @@ export const useRecipeStore = defineStore('recipe', () => {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
})
|
}).toArray()
|
||||||
}
|
}
|
||||||
// survival
|
// survival
|
||||||
else {
|
else {
|
||||||
return recipes.filter((item) => {
|
return await db.recipes.filter((item) => {
|
||||||
const stuffFlag = item.stuff.every(stuff => selectedStuff.value.includes(stuff))
|
const stuffFlag = item.stuff.every(stuff => selectedStuff.value.includes(stuff))
|
||||||
const toolFlag = item.tools?.includes(curTool.value)
|
const toolFlag = item.tools?.includes(curTool.value)
|
||||||
return curTool.value ? (stuffFlag && toolFlag) : stuffFlag
|
return Boolean(curTool.value ? (stuffFlag && toolFlag) : stuffFlag)
|
||||||
})
|
}).toArray()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认严格模式
|
||||||
|
const displayedRecipe = ref<RecipeItem[]>([])
|
||||||
|
watch([keyword, curStuff, curTool, curMode], async () => {
|
||||||
|
displayedRecipe.value = await searchRecipes()
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,8 +141,17 @@ export const useRecipeStore = defineStore('recipe', () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const recipesLength = ref(0)
|
||||||
|
onMounted(async () => {
|
||||||
|
db.recipes.count().then((count) => {
|
||||||
|
recipesLength.value = count
|
||||||
|
})
|
||||||
|
|
||||||
|
displayedRecipe.value = await searchRecipes()
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
recipes,
|
recipesLength,
|
||||||
|
|
||||||
keyword,
|
keyword,
|
||||||
curTool,
|
curTool,
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
export const appName = '隔离食用手册'
|
export const appName = '隔离食用手册'
|
||||||
export const appDescription = '好的,今天我们来做菜!'
|
export const appDescription = '好的,今天我们来做菜!'
|
||||||
|
|
||||||
|
export const namespace = 'cook'
|
||||||
|
export const lastDbUpdated = '2022-07-27 03:05:02'
|
||||||
|
|
||||||
export * from './links'
|
export * from './links'
|
||||||
|
|||||||
@@ -11,3 +11,9 @@
|
|||||||
|
|
||||||
- tags: 标签
|
- tags: 标签
|
||||||
- 杂烩:不会显示所有材料 emoji,而是显示 🍲
|
- 杂烩:不会显示所有材料 emoji,而是显示 🍲
|
||||||
|
|
||||||
|
## 数据库
|
||||||
|
|
||||||
|
使用 Dexie.js 重构数据查询
|
||||||
|
|
||||||
|
- [Dexie.js](https://github.com/dexie/Dexie.js): A Minimalistic Wrapper for IndexedDB
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
电饭煲卤菜(开店级别),鸡肉、鸡蛋、米,BV1ZA411E7KT,简单,小吃,,电饭煲,
|
电饭煲卤菜(开店级别),鸡肉、鸡蛋、米,BV1ZA411E7KT,简单,小吃,,电饭煲,
|
||||||
电饭煲卤肉蛋豆腐,鸡肉、鸡蛋、豆腐、米,BV1aM4y1L7QR,简单,小吃,,电饭煲,
|
电饭煲卤肉蛋豆腐,鸡肉、鸡蛋、豆腐、米,BV1aM4y1L7QR,简单,小吃,,电饭煲,
|
||||||
电饭煲版罗宋汤,牛肉、番茄、洋葱、芹菜、胡萝卜、土豆、包菜、香肠,BV16Q4y1m7nU,简单,杂烩,,电饭煲,
|
电饭煲版罗宋汤,牛肉、番茄、洋葱、芹菜、胡萝卜、土豆、包菜、香肠,BV16Q4y1m7nU,简单,杂烩,,电饭煲,
|
||||||
电饭煲版罗宋汤,牛肉、番茄、土豆、包菜、香肠,BV16Q4y1m7nU,,杂烩,,电饭煲,
|
|
||||||
电饭煲版一只番茄饭,土豆、胡萝卜、香肠、番茄、鸡蛋、米,BV1dj411f7sR,简单,杂烩,,电饭煲,
|
电饭煲版一只番茄饭,土豆、胡萝卜、香肠、番茄、鸡蛋、米,BV1dj411f7sR,简单,杂烩,,电饭煲,
|
||||||
电饭煲茄子烧肉焖饭,猪肉、茄子、番茄、土豆、洋葱、米,BV18T4y1c7s1,普通,杂烩,,电饭煲,
|
电饭煲茄子烧肉焖饭,猪肉、茄子、番茄、土豆、洋葱、米,BV18T4y1c7s1,普通,杂烩,,电饭煲,
|
||||||
电饭煲版茶叶蛋,鸡蛋,BV12W411R7LA,,,,电饭煲,
|
电饭煲版茶叶蛋,鸡蛋,BV12W411R7LA,,,,电饭煲,
|
||||||
|
|||||||
|
File diff suppressed because one or more lines are too long
@@ -45,6 +45,7 @@
|
|||||||
"@zadigetvoltaire/nuxt-gtm": "^0.0.13",
|
"@zadigetvoltaire/nuxt-gtm": "^0.0.13",
|
||||||
"consola": "^3.2.3",
|
"consola": "^3.2.3",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
|
"dexie": "^3.2.4",
|
||||||
"eslint": "^8.46.0",
|
"eslint": "^8.46.0",
|
||||||
"jsdom": "^22.1.0",
|
"jsdom": "^22.1.0",
|
||||||
"nuxt": "^3.6.5",
|
"nuxt": "^3.6.5",
|
||||||
|
|||||||
@@ -3,20 +3,18 @@ const rStore = useRecipeStore()
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div pt-4 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="重置"
|
@click="rStore.reset"
|
||||||
@click="rStore.reset"
|
>
|
||||||
>
|
<div v-if="rStore.selectedStuff.length" i-mdi-pot-steam-outline />
|
||||||
<div v-if="rStore.selectedStuff.length" i-mdi-pot-steam-outline />
|
<div v-else i-mdi-pot-mix-outline />
|
||||||
<div v-else i-mdi-pot-mix-outline />
|
</button>
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<p text="sm" m="b-4">
|
|
||||||
好的,今天我们来做菜!
|
|
||||||
</p>
|
|
||||||
<ChooseFood />
|
|
||||||
</div>
|
</div>
|
||||||
|
<p text="sm" m="b-4">
|
||||||
|
好的,今天我们来做菜!
|
||||||
|
</p>
|
||||||
|
<ChooseFood />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -79,6 +79,9 @@ devDependencies:
|
|||||||
cross-env:
|
cross-env:
|
||||||
specifier: ^7.0.3
|
specifier: ^7.0.3
|
||||||
version: 7.0.3
|
version: 7.0.3
|
||||||
|
dexie:
|
||||||
|
specifier: ^3.2.4
|
||||||
|
version: 3.2.4
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^8.46.0
|
specifier: ^8.46.0
|
||||||
version: 8.46.0
|
version: 8.46.0
|
||||||
@@ -5160,6 +5163,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==}
|
resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/dexie@3.2.4:
|
||||||
|
resolution: {integrity: sha512-VKoTQRSv7+RnffpOJ3Dh6ozknBqzWw/F3iqMdsZg958R0AS8AnY9x9d1lbwENr0gzeGJHXKcGhAMRaqys6SxqA==}
|
||||||
|
engines: {node: '>=6.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/diff-sequences@29.4.3:
|
/diff-sequences@29.4.3:
|
||||||
resolution: {integrity: sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==}
|
resolution: {integrity: sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==}
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export interface RecipeItem {
|
|||||||
/**
|
/**
|
||||||
* 工具
|
* 工具
|
||||||
*/
|
*/
|
||||||
tools?: string[]
|
tools: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Recipes = RecipeItem[]
|
export type Recipes = RecipeItem[]
|
||||||
|
|||||||
31
utils/db.ts
Normal file
31
utils/db.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import type { Table } from 'dexie'
|
||||||
|
import Dexie from 'dexie'
|
||||||
|
|
||||||
|
import recipeData from '../data/recipe.json'
|
||||||
|
import type { RecipeItem } from '~/types'
|
||||||
|
|
||||||
|
export interface DbRecipeItem extends RecipeItem {
|
||||||
|
id?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MySubClassedDexie extends Dexie {
|
||||||
|
recipes!: Table<DbRecipeItem>
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super('cook-db')
|
||||||
|
this.version(1).stores({
|
||||||
|
recipes: '++id, name, stuff, bv, difficulty, tags, methods, tools, link, description', // Primary key and indexed props
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const db = new MySubClassedDexie()
|
||||||
|
|
||||||
|
export function initDb() {
|
||||||
|
db.recipes.bulkPut(
|
||||||
|
(recipeData as RecipeItem[]).map((item, i) => ({
|
||||||
|
id: i,
|
||||||
|
...item,
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user