未登录的情况下,profile接口每次刷新报错

This commit is contained in:
expdsn 2024-11-15 19:03:00 +08:00
parent 0c188cc40b
commit eca34957a2
5 changed files with 182 additions and 147 deletions

View File

@ -83,9 +83,9 @@ export default defineComponent(() => {
const addTo = ref(layout.state.currentPage) const addTo = ref(layout.state.currentPage)
provide(AddToToken, addTo) provide(AddToToken, addTo)
onUnmounted(() => { // onUnmounted(() => {
store.type = 1 // store.type = 1
}) // })
return () => ( return () => (
<div <div
class={clsx( class={clsx(

View File

@ -5,6 +5,8 @@ import { EditOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons-vu
import asyncLoader from '@/utils/asyncLoader' import asyncLoader from '@/utils/asyncLoader'
import ThemeProvider from '@/utils/ThemeProvider' import ThemeProvider from '@/utils/ThemeProvider'
import { globalToast } from '@/main' import { globalToast } from '@/main'
import useUserStore from '@/user/useUserStore'
import useRouterStore from '@/useRouterStore'
const SearchAdder = asyncLoader(() => import('./SearchAdder')) const SearchAdder = asyncLoader(() => import('./SearchAdder'))
const SearchItem = defineComponent({ const SearchItem = defineComponent({
props: { props: {
@ -157,7 +159,12 @@ export default defineComponent(() => {
block block
icon={<PlusOutlined />} icon={<PlusOutlined />}
onClick={() => { onClick={() => {
showAdder.value = null if (useUserStore().isLogin) {
showAdder.value = null
} else {
globalToast.warning('请先登录')
useRouterStore().go('global-login')
}
}} }}
> >

View File

@ -79,6 +79,9 @@ export default defineStore('user', () => {
localStorage.setItem('token', val) localStorage.setItem('token', val)
if (!val) return if (!val) return
if (!isLogin.value) {
return
}
const res = await request<UserInfo>('GET', '/api/profile') const res = await request<UserInfo>('GET', '/api/profile')
Object.assign(profile, res) Object.assign(profile, res)
}, },

View File

@ -5,6 +5,8 @@ import upload from './upload'
import 'viewerjs/dist/viewer.css' import 'viewerjs/dist/viewer.css'
import { api as showViewer } from 'v-viewer' import { api as showViewer } from 'v-viewer'
import { globalToast } from '@/main' import { globalToast } from '@/main'
import useUserStore from '@/user/useUserStore'
import useRouterStore from '@/useRouterStore'
addIcons(MdUpload, FaEye) addIcons(MdUpload, FaEye)
@ -33,6 +35,7 @@ export default defineComponent({
}, },
setup(props, ctx) { setup(props, ctx) {
let input: HTMLInputElement | null = null let input: HTMLInputElement | null = null
return () => ( return () => (
<div> <div>
<input <input
@ -62,7 +65,12 @@ export default defineComponent({
backgroundImage: `url('${props.value}')` backgroundImage: `url('${props.value}')`
}} }}
onClick={() => { onClick={() => {
input?.click() if (useUserStore().isLogin) {
input?.click()
} else {
globalToast.warning('请先登录')
useRouterStore().go('global-login')
}
}} }}
> >
{props.value ? ( {props.value ? (

View File

@ -3,141 +3,149 @@ import { defineComponent, ref, watch } from 'vue'
import { VueCropper } from 'vue-cropper' import { VueCropper } from 'vue-cropper'
import 'vue-cropper/dist/index.css' import 'vue-cropper/dist/index.css'
import upload from './upload' import upload from './upload'
import { v4 as uuid } from "uuid" import { v4 as uuid } from 'uuid'
import { MdCroprotateRound, BiPlusLg } from "oh-vue-icons/icons"; import { MdCroprotateRound, BiPlusLg } from 'oh-vue-icons/icons'
import { OhVueIcon, addIcons, } from 'oh-vue-icons' import { OhVueIcon, addIcons } from 'oh-vue-icons'
import NativeColorPicker from './NativeColorPicker' import NativeColorPicker from './NativeColorPicker'
import useUserStore from '@/user/useUserStore'
import { globalToast } from '@/main'
import useRouterStore from '@/useRouterStore'
addIcons(MdCroprotateRound, BiPlusLg) addIcons(MdCroprotateRound, BiPlusLg)
export default defineComponent({ export default defineComponent({
emits: {
'update:value': (() => true) as (val: string) => boolean
},
setup(props, ctx) {
const inputRef = ref<HTMLInputElement | null>(null)
const showCutModel = ref(false)
const originFile = ref('')
const fillColor = ref('transparent')
const cropper = ref<any>(null)
const handleFile = (e: any) => {
const target = e.target as HTMLInputElement
emits: { const file = target.files?.[0]
'update:value': (() => true) as (val: string) => boolean target.value = ''
},
setup(props, ctx) {
const inputRef = ref<HTMLInputElement | null>(null)
const showCutModel = ref(false)
const originFile = ref('')
const fillColor = ref('transparent')
const cropper = ref<any>(null)
const handleFile = (e: any) => {
const target = e.target as HTMLInputElement
const file = target.files?.[0] if (!file) return
target.value = '' // upload(file).then(res => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = (e: any) => {
originFile.value = e?.target.result // 显示原始图片
showCutModel.value = true
}
// emit('update:icon', res || '')
// })
}
const handleFinish = (blob: any) => {
// 根据前几个字节推测文件类型(这里只考虑常见的图片类型)
if (!file) return // 使用 FileReader 对象读取 Blob 的前几个字节
// upload(file).then(res => { const reader = new FileReader()
const reader = new FileReader() reader.onloadend = function () {
reader.readAsDataURL(file) // 打印 File 对象以验证
reader.onload = (e: any) => {
originFile.value = e?.target.result // 显示原始图片
showCutModel.value = true
}
// emit('update:icon', res || '')
// })
}
const handleFinish = (blob: any) => {
// 根据前几个字节推测文件类型(这里只考虑常见的图片类型)
// 使用 FileReader 对象读取 Blob 的前几个字节 const fileData = new File([blob], `${uuid()}.png`, {
const reader = new FileReader() type: 'image/jpg',
reader.onloadend = function () { lastModified: Date.now()
// 打印 File 对象以验证 })
upload(fileData, 'customIcon').then((res) => {
showCutModel.value = false
const fileData = new File([blob], `${uuid()}.png`, { ctx.emit('update:value', res || '')
type: 'image/jpg', })
lastModified: Date.now() }
}) reader.readAsArrayBuffer(blob)
upload(fileData, 'customIcon').then((res) => { }
showCutModel.value = false watch(
fillColor,
ctx.emit('update:value', res || '') (e: string) => {
}) const elements = document.querySelectorAll('.cropper-crop-box')
} elements.forEach((element: any) => {
reader.readAsArrayBuffer(blob) element.style.backgroundColor = e // 修改颜色为蓝色
} })
watch( },
fillColor, {
(e: string) => { immediate: true
const elements = document.querySelectorAll('.cropper-crop-box') }
elements.forEach((element: any) => { )
element.style.backgroundColor = e // 修改颜色为蓝色 return () => (
}) <>
}, <Modal
{ open={showCutModel.value}
immediate: true onCancel={() => (showCutModel.value = false)}
} onOk={() => {
) cropper.value.getCropBlob((blob: any) => {
return () => ( handleFinish(blob)
<> })
<Modal }}
open={showCutModel.value} >
onCancel={() => showCutModel.value = false} <div class="w-full flex flex-col items-center gap-y-2">
onOk={() => { <div
cropper.value.getCropBlob((blob: any) => { class="w-[250px] h-[250px]"
handleFinish(blob) style={{
backgroundColor: fillColor.value || 'transparent'
}) }}
}} >
> <VueCropper
<div class="w-full flex flex-col items-center gap-y-2"> ref={cropper}
<div class="w-[250px] h-[250px]" style={{ autoCropWidth="250px"
backgroundColor: fillColor.value || 'transparent', autoCropHeight="250px"
}}> mode="contain"
<VueCropper outputType="png"
ref={cropper} img={originFile.value}
autoCropWidth="250px" autoCrop={true}
autoCropHeight="250px" fillColor={fillColor.value}
mode="contain" />
outputType="png" </div>
img={originFile.value} <div class="flex justify-between w-[250px]">
autoCrop={true} {/* <ArrowRotateClockwise24Regular
fillColor={fillColor.value}
/>
</div>
<div class="flex justify-between w-[250px]">
{/* <ArrowRotateClockwise24Regular
class="text-[10px] w-8 h-8 cursor-pointer" class="text-[10px] w-8 h-8 cursor-pointer"
onClick={() => ($refs.cropper as any).rotateRight()} onClick={() => ($refs.cropper as any).rotateRight()}
/> */} /> */}
<span class="flex items-center cursor-pointer" <span
onClick={() => { class="flex items-center cursor-pointer"
cropper.value.rotateRight() onClick={() => {
}}> cropper.value.rotateRight()
<OhVueIcon name="md-croprotate-round" scale={1} fill="#707070" ></OhVueIcon> }}
>
</span> <OhVueIcon name="md-croprotate-round" scale={1} fill="#707070"></OhVueIcon>
<span class="flex items-center gap-x-1"> </span>
<svg <span class="flex items-center gap-x-1">
onClick={() => cropper.value?.changeScale(1)} <svg
class="icon cursor-pointer" onClick={() => cropper.value?.changeScale(1)}
viewBox="0 0 1024 1024" class="icon cursor-pointer"
width="2rem" viewBox="0 0 1024 1024"
height="2rem" width="2rem"
> height="2rem"
<path >
d="M886.51776 799.66208l-139.93984-139.93984c-10.50624-10.50624-23.90016-16.13824-37.60128-17.44896 42.16832-52.59264 67.54304-119.1936 67.54304-191.6928 0-169.39008-137.80992-307.2-307.2-307.2s-307.2 137.80992-307.2 307.2 137.80992 307.2 307.2 307.2c63.91808 0 123.31008-19.6608 172.52352-53.18656 0.34816 15.23712 6.22592 30.37184 17.85856 42.00448l139.93984 139.93984c11.9808 12.00128 27.72992 18.00192 43.43808 18.00192s31.45728-6.00064 43.43808-18.00192C910.52032 862.55616 910.52032 823.66464 886.51776 799.66208zM469.31968 655.38048c-112.92672 0-204.8-91.87328-204.8-204.8s91.87328-204.8 204.8-204.8 204.8 91.87328 204.8 204.8S582.2464 655.38048 469.31968 655.38048zM610.14016 450.58048c0 22.60992-18.35008 40.96-40.96 40.96l-56.32 0 0 56.32c0 22.60992-18.35008 40.96-40.96 40.96s-40.96-18.35008-40.96-40.96l0-56.32-56.32 0c-22.60992 0-40.96-18.35008-40.96-40.96s18.35008-40.96 40.96-40.96l56.32 0 0-56.32c0-22.60992 18.35008-40.96 40.96-40.96s40.96 18.35008 40.96 40.96l0 56.32 56.32 0C591.79008 409.62048 610.14016 427.95008 610.14016 450.58048z" <path
fill="#707070" d="M886.51776 799.66208l-139.93984-139.93984c-10.50624-10.50624-23.90016-16.13824-37.60128-17.44896 42.16832-52.59264 67.54304-119.1936 67.54304-191.6928 0-169.39008-137.80992-307.2-307.2-307.2s-307.2 137.80992-307.2 307.2 137.80992 307.2 307.2 307.2c63.91808 0 123.31008-19.6608 172.52352-53.18656 0.34816 15.23712 6.22592 30.37184 17.85856 42.00448l139.93984 139.93984c11.9808 12.00128 27.72992 18.00192 43.43808 18.00192s31.45728-6.00064 43.43808-18.00192C910.52032 862.55616 910.52032 823.66464 886.51776 799.66208zM469.31968 655.38048c-112.92672 0-204.8-91.87328-204.8-204.8s91.87328-204.8 204.8-204.8 204.8 91.87328 204.8 204.8S582.2464 655.38048 469.31968 655.38048zM610.14016 450.58048c0 22.60992-18.35008 40.96-40.96 40.96l-56.32 0 0 56.32c0 22.60992-18.35008 40.96-40.96 40.96s-40.96-18.35008-40.96-40.96l0-56.32-56.32 0c-22.60992 0-40.96-18.35008-40.96-40.96s18.35008-40.96 40.96-40.96l56.32 0 0-56.32c0-22.60992 18.35008-40.96 40.96-40.96s40.96 18.35008 40.96 40.96l0 56.32 56.32 0C591.79008 409.62048 610.14016 427.95008 610.14016 450.58048z"
/> fill="#707070"
</svg> />
<svg </svg>
onClick={() => cropper.value?.changeScale(-1)} <svg
class="icon cursor-pointer" onClick={() => cropper.value?.changeScale(-1)}
viewBox="0 0 1024 1024" class="icon cursor-pointer"
width="2rem" viewBox="0 0 1024 1024"
height="2rem" width="2rem"
> height="2rem"
<path >
d="M886.51776 799.66208l-139.93984-139.93984c-10.50624-10.50624-23.90016-16.13824-37.60128-17.44896 42.16832-52.59264 67.54304-119.1936 67.54304-191.6928 0-169.39008-137.80992-307.2-307.2-307.2s-307.2 137.80992-307.2 307.2 137.80992 307.2 307.2 307.2c63.91808 0 123.31008-19.6608 172.52352-53.18656 0.34816 15.23712 6.22592 30.37184 17.85856 42.00448l139.93984 139.93984c11.9808 12.00128 27.72992 18.00192 43.43808 18.00192s31.45728-6.00064 43.43808-18.00192C910.52032 862.55616 910.52032 823.66464 886.51776 799.66208zM469.31968 655.38048c-112.92672 0-204.8-91.87328-204.8-204.8s91.87328-204.8 204.8-204.8 204.8 91.87328 204.8 204.8S582.2464 655.38048 469.31968 655.38048zM610.14016 450.58048c0 22.60992-18.35008 40.96-40.96 40.96l-194.56 0c-22.60992 0-40.96-18.35008-40.96-40.96s18.35008-40.96 40.96-40.96l194.56 0C591.79008 409.62048 610.14016 427.95008 610.14016 450.58048z" <path
fill="#707070" d="M886.51776 799.66208l-139.93984-139.93984c-10.50624-10.50624-23.90016-16.13824-37.60128-17.44896 42.16832-52.59264 67.54304-119.1936 67.54304-191.6928 0-169.39008-137.80992-307.2-307.2-307.2s-307.2 137.80992-307.2 307.2 137.80992 307.2 307.2 307.2c63.91808 0 123.31008-19.6608 172.52352-53.18656 0.34816 15.23712 6.22592 30.37184 17.85856 42.00448l139.93984 139.93984c11.9808 12.00128 27.72992 18.00192 43.43808 18.00192s31.45728-6.00064 43.43808-18.00192C910.52032 862.55616 910.52032 823.66464 886.51776 799.66208zM469.31968 655.38048c-112.92672 0-204.8-91.87328-204.8-204.8s91.87328-204.8 204.8-204.8 204.8 91.87328 204.8 204.8S582.2464 655.38048 469.31968 655.38048zM610.14016 450.58048c0 22.60992-18.35008 40.96-40.96 40.96l-194.56 0c-22.60992 0-40.96-18.35008-40.96-40.96s18.35008-40.96 40.96-40.96l194.56 0C591.79008 409.62048 610.14016 427.95008 610.14016 450.58048z"
/> fill="#707070"
</svg> />
</span> </svg>
</div> </span>
<NativeColorPicker value={fillColor.value} onUpdate:value={e => fillColor.value = e} transparent={true} /> </div>
{/* {props.colorList && ( <NativeColorPicker
value={fillColor.value}
onUpdate:value={(e) => (fillColor.value = e)}
transparent={true}
/>
{/* {props.colorList && (
<div class="w-[250px] flex justify-center"> <div class="w-[250px] flex justify-center">
<NativeColorPicker <NativeColorPicker
colorList={colorList} colorList={colorList}
@ -147,23 +155,32 @@ export default defineComponent({
/> />
</div> </div>
)} */} )} */}
</div>
</div> </Modal>
</Modal > <div
<div class="w-full h-full bg-white flex items-center justify-center" class="w-full h-full bg-white flex items-center justify-center"
onClick={() => { onClick={() => {
inputRef.value?.click?.() if (useUserStore().isLogin) {
}} inputRef.value?.click?.()
> } else {
<OhVueIcon name={BiPlusLg.name} fill='#666666' scale={2}></OhVueIcon> globalToast.warning('请先登录')
</div> useRouterStore().go('global-login')
<input // useAdderPageStore().type = 2
ref={inputRef} }
style={{ }}
display: 'none' >
}} accept=".jpg,.jpeg,.png,.svg" type="file" onChange={handleFile} /> <OhVueIcon name={BiPlusLg.name} fill="#666666" scale={2}></OhVueIcon>
</> </div>
) <input
} ref={inputRef}
style={{
display: 'none'
}}
accept=".jpg,.jpeg,.png,.svg"
type="file"
onChange={handleFile}
/>
</>
)
}
}) })