临时保存代码:番茄时钟
|
@ -28,6 +28,7 @@
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pinia-plugin-persistedstate": "^3.2.3",
|
"pinia-plugin-persistedstate": "^3.2.3",
|
||||||
"pixi.js": "^8.4.0",
|
"pixi.js": "^8.4.0",
|
||||||
|
"qrcode": "^1.5.4",
|
||||||
"sortablejs": "^1.15.3",
|
"sortablejs": "^1.15.3",
|
||||||
"ua-parser-js": "^1.0.38",
|
"ua-parser-js": "^1.0.38",
|
||||||
"uuid": "^10.0.0",
|
"uuid": "^10.0.0",
|
||||||
|
@ -44,6 +45,7 @@
|
||||||
"@types/ali-oss": "^6.16.11",
|
"@types/ali-oss": "^6.16.11",
|
||||||
"@types/crypto-js": "^4.2.2",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/node": "^20.14.5",
|
"@types/node": "^20.14.5",
|
||||||
|
"@types/qrcode": "^1.5.5",
|
||||||
"@types/sortablejs": "^1.15.8",
|
"@types/sortablejs": "^1.15.8",
|
||||||
"@types/ua-parser-js": "^0.7.39",
|
"@types/ua-parser-js": "^0.7.39",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/uuid": "^10.0.0",
|
||||||
|
|
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 727 B |
After Width: | Height: | Size: 525 B |
After Width: | Height: | Size: 707 B |
After Width: | Height: | Size: 536 B |
After Width: | Height: | Size: 252 B |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 8.3 KiB |
|
@ -1,14 +1,42 @@
|
||||||
import { defineComponent, reactive, Transition } from 'vue'
|
import { defineComponent, onMounted, reactive, ref, Transition, watch } from 'vue'
|
||||||
import useRouterStore from '@/useRouterStore'
|
import useRouterStore from '@/useRouterStore'
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import useUserStore from './useUserStore'
|
import useUserStore from './useUserStore'
|
||||||
|
import Logo from '~/public/logo.png'
|
||||||
|
import LogoIcon from '~/public/loginIcon.png'
|
||||||
|
import LogoClose from '~/public/icons/loginClose.png'
|
||||||
|
import { message, Spin } from 'ant-design-vue'
|
||||||
|
import { v4 as uuid } from 'uuid'
|
||||||
|
import QrCode from 'qrcode'
|
||||||
|
|
||||||
export default defineComponent(() => {
|
export default defineComponent(() => {
|
||||||
const router = useRouterStore()
|
const router = useRouterStore()
|
||||||
const user = useUserStore()
|
const user = useUserStore()
|
||||||
const form = reactive({
|
|
||||||
email: '',
|
const wxCode = ref('')
|
||||||
password: ''
|
const _id = ref(uuid())
|
||||||
|
onMounted(() => {
|
||||||
|
request<string>('GET', `/api/wxloginimg?uuid=${_id.value}`, {
|
||||||
|
returnType: 'text'
|
||||||
|
})
|
||||||
|
.then((res) => QrCode.toDataURL(res))
|
||||||
|
.then((res) => {
|
||||||
|
wxCode.value = res
|
||||||
|
})
|
||||||
|
})
|
||||||
|
watch(wxCode, (url, _, onCleanUp) => {
|
||||||
|
if (!url) return
|
||||||
|
const it = setInterval(() => {
|
||||||
|
request('GET', `/api/wxlogin2/access?uuid=${_id.value}`).then((res) => {
|
||||||
|
if (res) {
|
||||||
|
clearInterval(it)
|
||||||
|
console.log(res)
|
||||||
|
|
||||||
|
message.success('登录成功')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 2000)
|
||||||
|
onCleanUp(() => clearInterval(it))
|
||||||
})
|
})
|
||||||
return () => (
|
return () => (
|
||||||
<div class="fixed left-0 top-0 z-50 w-full">
|
<div class="fixed left-0 top-0 z-50 w-full">
|
||||||
|
@ -24,37 +52,36 @@ export default defineComponent(() => {
|
||||||
</Transition>
|
</Transition>
|
||||||
<Transition name="modal">
|
<Transition name="modal">
|
||||||
{router.path === 'global-login' && (
|
{router.path === 'global-login' && (
|
||||||
<div class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 overflow-hidden transition-all w-[540px] max-w-[90%] rounded-lg p-2 bg-white/40 backdrop-blur">
|
<div class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 overflow-hidden transition-all w-[540px] max-w-[90%] h-[400px] rounded-lg p-1 bg-white/30 backdrop-blur">
|
||||||
<div class="w-full h-full rounded-lg bg-white/80 overflow-hidden">
|
<div class="w-full h-full rounded-lg bg-white overflow-hidden relative">
|
||||||
<div class="flex justify-center py-4">
|
<div class="flex justify-center pt-8">
|
||||||
<img src="/logo.png" alt="logo" class="w-1/3" />
|
<img src={Logo} alt="logo" class="w-1/3" />
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center text-lg text-black/60 font-bold tracking-widest">
|
<div class={'flex flex-col justify-center items-center my-8 gap-y-7'}>
|
||||||
登录 Fatfox 新标签页
|
<div class={'w-[165px] h-[165px] border-[2px] border-[#d4d4d4] rounded-md'}>
|
||||||
|
{wxCode.value ? (
|
||||||
|
<img src={wxCode.value} alt="wxCode" class="w-full h-full " />
|
||||||
|
) : (
|
||||||
|
<div class="flex justify-center items-center w-full h-full">
|
||||||
|
<Spin></Spin>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
)}
|
||||||
测试用
|
</div>
|
||||||
<form>
|
|
||||||
<input placeholder="邮箱" v-model={form.email} />
|
<span class={'text-[#666] text-[16px] leading-[24px]'}>
|
||||||
<input placeholder="密码" type="password" v-model={form.password} />
|
打开微信<span class={'text-[#333] font-bold'}>扫一扫,关注公众号</span>
|
||||||
</form>
|
后即可登录/注册
|
||||||
<button
|
</span>
|
||||||
|
</div>
|
||||||
|
<img src={LogoIcon} alt="logo" class="w-[220px] absolute bottom-0 right-0 " />
|
||||||
|
<img
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
request<string>('POST', '/api/user/login', {
|
router.back()
|
||||||
data: form,
|
|
||||||
returnType: 'text'
|
|
||||||
}).then((res) => {
|
|
||||||
user.token = res
|
|
||||||
router.go('')
|
|
||||||
})
|
|
||||||
}}
|
}}
|
||||||
>
|
src={LogoClose}
|
||||||
立即登录
|
alt="close icon"
|
||||||
</button>
|
class={'w-[32px] right-2 top-2 absolute cursor-pointer'}
|
||||||
</div>
|
/>
|
||||||
<div class="flex justify-end py-4">
|
|
||||||
<img src="/logo.png" alt="logo" class="w-1/2 relative top-8 left-4 opacity-10" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent(() => {
|
||||||
|
return () => (
|
||||||
|
<div class="w-full h-full bg-[#ecfbff] flex flex-col">
|
||||||
|
large
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent(() => {
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<div class="w-full h-full bg-[#ecfbff] flex flex-col">
|
||||||
|
middle
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent(() => {
|
||||||
|
return () => (
|
||||||
|
<div
|
||||||
|
class="w-full h-full bg-red-50 flex "
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(180deg,#dcefff 0%,#e7ecff 100%)'
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
)
|
||||||
|
})
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent(() => {
|
||||||
|
return () => (
|
||||||
|
<div
|
||||||
|
class="w-full h-full items-center pl-3 gap-x-2 flex py-3 text-white"
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg,#5996ff 0%,#4862ff 100%)'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
|
@ -0,0 +1,30 @@
|
||||||
|
import asyncLoader from '@/utils/asyncLoader'
|
||||||
|
import type { Widget } from '..'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'gameNews',
|
||||||
|
label: '游戏资讯',
|
||||||
|
description: '游戏资讯',
|
||||||
|
icon: '/tab/icons/game_news_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
|
|
@ -8,6 +8,7 @@ import discount from './discount'
|
||||||
import hotspot from './hotspot'
|
import hotspot from './hotspot'
|
||||||
import constellation from './constellation'
|
import constellation from './constellation'
|
||||||
import gameVideo from './gameVideo'
|
import gameVideo from './gameVideo'
|
||||||
|
import work from './work'
|
||||||
export interface Widget {
|
export interface Widget {
|
||||||
name: string // 小组件类型唯一标识
|
name: string // 小组件类型唯一标识
|
||||||
label: string // 小组件名称
|
label: string // 小组件名称
|
||||||
|
@ -22,4 +23,4 @@ export interface Widget {
|
||||||
}[] // 不同尺寸小组件块
|
}[] // 不同尺寸小组件块
|
||||||
}
|
}
|
||||||
|
|
||||||
export default [calendar, weather, weApply, gameNews, eat, discount, hotspot, constellation, gameVideo] as Widget[]
|
export default [calendar, weather, weApply, gameNews, eat, discount, hotspot, constellation, gameVideo, work] as Widget[]
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent(() => {
|
||||||
|
return () => (
|
||||||
|
<div class="w-full h-full bg-[#ecfbff] flex flex-col">
|
||||||
|
large
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
|
@ -0,0 +1,204 @@
|
||||||
|
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 List from './modal_view/list'
|
||||||
|
import { DatePicker, Modal } from 'ant-design-vue'
|
||||||
|
import type { TomatoTarget } from './useTomatoStore'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import useTomatoStore from './useTomatoStore'
|
||||||
|
const workTab = [
|
||||||
|
{
|
||||||
|
title: '目标列表',
|
||||||
|
key: 'list',
|
||||||
|
icon: ListImg
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '目标日历',
|
||||||
|
key: 'schedule',
|
||||||
|
icon: DateImg
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '数据详情',
|
||||||
|
key: 'detail',
|
||||||
|
icon: DataImg
|
||||||
|
}
|
||||||
|
]
|
||||||
|
const EditContent = defineComponent(() => {
|
||||||
|
const store = useTomatoStore()
|
||||||
|
const form = ref<TomatoTarget>(
|
||||||
|
store.openShowModel || {
|
||||||
|
title: '',
|
||||||
|
id: '',
|
||||||
|
finishTime: dayjs().valueOf(),
|
||||||
|
remindTime: -1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return () => (
|
||||||
|
<div class={'w-full h-[300px] flex flex-col bg-white gap-y-2 items-start pl-2'}>
|
||||||
|
<span class={'text-[16px] font-bold text-[#333] mt-[10px]'}>新建目标</span>
|
||||||
|
<div
|
||||||
|
class={'w-full h-[40px] mt-4 relative rounded-lg pl-[50px] bg-black/[0.05]'}
|
||||||
|
style={{
|
||||||
|
boxShadow: 'inset 0 1px 6px #0000000d'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={AddImg}
|
||||||
|
alt="add img"
|
||||||
|
class={'left-4 absolute top-1/2 -translate-y-1/2 w-[15px] h-[16px]'}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
v-modal={form.value.title}
|
||||||
|
type="text"
|
||||||
|
placeholder="未命名目标"
|
||||||
|
class={'w-full bg-transparent outline-none text-[14px] text-[#333] h-full'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span class={'text-[#666] text-[14px] my-1'}>添加目标完成时间</span>
|
||||||
|
<div class={'flex items-center gap-x-2 '}>
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
form.value.finishTime = dayjs().valueOf()
|
||||||
|
}}
|
||||||
|
class={clsx(
|
||||||
|
' px-6 py-2 rounded-lg cursor-pointer',
|
||||||
|
dayjs(form.value.finishTime).isSame(dayjs(), 'day')
|
||||||
|
? 'bg-[#EBF0FF] text-[#5a6eff]'
|
||||||
|
: 'bg-black/[0.05]'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
今天
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
form.value.finishTime = dayjs().add(1, 'day').valueOf()
|
||||||
|
}}
|
||||||
|
class={clsx(
|
||||||
|
' px-6 py-2 rounded-lg cursor-pointer',
|
||||||
|
dayjs(form.value.finishTime).isSame(dayjs().add(1, 'day'), 'day')
|
||||||
|
? 'bg-[#EBF0FF] text-[#5a6eff]'
|
||||||
|
: 'bg-black/[0.05]'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
明天
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class={clsx(
|
||||||
|
' px-6 py-2 rounded-lg cursor-pointer relative',
|
||||||
|
!(
|
||||||
|
dayjs(form.value.finishTime).isSame(dayjs(), 'day') ||
|
||||||
|
dayjs(form.value.finishTime).isSame(dayjs().add(1, 'day'), 'day')
|
||||||
|
)
|
||||||
|
? 'bg-[#EBF0FF] text-[#5a6eff]'
|
||||||
|
: 'bg-black/[0.05]'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{dayjs(form.value.finishTime).format('YYYY-MM-DD')}
|
||||||
|
<DatePicker
|
||||||
|
class={'absolute opacity-0 left-0 top-0 w-full h-full'}
|
||||||
|
onChange={(e) => {
|
||||||
|
form.value.finishTime = dayjs(e).valueOf()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class={'text-[#666] text-[14px] my-1'}>添加提醒时间</span>
|
||||||
|
<div
|
||||||
|
class={clsx(
|
||||||
|
' px-6 py-2 rounded-lg cursor-pointer relative',
|
||||||
|
!(
|
||||||
|
dayjs(form.value.finishTime).isSame(dayjs(), 'day') ||
|
||||||
|
dayjs(form.value.finishTime).isSame(dayjs().add(1, 'day'), 'day')
|
||||||
|
)
|
||||||
|
? 'bg-[#EBF0FF] text-[#5a6eff]'
|
||||||
|
: 'bg-black/[0.05]'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{form.value.remindTime === null ? (
|
||||||
|
'不提醒'
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{dayjs(form.value.finishTime).format('YYYY-MM-DD')}
|
||||||
|
<DatePicker
|
||||||
|
class={'absolute opacity-0 left-0 top-0 w-full h-full'}
|
||||||
|
onChange={(e) => {
|
||||||
|
form.value.finishTime = dayjs(e).valueOf()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
export default defineComponent(() => {
|
||||||
|
const select = ref(0)
|
||||||
|
const store = useTomatoStore()
|
||||||
|
return () => (
|
||||||
|
<div class="w-full h-full flex bg-white">
|
||||||
|
<Modal
|
||||||
|
class={'bg-white p-0 rounded-lg'}
|
||||||
|
zIndex={60}
|
||||||
|
footer={null}
|
||||||
|
centered
|
||||||
|
open={store.openShowModel !== undefined}
|
||||||
|
onCancel={() => {
|
||||||
|
store.openShowModel = undefined
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<EditContent></EditContent>
|
||||||
|
</Modal>
|
||||||
|
<div class={'w-[174px] h-full bg-[#F8F8F8] flex py-10 flex-col items-center'}>
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
store.openShowModel = null
|
||||||
|
}}
|
||||||
|
class={
|
||||||
|
'w-[126px] h-[44px] leading-[44px] shadow-lg rounded-lg justify-center items-center gap-x-1 font-bold text-white flex '
|
||||||
|
}
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(225deg,#5A6EFF 0%,#519DFF 100%)'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img class={'w-[16px] h-[16px]'} src={PlusIcon} alt="" />
|
||||||
|
新建目标
|
||||||
|
</div>
|
||||||
|
<div class={'flex flex-col gap-y-1 mt-5 w-full'}>
|
||||||
|
{workTab.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
select.value = index
|
||||||
|
}}
|
||||||
|
class={clsx(
|
||||||
|
'w-full flex pl-6 items-center py-4 border-l-[8px] gap-x-2 cursor-pointer',
|
||||||
|
select.value === index
|
||||||
|
? 'bg-[#90adff2e] text-[#5a6eff] border-[#5a6eff]'
|
||||||
|
: 'text-[#666666] border-transparent hover:bg-[#97aff02e]'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<img class={'w-[18px] h-[18px]'} src={item.icon} alt="" />
|
||||||
|
<span>{item.title}</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class={'flex-1 w-0 h-full p-3'}>
|
||||||
|
{select.value === 0 ? (
|
||||||
|
<List></List>
|
||||||
|
) : select.value === 1 ? (
|
||||||
|
<div>目标日历</div>
|
||||||
|
) : select.value === 2 ? (
|
||||||
|
<div>数据详情</div>
|
||||||
|
) : (
|
||||||
|
<>loading</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent(() => {
|
||||||
|
return () => (
|
||||||
|
<div
|
||||||
|
class="w-full h-full items-center pl-3 gap-x-2 flex py-3 text-white"
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg,#5996ff 0%,#4862ff 100%)'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
|
@ -0,0 +1,24 @@
|
||||||
|
import asyncLoader from '@/utils/asyncLoader'
|
||||||
|
import type { Widget } from '..'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'work',
|
||||||
|
label: '番茄工作法',
|
||||||
|
description: '番茄记事法',
|
||||||
|
icon: '/tab/icons/work/tomato_work_icon.png',
|
||||||
|
modal: asyncLoader(() => import('./Modal')),
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
w: 2,
|
||||||
|
h: 1,
|
||||||
|
label: '小',
|
||||||
|
component: asyncLoader(() => import('./Small'))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
w: 4,
|
||||||
|
h: 2,
|
||||||
|
label: '大',
|
||||||
|
component: asyncLoader(() => import('./Large'))
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} as Widget
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { computed, defineComponent, ref, Transition } from 'vue'
|
||||||
|
import { OhVueIcon, addIcons } from 'oh-vue-icons'
|
||||||
|
import { MdClose, MdOpeninfull, MdClosefullscreen } from 'oh-vue-icons/icons'
|
||||||
|
import useTomatoStore from '../useTomatoStore'
|
||||||
|
addIcons(MdClose, MdOpeninfull, MdClosefullscreen)
|
||||||
|
|
||||||
|
export default defineComponent(
|
||||||
|
(props, ctx) => {
|
||||||
|
const show = ref(false)
|
||||||
|
const store = useTomatoStore()
|
||||||
|
return () => (
|
||||||
|
<div class="fixed left-0 top-0 z-[60] w-full">
|
||||||
|
{/* 背景遮罩 */}
|
||||||
|
<Transition>
|
||||||
|
{props.show && (
|
||||||
|
<div class="w-full h-screen bg-black/20 backdrop-blur" onClick={() => {}}></div>
|
||||||
|
)}
|
||||||
|
</Transition>
|
||||||
|
{/* 弹框主体 */}
|
||||||
|
<Transition name="modal">
|
||||||
|
{show.value && (
|
||||||
|
<div
|
||||||
|
class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 overflow-hidden transition-all"
|
||||||
|
style={{
|
||||||
|
width: '984px',
|
||||||
|
height: '580px',
|
||||||
|
borderRadius: '1rem'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{/* 关闭按钮 */}
|
||||||
|
<div
|
||||||
|
class={
|
||||||
|
'w-[16px] h-[16px] group flex justify-center items-center rounded-full overflow-hidden absolute bg-red-500/70 hover:bg-red-500 transition-all cursor-pointer z-30 top-4 right-6 '
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
store.isOpenEditModal = ''
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class={' items-center justify-center hidden group-hover:flex'}>
|
||||||
|
<OhVueIcon name="md-close" scale={0.6} fill="white" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full h-full flex justify-center items-center">
|
||||||
|
<Transition>{ctx.slots.default?.()}</Transition>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
props: ['show']
|
||||||
|
}
|
||||||
|
)
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent(() => {
|
||||||
|
return () => (
|
||||||
|
<div class={'w-full h-full p-3'}>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder='搜索目标'
|
||||||
|
class={' border-transparent pb-1 border-b-[1px] border-b-[#ddd] overflow-hidden outline-none border-[1px] w-full'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
import { reactive, ref } from "vue";
|
||||||
|
|
||||||
|
export type TomatoTarget = {
|
||||||
|
id: string;
|
||||||
|
finishTime: number;
|
||||||
|
remindTime: number | null;
|
||||||
|
title: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
export default defineStore("work", () => {
|
||||||
|
const state = reactive({
|
||||||
|
list: [] as TomatoTarget[],
|
||||||
|
})
|
||||||
|
const openShowModel = ref<undefined | null | TomatoTarget>()
|
||||||
|
|
||||||
|
return {
|
||||||
|
state,
|
||||||
|
openShowModel
|
||||||
|
}
|
||||||
|
})
|