Skip to content

Commit

Permalink
初步完成
Browse files Browse the repository at this point in the history
  • Loading branch information
Flauver committed Oct 6, 2024
1 parent 99f5534 commit 3e2dafd
Show file tree
Hide file tree
Showing 31 changed files with 1,344 additions and 151 deletions.
56 changes: 56 additions & 0 deletions components/search/Card.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<script setup lang="ts">
// @ts-nocheck
import ZitongLogo from "./assets/zitong.svg";
import YedianLogo from "./assets/yedian.png";
import BaiduLogo from "./assets/baidu.png";
import HandianLogo from "./assets/handian.png";
import { computed, inject } from "vue";
import { ZigenAndKeyArray } from "./share";
const p = defineProps<{
/** 查询的汉字 */
name: string,
data: ZigenAndKeyArray
}>()
const zigenFont = inject('font') || 'outi-yima' as string
const highlightStrokes = inject('high') as Set<string>
const uriText = computed(() => encodeURIComponent(p.name))
const unicode = computed(() => p.name.charCodeAt(0).toString(16).toUpperCase())
</script>

<template>
<div class="group border p-3 m-2 rounded-3xl shadow-md font-serif text-center bg-gray-100 dark:bg-slate-800">
<div class="text-4xl text-blue-800 dark:text-blue-400">{{ name }}</div>
<div class="text-xl mt-2">
<ruby v-for="zigenAndKey in data" :key="zigenAndKey.zigen">
<span :class="[zigenFont, { 'round-bg': highlightStrokes.has(zigenAndKey.zigen) }]">
{{ zigenAndKey.zigen }}</span>
<rp>(</rp>
<rt class="font-mono uppercase text-xl text-blue-400 dark:text-blue-200">
{{ zigenAndKey.key }}
</rt>
<rp>)</rp>
</ruby>
</div>
<div class="opacity-0 justify-center group-hover:opacity-100 duration-300 delay-100 transition-all">
<div class="flex justify-center dark:opacity-55 opacity-100">
<a :href="'https://zi.tools/zi/' + uriText" target="_blank" rel="noreferrer" title="字统网查询">
<img :src=ZitongLogo alt="字统网" width="22" />
</a>
<a :href="'http://www.yedict.com/zscontent.asp?uni=' + unicode" target="_blank" rel="noreferrer"
title="叶典网查询">
<img :src="YedianLogo" alt="叶典网" width="22" />
</a>
<a :href="'https://hanyu.baidu.com/s?wd=' + uriText" target="_blank" rel="noreferrer" title="百度汉语查询">
<img :src="BaiduLogo" alt="百度汉语" width="22" />
</a>
<a :href="'https://www.zdic.net/hans/' + uriText" target="_blank" rel="noreferrer" title="汉典查询">
<img :src="HandianLogo" alt="汉典网" width="22" />
</a>
</div>
</div>
</div>
</template>
71 changes: 71 additions & 0 deletions components/search/FetchSearch.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<script setup lang="ts">
import { onMounted, shallowRef, provide } from "vue";
import Search from "./Search.vue";
import { cache, HanziCard, HanziCardMap, ZigenCard, ZigenCardMap, fetchJsonWithCache, getSchemaNameFromRoute, ReformatHandler, useFetchJson } from "./share";
const p = defineProps<{
/**
* 存有汉字信息的JSON文件的路径
* 如果不填,则从URL里推断,chaifen.json
*/
chaifenJson?: string
/**
* 存有字根信息的JSON文件的路径
* 如果不填,则从URL里推断,zigen.json
*/
zigenJson?: string
/** 如果没有zigen.json文件,设为true
* 奕码和逸码vv9是直接从chaifen.json里获取编码的, 不需要zigen.json.
*/
noZigenJson?: boolean
/** 字根字体的class名字 */
zigenFont?: string
/** 方案的ID, 通常为方案泥 public 目录里的名称 ,省略则自动推断 */
id?: string
/** 需要高亮显示的字根 */
high?: string
/** 重定义 字根和它编码, 主要给奕码用 */
reformat?: ReformatHandler
}>()
// 字根的字体默认是楷体
provide('font', p.zigenFont ?? 'kaiti')
// 高亮的字根,默认为空的Set
provide('high', new Set(p.high))
// 一丨丿丶乙
//p.id.includes('easy') ? '' : '⼀⼂⺂⼁⼃')
const schemaData = shallowRef<{
zg?: ZigenCardMap,
cf: HanziCardMap,
}>()
const schemaName = p.id || getSchemaNameFromRoute()
const realJsonName = (json: string | undefined, jsonMainName: string) => json ? json : `/${schemaName}/${jsonMainName}.json`
const makeMapFromArray = <T extends { name: string }>(arr: T[]) => new Map(arr.map(v => [v.name, v]))
onMounted(async () => {
let id = schemaName
if (id in cache) {
//@ts-ignore
schemaData.value = cache[id]
return
}
const chaifenJson: HanziCard[] = await fetchJsonWithCache(realJsonName(p.chaifenJson, 'chaifen'))
const result = {
cf: makeMapFromArray(chaifenJson),
zg: p.noZigenJson ? undefined : makeMapFromArray(await fetchJsonWithCache(realJsonName(p.zigenJson, 'zigen')) as ZigenCard[])
}
cache[id] = result
schemaData.value = result
})
</script>

