From c98a7d70b15f65cb6a5531c34e8e45fc3a1cc7ab Mon Sep 17 00:00:00 2001 From: expdsn <18111002318@163.com> Date: Mon, 4 Nov 2024 19:30:31 +0800 Subject: [PATCH 1/8] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=95=AA=E8=8C=84?= =?UTF-8?q?=E6=97=B6=E5=B0=8F=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + public/icons/work/tomatoIconAdd.png | Bin 0 -> 325 bytes src/layout/grid/TomatoPage.tsx | 37 +++- src/main.ts | 2 +- src/widgets/work/Large.tsx | 67 ++++++- src/widgets/work/Modal.tsx | 3 +- src/widgets/work/modal_view/DataDetail.tsx | 202 +++++++++++++++++++++ src/widgets/work/modal_view/data.tsx | 9 - src/widgets/work/modal_view/list.tsx | 5 +- src/widgets/work/useTomatoStore.ts | 32 ++-- 10 files changed, 318 insertions(+), 40 deletions(-) create mode 100644 public/icons/work/tomatoIconAdd.png create mode 100644 src/widgets/work/modal_view/DataDetail.tsx delete mode 100644 src/widgets/work/modal_view/data.tsx diff --git a/package.json b/package.json index 7492369..ad633e6 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "clsx": "^2.1.1", "crypto-js": "^4.2.0", "dayjs": "^1.11.13", + "echarts": "^5.5.1", "gsap": "^3.12.5", "localforage": "^1.10.0", "lunar-typescript": "^1.7.5", diff --git a/public/icons/work/tomatoIconAdd.png b/public/icons/work/tomatoIconAdd.png new file mode 100644 index 0000000000000000000000000000000000000000..d2b1047240250d3338eef1d7c1f66b52ab09a362 GIT binary patch literal 325 zcmV-L0lNN)P)Px#|4BqaR9HvtmoaVvK@3IT?`Y_9fRtQ-1JI>S0TpdPxd4aY0tnKkf+8(l4v-6^ z%mL_V=p3!I#cBw6SF_Siv@@+e{$Jmou`LoiN{kPgke87th0LtDzW|;~pbuat$vog& z_E literal 0 HcmV?d00001 diff --git a/src/layout/grid/TomatoPage.tsx b/src/layout/grid/TomatoPage.tsx index c5f2fe4..fb6bd0b 100644 --- a/src/layout/grid/TomatoPage.tsx +++ b/src/layout/grid/TomatoPage.tsx @@ -1,4 +1,4 @@ -import { computed, defineComponent, onMounted, ref, Transition } from 'vue' +import { computed, defineComponent, onMounted, ref, Transition, watch } from 'vue' import returnImg from "~/public/icons/work/return.png" import endImg from "~/public/icons/work/tomotoIconEnd.png" import playWaveGif from "~/public/icons/work/playMusicIcon.gif" @@ -8,7 +8,7 @@ import useBackgroundStore from '../background/useBackgroundStore' import useLayoutStore from '../useLayoutStore' import useTomatoStore, { musicList } from '@/widgets/work/useTomatoStore' import Search from '../header/search' -import { Tooltip } from 'ant-design-vue' +import { Modal, Tooltip } from 'ant-design-vue' import { formatSeconds } from '@/utils/tool' export const DefaultPageSetting = [ { @@ -37,13 +37,11 @@ export const DefaultPageSetting = [ } ] export default defineComponent(() => { - const show = computed(() => true) - const selectMode = ref(0) const background = useBackgroundStore() const layout = useLayoutStore() - const store = useTomatoStore() const isFirst = ref(false) + const showSelectModal = ref(false) onMounted(() => { // 检查 localStorage 是否已经有访问记录 const visited = localStorage.getItem('hasVisited') @@ -54,9 +52,19 @@ export default defineComponent(() => { // 设置标记,后续访问不会再次显示 } }) + watch(() => + store.remainingTime + , (val) => { + console.log(val); + + if (val <= 0) { + store.stopTomatoTime() + } + }) return () => store.openFullscreen && (
+ {background.bgTrriger && ( <> @@ -76,6 +84,9 @@ export default defineComponent(() => {
+ + + { Array.from({ length: 60 }).map((_, idx) => (
{ return
- +
{ + store.state.isStart ? + store.stopTomatoTime() : + store.beginTomatoTime() + + }} class={"w-[44px] h-[44px] flex items-center justify-center rounded-lg cursor-pointer hover:opacity-90"} style={{ background: 'linear-gradient(225deg,#707eff 0%,#6b97ff 100%)', boxShadow: '0 2px 4px #0003' }}> - return + { + store.state.isStart ? + return + : + start + + }
diff --git a/src/main.ts b/src/main.ts index e08fc26..18e3c88 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,6 +7,7 @@ import App from './App.vue' import getFp from './utils/getFp' import vOutsideClick from './utils/vOutsideClick' import dayjs from 'dayjs' + import Toast, { useToast, type PluginOptions } from 'vue-toastification' import customParseFormat from 'dayjs/plugin/customParseFormat' import 'vue-toastification/dist/index.css' @@ -16,7 +17,6 @@ dayjs.locale('zh-cn') const app = createApp(App) export const globalToast = useToast() dayjs.extend(customParseFormat) - // ! persist 利用 localstorage,请不要在大量数据时使用 // 大量数据(扩张内容,文件),清直接使用 ./db.ts app.use(createPinia().use(persist)) diff --git a/src/widgets/work/Large.tsx b/src/widgets/work/Large.tsx index 996ea16..8677c4a 100644 --- a/src/widgets/work/Large.tsx +++ b/src/widgets/work/Large.tsx @@ -1,9 +1,72 @@ import { defineComponent } from 'vue' +import { formatSeconds } from '@/utils/tool' +import PlayStartImg from "~/public/icons/work/start.png" +import returnImg from "~/public/icons/work/return.png" +import PlusImg from "~/public/icons/work/tomatoIconAdd.png" +import dayjs from 'dayjs' +import { Tooltip } from 'ant-design-vue' +import useTomatoStore from './useTomatoStore' export default defineComponent(() => { + const store = useTomatoStore() return () => ( -
- +
+
+
+
无目标
+ + { + store.state.beginTime < 0 ? '15:00' : formatSeconds(store.remainingTime) + } + + 你今日已完成 + + + + {store.state.timeList.filter(val => dayjs(val).isSame(dayjs(), 'day')).length} + + 个番茄时 +
+
+
+ +
{ + e.stopPropagation() + store.openFullscreen = true + }} + class={"w-[42px] h-[42px] bg-white/40 backdrop-blur-md flex items-center justify-center rounded-xl"}> + start +
+
+ +
{ + e.stopPropagation() + store.beginTomatoTime() + store.openFullscreen = true + }}> + start +
+
+ +
{ + setTimeout(() => { + store.openShowModel = null + + }, 300) + }}> + start +
+
+ +
+
) }) diff --git a/src/widgets/work/Modal.tsx b/src/widgets/work/Modal.tsx index 421a779..a8f9cf4 100644 --- a/src/widgets/work/Modal.tsx +++ b/src/widgets/work/Modal.tsx @@ -13,6 +13,7 @@ import type { TomatoTarget } from './useTomatoStore' import dayjs from 'dayjs' import useTomatoStore from './useTomatoStore' import Calendar from './modal_view/calendar' +import DataDetail from './modal_view/DataDetail' const workTab = [ { title: '目标列表', @@ -235,7 +236,7 @@ export default defineComponent(() => { ) : select.value === 1 ? ( ) : select.value === 2 ? ( -
数据详情
+ ) : ( <>loading )} diff --git a/src/widgets/work/modal_view/DataDetail.tsx b/src/widgets/work/modal_view/DataDetail.tsx new file mode 100644 index 0000000..4346713 --- /dev/null +++ b/src/widgets/work/modal_view/DataDetail.tsx @@ -0,0 +1,202 @@ +import { defineComponent, onBeforeUnmount, onMounted, reactive, ref } from "vue"; +// 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。 +import * as echarts from 'echarts/core'; +import { LineChart, PieChart, } from 'echarts/charts'; +// 引入柱状图图表,图表后缀都为 Chart +import { BarChart } from 'echarts/charts'; +// 引入标题,提示框,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component +import { + TitleComponent, + TooltipComponent, + GridComponent, + DatasetComponent, + TransformComponent +} from 'echarts/components'; +// 标签自动布局、全局过渡动画等特性 +import { LabelLayout, UniversalTransition } from 'echarts/features'; +// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步 +import { CanvasRenderer } from 'echarts/renderers'; +import useTomatoStore from "../useTomatoStore"; +import dayjs from "dayjs"; +import gsap from 'gsap' +import { Progress } from "ant-design-vue"; + +// 注册必须的组件 +echarts.use([ + PieChart, + TitleComponent, + LineChart, + TooltipComponent, + GridComponent, + DatasetComponent, + TransformComponent, + BarChart, + LabelLayout, + UniversalTransition, + CanvasRenderer +]); + +// 接下来的使用就跟之前一样,初始化图表,设置配置项 + +export default defineComponent(() => { + const chart = ref(null); + const leftChat = ref(null) + const store = useTomatoStore() + const precent1 = reactive({ + number: 0 + }) + const precent2 = reactive({ + number: 0 + }) + let myChart: echarts.ECharts | null = null; + + const initChart = () => { + myChart = echarts.init(chart.value); + const option = { + + tooltip: { + trigger: 'axis', + formatter: (params: any) => { + const dataPoint = params[0]; + const timeInMinutes = dataPoint.value; + // 使用 HTML 标签格式化 tooltip 内容 + return `${dataPoint.name}
${timeInMinutes} 分钟`; + }, + }, + xAxis: { + type: 'category', + data: Array.from({ length: 7 }).map((_, idx) => (dayjs().subtract(idx, 'day').format('MM月DD日'))).reverse(), + }, + yAxis: { + type: 'value', + }, + series: [ + { + type: 'line', + data: Array.from({ length: 7 }).map((_, idx) => (dayjs().subtract(idx, 'day').format('MM月DD日'))) + .reverse() + .map(item => store.state.timeList.reduce((pre, cur) => { + if (dayjs(cur).isSame(dayjs(item, "MM月DD日"), 'day')) { + return pre + 1 + } + return 0 + }, 0) * 15), + lineStyle: { + color: '#C876FB', // 线条的颜色 + width: 2, // 线条宽度 + }, + itemStyle: { + color: '#FF8688', // 数据点的颜色 + }, + showSymbol: false, // 默认不显示数据点 + // hover 时显示数据点 + emphasis: { + itemStyle: { + color: '#FF8688', // 悬停时数据点的颜色 + + }, + showSymbol: true, // 悬停时显示数据点 + }, + }, + ], + }; + + myChart.setOption(option); + + }; + + onMounted(() => { + initChart(); + window.addEventListener('resize', myChart?.resize as any); + setTimeout(() => { + + }, 1000) + gsap.to(precent1, { duration: 1, number: Number(100) || 0 }) + gsap.to(precent2, { duration: 1, number: Number(100) || 0 }) + + }); + + onBeforeUnmount(() => { + window.removeEventListener('resize', myChart?.resize as any); + myChart?.dispose(); + }); + + return () => ( +
+
+
+
+ + +
+ 相比昨天 + +300% +
+
+
+ 今日专注时长 + 0.71 + h + +
+
+
+
+ + +
+ 相比昨天 + +300% +
+
+
+ 今日专注时长 + 0.71 + h + +
+
+
+
+ 专注时长历史趋势 +
+
+ +
+ 您的趋势向上,为了美好的明天,继续努力吧! +
+
+ ) +}) \ No newline at end of file diff --git a/src/widgets/work/modal_view/data.tsx b/src/widgets/work/modal_view/data.tsx deleted file mode 100644 index 9a88bab..0000000 --- a/src/widgets/work/modal_view/data.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { defineComponent } from "vue"; - -export default defineComponent(() => { - return () => ( -
- -
- ) -}) \ No newline at end of file diff --git a/src/widgets/work/modal_view/list.tsx b/src/widgets/work/modal_view/list.tsx index 5462391..22a90ef 100644 --- a/src/widgets/work/modal_view/list.tsx +++ b/src/widgets/work/modal_view/list.tsx @@ -86,7 +86,9 @@ export default defineComponent(() => {
- 你今日已完成 {store.state.list.filter(val => dayjs(val.finishTime).isSame(dayjs(), 'day') && val.isCompleted).length}个番茄时 + 你今日已完成 + {store.state.timeList.filter(val => dayjs(val).isSame(dayjs(), 'day')).length} + 个番茄时 不积跬步无以至千里、千里之行始于足下。
{ @@ -99,7 +101,6 @@ export default defineComponent(() => { store.stopTomatoTime() }} > - play img 停止计时 : diff --git a/src/widgets/work/useTomatoStore.ts b/src/widgets/work/useTomatoStore.ts index 95ad1ce..2a31ef0 100644 --- a/src/widgets/work/useTomatoStore.ts +++ b/src/widgets/work/useTomatoStore.ts @@ -42,15 +42,20 @@ export const musicList = [ export default defineStore("work", () => { const state = reactive({ list: [] as TomatoTarget[], - timeList: [] as TomatoTime[], + timeList: [] as number[], isPlaying: false as boolean, selectMusic: 0, isStart: false as boolean, beginTime: -1 as number }) - const time = useTimeStore() + const remainingTime = computed(() => { + if (!state.isStart) { + return 0 + } + return dayjs(state.beginTime).add(1, 'minute').diff(dayjs(time.date), 'second') + }) const beginTomatoTime = () => { state.beginTime = dayjs().valueOf() state.isStart = true @@ -60,27 +65,18 @@ export default defineStore("work", () => { state.isStart = false state.beginTime = -1 stopMusic() + if (remainingTime.value <= 0) { + state.timeList.push( + dayjs().valueOf() + ) + } } - const remainingTime = computed(() => { - const totalTime = TOTAL_TIME - return dayjs(state.beginTime).add(15, 'minute').diff(dayjs(time.date), 'second') - }) const playAudio = computed(() => { const audio = new Audio(musicList[state.selectMusic].music) return audio }) - watch(() => remainingTime, (val) => { - if (val.value < 0) { - state.isPlaying = false - state.isStart = false - state.beginTime = -1 - state.timeList.push({ - date: dayjs().valueOf(), - finishTime: TOTAL_TIME - }) - } - }) + // watch(() => state.isPlaying, (val) => { // if (val) { // playAudio.value.play() @@ -116,4 +112,4 @@ export default defineStore("work", () => { stopMusic, stopTomatoTime } -}) \ No newline at end of file +}) From 775ba4825998844eca10caefb09a21447ad589d0 Mon Sep 17 00:00:00 2001 From: expdsn <18111002318@163.com> Date: Tue, 5 Nov 2024 15:40:58 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=95=AA=E8=8C=84?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/game_video_bg_play.png | Bin 0 -> 2417 bytes public/icons/work/tomoto_gt.png | Bin 0 -> 321 bytes src/layout/adder/WidgetAdder.tsx | 15 +++- src/layout/grid/TomatoPage.tsx | 72 +++++++++++++++--- src/layout/grid/WelcomePage.tsx | 6 +- src/layout/grid/WidgetBlock.tsx | 5 +- src/settings/SettingsOverlay.tsx | 2 +- src/user/LoginModal.tsx | 6 +- src/widgets/gameVideo/Large.tsx | 6 +- src/widgets/work/Large.tsx | 24 ++++-- src/widgets/work/Modal.tsx | 12 +-- src/widgets/work/Small.tsx | 19 +++-- src/widgets/work/index.ts | 2 +- src/widgets/work/modal_view/DataDetail.tsx | 18 ++--- src/widgets/work/modal_view/calendar.tsx | 2 +- src/widgets/work/modal_view/list.tsx | 6 +- src/widgets/work/useTomatoStore.ts | 84 ++++++++++++--------- vite.config.ts | 2 +- 18 files changed, 192 insertions(+), 89 deletions(-) create mode 100644 public/icons/game_video_bg_play.png create mode 100644 public/icons/work/tomoto_gt.png diff --git a/public/icons/game_video_bg_play.png b/public/icons/game_video_bg_play.png new file mode 100644 index 0000000000000000000000000000000000000000..ae23531a1160e688dfb228490f5f9a6b4bc83bf7 GIT binary patch literal 2417 zcmV-%36A!OP)Px;D@jB_RA@uxntyB@M-|7vvp?>Kol9_O4V2czG^LSDiHd0XRY3~kA3_C{kU$g~ zoFWJYs6(JA3bT zcV^L>y*cl#_s(bE*$&D|C$DeMp8J00y*F>(8-^?VVl%1V^SsFM7-QZ{evjZ-H3v{i zHH4}GR3u)B zZs{*SUgtGqAi_{WFlq&&_5gx2A0_;Jy7ZXWrp5p$7(o!zU=dXT7&rS$d|0>=J!CPo zM2Qaye{)`N+A2S0Di5INoF`#S0>o6@qBa1+ zW>3CO;%UZ%!W(i7Bep-L4(MBj4R&B3fP~?JfG8NHK$M9Om0H7;0Tlc{X!vlj<<{s8;i`{gr3^I#JM%|p)ekT3G+b*j zbT?`;@VNi8}mS@tYq zx`53*)Nx(_!CWq_L9_W}A(V52>H!3oJ{9@-1zq~S7}2rq_>dI2^6vTQeVJoa*8x|D z8Dm(n`D0kHXeD&xtpyNP<~jUn-}kV0eHWO)!F2%=Pu9R34wm2r2zFZFx_KP#8-&ak zS{nTo0*n2hc`KM%0LuIuk~+AhV{7N2{4$?kbUnPh_}iB>;IF^UfEgO*Hz)A54PU`E z*R_JNSRRCp3%xtBW%VX>zHrHhz&V)7VG0*of=hSM>N%XWfPNJ(3W~}VW(7d5PX`4* zH?1S98`yDVK#E#+TNB)zf%X@6BT@HWTpZkwUvAul!~2IIOolsKoAB|a-^QG|A1GLZ z;QjdbsmJi>XZ9g$a0$VTyV4>Ot}Ek$VR0D`;*Gpu1)*3la~5Ey^n(AB`R8;4dye@L z{_c0rhv^vD{*NvnLyLVvYH+Q3_D+kUzJpA|_c<1{bf^NK}@Hsozf#>!=gk6uF zmKI<+9A=#>U4g8?$a1+V%b_K9K*L99rMM z5L(W@d;q9CV4MY14PZQ{(aayPeDS@Pmj#prkTx(?7l<+u?)KpKdp?I>Z8}pF1F|U> z!Gx%=HyBHXW_}eQ7nnP$BO6!+CQDGoR7?+!=$ zgiMELEfJ!<0A+%-5eg?llm}2My#3f%B2-Ga=Q$WSzZ>nVeu`I)rJ%#-Wz)RwbSv=UG0uM^L& z{|W9de}UOAVg6ENndWQt0Avo($w1p-vVdSMfa1X89o=ATE_%*AjForo!`2tOBLO&e zH%=Z|haY|8d6=#MbPkO+K>0mD*5pOI!HG6PG{}r>h7Q`Tz!hU|Xyp8wU_4L` zb4`IdOURs`YJ#-?S2G{34$pW|GzcJ=5K%WMSQVzy7!^lGlNu6&L3hYHm=qt&15m|K z!}37Y;cy)=Zg@rFgB_z1Ge42}SHB8G0ib*!SR16K2$jbO0yRVQq=r#jLkfTsn0@+R zSRRH|WS^mt=MCEbS85*`U)VoZApx3-WR2Y{2?-d#%G~=oS zu3BV8OC7B~fzHq*8zO4tDKCR%0no!>kDyd5kyv#lhCHMrdV@7?iPaWBlq)C* zI~ES!GD1 z4Um7A@}#K;h12~MO+E~vDgZ@p5VQiiFLg?Up3%91@TE?MDADqNOrP+YxWG67VF*zm zqU&Uno&AQD0ph#-t82o)Zco2c765#MP6P!d8oHdONM{vQuY26bJrM`bIS j+$-X+bR{4zr_cNk&|4Xr+8nbg00000NkvXXu0mjfrs`N- literal 0 HcmV?d00001 diff --git a/public/icons/work/tomoto_gt.png b/public/icons/work/tomoto_gt.png new file mode 100644 index 0000000000000000000000000000000000000000..046b4054a77f1404ec4f293d4c8f5a10736da6bc GIT binary patch literal 321 zcmV-H0lxl;P)Px#`$#7X4?G8?h<2s zBDn@&-ON5aEv0k^U_f%qd;j(mo`Ox&6m8o+0N4buVP@}rCu2#+0QN!%FAI*H&_Apt z4V-g3-uu_y`BKu5?Pd;I0+%d{{vG>SCY<`ZgsXC0EZ;Ems-xs-|<@jVvIG(gFgeXYUI8FX!o%V T`*{&-00000NkvXXu0mjf2W*QK literal 0 HcmV?d00001 diff --git a/src/layout/adder/WidgetAdder.tsx b/src/layout/adder/WidgetAdder.tsx index 6497d1b..5aef44b 100644 --- a/src/layout/adder/WidgetAdder.tsx +++ b/src/layout/adder/WidgetAdder.tsx @@ -33,7 +33,7 @@ export const WidgetItem = defineComponent({ >
@@ -119,12 +119,19 @@ export const WidgetItem = defineComponent({ }) export default defineComponent(() => { + const layout = useLayoutStore() return () => (
- {widgetList.map((el) => ( - - ))} + { + layout.state.current !== 1 ? + widgetList.filter(val => val.name !== 'tomato_work').map((el) => ( + + )) : + widgetList.map((el) => ( + + )) + }
) diff --git a/src/layout/grid/TomatoPage.tsx b/src/layout/grid/TomatoPage.tsx index fb6bd0b..6601cd9 100644 --- a/src/layout/grid/TomatoPage.tsx +++ b/src/layout/grid/TomatoPage.tsx @@ -1,9 +1,9 @@ import { computed, defineComponent, onMounted, ref, Transition, watch } from 'vue' -import returnImg from "~/public/icons/work/return.png" -import endImg from "~/public/icons/work/tomotoIconEnd.png" -import playWaveGif from "~/public/icons/work/playMusicIcon.gif" -import PlayStartImg from "~/public/icons/work/start.png" -import musicIcon from "~/public/icons/work/musicIcon.png" +import returnImg from "~/icons/work/return.png" +import endImg from "~/icons/work/tomotoIconEnd.png" +import playWaveGif from "~/icons/work/playMusicIcon.gif" +import PlayStartImg from "~/icons/work/start.png" +import musicIcon from "~/icons/work/musicIcon.png" import useBackgroundStore from '../background/useBackgroundStore' import useLayoutStore from '../useLayoutStore' import useTomatoStore, { musicList } from '@/widgets/work/useTomatoStore' @@ -84,8 +84,44 @@ export default defineComponent(() => {
- + { + showSelectModal.value = false + }}> +
+ 音乐选择 +
+ { + musicList.map((item, idx) => ( +
{ + store.state.selectMusic = idx + store.setTrack(idx) + }} + class={"bg-black/[0.05] cursor-pointer rounded-lg text-[#333] text-[14px] py-2 pl-10 border-[1px] relative border-transparent hover:border-[#5955FB]"}> + { + store.state.selectMusic === idx && + + + } + {item.name} +
+ )) + } +
+ +
{ Array.from({ length: 60 }).map((_, idx) => ( @@ -145,10 +181,15 @@ export default defineComponent(() => {
-
+ }} + onClick={() => { + showSelectModal.value = true + }} + > + { store.state.isPlaying ? return @@ -156,8 +197,19 @@ export default defineComponent(() => { return } {musicList[store.state.selectMusic].name} -
- start +
{ + e.stopPropagation() + store.togglePlay() + }} + class={"w-[26px] h-[26px] right-[-14px] rounded-full bg-[#c0c0c0] absolute flex items-center justify-center"}> + { + store.state.isPlaying ? + start + : + start + + }
diff --git a/src/layout/grid/WelcomePage.tsx b/src/layout/grid/WelcomePage.tsx index cb120fa..48d7ac7 100644 --- a/src/layout/grid/WelcomePage.tsx +++ b/src/layout/grid/WelcomePage.tsx @@ -1,7 +1,7 @@ import { computed, defineComponent, onMounted, ref, Transition } from 'vue' -import WelcomeImg from '~/public/icons/welcome/welcomeTitle.png' -import DivBgImg from '~/public/icons/welcome/back.png' -import startUseImg from '~/public/icons/welcome/startUse.png' +import WelcomeImg from '~/icons/welcome/welcomeTitle.png' +import DivBgImg from '~/icons/welcome/back.png' +import startUseImg from '~/icons/welcome/startUse.png' import useBackgroundStore from '../background/useBackgroundStore' import useLayoutStore from '../useLayoutStore' export const DefaultPageSetting = [ diff --git a/src/layout/grid/WidgetBlock.tsx b/src/layout/grid/WidgetBlock.tsx index 6c5d407..eca3ea9 100644 --- a/src/layout/grid/WidgetBlock.tsx +++ b/src/layout/grid/WidgetBlock.tsx @@ -16,7 +16,10 @@ export default defineComponent({ const router = useRouterStore() return () => { const placeholder = ( -
组件维护中
+
{ + e.preventDefault() + menu.open(props.block) + }}>组件维护中
) const selected = widgetList.find((el) => el.name === props.block.name) if (!selected) return placeholder diff --git a/src/settings/SettingsOverlay.tsx b/src/settings/SettingsOverlay.tsx index 4c890f9..693ca31 100644 --- a/src/settings/SettingsOverlay.tsx +++ b/src/settings/SettingsOverlay.tsx @@ -6,7 +6,7 @@ import asyncLoader from '@/utils/asyncLoader' import clsx from 'clsx' import { OhVueIcon } from 'oh-vue-icons' import { computed, defineComponent, Transition } from 'vue' -import SettingLineImg from '~/public/icons/settingLine.png' +import SettingLineImg from '~/icons/settingLine.png' const Content = asyncLoader(() => import('./SettingsOverlayContent')) const SettingsTab = defineComponent({ diff --git a/src/user/LoginModal.tsx b/src/user/LoginModal.tsx index 9720dff..8da06dc 100644 --- a/src/user/LoginModal.tsx +++ b/src/user/LoginModal.tsx @@ -2,9 +2,9 @@ import { defineComponent, onMounted, reactive, ref, Transition, watch } from 'vu import useRouterStore from '@/useRouterStore' import request from '@/utils/request' import useUserStore from './useUserStore' -import Logo from '~/public/logo.png' -import LogoIcon from '~/public/loginIcon.png' -import LogoClose from '~/public/icons/loginClose.png' +import Logo from '~//logo.png' +import LogoIcon from '~//loginIcon.png' +import LogoClose from '~/icons/loginClose.png' import { message, Spin } from 'ant-design-vue' import { v4 as uuid } from 'uuid' import QrCode from 'qrcode' diff --git a/src/widgets/gameVideo/Large.tsx b/src/widgets/gameVideo/Large.tsx index 00b953d..e04724b 100644 --- a/src/widgets/gameVideo/Large.tsx +++ b/src/widgets/gameVideo/Large.tsx @@ -3,6 +3,7 @@ import request from '@/utils/request' import { addIcons, OhVueIcon } from 'oh-vue-icons' import { computed, defineComponent, onMounted, ref, watch, type CSSProperties } from 'vue' import { FaChevronLeft } from 'oh-vue-icons/icons' +import PlayImg from "~/icons/game_video_bg_play.png" import type { CarouselRef } from 'ant-design-vue/es/carousel' import { randomNum } from '@/utils/tool' addIcons(FaChevronLeft) @@ -54,7 +55,9 @@ export default defineComponent(() => { }, 7000) }) return () => ( -
+
+ + {
{ backgroundRepeat: 'no-repeat' }} > +
{
{ e.stopPropagation() - store.beginTomatoTime() - store.openFullscreen = true + if (store.state.isStart) { + store.stopTomatoTime() + } else { + store.beginTomatoTime() + store.openFullscreen = true + + } }}> - start + { + store.state.isStart ? + start + : + start + + }
diff --git a/src/widgets/work/Modal.tsx b/src/widgets/work/Modal.tsx index a8f9cf4..af1732a 100644 --- a/src/widgets/work/Modal.tsx +++ b/src/widgets/work/Modal.tsx @@ -1,11 +1,11 @@ import clsx from 'clsx' import { defineComponent, ref } from 'vue' -import PlusIcon from '~/public/icons/work/tomato_work_add_icon.png' -import DataImg from '~/public/icons/work/dataImg.png' -import DateImg from '~/public/icons/work/dateImg.png' -import ListImg from '~/public/icons/work/listImg.png' -import AddImg from '~/public/icons/work/addTarget.png' -import DownImg from "~/public/icons/work/selectDown1.0.3.png" +import PlusIcon from '~/icons/work/tomato_work_add_icon.png' +import DataImg from '~/icons/work/dataImg.png' +import DateImg from '~/icons/work/dateImg.png' +import ListImg from '~/icons/work/listImg.png' +import AddImg from '~/icons/work/addTarget.png' +import DownImg from "~/icons/work/selectDown1.0.3.png" import { v4 as uuid } from "uuid" import List from './modal_view/list' import { DatePicker, Modal, TimePicker } from 'ant-design-vue' diff --git a/src/widgets/work/Small.tsx b/src/widgets/work/Small.tsx index bf0a763..ff2095a 100644 --- a/src/widgets/work/Small.tsx +++ b/src/widgets/work/Small.tsx @@ -3,12 +3,21 @@ import { defineComponent } from 'vue' export default defineComponent(() => { return () => (
- + +
+
+ 番茄时 +
+ 立即使用 +
+ +
+
+
+
) }) diff --git a/src/widgets/work/index.ts b/src/widgets/work/index.ts index 9be53cf..891fd6d 100644 --- a/src/widgets/work/index.ts +++ b/src/widgets/work/index.ts @@ -2,7 +2,7 @@ import asyncLoader from '@/utils/asyncLoader' import type { Widget } from '..' export default { - name: 'work', + name: 'tomato_work', label: '番茄工作法', description: '番茄记事法', icon: '/tab/icons/work/tomato_work_icon.png', diff --git a/src/widgets/work/modal_view/DataDetail.tsx b/src/widgets/work/modal_view/DataDetail.tsx index 4346713..e4f7ff7 100644 --- a/src/widgets/work/modal_view/DataDetail.tsx +++ b/src/widgets/work/modal_view/DataDetail.tsx @@ -1,4 +1,4 @@ -import { defineComponent, onBeforeUnmount, onMounted, reactive, ref } from "vue"; +import { computed, defineComponent, onBeforeUnmount, onMounted, reactive, ref } from "vue"; // 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。 import * as echarts from 'echarts/core'; import { LineChart, PieChart, } from 'echarts/charts'; @@ -145,12 +145,12 @@ export default defineComponent(() => { }}>
相比昨天 - +300% + {(store.todayHour - store.yestodayHour) >= 0 ? "+" : ''}{(store.todayHour - store.yestodayHour) * 100}%
-
+
今日专注时长 - 0.71 + {(store.todayHour * 0.15).toFixed(2)} h
@@ -176,13 +176,13 @@ export default defineComponent(() => { }}>
相比昨天 - +300% + {(store.todayFinishTarget - store.yesFinishTarget) >= 0 ? "+" : ''}{(store.todayFinishTarget - store.yesFinishTarget) * 100}%
-
- 今日专注时长 - 0.71 - h +
+ 今日完成目标数 + {store.todayFinishTarget} +
diff --git a/src/widgets/work/modal_view/calendar.tsx b/src/widgets/work/modal_view/calendar.tsx index 490689b..6d46ff9 100644 --- a/src/widgets/work/modal_view/calendar.tsx +++ b/src/widgets/work/modal_view/calendar.tsx @@ -1,6 +1,6 @@ import { useCalendarStore } from "@/widgets/calendar/useCalendarStore"; import { DatePicker } from "ant-design-vue"; -import DownImg from "~/public/icons/work/selectDown1.0.3.png" +import DownImg from "~/icons/work/selectDown1.0.3.png" import clsx from "clsx"; import dayjs from "dayjs"; import { defineComponent, ref } from "vue"; diff --git a/src/widgets/work/modal_view/list.tsx b/src/widgets/work/modal_view/list.tsx index 22a90ef..fd3ff17 100644 --- a/src/widgets/work/modal_view/list.tsx +++ b/src/widgets/work/modal_view/list.tsx @@ -1,10 +1,10 @@ import { computed, defineComponent, ref } from 'vue' import useTomatoStore from '../useTomatoStore' -import NoDataImg from "~/public/icons/work/noData.png" -import StopImg from "~/public/icons/work/tomotoIconEnd.png" +import NoDataImg from "~/icons/work/noData.png" +import StopImg from "~/icons/work/tomotoIconEnd.png" import clsx from 'clsx' import dayjs from 'dayjs' -import PlayImg from "~/public/icons/work/work_page-play.png" +import PlayImg from "~/icons/work/work_page-play.png" export default defineComponent(() => { const store = useTomatoStore() const searchText = ref('') diff --git a/src/widgets/work/useTomatoStore.ts b/src/widgets/work/useTomatoStore.ts index 2a31ef0..602d433 100644 --- a/src/widgets/work/useTomatoStore.ts +++ b/src/widgets/work/useTomatoStore.ts @@ -46,21 +46,17 @@ export default defineStore("work", () => { isPlaying: false as boolean, selectMusic: 0, isStart: false as boolean, - beginTime: -1 as number - + beginTime: -1 as number, }) + const audio = new Audio() const time = useTimeStore() const remainingTime = computed(() => { if (!state.isStart) { return 0 } - return dayjs(state.beginTime).add(1, 'minute').diff(dayjs(time.date), 'second') + return dayjs(state.beginTime).add(15, 'minute').diff(dayjs(time.date), 'second') }) - const beginTomatoTime = () => { - state.beginTime = dayjs().valueOf() - state.isStart = true - playMusic() - } + const stopTomatoTime = () => { state.isStart = false state.beginTime = -1 @@ -71,45 +67,65 @@ export default defineStore("work", () => { ) } } - - const playAudio = computed(() => { - const audio = new Audio(musicList[state.selectMusic].music) - return audio - }) - - // watch(() => state.isPlaying, (val) => { - // if (val) { - // playAudio.value.play() - // } else { - // playAudio.value.pause() - - // } - // }) - const playMusic = () => { - state.isPlaying = true - playAudio.value.play() + const togglePlay = () => { + if (state.isPlaying) { + audio.pause() + } else { + audio.play() + } + state.isPlaying = !state.isPlaying } - - const pauseMusic = () => { - state.isPlaying = false - playAudio.value.pause() + const setTrack = (trackIndex: number) => { + state.selectMusic = trackIndex + audio.src = musicList[trackIndex].music + audio.loop = true + audio.load() + if (state.isPlaying) { + audio.play() + } } const stopMusic = () => { + audio.pause() + audio.currentTime = 0 state.isPlaying = false - playAudio.value.pause() - playAudio.value.currentTime = 0 + } + const beginTomatoTime = () => { + state.beginTime = dayjs().valueOf() + state.isStart = true + setTrack(state.selectMusic) + togglePlay() + } const openShowModel = ref() const openFullscreen = ref(false) + const todayHour = computed(() => { + return state.timeList.filter(val => dayjs(val).isSame(dayjs(), 'day')).length + }) + const yestodayHour = computed(() => { + return state.timeList.filter(val => dayjs(val).isSame(dayjs().subtract(1, 'day'), 'day')).length + }) + const todayFinishTarget = computed(() => { + return state.list.filter(val => dayjs(val.finishTime).isSame(dayjs(), 'day') && val.isCompleted).length + }) + const yesFinishTarget = computed(() => { + return state.list.filter(val => dayjs(val.finishTime).isSame(dayjs().subtract(1, 'day'), 'day') && val.isCompleted).length + + }) return { state, openShowModel, openFullscreen, beginTomatoTime, remainingTime, - playMusic, - pauseMusic, + togglePlay, stopMusic, - stopTomatoTime + stopTomatoTime, + todayHour, + yestodayHour, + todayFinishTarget, + yesFinishTarget, + setTrack } +}, { + persist: true }) diff --git a/vite.config.ts b/vite.config.ts index 45b5c4d..01946b1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -31,7 +31,7 @@ export default defineConfig({ resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)), - '~': fileURLToPath(new URL('./', import.meta.url)) + '~': fileURLToPath(new URL('./public', import.meta.url)) } }, build: { From d0ed386313e337adc47ad5bd0ed8cbc18c083d80 Mon Sep 17 00:00:00 2001 From: expdsn <18111002318@163.com> Date: Tue, 5 Nov 2024 17:56:40 +0800 Subject: [PATCH 3/8] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=BB=8F=E5=85=B8?= =?UTF-8?q?=E5=8D=B3=E7=8E=A9=E5=B0=8F=E6=B8=B8=E6=88=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/classicPlay.png | Bin 0 -> 53460 bytes src/App.vue | 2 +- src/layout/adder/GameAdder.tsx | 69 ++++----- src/layout/grid/TomatoPage.tsx | 31 ++-- src/layout/header/search/SearchConfig.tsx | 2 +- src/layout/header/search/SearchHistory.tsx | 2 +- src/widgets/game/Large.tsx | 162 ++++++++++++++++++++- src/widgets/game/Middle.tsx | 10 -- src/widgets/game/Modal.tsx | 12 -- src/widgets/game/Small.tsx | 14 -- src/widgets/game/index.ts | 20 +-- src/widgets/index.ts | 3 +- src/widgets/work/index.ts | 13 +- 13 files changed, 229 insertions(+), 111 deletions(-) create mode 100644 public/icons/classicPlay.png delete mode 100644 src/widgets/game/Middle.tsx delete mode 100644 src/widgets/game/Modal.tsx delete mode 100644 src/widgets/game/Small.tsx diff --git a/public/icons/classicPlay.png b/public/icons/classicPlay.png new file mode 100644 index 0000000000000000000000000000000000000000..d801928c9805328d0f3ff48a6409148c0cbac857 GIT binary patch literal 53460 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 literal 0 HcmV?d00001 diff --git a/src/App.vue b/src/App.vue index ae94a70..732fce1 100644 --- a/src/App.vue +++ b/src/App.vue @@ -34,7 +34,7 @@ const layout = useLayoutStore() - +

diff --git a/src/layout/adder/GameAdder.tsx b/src/layout/adder/GameAdder.tsx index ba7b19c..3bcc421 100644 --- a/src/layout/adder/GameAdder.tsx +++ b/src/layout/adder/GameAdder.tsx @@ -1,6 +1,6 @@ import CategoryTab from '@/utils/CategoryTab' import request from '@/utils/request' -import { computed, defineComponent, inject, ref, watch } from 'vue' +import { computed, defineComponent, inject, ref, watch } from 'vue' import clsx from 'clsx' import useLayoutStore from '../useLayoutStore' import { AddToToken } from './AdderPage' @@ -9,9 +9,9 @@ import { frontAddress, ossBase } from '@/config' import dayjs from 'dayjs' import { generateRandomString } from '@/utils/tool' import MD5 from 'crypto-js/md5' -const SECRET = 'A1Cv12olxT12dOE3xA1vPA==' -const URL_ADDRESS = 'http://newfatfox.oss-cn-beijing.aliyuncs.com' -interface GameType { +export const SECRET = 'A1Cv12olxT12dOE3xA1vPA==' +export const URL_ADDRESS = 'http://newfatfox.oss-cn-beijing.aliyuncs.com' +export interface GameType { id: string name: string rom: string @@ -21,7 +21,7 @@ interface GameType { despt: string icon: string } -interface OtherGame { +export interface OtherGame { id: number // 游戏ID category_ids: number[] // 分类ID数组 rank: number // 排名 @@ -33,6 +33,32 @@ interface OtherGame { cover_url: string // 封面URL corner_mark: number // 角标标识 } +export const DefautGameTypeList = [ + { + id: 'fc', + type: '经典红白机', + attr: 0, + oridinal: 0 + }, + { + id: 'md', + type: '经典世嘉', + attr: 1, + oridinal: 1 + }, + { + id: 'yiqiyoo', + type: '休闲游戏', + attr: 1, + oridinal: 2 + }, + { + id: 'gba', + type: '经典GBA', + attr: 3, + oridinal: 3 + } +] export const GameItem = defineComponent({ props: { content: { @@ -100,9 +126,9 @@ export const GameItem = defineComponent({ id: uuid(), link: !props.content.rom.startsWith('http') ? `${frontAddress}/emu/#/home?params=${JSON.stringify({ - ...props.content, - rom: ossBase + '/' + props.content.rom - })}` + ...props.content, + rom: ossBase + '/' + props.content.rom + })}` : props.content.rom, name: '', label: props.content.name, @@ -188,32 +214,7 @@ export default defineComponent(() => {
{ selectType.value = e diff --git a/src/layout/grid/TomatoPage.tsx b/src/layout/grid/TomatoPage.tsx index 6601cd9..0b658d9 100644 --- a/src/layout/grid/TomatoPage.tsx +++ b/src/layout/grid/TomatoPage.tsx @@ -10,6 +10,7 @@ import useTomatoStore, { musicList } from '@/widgets/work/useTomatoStore' import Search from '../header/search' import { Modal, Tooltip } from 'ant-design-vue' import { formatSeconds } from '@/utils/tool' +import clsx from 'clsx' export const DefaultPageSetting = [ { name: '游戏', @@ -55,7 +56,6 @@ export default defineComponent(() => { watch(() => store.remainingTime , (val) => { - console.log(val); if (val <= 0) { store.stopTomatoTime() @@ -123,28 +123,33 @@ export default defineComponent(() => { }}>确定
- { - Array.from({ length: 60 }).map((_, idx) => ( -
+ { + Array.from({ length: 60 }).map((_, idx) => ( +
= idx) ? "bg-white" : "bg-white/50" + )} style={{ + transformOrigin: '250px', + borderRadius: '3px', + transform: `rotateZ(${idx * 6}deg)` - }}> + }}> + +
+ )) + } +
-
- )) - }
专注中 {!store.state.isStart ? '15:00' : formatSeconds(store.remainingTime)}
-
+
-
+
{ diff --git a/src/layout/header/search/SearchConfig.tsx b/src/layout/header/search/SearchConfig.tsx index 736fa07..9577b14 100644 --- a/src/layout/header/search/SearchConfig.tsx +++ b/src/layout/header/search/SearchConfig.tsx @@ -14,7 +14,7 @@ export default defineComponent({ const router = useRouterStore() return () => (
{ search.showSearchConfig = false }} diff --git a/src/layout/header/search/SearchHistory.tsx b/src/layout/header/search/SearchHistory.tsx index bca4c44..01239dc 100644 --- a/src/layout/header/search/SearchHistory.tsx +++ b/src/layout/header/search/SearchHistory.tsx @@ -11,7 +11,7 @@ export default defineComponent(() => { const settings = useSettingsStore() return () => settings.state.showHistory && ( -
+
{searchConfig.history.map((item, idx) => (
{ + const selectType = ref('fc') + const appList = ref([]) + const hoverId = ref(0) + const loading = ref(false) + const fetchGame = async (page: number) => { + const parems = `nonce=${generateRandomString(8)}&pid=PIDc8uT24mpo×tamp=${dayjs().unix()}` + const sign = MD5(parems + SECRET).toString() + const response = await fetch( + `https://ge.yiqiyoo.com/game/v2/third-part/games?${parems}&sign=${sign}&paginate.limit=99&paginate.page=${page}` + ) + const res = await response.json() + return res.data.items + } + watch( + selectType, + (val) => { + console.log(val); + appList.value = [] + loading.value = true + + if (val !== 'yiqiyoo') { + request('GET', `/api/games?type=${val}`) + .then((res) => { + appList.value = res + }) + .finally(() => { + loading.value = false + }) + } else { + try { + Promise.all([fetchGame(1)]).then((res) => { + const resData = res.flat() as OtherGame[] + appList.value = resData.map((el) => ({ + id: el.id.toString(), + name: el.name, + despt: el.short_description, + icon: el.icon, + rom: el.url, + playstation: el.url, + hot: el.rank, + category: el.category_ids[0].toString() + })) + }) + } catch (err) { + console.error(err) + } finally { + loading.value = false + } + } + }, + { + immediate: true + } + ) return () => ( -
- large +
{ + + }} + > +
+
+
+ { + DefautGameTypeList.map(item => ( +
{ + selectType.value = item.id + }} + class={clsx("flex items-center jusitfy-center relative py-4 text-[13px]", + selectType.value === item.id ? "text-[#589fff]" : " text-[#589fffcc]" + )} > + {item.type} + { + selectType.value === item.id && +
+ } +
+ )) + } +
+ 查看更多 + +
+ { + !loading.value && + +
+
+ { + appList.value.filter((_, index) => index < 10).map((item, idx) => ( +
{ + hoverId.value = idx + }} + style={{ + background: hoverId.value === idx ? "rgba(61,80,105,.8)" : "transparent" + }}> +
{idx + 1}
+
+ { + hoverId.value === idx ? +
+
+ +
+ {item.name} + {item.despt} + +
+
+ +
: +
+ {item.name} + {item.despt} + +
+ } + +
+
+ )) + } +
+
+ } +
) }) diff --git a/src/widgets/game/Middle.tsx b/src/widgets/game/Middle.tsx deleted file mode 100644 index 53edc23..0000000 --- a/src/widgets/game/Middle.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { defineComponent } from 'vue' - -export default defineComponent(() => { - - return () => ( -
- middle -
- ) -}) diff --git a/src/widgets/game/Modal.tsx b/src/widgets/game/Modal.tsx deleted file mode 100644 index 9890740..0000000 --- a/src/widgets/game/Modal.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { defineComponent } from 'vue' - -export default defineComponent(() => { - return () => ( -
- ) -}) diff --git a/src/widgets/game/Small.tsx b/src/widgets/game/Small.tsx deleted file mode 100644 index bf0a763..0000000 --- a/src/widgets/game/Small.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { defineComponent } from 'vue' - -export default defineComponent(() => { - return () => ( -
- -
- ) -}) diff --git a/src/widgets/game/index.ts b/src/widgets/game/index.ts index 5f92e14..6cd4ee7 100644 --- a/src/widgets/game/index.ts +++ b/src/widgets/game/index.ts @@ -3,23 +3,11 @@ import type { Widget } from '..' export default { name: 'gameNews', - label: '游戏资讯', - description: '游戏资讯', - icon: '/tab/icons/game_news_icon.png', - modal: asyncLoader(() => import('./Modal')), + label: '经典即玩游戏', + description: '经典即玩游戏', + icon: '/tab/icons/classicPlay.png', + modal: null, list: [ - { - w: 2, - h: 1, - label: '小', - component: asyncLoader(() => import('./Small')) - }, - { - w: 2, - h: 2, - label: '中', - component: asyncLoader(() => import('./Middle')) - }, { w: 4, h: 2, diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 88d59c7..3cb7e39 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -9,6 +9,7 @@ import hotspot from './hotspot' import constellation from './constellation' import gameVideo from './gameVideo' import work from './work' +import game from './game' export interface Widget { name: string // 小组件类型唯一标识 label: string // 小组件名称 @@ -23,4 +24,4 @@ export interface Widget { }[] // 不同尺寸小组件块 } -export default [calendar, weather, weApply, gameNews, eat, discount, hotspot, constellation, gameVideo, work] as Widget[] +export default [game, calendar, weather, weApply, gameNews, eat, discount, hotspot, constellation, gameVideo, work] as Widget[] diff --git a/src/widgets/work/index.ts b/src/widgets/work/index.ts index 891fd6d..f3394fa 100644 --- a/src/widgets/work/index.ts +++ b/src/widgets/work/index.ts @@ -8,17 +8,18 @@ export default { icon: '/tab/icons/work/tomato_work_icon.png', modal: asyncLoader(() => import('./Modal')), list: [ + { + w: 4, + h: 2, + label: '大', + component: asyncLoader(() => import('./Large')) + }, { w: 2, h: 1, label: '小', component: asyncLoader(() => import('./Small')) }, - { - w: 4, - h: 2, - label: '大', - component: asyncLoader(() => import('./Large')) - } + ] } as Widget From 847f1df785ff015c4e1ed8e071c7eb38222619f7 Mon Sep 17 00:00:00 2001 From: expdsn <18111002318@163.com> Date: Tue, 5 Nov 2024 19:26:59 +0800 Subject: [PATCH 4/8] =?UTF-8?q?=E6=94=B9=E5=8F=98adderpage=E7=9A=84?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/adder/AdderPage.tsx | 31 ++++++++++++++------------ src/layout/adder/useAdderPageStore.tsx | 9 ++++++++ src/widgets/game/Large.tsx | 11 +++++++-- 3 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 src/layout/adder/useAdderPageStore.tsx diff --git a/src/layout/adder/AdderPage.tsx b/src/layout/adder/AdderPage.tsx index a8f2206..20feba2 100644 --- a/src/layout/adder/AdderPage.tsx +++ b/src/layout/adder/AdderPage.tsx @@ -1,4 +1,4 @@ -import { computed, defineComponent, provide, ref, type InjectionKey, type Ref } from 'vue' +import { computed, defineComponent, inject, onMounted, onUnmounted, provide, ref, type InjectionKey, type Ref } from 'vue' import useLayoutStore from '../useLayoutStore' import { OhVueIcon, addIcons } from 'oh-vue-icons' import { @@ -15,6 +15,7 @@ import { Form, Input, Select } from 'ant-design-vue' import HotAdder from './HotAdder' import GameAdder from './GameAdder' import work_add_main_checked from '/tab/icons/work_add_main_checked.png' +import useAdderPageStore from './useAdderPageStore' addIcons(MdKeyboardcommandkey, FaCompass, FaPencilRuler, IoGameController) const ItemButton = defineComponent({ @@ -67,13 +68,15 @@ const ItemButton = defineComponent({ }) export const AddToToken = Symbol('addTo') as InjectionKey> - export default defineComponent(() => { const layout = useLayoutStore() const isGame = computed(() => layout.state.current === 0) - const type = ref(1) + const store = useAdderPageStore() const addTo = ref(layout.state.currentPage) provide(AddToToken, addTo) + onUnmounted(()=> { + store.type = 1 + }) return () => (
{ { - type.value = 0 + store.type = 0 }} /> { - type.value = 1 + store.type = 1 }} /> { - type.value = 2 + store.type = 2 }} /> { - type.value = 3 + store.type = 3 }} />
@@ -146,11 +149,11 @@ export default defineComponent(() => { { From 4446ba375943c4323265130a0df7f8a9800584f9 Mon Sep 17 00:00:00 2001 From: expdsn <18111002318@163.com> Date: Tue, 5 Nov 2024 19:37:30 +0800 Subject: [PATCH 5/8] clear --- src/layout/adder/AdderPage.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/layout/adder/AdderPage.tsx b/src/layout/adder/AdderPage.tsx index 20feba2..66f669b 100644 --- a/src/layout/adder/AdderPage.tsx +++ b/src/layout/adder/AdderPage.tsx @@ -83,10 +83,6 @@ export default defineComponent(() => { 'w-full h-full relative flex ', isGame.value ? 'bg-[#2C2E3D]' : 'bg-[#fffc] backdrop-blur' )} - // style={{ - // backgroundImage: `url('/tab/bg/gameModel.png')`, - // backgroundSize: '100% 100%' - // }} >
Date: Thu, 7 Nov 2024 18:48:45 +0800 Subject: [PATCH 6/8] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=86=E7=AC=94?= =?UTF-8?q?=E8=AE=A1=E6=9C=AC=E7=9A=84=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 9 ++ public/icons/notepad/decorative.png | Bin 0 -> 2020 bytes public/icons/notepad/delete.png | Bin 0 -> 440 bytes public/icons/notepad/note_pad_line.png | Bin 0 -> 3800 bytes public/icons/notepad/top.png | Bin 0 -> 634 bytes src/layout/grid/BlockWrapper.tsx | 2 +- src/layout/grid/TomatoPage.tsx | 7 -- src/main.css | 42 ++++++++ src/utils/CategoryTab.tsx | 1 - src/widgets/index.ts | 3 +- src/widgets/notepad/Large.tsx | 29 +++++ src/widgets/notepad/Middle.tsx | 21 ++++ src/widgets/notepad/Modal.tsx | 138 ++++++++++++++++++++++++ src/widgets/notepad/Small.tsx | 22 ++++ src/widgets/notepad/editor.tsx | 72 +++++++++++++ src/widgets/notepad/index.ts | 30 ++++++ src/widgets/notepad/useNotepadStore.tsx | 137 +++++++++++++++++++++++ src/widgets/work/useTomatoStore.ts | 9 +- tailwind.config.cjs | 12 +++ tailwind.config.js | 10 -- 20 files changed, 523 insertions(+), 21 deletions(-) create mode 100644 public/icons/notepad/decorative.png create mode 100644 public/icons/notepad/delete.png create mode 100644 public/icons/notepad/note_pad_line.png create mode 100644 public/icons/notepad/top.png create mode 100644 src/widgets/notepad/Large.tsx create mode 100644 src/widgets/notepad/Middle.tsx create mode 100644 src/widgets/notepad/Modal.tsx create mode 100644 src/widgets/notepad/Small.tsx create mode 100644 src/widgets/notepad/editor.tsx create mode 100644 src/widgets/notepad/index.ts create mode 100644 src/widgets/notepad/useNotepadStore.tsx create mode 100644 tailwind.config.cjs delete mode 100644 tailwind.config.js diff --git a/package.json b/package.json index ad633e6..34d375e 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,16 @@ "dependencies": { "@ant-design/icons-vue": "^7.0.1", "@fingerprintjs/fingerprintjs": "^4.4.3", + "@milkdown-lab/plugin-menu": "^1.3.1", + "@milkdown/kit": "7.5.0", + "@milkdown/plugin-menu": "^6.5.4", + "@milkdown/plugin-prism": "^7.5.0", + "@milkdown/plugin-tooltip": "^7.5.3", + "@milkdown/theme-nord": "7.5.0", + "@milkdown/vue": "7.5.0", "@pixi/spine-pixi": "^2.1.0", + "@tailwindcss/typography": "^0.5.9", + "@type-config/strict": "^1.2.1", "ali-oss": "^6.21.0", "ant-design-vue": "4.x", "clsx": "^2.1.1", diff --git a/public/icons/notepad/decorative.png b/public/icons/notepad/decorative.png new file mode 100644 index 0000000000000000000000000000000000000000..0551513f8933d58d8ce21996ea464cb0e319f02f GIT binary patch literal 2020 zcmeH|`#Tc~7{|ACNV%qqvDxXMP8ZE(nM*U|kj6-bbaO0eK7+l{ zZ$wgczR+XCXebxI5S)bVguqFMBJX!=SE=>L@ApBqx`z{B_ZdZr7tvw%16|(_6!UG| zJz};V+{L(TQ`KyC!|99#YjH#TM-%VBCDU8o({KHnFt9C)BkC(SsjYMW+* zQ9#i97zcn9`kDoU8tMSVh(yy_INm(#sKu;l1E%XdaeQ~QNvE}Wd~jI3ILeapK5**D zQOl$*DZ^+zBw8<~Fq}Dcs!4r-bB$Qv*midRigTc23SQEKu@Io+0nOm>$sHoM2b~-1 zeymMuT)kIs3=dM7vs-WPWeYoyvEh5Sf<9V7M|ME zlRS4mxQy|tl}$JEdZI056-bytQ1Fq-h2dB*e359sacowIHVl$2qyP|bf2Dm<{W`6C zeezU77I0dlaPmWh4A%LnezCH>Lw>X8{ftL@OE^hWdx-pgRz;fDORQbZ&$x7@`dq4P zOyQKtAI{^)?GipM$)~=%ARp!PHA|@za^BiRZ!b9>D?1vri;y{mXzC{?k7voo(h#-N zw7KFjH?@6CARyZ`UHEuTvhFDPb82nPYxeC>dss^tRPEhU4)+PCE3~XT9f)EiOO|1) z$mMDY3r;zAT@b}aii$hJ;ry`U9w<1Lb(gdrzATXg9pO<4Ed(-B};BmtCWI+2OO6FJ{-!2bST%DRBbq^g%>x zD8=r$_X9jRu@BT~jpQO*g{?$$oL;lTyU+R=2qYtG#RO%^>91kWkxI}+c8*)kvgke9 z2vrKjkJK%PN*XtOadd8{7B8dp6@kjsfv?{|oLgSWcx+gUc zgL@{L5b<>Hoz5 literal 0 HcmV?d00001 diff --git a/public/icons/notepad/delete.png b/public/icons/notepad/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..9bf9ab249c84871e06fd7c1bb1fbcbe488a01198 GIT binary patch literal 440 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU1|)m_?Z^dEjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(TE3f@ot-6T z9Nm|_joDZGXqHmm!FSo#v>z+CG5-Xe6#~x{xMf7^e`^V z+j*`>kwYZmpc;p0@*!pSbs{I{EpAmlQEC%b+kCGvBGy*R!-+#+u5{y0sqA;k2lYgj z9*FUta<|!zx6evIHSXkto;C%^#ES{9t^unVmtEB~YdF`5tzy s*#EzeuUC4swP%$KZ{tM)iCc;c3=(@ZUH(32&jE#+r>mdKI;Vst00B~xV*mgE literal 0 HcmV?d00001 diff --git a/public/icons/notepad/note_pad_line.png b/public/icons/notepad/note_pad_line.png new file mode 100644 index 0000000000000000000000000000000000000000..a4293b72117f27617d5e88041874d5396f51d978 GIT binary patch literal 3800 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 CgY^pl literal 0 HcmV?d00001 diff --git a/src/layout/grid/BlockWrapper.tsx b/src/layout/grid/BlockWrapper.tsx index c908564..c6cd991 100644 --- a/src/layout/grid/BlockWrapper.tsx +++ b/src/layout/grid/BlockWrapper.tsx @@ -22,7 +22,7 @@ export default defineComponent({ setup(props) { const settings = useSettingsStore() const layout = useLayoutStore() - let it = 0 + let it: any = 0 const hover = ref(false) return () => (
{ // 设置标记,后续访问不会再次显示 } }) - watch(() => - store.remainingTime - , (val) => { - if (val <= 0) { - store.stopTomatoTime() - } - }) return () => store.openFullscreen && (
diff --git a/src/main.css b/src/main.css index c2c8c63..3ef721b 100644 --- a/src/main.css +++ b/src/main.css @@ -2,6 +2,48 @@ @tailwind components; @tailwind utilities; +.milkdown { + @apply bg-slate-50 p-3 border rounded; + + width: 100%; + height: calc(100% - 18px); + border-radius: 12px 12px 20px 20px; + background: rgba(189, 171, 155, 0.1) !important; + border: none !important; + box-shadow: 0 0 #fff !important; + color: #333 !important; + box-sizing: border-box; + overflow-y: auto; + position: relative; + padding-top: 80px; +} +.milkdown-menu { + position: absolute; + left: 0; + top: 0; + right: 0; + overflow: hidden; + border-radius: 12px 12px 0 0 !important; + padding: 0; + background-color: rgba(215, 203, 185, 0.4) !important; + border: none !important; + outline: none; + margin-bottom: 10px; +} +.milkdown ul { + margin: 0; + border: none; +} +.milkdown-menu ul li { + margin: 0; + padding: 0; +} +.milkdown-menu button { + color: #bca694 !important; + font-weight: bold; + padding-top: 5px !important; + padding-bottom: 5px !important; +} :root { text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; diff --git a/src/utils/CategoryTab.tsx b/src/utils/CategoryTab.tsx index 788edeb..05f8d52 100644 --- a/src/utils/CategoryTab.tsx +++ b/src/utils/CategoryTab.tsx @@ -35,7 +35,6 @@ export default defineComponent({ }) watch(number, (n, old) => { - console.log(Math.abs(n - old) / 400) gsap.to(tweened, { number: n, diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 3cb7e39..aae30f9 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -10,6 +10,7 @@ import constellation from './constellation' import gameVideo from './gameVideo' import work from './work' import game from './game' +import notepad from './notepad' export interface Widget { name: string // 小组件类型唯一标识 label: string // 小组件名称 @@ -24,4 +25,4 @@ export interface Widget { }[] // 不同尺寸小组件块 } -export default [game, calendar, weather, weApply, gameNews, eat, discount, hotspot, constellation, gameVideo, work] as Widget[] +export default [game, calendar, weather, weApply, gameNews, eat, discount, hotspot, constellation, gameVideo, work, notepad] as Widget[] diff --git a/src/widgets/notepad/Large.tsx b/src/widgets/notepad/Large.tsx new file mode 100644 index 0000000..0d5747b --- /dev/null +++ b/src/widgets/notepad/Large.tsx @@ -0,0 +1,29 @@ +import { defineComponent } from 'vue' +import useNotepadStore from './useNotepadStore' + +export default defineComponent(() => { + const store = useNotepadStore() + + return () => ( +
+
+ + 记事本 + +
+
+
+ 欢迎使用记事本 + +
+ { + store.state.list.filter((_, idx) => idx < 4).map(item => ( +
+
{item.title || '新建笔记'}
+
+ )) + } +
+
+ ) +}) diff --git a/src/widgets/notepad/Middle.tsx b/src/widgets/notepad/Middle.tsx new file mode 100644 index 0000000..9a87f45 --- /dev/null +++ b/src/widgets/notepad/Middle.tsx @@ -0,0 +1,21 @@ +import { defineComponent } from 'vue' +import useNotepadStore from './useNotepadStore' + +export default defineComponent(() => { + const store = useNotepadStore() + return () => ( +
+
+ 欢迎使用记事本 + +
+ { + store.state.list.filter((_, idx) => idx < 4).map(item => ( +
+
{item.title || '新建笔记'}
+
+ )) + } +
+ ) +}) diff --git a/src/widgets/notepad/Modal.tsx b/src/widgets/notepad/Modal.tsx new file mode 100644 index 0000000..963eca9 --- /dev/null +++ b/src/widgets/notepad/Modal.tsx @@ -0,0 +1,138 @@ +import { addIcons, OhVueIcon } from 'oh-vue-icons' +import { computed, defineComponent, onMounted, ref } from 'vue' +import decorativeImg from "~/icons/notepad/decorative.png" +import { HiSearch } from "oh-vue-icons/icons"; +import useNotepadStore from './useNotepadStore'; +import dayjs from 'dayjs'; +import clsx from 'clsx'; +import Editor from './editor'; +import "@milkdown/theme-nord/style.css" +import "@milkdown-lab/plugin-menu/style.css" +import { MilkdownProvider } from '@milkdown/vue'; +addIcons(HiSearch) +export default defineComponent(() => { + const store = useNotepadStore() + const selectId = ref(store.state.list[0]?.id || '') + const trriger = ref(true) + const searchWorks = ref('') + const currentIndex = computed(() => { + trriger.value = false + setTimeout(() => { + trriger.value = true + }, 0) + return store.state.list.findIndex(val => val.id === selectId.value) + }) + const showList = computed(() => { + return store.state.list.map(val => val).sort(a => a.pin ? -1 : 1) + }) + return () => ( +
+
+
+
+ { + searchWorks.value = e.target.value + }} + placeholder='输入内容' + class={"w-full outline-none h-full pl-2 pr-8 border-[1px] border-[#ddd] rounded-lg text-[#333] placeholder:text-[#C5C5C5]"} /> + +
+ +
+
+
+ { + showList.value.filter(val => val.content.includes(searchWorks.value)).map((item) => ( +
{ + selectId.value = item.id + }} + class={clsx("flex justify-between w-full cursor-pointer h-[66px] p-2 pl-3 rounded-lg group ", + selectId.value === item.id ? "bg-[#c7ad9666]" : "bg-[#bdab9b33]" + )}> +
+ {item.title || '新建笔记'} + {dayjs(item.date).format('YYYY-MM-DD')} +
+
+ { + item.pin = !item.pin + + } + + } + src='/tab/icons/notepad/top.png' alt='top' class={clsx("w-[22px]", item.pin ? "" : "hidden opacity-70 group-hover:block")}> + { + const idx = store.state.list.findIndex(val => val.id === item.id) + if (idx !== -1) { + store.state.list.splice(idx, 1) + // if (index === showList.value.length - 1) { + // selectId.value = showList.value[index - 2]?.id || '' + // } else { + // selectId.value = showList.value[index + 1]?.id || '' + // } + // selectId.value = showList.value[index - 1 > 0 ? index - 1 : (showList.value.length - 1)]?.id || '' + } + + }} + src='/tab/icons/notepad/delete.png' alt='delete' class={"hidden group-hover:block w-[22px] opacity-70"}> +
+
+ )) + } +
+
+
+
+
+ + decorativeImg +
+ { + if (store.state.list[currentIndex.value]) { + store.state.list[currentIndex.value].title = e.target.value + } + }} + type="text" class={"w-full border-b-[1px] pb-[3px] border-b-[#bdab9b] outline-none "} + value={store.state.list[currentIndex.value]?.title || ''} /> +
+ { + trriger.value && + + { + if (store.state.list[currentIndex.value]) { + store.state.list[currentIndex.value].content = e + } + }}> + + } + + + +
+ +
+ + +
+ +
+
+ ) +}) diff --git a/src/widgets/notepad/Small.tsx b/src/widgets/notepad/Small.tsx new file mode 100644 index 0000000..c8c7454 --- /dev/null +++ b/src/widgets/notepad/Small.tsx @@ -0,0 +1,22 @@ +import { defineComponent } from 'vue' + +export default defineComponent(() => { + return () => ( +
+ +
+
+ 记事本 +
+ 立即创建 +
+ 》 +
+
+
+
+
+ ) +}) diff --git a/src/widgets/notepad/editor.tsx b/src/widgets/notepad/editor.tsx new file mode 100644 index 0000000..a54869a --- /dev/null +++ b/src/widgets/notepad/editor.tsx @@ -0,0 +1,72 @@ +import { Milkdown, useEditor } from '@milkdown/vue'; +import { defaultValueCtx, Editor, rootCtx } from '@milkdown/kit/core'; +import { nord } from '@milkdown/theme-nord' +import { commonmark } from '@milkdown/kit/preset/commonmark' +import { gfm } from '@milkdown/kit/preset/gfm'; +import { defineComponent, watch} from 'vue'; +import { menu, menuConfigCtx, type MenuConfigItem } from '@milkdown-lab/plugin-menu' +import { listener, listenerCtx } from '@milkdown/kit/plugin/listener'; + + +const menuItems: MenuConfigItem[][] = [ + [ + { + type: 'button', + content: 'B', + // commandKey + key: 'ToggleStrong', + }, + { + type: 'button', + content: 'I', + key: 'ToggleEmphasis', + }, + { + type: 'button', + content: 'S', + key: 'ToggleStrikeThrough', + }, + ], +] +export default defineComponent({ + props: { + modelValue: { + type: String, + default: '', + } + }, + emits: ['update:modelValue'], + setup: (props, ct) => { + + useEditor((root) => { + return Editor.make() + .config(nord) + .config((ctx) => { + const listener = ctx.get(listenerCtx); + ctx.set(menuConfigCtx.key, { + attributes: { class: 'milkdown-menu', 'data-menu': 'true' }, + items: menuItems, + }) + ctx.set(rootCtx, document.querySelector('#app')) + listener.markdownUpdated((ctx, markdown, prevMarkdown) => { + if (markdown !== prevMarkdown) { + ct.emit('update:modelValue', markdown) + } + }) + ctx.set(rootCtx, root) + ctx.set(defaultValueCtx, props.modelValue || ' ') + }) + .use(listener) + .use(commonmark) + .use(gfm) + .use(menu) + + + }) + return () => ( + + + ) + } +}) + diff --git a/src/widgets/notepad/index.ts b/src/widgets/notepad/index.ts new file mode 100644 index 0000000..7758f9f --- /dev/null +++ b/src/widgets/notepad/index.ts @@ -0,0 +1,30 @@ +import asyncLoader from '@/utils/asyncLoader' +import type { Widget } from '..' + +export default { + name: 'notepad', + label: '记事本', + description: '记事本', + icon: '/tab/icons/note_pad_icon.png', + modal: asyncLoader(() => import('./Modal')), + list: [ + { + w: 2, + h: 1, + label: '小', + component: asyncLoader(() => import('./Small')) + }, + { + w: 2, + h: 2, + label: '中', + component: asyncLoader(() => import('./Middle')) + }, + { + w: 4, + h: 2, + label: '大', + component: asyncLoader(() => import('./Large')) + } + ] +} as Widget diff --git a/src/widgets/notepad/useNotepadStore.tsx b/src/widgets/notepad/useNotepadStore.tsx new file mode 100644 index 0000000..d35d1c0 --- /dev/null +++ b/src/widgets/notepad/useNotepadStore.tsx @@ -0,0 +1,137 @@ +import { defineStore } from "pinia"; +import { reactive } from "vue"; +import { v4 as uuid } from "uuid" +import dayjs from "dayjs"; +export const DEFALUT_DATA = { + content: ` +欢迎来到FatfoxTab新标签页平台!在这里您将发现海量有趣的内容和实用的工具。 + + +为了让您有更好的体验,我们为您提供了这个新手引导。接下来,让我们一起了解如何更好的使用我们的平台。 + +## **1. 功能模块** + +我们的产品有多个功能模块,每个模块都有不同的功能。以下是一些常用的功能模块: + + +编辑主页:右键点击桌面空白处可快速编辑主页 添加网址导航及功能组件,更换壁纸等。 + +左侧栏添加:左侧栏下方点击【添加】即可编辑自己常用分类工具栏。 + +消息反馈:可以在反馈模块中查看您的收件箱和发件箱,及对产品提出的改进建议及BUG反馈。 + +设置:在左侧栏下方设置内均可以对页面展示样式进行个性化调整。 + +快捷键设置:鼠标拉动网址导航-放置对应快捷键-点击对应快捷键既可跳转网址。 + +页面底部快捷介绍:为了符合用户的体验操作,产品设置了快捷键点击跳转网页。 + + +## **2. 模式切换** + +FatfoxTab新标签页共分为四个模式; + +工作/游戏/轻娱/极简 + +鼠标移入左边栏左上角模式切换,可自行切换自己所需要的模式。 + + +## **3. 工作模式** + +【番茄工作法】 + +新建目标:点击新建目标即添加今日待完成事项,开始计时后每15分钟为一个目标周期进行倒计时展示。 + +目标列表:目标列表展示您今日所创建的待完成事项,完成后点击前方按钮即可进行划线标注完成。 + +查看日程:以日历的形式记录您所创建的所有任务。 + +数据概况:以折线图的的形式记录近段时间的专注时长。 + +音乐播放:开始计时后点击音乐模块的播放键即可播放。 + + +## **4. 游戏模式** + +专为游戏爱好者提供了PC游戏、主机游戏、手游等相关内容-最新的游戏资讯、最全的游戏折扣、最热门的游戏视频,给您最好的游戏体验。 + + +## **5. AI助手** + +免费使用:每天30次免费聊天,让您免费接触前沿生产力。 + +结果增强:通过小助手,增强您的搜索结果,让您获得更多精准搜索结果。 + +指令助手:预设超多的AI对话指令模板,对话交流,适用不同需求。 + +一键访问最佳大语言模型。提出任何问题,实时获得准确、简洁的回答。感受终极人工智能体验。希望打开FatfoxTab新标签页后 每天都有好心情哦~ + + +## **6. 注册/登录** + +鼠标点击左侧栏左下角,点击人物头像,微信扫一扫或邮箱登录。 + + +## **7. 自定义功能** + +1.自定义新标签页中的小组件和图标,支持随意拖拽布置,任意搭配。 + +2.快速添加常用网站或小组件到主页。 + +3.自定义搜索引擎,快捷切换百度/谷歌/必应等搜索引擎。 + +4.自定义壁纸,海量高清壁纸任你选择,包括自然、海洋、建筑、动物等类别。 + +5.自定义左侧栏,支持图标分类。办公娱乐更加得心应手,可设置左侧栏隐藏或显示。 + +6.自定义底部栏,收纳常用网站,一键进入更方便,可设置底部栏隐藏或显示。 + +7.登录/注册FatfoxTab账号,可在不同设备备份、同步你的数据。 + +8.你可以接收到我们向你发送的消息通知。 + +9.工作模式-番茄工作法专属轻音乐。 + +10.支持组件尺寸调整,可调大、中、小 三种模式。 + +11.系统状态小组件,实时显示CPU、内存的使用情况。 + +12.游戏折扣、热门游戏、星座运势等小组件。 + +13.自定义静态动态壁纸,可下载可设置毛玻璃效果。 + + +更多新功能正在加速开发中,敬请期待... + +`, + title: "FatFoxTab指南", + date: 1730877843004, + id: "defautId" +}; +export type NotepadItem = { + title: string + content: string + id: string + date: number + pin: boolean +} +export default defineStore("notepad", () => { + const state = reactive({ + list: [DEFALUT_DATA] as NotepadItem[] + }) + const addNewNote = () => { + state.list.unshift({ + id: uuid(), + title: '', + date: dayjs().valueOf(), + content: '', + pin: false + }) + } + return { + state, + addNewNote + } +}, { + persist: true +}) \ No newline at end of file diff --git a/src/widgets/work/useTomatoStore.ts b/src/widgets/work/useTomatoStore.ts index 602d433..4441f4a 100644 --- a/src/widgets/work/useTomatoStore.ts +++ b/src/widgets/work/useTomatoStore.ts @@ -54,7 +54,7 @@ export default defineStore("work", () => { if (!state.isStart) { return 0 } - return dayjs(state.beginTime).add(15, 'minute').diff(dayjs(time.date), 'second') + return dayjs(state.beginTime).add(1, 'minute').diff(dayjs(time.date), 'second') }) const stopTomatoTime = () => { @@ -96,6 +96,12 @@ export default defineStore("work", () => { togglePlay() } + watch(remainingTime, (val) => { + if (val <= 0) { + stopTomatoTime() + + } + }) const openShowModel = ref() const openFullscreen = ref(false) const todayHour = computed(() => { @@ -111,6 +117,7 @@ export default defineStore("work", () => { return state.list.filter(val => dayjs(val.finishTime).isSame(dayjs().subtract(1, 'day'), 'day') && val.isCompleted).length }) + return { state, openShowModel, diff --git a/tailwind.config.cjs b/tailwind.config.cjs new file mode 100644 index 0000000..4e753be --- /dev/null +++ b/tailwind.config.cjs @@ -0,0 +1,12 @@ +/* eslint-disable no-undef */ +/* Copyright 2021, Milkdown by Mirone. */ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], + darkMode: 'class', + theme: { + extend: {} + }, + + plugins: [require('@tailwindcss/typography')] +} diff --git a/tailwind.config.js b/tailwind.config.js deleted file mode 100644 index da89b54..0000000 --- a/tailwind.config.js +++ /dev/null @@ -1,10 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -export default { - content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'], - darkMode: 'selector', - theme: { - fontFamily: { - 'din': 'DIN-Black' - } - } -} From bbfd1284e947d9c8caf5757567452ae88c10cf73 Mon Sep 17 00:00:00 2001 From: expdsn <18111002318@163.com> Date: Fri, 8 Nov 2024 14:50:27 +0800 Subject: [PATCH 7/8] save --- src/widgets/discount/Modal.tsx | 5 +++-- src/widgets/discount/useDiscountStore.ts | 14 +++++--------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/widgets/discount/Modal.tsx b/src/widgets/discount/Modal.tsx index a503969..0c1c069 100644 --- a/src/widgets/discount/Modal.tsx +++ b/src/widgets/discount/Modal.tsx @@ -4,9 +4,10 @@ import { RiTimeLine } from 'oh-vue-icons/icons' import { addIcons, OhVueIcon } from 'oh-vue-icons' import { IoCloseCircleOutline, RiCloseCircleLine } from 'oh-vue-icons/icons' import dayjs from 'dayjs' +import useDiscountStore from './useDiscountStore' addIcons(RiTimeLine, IoCloseCircleOutline, RiCloseCircleLine) export default defineComponent(() => { - const store = useGameNews() + const store = useDiscountStore() const containerRef = ref(null as VNodeRef | null) const searchText = ref('') const handleScroll = () => { @@ -58,7 +59,7 @@ export default defineComponent(() => { class={ 'flex cursor-pointer h-[215px] overflow-hidden bg-[#17212d] items-center flex-col rounded-lg relative ' } - onClick={() => {}} + onClick={() => { }} key={index} > diff --git a/src/widgets/discount/useDiscountStore.ts b/src/widgets/discount/useDiscountStore.ts index 34128c4..6d91a5e 100644 --- a/src/widgets/discount/useDiscountStore.ts +++ b/src/widgets/discount/useDiscountStore.ts @@ -23,18 +23,14 @@ export default defineStore("gameDiscount", () => { const loading = ref(false) const noMoreData = ref(false) const state = reactive({ - pageId: 1, - name: '', + pageSize: 1, + pageIndex: 1, + find: '' }) const getList = async () => { const res = await request<{ data: GameDiscount[]; - }>('POST', '/api/gameDiscount', { - data: { - pageId: state.pageId, - name: state.name - } - }) + }>('GET', `/api/gameDiscount?pageSize=${state.pageSize}&pageIndex=${state.pageIndex}&find=${state.find}`) return res.data } const getNews = async () => { @@ -47,7 +43,7 @@ export default defineStore("gameDiscount", () => { noMoreData.value = true; } else { list.value.push(...data); - state.pageId += 1; + state.pageIndex += 1; } } catch (e) { console.log(e); From 33ea67f34bd4b0a28175cff911e3a228d54b2f25 Mon Sep 17 00:00:00 2001 From: expdsn <18111002318@163.com> Date: Fri, 8 Nov 2024 15:36:31 +0800 Subject: [PATCH 8/8] =?UTF-8?q?=E6=8E=A5=E5=A5=BD=E4=BA=86=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/adder/AdderPage.tsx | 2 +- src/user/AvatarCircle.tsx | 12 +++++++++--- src/user/LoginModal.tsx | 7 +++++-- src/user/useUserStore.ts | 6 ++++-- src/widgets/discount/Modal.tsx | 6 +++--- src/widgets/discount/useDiscountStore.ts | 10 +++++----- 6 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/layout/adder/AdderPage.tsx b/src/layout/adder/AdderPage.tsx index 66f669b..c4e65b3 100644 --- a/src/layout/adder/AdderPage.tsx +++ b/src/layout/adder/AdderPage.tsx @@ -14,7 +14,7 @@ import WidgetAdder from './WidgetAdder' import { Form, Input, Select } from 'ant-design-vue' import HotAdder from './HotAdder' import GameAdder from './GameAdder' -import work_add_main_checked from '/tab/icons/work_add_main_checked.png' +import work_add_main_checked from '/icons/work_add_main_checked.png' import useAdderPageStore from './useAdderPageStore' addIcons(MdKeyboardcommandkey, FaCompass, FaPencilRuler, IoGameController) diff --git a/src/user/AvatarCircle.tsx b/src/user/AvatarCircle.tsx index 3a50ce8..45007a3 100644 --- a/src/user/AvatarCircle.tsx +++ b/src/user/AvatarCircle.tsx @@ -2,20 +2,26 @@ import { defineComponent } from 'vue' import { OhVueIcon, addIcons } from 'oh-vue-icons' import { FaUserAlt } from 'oh-vue-icons/icons' import useUserStore from './useUserStore' +import { watch } from 'vue' addIcons(FaUserAlt) export default defineComponent(() => { - const { profile } = useUserStore() + const store = useUserStore() + watch(() => store.profile.avatar, (e) => { + console.log(e); + + console.log('avatar change') + }) return () => { return (
- {!profile.avatar && } + {!store.profile.avatar && }
) } diff --git a/src/user/LoginModal.tsx b/src/user/LoginModal.tsx index 8da06dc..a34205e 100644 --- a/src/user/LoginModal.tsx +++ b/src/user/LoginModal.tsx @@ -27,11 +27,14 @@ export default defineComponent(() => { watch(wxCode, (url, _, onCleanUp) => { if (!url) return const it = setInterval(() => { - request('GET', `/api/wxlogin2/access?uuid=${_id.value}`).then((res) => { + request('GET', `/api/wxlogin2/access?uuid=${_id.value}`, { + returnType: 'text' + }).then((res) => { if (res) { clearInterval(it) console.log(res) - + user.token = res + router.back() message.success('登录成功') } }) diff --git a/src/user/useUserStore.ts b/src/user/useUserStore.ts index 20aacd7..3a299dd 100644 --- a/src/user/useUserStore.ts +++ b/src/user/useUserStore.ts @@ -23,13 +23,14 @@ export default defineStore('user', () => { watch(token, (val) => { localStorage.setItem('token', val) }) - const profile = reactive(defaultUserInfo) + const profile = reactive({ ...defaultUserInfo }) watch( token, (val) => { if (!val) return request('GET', '/api/profile').then((res) => { Object.assign(profile, res) + }) }, { immediate: true } @@ -37,7 +38,8 @@ export default defineStore('user', () => { const isLogin = computed(() => !!token.value && !!profile.id) const logout = () => { token.value = '' - Object.assign(profile, defaultUserInfo) + Object.assign(profile, { ...defaultUserInfo }) + // profile.avatar = '' } return { token, diff --git a/src/widgets/discount/Modal.tsx b/src/widgets/discount/Modal.tsx index 0c1c069..d4a5492 100644 --- a/src/widgets/discount/Modal.tsx +++ b/src/widgets/discount/Modal.tsx @@ -84,13 +84,13 @@ export default defineComponent(() => { -13%
- ¥{item.commdity[0].price} + ¥{item.commdity[0]?.price} - ¥{item.commdity[0].oldprice} + ¥{item.commdity[0]?.oldprice} - 剩余{item.commdity[0].oldprice}天 + 剩余{item.commdity[0]?.oldprice}天
diff --git a/src/widgets/discount/useDiscountStore.ts b/src/widgets/discount/useDiscountStore.ts index 6d91a5e..f63aff1 100644 --- a/src/widgets/discount/useDiscountStore.ts +++ b/src/widgets/discount/useDiscountStore.ts @@ -28,16 +28,16 @@ export default defineStore("gameDiscount", () => { find: '' }) const getList = async () => { - const res = await request<{ - data: GameDiscount[]; - }>('GET', `/api/gameDiscount?pageSize=${state.pageSize}&pageIndex=${state.pageIndex}&find=${state.find}`) - return res.data + const res = await request< + GameDiscount[] + >('GET', `/api/gameDiscount?pageSize=${state.pageSize}&pageIndex=${state.pageIndex}&find=${state.find}&type=all`) + return res } const getNews = async () => { if (loading.value || noMoreData.value) return; - loading.value = true; try { + loading.value = true; const data = await getList() if (data.length === 0) { noMoreData.value = true;