From 6d19fcc3bb2eae66eea0f988d923b2890bbb2307 Mon Sep 17 00:00:00 2001 From: wanglu Date: Fri, 8 Apr 2022 22:14:50 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E5=8F=AF=E4=BB=A5=E6=90=9C=E7=B4=A2url?= =?UTF-8?q?=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker.sh | 4 ++-- public/asset-manifest.json | 6 +++--- public/index.html | 2 +- public/static/js/main.8d96d695.chunk.js | 2 -- public/static/js/main.8d96d695.chunk.js.map | 1 - public/static/js/main.fddac8bf.chunk.js | 2 ++ public/static/js/main.fddac8bf.chunk.js.map | 1 + push.sh | 5 +++++ ui/website/src/components/Content/index.tsx | 6 ++++-- 9 files changed, 18 insertions(+), 11 deletions(-) delete mode 100644 public/static/js/main.8d96d695.chunk.js delete mode 100644 public/static/js/main.8d96d695.chunk.js.map create mode 100644 public/static/js/main.fddac8bf.chunk.js create mode 100644 public/static/js/main.fddac8bf.chunk.js.map create mode 100644 push.sh diff --git a/docker.sh b/docker.sh index f64db1d..abaac2b 100644 --- a/docker.sh +++ b/docker.sh @@ -1,2 +1,2 @@ -docker build -t mereith/van-nav:v1.0.6 . -docker push mereith/van-nav:v1.0.6 \ No newline at end of file +docker build -t mereith/van-nav:v1.0.7 . +docker push mereith/van-nav:v1.0.7 \ No newline at end of file diff --git a/public/asset-manifest.json b/public/asset-manifest.json index ead2d1f..a76ef18 100644 --- a/public/asset-manifest.json +++ b/public/asset-manifest.json @@ -1,8 +1,8 @@ { "files": { "main.css": "/static/css/main.ab172139.chunk.css", - "main.js": "/static/js/main.8d96d695.chunk.js", - "main.js.map": "/static/js/main.8d96d695.chunk.js.map", + "main.js": "/static/js/main.fddac8bf.chunk.js", + "main.js.map": "/static/js/main.fddac8bf.chunk.js.map", "runtime-main.js": "/static/js/runtime-main.bd3f33bc.js", "runtime-main.js.map": "/static/js/runtime-main.bd3f33bc.js.map", "static/js/2.a3da8219.chunk.js": "/static/js/2.a3da8219.chunk.js", @@ -17,6 +17,6 @@ "static/js/runtime-main.bd3f33bc.js", "static/js/2.a3da8219.chunk.js", "static/css/main.ab172139.chunk.css", - "static/js/main.8d96d695.chunk.js" + "static/js/main.fddac8bf.chunk.js" ] } \ No newline at end of file diff --git a/public/index.html b/public/index.html index 65fecb4..e657eac 100644 --- a/public/index.html +++ b/public/index.html @@ -1 +1 @@ -
\ No newline at end of file +
\ No newline at end of file diff --git a/public/static/js/main.8d96d695.chunk.js b/public/static/js/main.8d96d695.chunk.js deleted file mode 100644 index 67c38af..0000000 --- a/public/static/js/main.8d96d695.chunk.js +++ /dev/null @@ -1,2 +0,0 @@ -(this.webpackJsonptool=this.webpackJsonptool||[]).push([[0],{28:function(e,t,c){},29:function(e,t,c){},31:function(e,t,c){},32:function(e,t,c){},34:function(e,t,c){},35:function(e,t,c){},58:function(e,t,c){},59:function(e,t,c){},60:function(e,t,c){"use strict";c.r(t);var n=c(1),a=c.n(n),r=c(17),i=c.n(r),s=(c(28),c(29),c(6)),o=c(4),l=c(5),d=c.n(l),u=(c(31),c(32),c(0)),j=function(e){var t=e.title,c=e.url,n=e.des,a=e.logo,r=e.catelog,i=e.onClick;return Object(u.jsx)("a",{href:c,onClick:function(){i()},target:"_blank",rel:"noreferrer",className:"card-box",children:Object(u.jsxs)("div",{className:"card-content",children:[Object(u.jsx)("div",{className:"card-left",children:Object(u.jsx)("img",{src:a,alt:t})}),Object(u.jsxs)("div",{className:"card-right",children:[Object(u.jsxs)("div",{className:"card-right-top",children:[Object(u.jsx)("span",{className:"card-right-title",children:t}),Object(u.jsx)("span",{className:"card-tag",children:r})]}),Object(u.jsx)("div",{className:"card-right-bottom",children:n})]})]})})},v=(c(34),function(e){var t=function(e){if("Enter"===e.code||/[a-zA-Z0-9]|[\u4e00-\u9fa5]/g.test(e.key)){var t=document.getElementById("search-bar");t&&t.focus()}};return Object(n.useEffect)((function(){return document.addEventListener("keydown",t),function(){document.removeEventListener("keydown",t)}})),Object(u.jsx)("div",{className:"search span-3",children:Object(u.jsx)("div",{className:"search-wraper",children:Object(u.jsx)("input",{id:"search-bar",type:"search",placeholder:"\u6309\u56de\u8f66\u952e\u805a\u7126\u5e76\u641c\u7d22\u5e94\u7528",value:e.searchString,onChange:function(t){var c=t.target.value.trim();e.setSearchText(c)}})})})}),b=(c(35),function(e){return Object(u.jsx)("div",{className:"loading span-3",children:Object(u.jsxs)("div",{className:"lds-ring",children:[Object(u.jsx)("div",{}),Object(u.jsx)("div",{}),Object(u.jsx)("div",{}),Object(u.jsx)("div",{})]})})}),h=c(18),g=c(22),m=c.n(g),f=function(){var e=Object(s.a)(d.a.mark((function e(){var t,c,n,a;return d.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,m.a.get("/api/");case 2:return t=e.sent,c=t.data,n=c.data,(a=[]).push("\u5168\u90e8\u5de5\u5177"),n.tools.forEach((function(e){a.includes(e.catelog)||a.push(e.catelog)})),a.push("\u7ba1\u7406\u540e\u53f0"),n.tools.push({id:999999999999,catelog:"\u7ba1\u7406\u540e\u53f0",name:"\u672c\u7ad9\u7ba1\u7406\u540e\u53f0",desc:"\u672c\u5bfc\u822a\u7ad9\u7684\u7ba1\u7406\u540e\u53f0\u54e6",url:"admin",logo:"https://pic.mereith.com/img/admin-fill.png"}),n.catelogs=a,e.abrupt("return",n);case 12:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}(),O=f,p=(c(58),function(e){var t=e.tags,c=void 0===t?["all"]:t,a=e.onTagChange,r=e.currTag,i=Object(n.useCallback)((function(){return c.map((function(e){return Object(u.jsx)("span",{className:"select-tag ".concat(r===e?"select-tag-active":""),onClick:function(){a(e)},children:e},"".concat(e,"-select-tag"))}))}),[c,a,r]);return Object(u.jsx)("div",{className:"tag-selector span-3",children:Object(u.jsx)("div",{className:"tag-selector-wrapper",children:i()})})}),x=void 0,w=c(23),k=function(e,t){var c=e.toLowerCase(),n=t.toLowerCase(),a=c.includes(n),r=Boolean(w.a.match(c,n));return a||r},N=function(e){var t,c,a,r,i,l=Object(n.useState)({}),g=Object(o.a)(l,2),m=g[0],f=g[1],w=Object(n.useState)(!0),N=Object(o.a)(w,2),y=N[0],S=N[1],C=Object(n.useState)("\u5168\u90e8\u5de5\u5177"),E=Object(o.a)(C,2),L=E[0],T=E[1],I=Object(n.useState)(""),B=Object(o.a)(I,2),M=B[0],F=B[1],z=Object(n.useState)(""),A=Object(o.a)(z,2),q=A[0],J=A[1],P=Object(n.useCallback)(Object(s.a)(d.a.mark((function e(){var t,c;return d.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,S(!0),e.next=4,O();case 4:t=e.sent,f(t),(c=window.localStorage.getItem("tag"))&&""!==c&&null!==t&&void 0!==t&&t.catelogs&&null!==t&&void 0!==t&&t.catelogs.includes(c)&&T(c),e.next=13;break;case 10:e.prev=10,e.t0=e.catch(0),console.log(e.t0);case 13:return e.prev=13,S(!1),e.finish(13);case 16:case"end":return e.stop()}}),e,null,[[0,10,13,16]])}))),[f,S,T]);Object(n.useEffect)((function(){P()}),[P]);var Z=function(){J(""),F("");var e=window.localStorage.getItem("tag");e&&""!==e&&T(e)},_=function(e,t){var c=Object(n.useRef)({time:null}).current;return Object(n.useCallback)((function(){for(var n=arguments.length,a=new Array(n),r=0;r {\r\n return (\r\n {\r\n onClick()\r\n }} target=\"_blank\" rel=\"noreferrer\" className=\"card-box\">\r\n
\r\n
\r\n {title}\r\n
\r\n
\r\n
\r\n {title}\r\n {catelog}\r\n
\r\n
{des}
\r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default Card;\r\n","import { useEffect } from \"react\";\r\nimport \"./index.scss\";\r\n// import { useState } from 'react';\r\n\r\ninterface SearchBarProps {\r\n setSearchText: (t: string) => void;\r\n searchString: string;\r\n}\r\nconst SearchBar = (props: SearchBarProps) => {\r\n const onKeyDown = (ev) => {\r\n const reg = /[a-zA-Z0-9]|[\\u4e00-\\u9fa5]/g;\r\n if(ev.code === \"Enter\" || reg.test(ev.key)) {\r\n const el = document.getElementById(\"search-bar\");\r\n if (el) {\r\n el.focus();\r\n }\r\n }\r\n }\r\n useEffect(()=> {\r\n document.addEventListener(\"keydown\",onKeyDown);\r\n return () => {\r\n document.removeEventListener(\"keydown\",onKeyDown)\r\n }\r\n })\r\n return (\r\n
\r\n
\r\n {\r\n const v = ev.target.value.trim();\r\n props.setSearchText(v);\r\n }}\r\n >\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default SearchBar;\r\n","import \"./index.scss\";\nexport const Loading = (props: any) => {\n return (\n
\n
\n
\n
\n
\n
\n
\n
\n );\n};\n","import axios from \"axios\";\r\nconst baseUrl = \"/api/\";\r\n// const baseUrl = \"https://tools.mereith.com/api/\";\r\nexport const FetchList =async () => {\r\n const {data: raw} = await axios.get(baseUrl);\r\n const {data} = raw;\r\n // 获取分类\r\n const catelogs = [];\r\n catelogs.push(\"全部工具\")\r\n data.tools.forEach(item => {\r\n if (!catelogs.includes(item.catelog)) {\r\n catelogs.push(item.catelog);\r\n }\r\n });\r\n catelogs.push(\"管理后台\");\r\n data.tools.push({\r\n id: 999999999999,\r\n catelog: \"管理后台\",\r\n name: \"本站管理后台\",\r\n desc: \"本导航站的管理后台哦\",\r\n url: \"admin\",\r\n logo: \"https://pic.mereith.com/img/admin-fill.png\",\r\n })\r\n data.catelogs = catelogs;\r\n return data;\r\n};\r\nexport default FetchList;\r\n\r\n\r\n","import \"./index.scss\";\nimport { useCallback } from \"react\";\ninterface TagSelectorProps {\n tags: any;\n onTagChange: (newTag: string) => void;\n currTag: string;\n}\nconst TagSelector = (props: TagSelectorProps) => {\n const { tags = [\"all\"], onTagChange, currTag } = props;\n\n const renderTags = useCallback(() => {\n return tags.map((each) => {\n return (\n {\n onTagChange(each);\n }}\n >\n {each}\n \n );\n });\n }, [tags, onTagChange, currTag]);\n return (\n
\n
\n {renderTags()}\n
\n
\n );\n};\n\nexport default TagSelector;\n","import \"./index.scss\";\r\nimport CardV2 from \"../CardV2\";\r\nimport SearchBar from \"../SearchBar\";\r\nimport { Loading } from \"../Loading\";\r\nimport { Helmet } from \"react-helmet\";\r\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\r\nimport FetchList from \"../../utils/api\";\r\nimport TagSelector from \"../TagSelector\";\r\nimport { useDebounce } from \"../../utils/tools\";\r\nimport pinyin from \"pinyin-match\";\r\n\r\nconst mutiSearch = (s, t) => {\r\n const source = (s as string).toLowerCase();\r\n const target = t.toLowerCase();\r\n const rawInclude = source.includes(target);\r\n const pinYinInlcude = Boolean(pinyin.match(source, target));\r\n return rawInclude || pinYinInlcude;\r\n};\r\n\r\nconst Content = (props: any) => {\r\n const [data, setData] = useState({});\r\n const [loading, setLoading] = useState(true);\r\n const [currTag, setCurrTag] = useState(\"全部工具\");\r\n const [searchString, setSearchString] = useState(\"\");\r\n const [val, setVal] = useState(\"\");\r\n const loadData = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const r = await FetchList();\r\n setData(r);\r\n const tagInLocalStorage = window.localStorage.getItem(\"tag\");\r\n if (tagInLocalStorage && tagInLocalStorage !== \"\") {\r\n if (r?.catelogs && r?.catelogs.includes(tagInLocalStorage)) {\r\n setCurrTag(tagInLocalStorage);\r\n }\r\n }\r\n } catch (e) {\r\n console.log(e);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [setData, setLoading, setCurrTag]);\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const handleSetCurrTag = (tag: string) => {\r\n setCurrTag(tag);\r\n window.localStorage.setItem(\"tag\", tag);\r\n resetSearch();\r\n };\r\n\r\n const resetSearch = () => {\r\n setVal(\"\");\r\n setSearchString(\"\");\r\n const tagInLocalStorage = window.localStorage.getItem(\"tag\");\r\n if (tagInLocalStorage && tagInLocalStorage !== \"\") {\r\n setCurrTag(tagInLocalStorage);\r\n }\r\n };\r\n\r\n const handleSetSearch = useDebounce((val: string) => {\r\n if (val !== \"\" && val) {\r\n setCurrTag(\"全部工具\");\r\n setSearchString(val);\r\n } else {\r\n resetSearch();\r\n }\r\n }, 500);\r\n\r\n const filteredData = useMemo(() => {\r\n if (data.tools) {\r\n return data.tools\r\n .filter((item: any) => {\r\n if (currTag === \"全部工具\") {\r\n return true;\r\n }\r\n return item.catelog === currTag;\r\n })\r\n .filter((item: any) => {\r\n if (searchString === \"\") {\r\n return true;\r\n }\r\n return (\r\n mutiSearch(item.name, searchString) ||\r\n mutiSearch(item.desc, searchString)\r\n );\r\n });\r\n } else {\r\n return [];\r\n }\r\n }, [data, currTag, searchString]);\r\n\r\n const renderCardsV2 = useCallback(() => {\r\n return filteredData.map((item) => {\r\n return (\r\n {\r\n resetSearch();\r\n }}\r\n />\r\n );\r\n });\r\n }, [filteredData]);\r\n\r\n const onKeyEnter = (ev) => {\r\n const searchEl: any = document.getElementById(\"search-bar\");\r\n const cards = data?.tools?.filter((item: any) => {\r\n if (searchEl?.value === \"\") {\r\n return true;\r\n }\r\n return (\r\n mutiSearch(item.name, searchEl?.value) ||\r\n mutiSearch(item.desc, searchEl?.value)\r\n );\r\n });\r\n if (ev.code === \"Enter\") {\r\n if (cards && cards.length) {\r\n window.open(cards[0]?.url, \"_blank\");\r\n resetSearch();\r\n }\r\n }\r\n document.removeEventListener(\"keydown\", onKeyEnter);\r\n };\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n {data?.setting?.title ?? \"Mereith's Nav Site\"}\r\n \r\n
\r\n
\r\n {\r\n setVal(t);\r\n handleSetSearch(t);\r\n document.addEventListener(\"keydown\", onKeyEnter);\r\n }}\r\n />\r\n \r\n
\r\n
\r\n
\r\n
\r\n {loading ? : renderCardsV2()}\r\n {/*
\r\n
\r\n
\r\n
*/}\r\n
\r\n
\r\n \r\n );\r\n};\r\n\r\nexport default Content;\r\n","import { useRef, useCallback } from \"react\";\n\nexport const useDebounce = (fn: any, delay: number) => {\n const { current } = useRef<{ time: any }>({ time: null });\n return useCallback(\n (...args: any[]) => {\n if (current.time) {\n clearTimeout(current.time);\n current.time = null;\n }\n current.time = setTimeout(() => {\n fn.apply(this, args);\n clearTimeout(current.time);\n current.time = null;\n }, delay);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [current, delay]\n );\n};","import { useEffect, useState } from \"react\";\nimport \"./index.scss\";\nconst getInitMode = () => {\n const mode = window.localStorage.getItem(\"theme\");\n if (mode) {\n return mode;\n } else {\n return \"day\";\n }\n};\nconst DarkSwitch = () => {\n const [mode, setMode] = useState(getInitMode());\n useEffect(() => {\n if (mode !== \"day\") {\n const bodyEl = document.querySelector(\"body\");\n if (bodyEl) {\n bodyEl.classList.toggle(\"dark-mode\", true);\n }\n window.localStorage.setItem(\"theme\", 'dark');\n }\n });\n const sunIcon = (\n \n \n \n \n );\n const moonIcon = (\n \n \n \n );\n const handleSwitch = () => {\n // 先找现在的颜色主题\n const toSet = mode === \"day\" ? \"dark\" : \"day\";\n window.localStorage.setItem(\"theme\", toSet);\n const bodyEl = document.querySelector(\"body\");\n if (bodyEl) {\n if (toSet === \"day\") {\n bodyEl.classList.toggle(\"dark-mode\", false);\n } else {\n bodyEl.classList.toggle(\"dark-mode\", true);\n }\n }\n setMode(toSet);\n };\n return (\n
\n {mode === \"day\" ? moonIcon : sunIcon}\n
\n );\n};\nexport default DarkSwitch;\n","import \"./App.scss\";\r\nimport Content from \"./components/Content\";\r\nimport DarkSwitch from \"./components/DarkSwitch\";\r\nfunction App() {\r\n return (\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n );\r\n}\r\n\r\nexport default App;\r\n","import { ReportHandler } from 'web-vitals';\r\n\r\nconst reportWebVitals = (onPerfEntry?: ReportHandler) => {\r\n if (onPerfEntry && onPerfEntry instanceof Function) {\r\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\r\n getCLS(onPerfEntry);\r\n getFID(onPerfEntry);\r\n getFCP(onPerfEntry);\r\n getLCP(onPerfEntry);\r\n getTTFB(onPerfEntry);\r\n });\r\n }\r\n};\r\n\r\nexport default reportWebVitals;\r\n","import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport './index.scss';\r\nimport App from './App';\r\nimport reportWebVitals from './reportWebVitals';\r\n\r\nReactDOM.render(\r\n \r\n \r\n ,\r\n document.getElementById('root')\r\n);\r\n\r\n// If you want to start measuring performance in your app, pass a function\r\n// to log results (for example: reportWebVitals(console.log))\r\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\r\nreportWebVitals();\r\n"],"sourceRoot":""} \ No newline at end of file diff --git a/public/static/js/main.fddac8bf.chunk.js b/public/static/js/main.fddac8bf.chunk.js new file mode 100644 index 0000000..5c40b50 --- /dev/null +++ b/public/static/js/main.fddac8bf.chunk.js @@ -0,0 +1,2 @@ +(this.webpackJsonptool=this.webpackJsonptool||[]).push([[0],{28:function(e,t,c){},29:function(e,t,c){},31:function(e,t,c){},32:function(e,t,c){},34:function(e,t,c){},35:function(e,t,c){},58:function(e,t,c){},59:function(e,t,c){},60:function(e,t,c){"use strict";c.r(t);var n=c(1),a=c.n(n),r=c(17),i=c.n(r),s=(c(28),c(29),c(6)),o=c(4),l=c(5),d=c.n(l),u=(c(31),c(32),c(0)),j=function(e){var t=e.title,c=e.url,n=e.des,a=e.logo,r=e.catelog,i=e.onClick;return Object(u.jsx)("a",{href:c,onClick:function(){i()},target:"_blank",rel:"noreferrer",className:"card-box",children:Object(u.jsxs)("div",{className:"card-content",children:[Object(u.jsx)("div",{className:"card-left",children:Object(u.jsx)("img",{src:a,alt:t})}),Object(u.jsxs)("div",{className:"card-right",children:[Object(u.jsxs)("div",{className:"card-right-top",children:[Object(u.jsx)("span",{className:"card-right-title",children:t}),Object(u.jsx)("span",{className:"card-tag",children:r})]}),Object(u.jsx)("div",{className:"card-right-bottom",children:n})]})]})})},v=(c(34),function(e){var t=function(e){if("Enter"===e.code||/[a-zA-Z0-9]|[\u4e00-\u9fa5]/g.test(e.key)){var t=document.getElementById("search-bar");t&&t.focus()}};return Object(n.useEffect)((function(){return document.addEventListener("keydown",t),function(){document.removeEventListener("keydown",t)}})),Object(u.jsx)("div",{className:"search span-3",children:Object(u.jsx)("div",{className:"search-wraper",children:Object(u.jsx)("input",{id:"search-bar",type:"search",placeholder:"\u6309\u56de\u8f66\u952e\u805a\u7126\u5e76\u641c\u7d22\u5e94\u7528",value:e.searchString,onChange:function(t){var c=t.target.value.trim();e.setSearchText(c)}})})})}),b=(c(35),function(e){return Object(u.jsx)("div",{className:"loading span-3",children:Object(u.jsxs)("div",{className:"lds-ring",children:[Object(u.jsx)("div",{}),Object(u.jsx)("div",{}),Object(u.jsx)("div",{}),Object(u.jsx)("div",{})]})})}),h=c(18),g=c(22),m=c.n(g),f=function(){var e=Object(s.a)(d.a.mark((function e(){var t,c,n,a;return d.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,m.a.get("/api/");case 2:return t=e.sent,c=t.data,n=c.data,(a=[]).push("\u5168\u90e8\u5de5\u5177"),n.tools.forEach((function(e){a.includes(e.catelog)||a.push(e.catelog)})),a.push("\u7ba1\u7406\u540e\u53f0"),n.tools.push({id:999999999999,catelog:"\u7ba1\u7406\u540e\u53f0",name:"\u672c\u7ad9\u7ba1\u7406\u540e\u53f0",desc:"\u672c\u5bfc\u822a\u7ad9\u7684\u7ba1\u7406\u540e\u53f0\u54e6",url:"admin",logo:"https://pic.mereith.com/img/admin-fill.png"}),n.catelogs=a,e.abrupt("return",n);case 12:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}(),O=f,p=(c(58),function(e){var t=e.tags,c=void 0===t?["all"]:t,a=e.onTagChange,r=e.currTag,i=Object(n.useCallback)((function(){return c.map((function(e){return Object(u.jsx)("span",{className:"select-tag ".concat(r===e?"select-tag-active":""),onClick:function(){a(e)},children:e},"".concat(e,"-select-tag"))}))}),[c,a,r]);return Object(u.jsx)("div",{className:"tag-selector span-3",children:Object(u.jsx)("div",{className:"tag-selector-wrapper",children:i()})})}),x=void 0,w=c(23),k=function(e,t){var c=e.toLowerCase(),n=t.toLowerCase(),a=c.includes(n),r=Boolean(w.a.match(c,n));return a||r},N=function(e){var t,c,a,r,i,l=Object(n.useState)({}),g=Object(o.a)(l,2),m=g[0],f=g[1],w=Object(n.useState)(!0),N=Object(o.a)(w,2),y=N[0],S=N[1],C=Object(n.useState)("\u5168\u90e8\u5de5\u5177"),E=Object(o.a)(C,2),L=E[0],T=E[1],I=Object(n.useState)(""),B=Object(o.a)(I,2),M=B[0],F=B[1],z=Object(n.useState)(""),A=Object(o.a)(z,2),q=A[0],J=A[1],P=Object(n.useCallback)(Object(s.a)(d.a.mark((function e(){var t,c;return d.a.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,S(!0),e.next=4,O();case 4:t=e.sent,f(t),(c=window.localStorage.getItem("tag"))&&""!==c&&null!==t&&void 0!==t&&t.catelogs&&null!==t&&void 0!==t&&t.catelogs.includes(c)&&T(c),e.next=13;break;case 10:e.prev=10,e.t0=e.catch(0),console.log(e.t0);case 13:return e.prev=13,S(!1),e.finish(13);case 16:case"end":return e.stop()}}),e,null,[[0,10,13,16]])}))),[f,S,T]);Object(n.useEffect)((function(){P()}),[P]);var Z=function(){J(""),F("");var e=window.localStorage.getItem("tag");e&&""!==e&&T(e)},_=function(e,t){var c=Object(n.useRef)({time:null}).current;return Object(n.useCallback)((function(){for(var n=arguments.length,a=new Array(n),r=0;r {\r\n return (\r\n {\r\n onClick()\r\n }} target=\"_blank\" rel=\"noreferrer\" className=\"card-box\">\r\n
\r\n
\r\n {title}\r\n
\r\n
\r\n
\r\n {title}\r\n {catelog}\r\n
\r\n
{des}
\r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default Card;\r\n","import { useEffect } from \"react\";\r\nimport \"./index.scss\";\r\n// import { useState } from 'react';\r\n\r\ninterface SearchBarProps {\r\n setSearchText: (t: string) => void;\r\n searchString: string;\r\n}\r\nconst SearchBar = (props: SearchBarProps) => {\r\n const onKeyDown = (ev) => {\r\n const reg = /[a-zA-Z0-9]|[\\u4e00-\\u9fa5]/g;\r\n if(ev.code === \"Enter\" || reg.test(ev.key)) {\r\n const el = document.getElementById(\"search-bar\");\r\n if (el) {\r\n el.focus();\r\n }\r\n }\r\n }\r\n useEffect(()=> {\r\n document.addEventListener(\"keydown\",onKeyDown);\r\n return () => {\r\n document.removeEventListener(\"keydown\",onKeyDown)\r\n }\r\n })\r\n return (\r\n
\r\n
\r\n {\r\n const v = ev.target.value.trim();\r\n props.setSearchText(v);\r\n }}\r\n >\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport default SearchBar;\r\n","import \"./index.scss\";\nexport const Loading = (props: any) => {\n return (\n
\n
\n
\n
\n
\n
\n
\n
\n );\n};\n","import axios from \"axios\";\r\nconst baseUrl = \"/api/\";\r\n// const baseUrl = \"https://tools.mereith.com/api/\";\r\nexport const FetchList =async () => {\r\n const {data: raw} = await axios.get(baseUrl);\r\n const {data} = raw;\r\n // 获取分类\r\n const catelogs = [];\r\n catelogs.push(\"全部工具\")\r\n data.tools.forEach(item => {\r\n if (!catelogs.includes(item.catelog)) {\r\n catelogs.push(item.catelog);\r\n }\r\n });\r\n catelogs.push(\"管理后台\");\r\n data.tools.push({\r\n id: 999999999999,\r\n catelog: \"管理后台\",\r\n name: \"本站管理后台\",\r\n desc: \"本导航站的管理后台哦\",\r\n url: \"admin\",\r\n logo: \"https://pic.mereith.com/img/admin-fill.png\",\r\n })\r\n data.catelogs = catelogs;\r\n return data;\r\n};\r\nexport default FetchList;\r\n\r\n\r\n","import \"./index.scss\";\nimport { useCallback } from \"react\";\ninterface TagSelectorProps {\n tags: any;\n onTagChange: (newTag: string) => void;\n currTag: string;\n}\nconst TagSelector = (props: TagSelectorProps) => {\n const { tags = [\"all\"], onTagChange, currTag } = props;\n\n const renderTags = useCallback(() => {\n return tags.map((each) => {\n return (\n {\n onTagChange(each);\n }}\n >\n {each}\n \n );\n });\n }, [tags, onTagChange, currTag]);\n return (\n
\n
\n {renderTags()}\n
\n
\n );\n};\n\nexport default TagSelector;\n","import \"./index.scss\";\r\nimport CardV2 from \"../CardV2\";\r\nimport SearchBar from \"../SearchBar\";\r\nimport { Loading } from \"../Loading\";\r\nimport { Helmet } from \"react-helmet\";\r\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\r\nimport FetchList from \"../../utils/api\";\r\nimport TagSelector from \"../TagSelector\";\r\nimport { useDebounce } from \"../../utils/tools\";\r\nimport pinyin from \"pinyin-match\";\r\n\r\nconst mutiSearch = (s, t) => {\r\n const source = (s as string).toLowerCase();\r\n const target = t.toLowerCase();\r\n const rawInclude = source.includes(target);\r\n const pinYinInlcude = Boolean(pinyin.match(source, target));\r\n return rawInclude || pinYinInlcude;\r\n};\r\n\r\nconst Content = (props: any) => {\r\n const [data, setData] = useState({});\r\n const [loading, setLoading] = useState(true);\r\n const [currTag, setCurrTag] = useState(\"全部工具\");\r\n const [searchString, setSearchString] = useState(\"\");\r\n const [val, setVal] = useState(\"\");\r\n const loadData = useCallback(async () => {\r\n try {\r\n setLoading(true);\r\n const r = await FetchList();\r\n setData(r);\r\n const tagInLocalStorage = window.localStorage.getItem(\"tag\");\r\n if (tagInLocalStorage && tagInLocalStorage !== \"\") {\r\n if (r?.catelogs && r?.catelogs.includes(tagInLocalStorage)) {\r\n setCurrTag(tagInLocalStorage);\r\n }\r\n }\r\n } catch (e) {\r\n console.log(e);\r\n } finally {\r\n setLoading(false);\r\n }\r\n }, [setData, setLoading, setCurrTag]);\r\n useEffect(() => {\r\n loadData();\r\n }, [loadData]);\r\n\r\n const handleSetCurrTag = (tag: string) => {\r\n setCurrTag(tag);\r\n window.localStorage.setItem(\"tag\", tag);\r\n resetSearch();\r\n };\r\n\r\n const resetSearch = () => {\r\n setVal(\"\");\r\n setSearchString(\"\");\r\n const tagInLocalStorage = window.localStorage.getItem(\"tag\");\r\n if (tagInLocalStorage && tagInLocalStorage !== \"\") {\r\n setCurrTag(tagInLocalStorage);\r\n }\r\n };\r\n\r\n const handleSetSearch = useDebounce((val: string) => {\r\n if (val !== \"\" && val) {\r\n setCurrTag(\"全部工具\");\r\n setSearchString(val);\r\n } else {\r\n resetSearch();\r\n }\r\n }, 500);\r\n\r\n const filteredData = useMemo(() => {\r\n if (data.tools) {\r\n return data.tools\r\n .filter((item: any) => {\r\n if (currTag === \"全部工具\") {\r\n return true;\r\n }\r\n return item.catelog === currTag;\r\n })\r\n .filter((item: any) => {\r\n if (searchString === \"\") {\r\n return true;\r\n }\r\n return (\r\n mutiSearch(item.name, searchString) ||\r\n mutiSearch(item.desc, searchString) || \r\n mutiSearch(item.url, searchString)\r\n );\r\n });\r\n } else {\r\n return [];\r\n }\r\n }, [data, currTag, searchString]);\r\n\r\n const renderCardsV2 = useCallback(() => {\r\n return filteredData.map((item) => {\r\n return (\r\n {\r\n resetSearch();\r\n }}\r\n />\r\n );\r\n });\r\n }, [filteredData]);\r\n\r\n const onKeyEnter = (ev) => {\r\n const searchEl: any = document.getElementById(\"search-bar\");\r\n const cards = data?.tools?.filter((item: any) => {\r\n if (searchEl?.value === \"\") {\r\n return true;\r\n }\r\n return (\r\n mutiSearch(item.name, searchEl?.value) ||\r\n mutiSearch(item.desc, searchEl?.value) || \r\n mutiSearch(item.url, searchEl?.value)\r\n );\r\n });\r\n if (ev.code === \"Enter\") {\r\n if (cards && cards.length) {\r\n window.open(cards[0]?.url, \"_blank\");\r\n resetSearch();\r\n }\r\n }\r\n document.removeEventListener(\"keydown\", onKeyEnter);\r\n };\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n {data?.setting?.title ?? \"Mereith's Nav Site\"}\r\n \r\n
\r\n
\r\n {\r\n setVal(t);\r\n handleSetSearch(t);\r\n document.addEventListener(\"keydown\", onKeyEnter);\r\n }}\r\n />\r\n \r\n
\r\n
\r\n
\r\n
\r\n {loading ? : renderCardsV2()}\r\n {/*
\r\n
\r\n
\r\n
*/}\r\n
\r\n
\r\n \r\n );\r\n};\r\n\r\nexport default Content;\r\n","import { useRef, useCallback } from \"react\";\n\nexport const useDebounce = (fn: any, delay: number) => {\n const { current } = useRef<{ time: any }>({ time: null });\n return useCallback(\n (...args: any[]) => {\n if (current.time) {\n clearTimeout(current.time);\n current.time = null;\n }\n current.time = setTimeout(() => {\n fn.apply(this, args);\n clearTimeout(current.time);\n current.time = null;\n }, delay);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [current, delay]\n );\n};","import { useEffect, useState } from \"react\";\nimport \"./index.scss\";\nconst getInitMode = () => {\n const mode = window.localStorage.getItem(\"theme\");\n if (mode) {\n return mode;\n } else {\n return \"day\";\n }\n};\nconst DarkSwitch = () => {\n const [mode, setMode] = useState(getInitMode());\n useEffect(() => {\n if (mode !== \"day\") {\n const bodyEl = document.querySelector(\"body\");\n if (bodyEl) {\n bodyEl.classList.toggle(\"dark-mode\", true);\n }\n window.localStorage.setItem(\"theme\", 'dark');\n }\n });\n const sunIcon = (\n \n \n \n \n );\n const moonIcon = (\n \n \n \n );\n const handleSwitch = () => {\n // 先找现在的颜色主题\n const toSet = mode === \"day\" ? \"dark\" : \"day\";\n window.localStorage.setItem(\"theme\", toSet);\n const bodyEl = document.querySelector(\"body\");\n if (bodyEl) {\n if (toSet === \"day\") {\n bodyEl.classList.toggle(\"dark-mode\", false);\n } else {\n bodyEl.classList.toggle(\"dark-mode\", true);\n }\n }\n setMode(toSet);\n };\n return (\n
\n {mode === \"day\" ? moonIcon : sunIcon}\n
\n );\n};\nexport default DarkSwitch;\n","import \"./App.scss\";\r\nimport Content from \"./components/Content\";\r\nimport DarkSwitch from \"./components/DarkSwitch\";\r\nfunction App() {\r\n return (\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n );\r\n}\r\n\r\nexport default App;\r\n","import { ReportHandler } from 'web-vitals';\r\n\r\nconst reportWebVitals = (onPerfEntry?: ReportHandler) => {\r\n if (onPerfEntry && onPerfEntry instanceof Function) {\r\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\r\n getCLS(onPerfEntry);\r\n getFID(onPerfEntry);\r\n getFCP(onPerfEntry);\r\n getLCP(onPerfEntry);\r\n getTTFB(onPerfEntry);\r\n });\r\n }\r\n};\r\n\r\nexport default reportWebVitals;\r\n","import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport './index.scss';\r\nimport App from './App';\r\nimport reportWebVitals from './reportWebVitals';\r\n\r\nReactDOM.render(\r\n \r\n \r\n ,\r\n document.getElementById('root')\r\n);\r\n\r\n// If you want to start measuring performance in your app, pass a function\r\n// to log results (for example: reportWebVitals(console.log))\r\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\r\nreportWebVitals();\r\n"],"sourceRoot":""} \ No newline at end of file diff --git a/push.sh b/push.sh new file mode 100644 index 0000000..7b770ae --- /dev/null +++ b/push.sh @@ -0,0 +1,5 @@ +git add . +git commit -m $2 +git tag -a $1 -m $2 +git push +git push origin --tags \ No newline at end of file diff --git a/ui/website/src/components/Content/index.tsx b/ui/website/src/components/Content/index.tsx index 3f52f75..4ce7483 100644 --- a/ui/website/src/components/Content/index.tsx +++ b/ui/website/src/components/Content/index.tsx @@ -83,7 +83,8 @@ const Content = (props: any) => { } return ( mutiSearch(item.name, searchString) || - mutiSearch(item.desc, searchString) + mutiSearch(item.desc, searchString) || + mutiSearch(item.url, searchString) ); }); } else { @@ -117,7 +118,8 @@ const Content = (props: any) => { } return ( mutiSearch(item.name, searchEl?.value) || - mutiSearch(item.desc, searchEl?.value) + mutiSearch(item.desc, searchEl?.value) || + mutiSearch(item.url, searchEl?.value) ); }); if (ev.code === "Enter") {