<template>
<div class="text-gray-600" v-if="!schemaData">正在加载拆分数据……</div>
<Search v-else :hanziMap="schemaData.cf" :zigenMap="schemaData.zg" :reformat />
</template>
72 changes: 72 additions & 0 deletions components/search/Search.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<script setup lang="ts">
/** 注意要 provide 字根字体的名称 */
import { shallowRef } from "vue";
import { watchThrottled, useUrlSearchParams } from "@vueuse/core";
import SearchAsync from "./SearchAsync.vue";
import SearchHanzi from "./SearchHanzi.vue";
import SearchHelp from "./SearchHelp.vue";
import type { HanziCardMap, ZigenCardMap, ReformatHandler, SearchCardsPropsArray } from "./share";
import { textToCardsProps } from "./share";
const p = defineProps<{
/** 汉字到拆分表的映射 */
hanziMap: HanziCardMap
/** 字根到按键的映射,
* 汉字的拆分表可能含有编码信息,这时候就不需要zigenMap了 */
zigenMap?: ZigenCardMap
/** 重定义 字根和它编码 */
reformat?: ReformatHandler
}>()
const customTextToCardsProps = (text: string) => textToCardsProps(text, p.hanziMap, p.zigenMap, p.reformat)
const urlSearchParams = useUrlSearchParams()
const userInput = shallowRef(urlSearchParams?.q || '')
const searchPatterns = shallowRef<string[]>([])
/** 反查的类型:字、拼音、四角(笔画)、空类型 */
const kind = shallowRef<'z' | 'p' | 'b' | ''>()
// 推断用户输入的类型
watchThrottled(userInput, () => {
const user = userInput.value as string
urlSearchParams.q = user
searchPatterns.value = [...user]
if (/^\d+/.test(user)) {
kind.value = 'b'
} else if (/^[a-z]+/.test(user)) {
kind.value = 'p'
} else if (user.length) {
kind.value = 'z'
} else {
kind.value = ''
}
}, { throttle: 300, immediate: true })
const searchHanzi = () => customTextToCardsProps(searchPatterns.value.join(''))
const handler = (json: any, text: string): SearchCardsPropsArray => (text in json) ? customTextToCardsProps(json[text] as string) : []
</script>

<template>
<label class="input input-bordered bg-gray-100 dark:bg-slate-800 flex items-center gap-2 mt-8">
<input type="text" class="grow" placeholder="查询的文本 / 全拼 / 四角号码 / 笔画" v-model="userInput" />
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-4 h-4 opacity-70">
<path fill-rule="evenodd"
d="M9.965 11.026a5 5 0 1 1 1.06-1.06l2.755 2.754a.75.75 0 1 1-1.06 1.06l-2.755-2.754ZM10.5 7a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Z"
clip-rule="evenodd" />
</svg>
</label>

<div class="flex justify-center py-2">
<SearchHelp />
</div>

<div v-if="kind === ''" class="opacity-40 text-center p-9 tracking-widest">从上方搜索条开始反查吧!</div>
<SearchHanzi v-else-if="kind === 'z'" :result="searchHanzi()" />
<SearchAsync v-else-if="kind === 'p'" title="拼音" json="/data/pinyin.json" :handler :text="searchPatterns" />
<template v-else>
<SearchAsync title="笔划" json="/data/bihua.json" :handler :text="searchPatterns" />
<SearchAsync title="四角" json="/data/sijiao.json" :handler :text="searchPatterns" />
</template>
</template>
48 changes: 48 additions & 0 deletions components/search/SearchAsync.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<script setup lang="ts">
import { onMounted, shallowRef, computed } from "vue";
import Card from "./Card.vue";
import { cache, fetchJsonWithCache, SearchCardsPropsArray, prehandleJson } from "./share";
const p = defineProps<{
/** 需要请求的json的路径,注意要以 / 开头 */
json: string,
/** 数据的标题,不能用__proto__ */
title: string,
/** 有了json数据后,生成查询的结果列表 */
handler: (json: object, text: string) => SearchCardsPropsArray
/** 要查询的字符 */
text: string[]
}>()
const data = shallowRef(cache[p.title])
onMounted(async () => {
const title = p.title
if (title in cache) return;
let json = await fetchJsonWithCache(p.json)
if (title === '四角')
json = prehandleJson(json)
cache[title] = json
data.value = json
})
const result = computed(() => {
if (!data.value || !p.text) return null;
return p.handler(data.value, p.text.join(''))
})
</script>

