完成了自定义网址
This commit is contained in:
parent
7e2112aec6
commit
744c02798a
|
@ -17,6 +17,7 @@
|
|||
"@fingerprintjs/fingerprintjs": "^4.4.3",
|
||||
"ali-oss": "^6.21.0",
|
||||
"ant-design-vue": "4.x",
|
||||
"clsx": "^2.1.1",
|
||||
"dayjs": "^1.11.13",
|
||||
"localforage": "^1.10.0",
|
||||
"lunar-typescript": "^1.7.5",
|
||||
|
|
|
@ -4,6 +4,7 @@ import useLayoutStore from '../useLayoutStore'
|
|||
import { OhVueIcon, addIcons } from 'oh-vue-icons'
|
||||
import { MdKeyboardcommandkey, FaCompass, FaPencilRuler } from 'oh-vue-icons/icons'
|
||||
import CustomAdder from './CustomAdder'
|
||||
import clsx from 'clsx'
|
||||
addIcons(MdKeyboardcommandkey, FaCompass, FaPencilRuler)
|
||||
|
||||
const ItemButton = defineComponent({
|
||||
|
@ -53,7 +54,7 @@ export default defineComponent(() => {
|
|||
const isGame = computed(() => layout.state.current === 0)
|
||||
const type = ref(1)
|
||||
return () => (
|
||||
<div class="w-full h-full relative flex">
|
||||
<div class={clsx("w-full h-full relative flex", isGame.value&&"bg-[#2c2e3e]")}>
|
||||
{isGame.value && <AdderPageBack />}
|
||||
<div
|
||||
class={
|
||||
|
@ -89,7 +90,7 @@ export default defineComponent(() => {
|
|||
<div
|
||||
class={
|
||||
'w-0 h-full flex-grow relative z-10 flex flex-col ' +
|
||||
(isGame.value ? '' : 'bg-white/40 backdrop-blur')
|
||||
(isGame.value ? '' : 'bg-white/80 backdrop-blur')
|
||||
}
|
||||
onContextmenu={(e) => e.stopPropagation()}
|
||||
>
|
||||
|
|
|
@ -10,7 +10,7 @@ export default defineComponent(() => () => (
|
|||
>
|
||||
<path
|
||||
d="M16 16C20 11.5 20 5 20 5H880.084C880.084 5 879.089 12.4299 883.067 16.8879C887.045 21.3458 895 21.8411 895 21.8411V518C895 518 887.045 516.5 883.067 521.5C879.089 526.5 880.084 535 880.084 535H20C20 535 19 528.5 16 524C13 519.5 5 518 5 518V22.5C5 22.5 12 20.5 16 16Z"
|
||||
fill="#1F2028"
|
||||
fill="#2c2e3e"
|
||||
/>
|
||||
<path
|
||||
d="M804.5 26.5C804.5 9.5 793.333 6.83333 789 6H878.5C878.5 6 885.5 6.85714 890 12C894.5 17.1429 894.5 22.5 894.5 22.5V67.5C894.5 67.5 856.5 66.5 853.5 58C850.5 49.5 854 38.5 850.5 30.5C848 25.5 840.5 25 831 27C821.5 29 804 35 804.5 26.5Z"
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import { computed, defineComponent, reactive } from 'vue'
|
||||
import { computed, defineComponent, reactive, ref, watch } from 'vue'
|
||||
import useLayoutStore from '../useLayoutStore'
|
||||
import { ConfigProvider, Form, Input, theme } from 'ant-design-vue'
|
||||
import { OhVueIcon, addIcons } from 'oh-vue-icons'
|
||||
import { MdUpload, MdImage } from 'oh-vue-icons/icons'
|
||||
import { MdUpload, MdImage, MdCheck } from 'oh-vue-icons/icons'
|
||||
import clsx from 'clsx'
|
||||
import ImageUploader from '@/utils/ImageUploader'
|
||||
import useLink from './useLink'
|
||||
|
||||
addIcons(MdUpload, MdImage)
|
||||
addIcons(MdUpload, MdImage, MdCheck)
|
||||
|
||||
const TypeSelector = defineComponent({
|
||||
props: {
|
||||
|
@ -36,32 +39,70 @@ const TypeSelector = defineComponent({
|
|||
setup(props, ctx) {
|
||||
return () => (
|
||||
<div class="flex gap-4">
|
||||
<div
|
||||
class="w-[64px] h-[65px] bg-center bg-no-repeat bg-cover rounded-lg overflow-hidden flex justify-center items-center cursor-pointer hover:scale-105 transition-all"
|
||||
style={{
|
||||
backgroundImage: `url('${props.icon}')`,
|
||||
backgroundColor: props.icon ? '' : 'rgba(0,0,0,0.2)'
|
||||
}}
|
||||
>
|
||||
{!props.icon && <OhVueIcon name="md-image" fill="white" scale={1.8} />}
|
||||
</div>
|
||||
<div
|
||||
class="w-[64px] h-[65px] bg-center bg-no-repeat bg-cover rounded-lg overflow-hidden flex justify-center items-center cursor-pointer hover:scale-105 transition-all"
|
||||
style={{
|
||||
backgroundColor: props.background
|
||||
}}
|
||||
>
|
||||
<span
|
||||
class="text-[30px]"
|
||||
<div class={'flex justify-center flex-col items-center gap-y-1'}>
|
||||
<div
|
||||
class="w-[47px] relative h-[47px] bg-center bg-no-repeat bg-cover rounded-lg overflow-hidden flex justify-center items-center cursor-pointer hover:scale-105 transition-all"
|
||||
style={{
|
||||
color: props.color
|
||||
backgroundImage: `url('${props.icon}')`,
|
||||
backgroundColor: props.icon ? '' : 'rgba(0,0,0,0.2)'
|
||||
}}
|
||||
onClick={() => {
|
||||
ctx.emit('update:value', 0)
|
||||
}}
|
||||
>
|
||||
{props.text ? props.text.substring(0, 2) : 'A'}
|
||||
</span>
|
||||
{!props.icon && <OhVueIcon name="md-image" fill="white" scale={1.8} />}
|
||||
{props.value === 0 && (
|
||||
<div
|
||||
class={
|
||||
'w-[20px] h-[20px] rounded bg-white/50 flex items-center justify-center absolute right-0 bottom-0'
|
||||
}
|
||||
>
|
||||
<OhVueIcon name="md-check" fill="red" scale={0.8}></OhVueIcon>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<span class={'text-[12px]'}>默认</span>
|
||||
</div>
|
||||
<div class="w-[64px] h-[65px] rounded-lg flex justify-center items-center bg-white shadow cursor-pointer hover:scale-105 transition-all">
|
||||
<OhVueIcon name="md-upload" fill="rgba(0,0,0,0.4)" scale={1.8} />
|
||||
<div class={'flex justify-center flex-col items-center gap-y-1 '}>
|
||||
<div
|
||||
class="w-[44px] relative h-[44px] bg-center bg-no-repeat bg-cover rounded-lg overflow-hidden flex justify-center items-center cursor-pointer hover:scale-105 transition-all"
|
||||
style={{
|
||||
backgroundColor: props.background
|
||||
}}
|
||||
onClick={() => {
|
||||
ctx.emit('update:value', 1)
|
||||
}}
|
||||
>
|
||||
<span
|
||||
class="text-[20px]"
|
||||
style={{
|
||||
color: props.color
|
||||
}}
|
||||
>
|
||||
{props.text ? props.text.substring(0, 2) : 'A'}
|
||||
</span>
|
||||
{props.value === 1 && (
|
||||
<div
|
||||
class={
|
||||
'w-[20px] h-[20px] rounded bg-white/50 flex items-center justify-center absolute right-0 bottom-0'
|
||||
}
|
||||
>
|
||||
<OhVueIcon name="md-check" fill="red" scale={0.8}></OhVueIcon>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<span class={'text-[12px]'}>文字</span>
|
||||
</div>
|
||||
<div class={'flex justify-center flex-col items-center gap-y-1'}>
|
||||
<div class="w-[44px] h-[44px] rounded-lg flex justify-center items-center bg-white shadow cursor-pointer hover:scale-105 transition-all">
|
||||
<ImageUploader
|
||||
width={44}
|
||||
onUpdate:value={(e) => {
|
||||
ctx.emit('update:icon', e)
|
||||
}}
|
||||
></ImageUploader>
|
||||
</div>
|
||||
<span class={'text-[12px]'}>自定义</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -81,7 +122,6 @@ export default defineComponent({
|
|||
},
|
||||
setup(props, ctx) {
|
||||
const layout = useLayoutStore()
|
||||
const isGame = computed(() => layout.state.current === 0)
|
||||
const form = reactive({
|
||||
link: '',
|
||||
name: '',
|
||||
|
@ -91,45 +131,88 @@ export default defineComponent({
|
|||
icon: '',
|
||||
type: 0 // 0 默认,1 文字
|
||||
})
|
||||
const isGame = computed(() => layout.state.current === 0)
|
||||
const debounced = ref('')
|
||||
watch(
|
||||
() => form.link,
|
||||
(val, _, onCleanup) => {
|
||||
const it = setTimeout(() => {
|
||||
debounced.value = val
|
||||
}, 500)
|
||||
onCleanup(() => {
|
||||
clearTimeout(it)
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
const info = useLink(debounced)
|
||||
console.log(info);
|
||||
|
||||
watch(info, (val) => {
|
||||
console.log(val);
|
||||
|
||||
if (val.name) form.name = val.name
|
||||
if (val.icon) form.icon = val.icon
|
||||
|
||||
})
|
||||
return () => (
|
||||
<div
|
||||
class={
|
||||
'absolute left-0 top-0 w-full h-full rounded-lg p-4 ' +
|
||||
'absolute left-0 top-0 w-full h-full rounded-2xl p-5 ' +
|
||||
(isGame.value ? 'bg-white/20' : 'bg-white/20')
|
||||
}
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<div></div>
|
||||
</div>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
token: isGame.value
|
||||
? theme.darkAlgorithm(theme.defaultSeed)
|
||||
: theme.defaultAlgorithm(theme.defaultSeed)
|
||||
}}
|
||||
>
|
||||
<Form model={form} class="flex flex-col" colon={false}>
|
||||
<Form.Item label="地址" name="link" class="w-[380px]" >
|
||||
<Input v-model:value={form.link} />
|
||||
</Form.Item>
|
||||
<Form.Item label="名称" name="name" class="w-[380px]">
|
||||
<Input v-model:value={form.name} />
|
||||
</Form.Item>
|
||||
<Form.Item label="图标" name="text">
|
||||
<Input v-model:value={form.text} />
|
||||
</Form.Item>
|
||||
<Form.Item name="type" label=" " class="">
|
||||
<TypeSelector
|
||||
v-model:value={form.type}
|
||||
v-model:icon={form.icon}
|
||||
text={form.text}
|
||||
color={form.color}
|
||||
background={form.background}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
</Form>
|
||||
</ConfigProvider>
|
||||
<div class={clsx('flex flex-col text-[14px] gap-y-3', isGame.value ? 'text-white' : '')}>
|
||||
<div class={clsx('gap-x-6 flex items-center')}>
|
||||
<span>地址</span>
|
||||
<input
|
||||
v-model={form.link}
|
||||
placeholder="搜索想要添加的网址导航"
|
||||
class={clsx(
|
||||
'w-[350px] rounded-md outline-none h-[40px] px-[10px]',
|
||||
isGame.value ? 'bg-black/[.1]' : ''
|
||||
)}
|
||||
></input>
|
||||
<span class={'cursor-pointer'}>获取地址</span>
|
||||
</div>
|
||||
<div class={clsx('gap-x-6 flex items-center')}>
|
||||
<span>名称</span>
|
||||
<input
|
||||
v-model={form.name}
|
||||
placeholder="网站名称"
|
||||
class={clsx(
|
||||
'w-[350px] rounded-md outline-none h-[40px] px-[10px]',
|
||||
isGame.value ? 'bg-black/[.1]' : ''
|
||||
)}
|
||||
></input>
|
||||
</div>
|
||||
<div class={clsx('gap-x-6 flex items-start')}>
|
||||
<span>图标</span>
|
||||
<TypeSelector
|
||||
v-model:value={form.type}
|
||||
v-model:icon={form.icon}
|
||||
text={form.text}
|
||||
color={form.color}
|
||||
background={form.background}
|
||||
/>
|
||||
</div>
|
||||
<div class={clsx('gap-x-6 flex items-center')}>
|
||||
<span></span>
|
||||
<button
|
||||
v-model:value={form.name}
|
||||
placeholder="网站名称"
|
||||
class={clsx(
|
||||
'bg-gradient-to-b from-[#ffaa4e] to-[#ff6227] rounded-lg w-[94px] h-[40px] text-[16px] ',
|
||||
isGame.value ? 'bg-black/[.1]' : ''
|
||||
)}
|
||||
>
|
||||
确定
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import request from '@/utils/request'
|
||||
import { reactive, watch, type Ref } from 'vue'
|
||||
|
||||
export interface LinkInfo {
|
||||
background: string
|
||||
desc: string
|
||||
icon: string
|
||||
link: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export default function useLink(url: Ref<string>) {
|
||||
const info = reactive<LinkInfo>({
|
||||
background: '',
|
||||
desc: '',
|
||||
icon: '',
|
||||
link: '',
|
||||
name: ''
|
||||
})
|
||||
watch(
|
||||
url,
|
||||
(val) => {
|
||||
if (!val) return
|
||||
const tag = val.match(/(?<=http(s?):\/\/)[^/]*/g)?.[0] || val
|
||||
console.log(tag);
|
||||
|
||||
request<LinkInfo>('GET', `/api/app/pic/info/${tag}`).then((res) => {
|
||||
Object.assign(info, res)
|
||||
})
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
return info
|
||||
}
|
|
@ -89,7 +89,7 @@ export default defineComponent({
|
|||
<OhVueIcon name="md-upload" scale={2} fill="rgba(0,0,0,0.2)" />
|
||||
)}
|
||||
</div>
|
||||
<div class="text-xs mt-1 text-black/60">支持上传 .png, .jpeg, .jpg, .svg</div>{' '}
|
||||
{/* <div class="text-xs mt-1 text-black/60">支持上传 .png, .jpeg, .jpg, .svg</div>{' '} */}
|
||||
</ConfigProvider>
|
||||
</div>
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue