完成问题反馈

This commit is contained in:
plightfield 2024-11-12 18:09:34 +08:00
parent b65584e4af
commit 3d7eec25b2
10 changed files with 194 additions and 20 deletions

View File

@ -2,16 +2,16 @@ export const aIUrl = 'https://metaso.cn/?s=uitab&referrer_s=uitab&q='
export const translateUrl = 'https://fanyi.baidu.com/mtpe-individual/multimodal?lang=zh2en&query='
// oss地址
export const ossBase = import.meta.env.PROD
? 'https://oss.goosetab.com'
: 'https://oss.goosetab.com'
? 'https://newfatfox.oss-cn-beijing.aliyuncs.com'
: 'https://newfatfox.oss-cn-beijing.aliyuncs.com'
// 前端地址
export const frontAddress = import.meta.env.PROD
? 'http://goosetab.com'
: 'http://goosetab.com'
export const frontAddress = import.meta.env.PROD ? 'http://goosetab.com' : 'http://goosetab.com'
// oss cdn 加速地址
export const ossCdnBase = import.meta.env.PROD ? ossBase : ossBase
export const ossCdnBase = import.meta.env.PROD
? 'https://oss.goosetab.com'
: 'https://oss.goosetab.com'
// 后端地址
export const apiBase = import.meta.env.PROD

View File