<template>
<h3 v-if="!(result)" class="text-center text-gray-500 text-lg">
正在加载{{ title }}的数据… …
</h3>
<template v-else-if="result.length">
<h3 class="text-gray-500 text-center">
{{ title }}查询
<span class="text-sm">(共 {{ result.length }} 条)</span>
</h3>
<div class="flex justify-center flex-wrap my-8">
<Card v-for="r of result" :key="r.zi" :name="r.zi" :data="r.data" />
</div>
</template>
</template>
13 changes: 13 additions & 0 deletions components/search/SearchHanzi.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script setup lang="ts">
import Card from "./Card.vue";
import { type SearchCardsPropsArray } from "./share";
defineProps<{
result: SearchCardsPropsArray
}>()
</script>

<template>
<div class="flex justify-center flex-wrap my-8">
<Card v-for="r of result" :key="r.zi" :name="r.zi" :data="r.data" />
</div>
</template>
68 changes: 68 additions & 0 deletions components/search/SearchHelp.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<template>
<!-- Open the modal using ID.showModal() method -->
<button class="btn btn-ghost btn-sm text-slate-500 font-normal" onclick="my_modal_2.showModal()">
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 32 32">
<path fill="currentColor"
d="M16 2a14 14 0 1 0 14 14A14 14 0 0 0 16 2m0 26a12 12 0 1 1 12-12a12 12 0 0 1-12 12" />
<circle cx="16" cy="23.5" r="1.5" fill="currentColor" />
<path fill="currentColor"
d="M17 8h-1.5a4.49 4.49 0 0 0-4.5 4.5v.5h2v-.5a2.5 2.5 0 0 1 2.5-2.5H17a2.5 2.5 0 0 1 0 5h-2v4.5h2V17a4.5 4.5 0 0 0 0-9" />
</svg>
查询功能说明
</button>
<dialog id="my_modal_2" class="modal">
<div class="modal-box bg-slate-100 dark:bg-slate-800">
<form method="dialog">
<button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</button>
</form>
<p>
这个网页可以方便地查询逸码的拆分,可以链接到
<a href="https://zi.tools/" target="_blank" rel="noreferrer">
字统网
</a>
<a href="http://yedict.com/" target="_blank" rel="noreferrer">
叶典网
</a>
<a href="https://hanyu.baidu.com/" target="_blank" rel="noreferrer">
百度汉语
</a>
<a href="https://www.zdic.net/" target="_blank" rel="noreferrer">
汉典网
</a>
。本网页会过滤码表之外的字符。
<p>网页在第一次查询拼音、四角、笔画时,需要下载相应的数据,请稍后。</p>

</p>
<h4>① 查询汉字</h4>
<p>
输入要查询的文字(可多个汉字),程序会显示每个汉字的拆分。
</p>
<h4>② 拼音反查</h4>
<p>
输入全拼(例如:<code>hao</code>),返回所有相关汉字的拆分。
</p>
<h4>③ 笔画反查</h4>
<p>
连续输入 12345
这五个数字,分别表示“横竖撇点折”。复杂汉字,输入完 <b>6</b>
个笔画后,再输入汉字的 <b>最后一笔</b>。
</p>
<h4>④ 四角反查</h4>
<p>
输入
<a href="https://baike.baidu.com/item/%E5%9B%9B%E8%A7%92%E5%8F%B7%E7%A0%81/1217626" target="_blank"
rel="noreferrer">
四角号码
</a>{" "}
反查相关汉字。填入4个数字或5个数字。
</p>
</div>

<form method="dialog" class="modal-backdrop">
<button>关闭对话框</button>
</form>
</dialog>
</template>
Binary file added components/search/assets/baidu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added components/search/assets/handian.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added components/search/assets/yedian.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions components/search/assets/zitong.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 3e2dafd

Please sign in to comment.