@ -25,8 +25,6 @@ export const Letter24 = [
'R'
]
export default defineComponent({
name: 'SiderSetting',
props: {},
setup() {
const settings = useSettingsStore()
const layout = useLayoutStore()
@ -71,7 +69,6 @@ export default defineComponent({
<span class={'w-[20px]'}>{idx + 1}</span>
<div
class={clsx(
'flex-1 bg-black/[0.05] border-[1px] py-1 rounded-lg relative flex items-center pl-4 border-transparent hover:border-[#ffa94d]'
)}
>

View File

@ -0,0 +1,169 @@
import { computed, defineComponent, reactive, toRaw } from 'vue'
import useLayoutStore from '../useLayoutStore'
import ImageUploader from '@/utils/ImageUploader'
import { MdInbox } from 'oh-vue-icons/icons'
import { addIcons, OhVueIcon } from 'oh-vue-icons'
import { message, Modal, Table } from 'ant-design-vue'
import request from '@/utils/request'
import db from '@/db'
addIcons(MdInbox)
export interface Feedback {
description: string
qq: string
phone: string
images: string[]
time: number
}
const defaultData: Omit<Feedback, 'time'> = {
description: '',
qq: '',
phone: '',
images: [] as string[]
}
export default defineComponent(() => {
const data = reactive({ ...defaultData })
const layout = useLayoutStore()
const isGame = computed(() => {
return layout.state.current === 0
})
const img1 = computed({
get: () => data.images[0],
set: (val) => (data.images[0] = val)
})
const img2 = computed({
get: () => data.images[1],
set: (val) => (data.images[1] = val)
})
const img3 = computed({
get: () => data.images[2],
set: (val) => (data.images[2] = val)
})
return () => (
<div class={'p-4 ' + (isGame.value ? 'text-white' : 'text-black/60')}>
<div class="flex justify-between items-center">
<div>
<span class="text-red-500">*</span>
</div>
<div
class="cursor-pointer"
onClick={async () => {
let his = await db.getItem<Feedback[]>('feedbacks')
if (!his) his = []
const ins = Modal.info({
title: '历史反馈',
width: '1024px',
maskClosable: true,
content: () => (
<Table
class="max-h-[50vh] overflow-y-auto"
dataSource={his.reverse()}
rowKey="time"
pagination={false}
columns={[
{
title: '时间',
customRender: ({ record }) => new Date(record.time).toLocaleString()
},
{
title: '问题描述',
customRender: ({ record }) => (
<div class="w-[200px] break-all">{record.description}</div>
)
},
{
title: 'QQ',
dataIndex: 'qq'
},
{
title: '手机号',
dataIndex: 'phone'
},
{
title: '图片',
customRender: ({ record }) => (
<div class="flex gap-2">
{record?.images?.map?.((img: string) => (
<img src={img} class="w-16 object-cover" />
))}
</div>
)
}
]}
></Table>
),
onOk() {
console.log('OK')
ins.destroy()
},
onCancel() {
ins.destroy()
}
})
}}
>
<OhVueIcon
name="md-inbox"
fill={isGame.value ? 'rgba(255,255,255,.8)' : 'rgba(0,0,0,.8)'}
/>
</div>
</div>
<div class={'mt-2 ' + (isGame.value ? 'bg-white/10 text-white' : 'bg-black/5 text-black/60')}>
<textarea
v-model={data.description}
class="bg-transparent no-textarea w-full p-2"
style={{
color: isGame.value ? 'white' : 'black'
}}
/>
<div class="p-2 flex gap-2">
<ImageUploader width={42} v-model:value={img1.value} />
<ImageUploader width={42} v-model:value={img2.value} />
<ImageUploader width={42} v-model:value={img3.value} />
</div>
</div>
<div class="mt-4"></div>
<div class="text-sm">便</div>
<div class="grid grid-cols-2 gap-2 text-sm mt-2">
<input
v-model={data.qq}
placeholder="QQ号"
class={'p-2 rounded-lg ' + (isGame.value ? 'bg-white/10' : 'bg-black/5')}
/>
<input
v-model={data.phone}
placeholder="手机号"
class={'p-2 rounded-lg ' + (isGame.value ? 'bg-white/10' : 'bg-black/5')}
/>
</div>
<div
onClick={async () => {
if (!data.description) {
message.error('问题描述不能为空')
return
}
let his = await db.getItem<Feedback[]>('feedbacks')
if (!his) his = []
await db.setItem('feedbacks', [...his, { ...toRaw(data), time: Date.now() }])
await request('POST', '/api/feedback', {
data: {
content: data.description,
qq: data.qq,
phone: data.phone,
imgs: data.images
},
returnType: 'text'
})
message.success('提交成功')
Object.assign(data, { ...defaultData })
}}
class="mt-4 text-center rounded py-1 cursor-pointer bg-[#ffa93d] text-white"
>
</div>
</div>
)
})

View File

@ -5,8 +5,6 @@ import clsx from 'clsx'
import { defineComponent } from 'vue'
export default defineComponent({
name: 'SiderSetting',
props: {},
setup() {
const settings = useSettingsStore()
return () => (
@ -18,7 +16,7 @@ export default defineComponent({
>
<Button type="primary"></Button>
</SettingItem>
<p class={"text-[#666] text-[12px]"}></p>
<p class={'text-[#666] text-[12px]'}></p>
</div>
)
}

View File

@ -5,8 +5,6 @@ import { defineComponent, ref } from 'vue'
import useSearchConfigStore from '../header/search/useSearchConfigStore'
export default defineComponent({
name: 'SearchSetting',
props: {},
setup() {
const settings = useSettingsStore()
const searchStore = useSearchConfigStore()

View File

@ -6,8 +6,6 @@ import { defineComponent } from 'vue'
import useLayoutStore from '../useLayoutStore'
export default defineComponent({
name: 'SiderSetting',
props: {},
setup() {
const settings = useSettingsStore()
const layout = useLayoutStore()

View File

@ -30,8 +30,6 @@ const list: {
}
]
export default defineComponent({
name: 'SearchSetting',
props: {},
setup() {
const settings = useSettingsStore()
const searchStore = useSearchConfigStore()

View File

@ -44,6 +44,19 @@
padding-top: 5px !important;
padding-bottom: 5px !important;
}
.no-textarea:focus {
outline: none !important;
border: none !important;
}
.no-textarea:hover {
outline: none !important;
border: none !important;
}
.no-textarea {
outline: none !important;
border: none !important;
}
:root {
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;

View File

@ -8,6 +8,7 @@ import SearchSetting from '@/layout/grid/SearchSetting'
import TimeSetting from '@/layout/grid/TimeSetting'
import SiderSetting from '@/layout/grid/SiderSetting'
import DockSetting from '@/layout/grid/DockSetting'
import Feedback from '@/layout/grid/Feedback'
import Reset from '@/layout/grid/Reset'
export default defineComponent(() => {
@ -32,6 +33,8 @@ export default defineComponent(() => {
<DockSetting />
) : router.path === 'settings-reset' ? (
<Reset />
) : router.path === 'settings-fallback' ? (
<Feedback />
) : null}
</ThemeProvider>
</div>

View File

@ -23,7 +23,7 @@ export default defineStore('user', () => {
watch(token, (val) => {
localStorage.setItem('token', val)
})
const profile = reactive({...defaultUserInfo})
const profile = reactive({ ...defaultUserInfo })
watch(
token,
(val) => {
@ -37,7 +37,7 @@ 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 = ''
}
// 自动备份