✨ 完成大作业部分及其打磨
This commit is contained in:
parent
3ab2c26776
commit
0622b15509
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const colorMode = useColorMode();
|
const colorMode = useColorMode();
|
||||||
|
useHead({
|
||||||
|
title: `Lichx's WebClass`,
|
||||||
|
});
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (colorMode.value === 'dark') {
|
if (colorMode.value === 'dark') {
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import BackButton from '~/components/BackButton.vue';
|
||||||
|
import { MdEditor } from 'md-editor-v3';
|
||||||
|
import 'md-editor-v3/lib/style.css';
|
||||||
|
|
||||||
|
const emit = defineEmits(['articleEditFinish']);
|
||||||
|
const { baseContent, baseTitle, saveButton } = defineProps({
|
||||||
|
baseContent: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
baseTitle: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
saveButton: {
|
||||||
|
type: String,
|
||||||
|
default: '保存文章',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const content = ref(baseContent);
|
||||||
|
const title = ref(baseTitle);
|
||||||
|
|
||||||
|
async function saveArticle() {
|
||||||
|
if (title.value === '' || content.value === '') {
|
||||||
|
await MessagePlugin.error('标题和正文不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('articleEditFinish', {
|
||||||
|
title: title.value,
|
||||||
|
content: content.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-6">
|
||||||
|
<back-button class="ml-3" />
|
||||||
|
<div
|
||||||
|
class="m-2 bg-white rounded-xl p-6 border-gray-200 border-2 min-h-[300px] dark:bg-neutral-800 dark:border-zinc-600"
|
||||||
|
>
|
||||||
|
<t-form @submit="saveArticle">
|
||||||
|
<t-form-item name="title" label="标题">
|
||||||
|
<t-input v-model="title"></t-input>
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item name="content" label="正文">
|
||||||
|
<MdEditor v-model="content" :theme="useColorMode().preference"/>
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item>
|
||||||
|
<t-button theme="primary" type="submit">{{ saveButton }}</t-button>
|
||||||
|
</t-form-item>
|
||||||
|
</t-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,7 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<t-button theme="primary" variant="base" @click="() => useRouter().back()">
|
||||||
|
<t-icon name="arrow-left" size="22px" />返回
|
||||||
|
</t-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,116 @@
|
||||||
|
<script setup lang="tsx">
|
||||||
|
import { ExampleUserInfo } from '~/stores/user';
|
||||||
|
|
||||||
|
const { avatarUrl, showWelcome, data } = defineProps({
|
||||||
|
avatarUrl: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
showWelcome: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: ExampleUserInfo,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function doShow(x: string) {
|
||||||
|
const notShow = [
|
||||||
|
'userAvatarPath',
|
||||||
|
'userAvatarUrl',
|
||||||
|
'userId',
|
||||||
|
'usernameOrEmail',
|
||||||
|
'lastGetTime',
|
||||||
|
];
|
||||||
|
for (const i of notShow) {
|
||||||
|
if (x === i) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function toChinese(x: string) {
|
||||||
|
const map = {
|
||||||
|
userName: '用户名',
|
||||||
|
userId: '用户ID',
|
||||||
|
userEmail: '邮箱',
|
||||||
|
phone: '手机号',
|
||||||
|
lastGetTime: '最后登录时间',
|
||||||
|
userAvatar: '头像',
|
||||||
|
userAmount: '余额',
|
||||||
|
userBirthday: '生日',
|
||||||
|
};
|
||||||
|
return map[x as keyof typeof map];
|
||||||
|
}
|
||||||
|
function getIcon(key: string) {
|
||||||
|
const map = {
|
||||||
|
userName: 'user',
|
||||||
|
userEmail: 'mail',
|
||||||
|
userAmount: 'money',
|
||||||
|
userBirthday: 'cake',
|
||||||
|
};
|
||||||
|
const val = map[key as keyof typeof map];
|
||||||
|
return <t-icon v-if="" class="t-menu__operations-icon" name={val} />;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-6">
|
||||||
|
<div class="m-2">
|
||||||
|
<slot name="header"></slot>
|
||||||
|
</div>
|
||||||
|
<div class="flex md:flex-row flex-col">
|
||||||
|
<div
|
||||||
|
class="flex-[1] m-2 h-full bg-white rounded-xl border-gray-200 border-2 min-h-[300px] min-w-48 dark:bg-zinc-800 dark:border-zinc-600"
|
||||||
|
>
|
||||||
|
<div class="flex flex-row md:flex-col justify-center p-4">
|
||||||
|
<t-image
|
||||||
|
:src="avatarUrl"
|
||||||
|
alt="头像"
|
||||||
|
:fit="'contain'"
|
||||||
|
shape="circle"
|
||||||
|
class="max-h-72 max-w-72 m-auto"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-if="showWelcome"
|
||||||
|
class="text-2xl ml-auto mr-auto md:mt-6 mt-20 mb-6"
|
||||||
|
>欢迎 {{ data.userName }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="flex-[2] m-2 bg-white rounded-xl border-gray-200 border-2 flex justify-center pt-8 min-w-[558px] dark:bg-[rgb(36,36,36)] dark:border-zinc-600"
|
||||||
|
>
|
||||||
|
<t-card
|
||||||
|
title="个人信息"
|
||||||
|
class="w-10/12 max-w-[700px]"
|
||||||
|
:bordered="false"
|
||||||
|
>
|
||||||
|
<t-row v-for="(value, key) of data" :key="key" class="w-full">
|
||||||
|
<div
|
||||||
|
v-if="doShow(key)"
|
||||||
|
class="border-collapse flex flex-row w-full h-10"
|
||||||
|
>
|
||||||
|
<t-col
|
||||||
|
class="flex-[1] flex justify-center border-2 items-center dark:border-zinc-600"
|
||||||
|
>{{ toChinese(key) }}</t-col
|
||||||
|
>
|
||||||
|
<t-col
|
||||||
|
class="flex-[2] border-2 flex items-center dark:border-zinc-600"
|
||||||
|
>
|
||||||
|
<span class="ml-4">
|
||||||
|
<component :is="getIcon(key)" />
|
||||||
|
{{ value }}
|
||||||
|
</span>
|
||||||
|
</t-col>
|
||||||
|
</div>
|
||||||
|
</t-row>
|
||||||
|
</t-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="less"></style>
|
|
@ -13,16 +13,11 @@
|
||||||
const pagination = defineModel<TableProps['pagination']>('pagination');
|
const pagination = defineModel<TableProps['pagination']>('pagination');
|
||||||
|
|
||||||
async function onPageChange(pageInfo: { current: number; pageSize: number }) {
|
async function onPageChange(pageInfo: { current: number; pageSize: number }) {
|
||||||
console.log('Page change');
|
|
||||||
console.log(pageInfo);
|
|
||||||
emit('pageChange', pageInfo);
|
emit('pageChange', pageInfo);
|
||||||
}
|
}
|
||||||
function onRowClick(x: RowEventContext<TableRowData>) {
|
function onRowClick(x: RowEventContext<TableRowData>) {
|
||||||
emit('onRowClick', x);
|
emit('onRowClick', x);
|
||||||
}
|
}
|
||||||
function onSelectChange() {
|
|
||||||
console.log('Select change');
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -37,7 +32,6 @@
|
||||||
:lazy-load="true"
|
:lazy-load="true"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@page-change="onPageChange"
|
@page-change="onPageChange"
|
||||||
@select-change="onSelectChange"
|
|
||||||
@row-click="onRowClick"
|
@row-click="onRowClick"
|
||||||
>
|
>
|
||||||
</t-table>
|
</t-table>
|
||||||
|
|
|
@ -12,12 +12,7 @@
|
||||||
);
|
);
|
||||||
const store = useUserStore();
|
const store = useUserStore();
|
||||||
const modeName = ref('sunny');
|
const modeName = ref('sunny');
|
||||||
// watch()
|
|
||||||
// computed(())
|
|
||||||
watch(useWindowSize().width, (val) => {
|
watch(useWindowSize().width, (val) => {
|
||||||
console.log(val);
|
|
||||||
console.log(collapsed.value);
|
|
||||||
console.log(manualCollapsed.value);
|
|
||||||
setCollapsed(val);
|
setCollapsed(val);
|
||||||
});
|
});
|
||||||
function setCollapsed(val: number) {
|
function setCollapsed(val: number) {
|
||||||
|
@ -42,8 +37,6 @@
|
||||||
|
|
||||||
function changeMode() {
|
function changeMode() {
|
||||||
const x = useColorMode();
|
const x = useColorMode();
|
||||||
console.log(x.preference);
|
|
||||||
console.log(x.value);
|
|
||||||
if (x.preference === 'light') {
|
if (x.preference === 'light') {
|
||||||
x.preference = 'dark';
|
x.preference = 'dark';
|
||||||
modeName.value = 'moon';
|
modeName.value = 'moon';
|
||||||
|
@ -56,7 +49,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function changeTheme() {
|
function changeTheme() {
|
||||||
console.log(theme.theme);
|
|
||||||
if (theme.theme === 'default') {
|
if (theme.theme === 'default') {
|
||||||
theme.setTheme('test');
|
theme.setTheme('test');
|
||||||
} else if (theme.theme === 'test') {
|
} else if (theme.theme === 'test') {
|
||||||
|
@ -98,7 +90,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<t-layout class="h-full">
|
<t-layout class="h-screen w-screen">
|
||||||
<t-header>
|
<t-header>
|
||||||
<t-head-menu value="item1" height="120px">
|
<t-head-menu value="item1" height="120px">
|
||||||
<span class="text-xl">李晨鑫 的 Web 实验</span>
|
<span class="text-xl">李晨鑫 的 Web 实验</span>
|
||||||
|
@ -203,8 +195,8 @@
|
||||||
</template>
|
</template>
|
||||||
</t-menu>
|
</t-menu>
|
||||||
</t-aside>
|
</t-aside>
|
||||||
<t-layout>
|
<t-layout class="overflow-auto">
|
||||||
<t-content class="overflow-auto">
|
<t-content>
|
||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
</t-content>
|
</t-content>
|
||||||
<t-footer class="m-auto">
|
<t-footer class="m-auto">
|
||||||
|
@ -221,10 +213,12 @@
|
||||||
:deep(.t-layout__sider) {
|
:deep(.t-layout__sider) {
|
||||||
@apply w-16;
|
@apply w-16;
|
||||||
}
|
}
|
||||||
|
height: calc(100vh - 56px);
|
||||||
}
|
}
|
||||||
.non-collapsed {
|
.non-collapsed {
|
||||||
:deep(.t-layout__sider) {
|
:deep(.t-layout__sider) {
|
||||||
@apply w-60;
|
@apply w-60;
|
||||||
}
|
}
|
||||||
|
height: calc(100vh - 56px);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { MdPreview } from 'md-editor-v3';
|
||||||
|
import 'md-editor-v3/lib/style.css';
|
||||||
|
import BackButton from '~/components/BackButton.vue';
|
||||||
|
const store = useArticleStore();
|
||||||
|
const content = store.currentArticle.content;
|
||||||
|
const title = store.currentArticle.title;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="p-6">
|
||||||
|
<back-button class="ml-3" />
|
||||||
|
<div
|
||||||
|
class="m-2 bg-white rounded-xl p-6 border-gray-200 border-2 min-h-[300px] dark:bg-black dark:border-zinc-600"
|
||||||
|
>
|
||||||
|
<span class="text-4xl">{{ title }}</span>
|
||||||
|
<MdPreview
|
||||||
|
v-model="content"
|
||||||
|
:theme="useColorMode().preference"
|
||||||
|
class="mt-6"
|
||||||
|
></MdPreview>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
const store = useArticleStore();
|
||||||
|
const content = ref(store.currentArticle.content);
|
||||||
|
const title = ref(store.currentArticle.title);
|
||||||
|
|
||||||
|
async function saveArticle(data: { title: string; content: string }) {
|
||||||
|
store.currentArticle.title = data.title;
|
||||||
|
store.currentArticle.content = data.content;
|
||||||
|
await store.modifyArticle();
|
||||||
|
useRouter().back();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<ArticleEditor
|
||||||
|
:base-content="content"
|
||||||
|
:base-title="title"
|
||||||
|
:save-button="'更改文章'"
|
||||||
|
@article-edit-finish="saveArticle"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="less"></style>
|
|
@ -1,11 +1,125 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="tsx">
|
||||||
|
import SuperTable from '~/components/SuperTable.vue';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import type { TableProps, TableRowData } from 'tdesign-vue-next';
|
||||||
|
import { useWindowSize } from '@vueuse/core';
|
||||||
|
|
||||||
|
const store = useArticleStore();
|
||||||
|
const { pagination, articleList } = storeToRefs(store);
|
||||||
|
|
||||||
|
const columns = ref<TableProps['columns']>([
|
||||||
|
{
|
||||||
|
colKey: 'index',
|
||||||
|
title: '序号',
|
||||||
|
cell: (_, { rowIndex }: { rowIndex: number }) => (
|
||||||
|
<div>
|
||||||
|
{(pagination.value!.current! - 1) * pagination.value!.pageSize! +
|
||||||
|
rowIndex +
|
||||||
|
1}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colKey: 'name',
|
||||||
|
title: '作者姓名',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colKey: 'amount',
|
||||||
|
title: '文章数量',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
colKey: 'operator',
|
||||||
|
title: '操作',
|
||||||
|
cell: (_, { row }) => (
|
||||||
|
<div class="w-40 flex flex-row justify-evenly">
|
||||||
|
<t-button onClick={() => manageArticle(row)}>进入文章管理</t-button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
function pageChange(x: { current: number; pageSize: number }) {
|
||||||
|
if (pagination.value) {
|
||||||
|
pagination.value.current = x.current;
|
||||||
|
pagination.value.pageSize = x.pageSize;
|
||||||
|
store.getArticleList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function manageArticle(row: TableRowData) {
|
||||||
|
const router = useRouter();
|
||||||
|
router.push(`/base/articleManage/${row.id}`);
|
||||||
|
// router.push()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await store.getTotal();
|
||||||
|
await store.getArticleList();
|
||||||
|
const chartDom = document.getElementById('echarts')!;
|
||||||
|
const chart = echarts.init(chartDom);
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: '柱状图示例',
|
||||||
|
left: 'center',
|
||||||
|
},
|
||||||
|
tooltip: {},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: articleList.value.map((item: ArticleUser) => item.name),
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: articleList.value.map((item: ArticleUser) => item.amount),
|
||||||
|
type: 'bar',
|
||||||
|
itemStyle: {
|
||||||
|
color: (params: { dataIndex: number }) => {
|
||||||
|
const colors = [
|
||||||
|
'#f1dbc3',
|
||||||
|
'#7493a8',
|
||||||
|
'#edc5ac',
|
||||||
|
'#cdaba2',
|
||||||
|
'#abb0b3',
|
||||||
|
'#cfc2b9',
|
||||||
|
'#a2979f',
|
||||||
|
];
|
||||||
|
return colors[params.dataIndex % colors.length];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
chart.setOption(option);
|
||||||
|
watch(useWindowSize().width, (_val) => {
|
||||||
|
chart.resize();
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div class="p-6">
|
||||||
|
<div class="flex md:flex-row flex-col">
|
||||||
|
<div
|
||||||
|
class="flex-[1] m-2 p-6 bg-white rounded-xl dark:bg-zinc-800 border-2 dark:border-zinc-600"
|
||||||
|
>
|
||||||
|
<SuperTable
|
||||||
|
v-model:pagination="pagination"
|
||||||
|
:data="articleList"
|
||||||
|
:columns="columns"
|
||||||
|
:loading="false"
|
||||||
|
@page-change="pageChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="m-2 flex-[1] p-6 bg-white dark:bg-zinc-800 border-2 dark:border-zinc-600 rounded-xl"
|
||||||
|
>
|
||||||
|
<div id="echarts" class="w-full h-96"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less"></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
try {
|
try {
|
||||||
avatarURL.value = (await useUserStore().getAvatarURL())!;
|
avatarURL.value = (await useUserStore().getAvatarURL())!;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
await MessagePlugin.error(e as string);
|
||||||
}
|
}
|
||||||
console.log(avatarURL.value);
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -37,5 +36,3 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="less"></style>
|
|
||||||
|
|
|
@ -1,99 +1,15 @@
|
||||||
<script setup lang="tsx">
|
<script setup lang="ts">
|
||||||
useSystemStore().currentPage = 'home';
|
import BasicInfo from '~/components/BasicInfo.vue';
|
||||||
const avatarURL = ref('');
|
const avatarURL = ref('');
|
||||||
|
useSystemStore().currentPage = 'home';
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
avatarURL.value = (await useUserStore().getAvatarURL())!;
|
avatarURL.value = (await useUserStore().getAvatarURL())!;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
await MessagePlugin.error(e as string);
|
||||||
}
|
}
|
||||||
console.log(avatarURL.value);
|
|
||||||
});
|
});
|
||||||
function doShow(x: string) {
|
|
||||||
const notShow = ['userAvatar', 'userId', 'usernameOrEmail', 'lastGetTime'];
|
|
||||||
for (const i of notShow) {
|
|
||||||
if (x === i) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
function toChinese(x: string) {
|
|
||||||
const map = {
|
|
||||||
userName: '用户名',
|
|
||||||
userId: '用户ID',
|
|
||||||
userEmail: '邮箱',
|
|
||||||
phone: '手机号',
|
|
||||||
lastGetTime: '最后登录时间',
|
|
||||||
userAvatar: '头像',
|
|
||||||
userAmount: '余额',
|
|
||||||
userBirthday: '生日',
|
|
||||||
};
|
|
||||||
return map[x as keyof typeof map];
|
|
||||||
}
|
|
||||||
function getIcon(key: string) {
|
|
||||||
const map = {
|
|
||||||
userName: 'user',
|
|
||||||
userEmail: 'mail',
|
|
||||||
userAmount: 'money',
|
|
||||||
userBirthday: 'cake',
|
|
||||||
};
|
|
||||||
const val = map[key as keyof typeof map];
|
|
||||||
return <t-icon v-if="" class="t-menu__operations-icon" name={val} />;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="p-6">
|
<BasicInfo :avatar-url="avatarURL" :data="useUserStore().$state" />
|
||||||
<div class="flex md:flex-row flex-col">
|
|
||||||
<div
|
|
||||||
class="flex-[1] m-2 h-full bg-white rounded-xl border-gray-200 border-2 min-h-[300px] min-w-48"
|
|
||||||
>
|
|
||||||
<div class="flex flex-row md:flex-col justify-center p-4">
|
|
||||||
<t-image
|
|
||||||
:src="avatarURL"
|
|
||||||
alt="头像"
|
|
||||||
:fit="'contain'"
|
|
||||||
shape="circle"
|
|
||||||
class="max-h-72 max-w-72 m-auto"
|
|
||||||
/>
|
|
||||||
<span class="text-2xl ml-auto mr-auto md:mt-6 mt-20 mb-6"
|
|
||||||
>欢迎 {{ useUserStore().userName }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="flex-[2] m-2 bg-white rounded-xl border-gray-200 border-2 flex justify-center pt-8 min-w-[558px]"
|
|
||||||
>
|
|
||||||
<t-card
|
|
||||||
title="个人信息"
|
|
||||||
class="w-10/12 max-w-[700px]"
|
|
||||||
:bordered="false"
|
|
||||||
>
|
|
||||||
<t-row
|
|
||||||
v-for="(value, key) of useUserStore().$state"
|
|
||||||
:key="key"
|
|
||||||
class="w-full"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-if="doShow(key)"
|
|
||||||
class="border-collapse flex flex-row w-full h-10"
|
|
||||||
>
|
|
||||||
<t-col
|
|
||||||
class="flex-[1] flex justify-center border-2 items-center"
|
|
||||||
>{{ toChinese(key) }}</t-col
|
|
||||||
>
|
|
||||||
<t-col class="flex-[2] border-2 flex items-center">
|
|
||||||
<span class="ml-4">
|
|
||||||
<component :is="getIcon(key)" />
|
|
||||||
{{ value }}
|
|
||||||
</span>
|
|
||||||
</t-col>
|
|
||||||
</div>
|
|
||||||
</t-row>
|
|
||||||
</t-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="less"></style>
|
|
||||||
|
|
|
@ -45,7 +45,6 @@
|
||||||
for (const [key, value] of Object.entries(cityDataTyped['00']!)) {
|
for (const [key, value] of Object.entries(cityDataTyped['00']!)) {
|
||||||
if (value === name) {
|
if (value === name) {
|
||||||
provinceIndex.value = key;
|
provinceIndex.value = key;
|
||||||
console.log('finish');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import SuperTable from '~/components/SuperTable.vue';
|
import SuperTable from '~/components/SuperTable.vue';
|
||||||
import type { TableProps, TableRowData } from 'tdesign-vue-next';
|
import type { TableProps, TableRowData } from 'tdesign-vue-next';
|
||||||
import PeopleForm from '~/pages/base/index/peopleManage/components/PeopleForm.vue';
|
import PeopleForm from '~/pages/base/index/peopleManage/components/PeopleForm.vue';
|
||||||
|
import { TButton } from '#components';
|
||||||
const store = usePeopleStore();
|
const store = usePeopleStore();
|
||||||
|
|
||||||
const { peopleList, pagination, situation } = storeToRefs(usePeopleStore());
|
const { peopleList, pagination, situation } = storeToRefs(usePeopleStore());
|
||||||
|
@ -46,12 +46,23 @@
|
||||||
{
|
{
|
||||||
colKey: 'operator',
|
colKey: 'operator',
|
||||||
title: '操作',
|
title: '操作',
|
||||||
cell: (_, { row }) => (
|
cell: (_, { row }) =>
|
||||||
<div class="w-40 flex flex-row justify-evenly">
|
h('div', { class: 'w-40 flex flex-row justify-evenly' }, [
|
||||||
<t-button onClick={() => editUser(row)}>编辑</t-button>
|
h(
|
||||||
<t-button onClick={() => deleteUser(row)}>删除</t-button>
|
TButton,
|
||||||
</div>
|
{
|
||||||
),
|
onClick: () => editUser(row),
|
||||||
|
},
|
||||||
|
{ default: () => '编辑' },
|
||||||
|
),
|
||||||
|
h(
|
||||||
|
TButton,
|
||||||
|
{
|
||||||
|
onClick: () => showDeleteUserDialog(row),
|
||||||
|
},
|
||||||
|
{ default: () => '删除' },
|
||||||
|
),
|
||||||
|
]),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -63,29 +74,34 @@
|
||||||
await store.getTotal();
|
await store.getTotal();
|
||||||
});
|
});
|
||||||
|
|
||||||
function editUser(_row: TableRowData) {
|
function editUser(row: TableRowData) {
|
||||||
if (form.value) form.value.resetForm();
|
if (form.value) form.value.resetForm();
|
||||||
store.currentForm = {
|
store.currentForm = {
|
||||||
...peopleList.value.find((e) => e.id === _row.id)!,
|
...peopleList.value.find((e) => e.id === row.id)!,
|
||||||
} as PeopleInfo;
|
} as PeopleInfo;
|
||||||
console.log(store.currentForm.province);
|
|
||||||
form.value?.setProvinceIndexByName(store.currentForm.province);
|
form.value?.setProvinceIndexByName(store.currentForm.province);
|
||||||
console.log(store.currentForm);
|
|
||||||
store.showEditPeople = true;
|
store.showEditPeople = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteUser(_row: TableRowData) {
|
const showDeleteDialog = ref(false);
|
||||||
store.deletePeople(_row.id);
|
let deleteRowId = 0;
|
||||||
console.log(_row);
|
|
||||||
|
function showDeleteUserDialog(row: TableRowData) {
|
||||||
|
deleteRowId = row.id;
|
||||||
|
showDeleteDialog.value = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pageChange(x: { current: number; pageSize: number }) {
|
function deleteUser() {
|
||||||
|
showDeleteDialog.value = false;
|
||||||
|
store.deletePeople(deleteRowId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pageChange(x: { current: number; pageSize: number }) {
|
||||||
if (pagination.value) {
|
if (pagination.value) {
|
||||||
pagination.value.current = x.current;
|
pagination.value.current = x.current;
|
||||||
pagination.value.pageSize = x.pageSize;
|
pagination.value.pageSize = x.pageSize;
|
||||||
store.getPeopleList();
|
await store.getPeopleList();
|
||||||
}
|
}
|
||||||
console.log(store.pagination);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function doSearch() {
|
async function doSearch() {
|
||||||
|
@ -147,6 +163,15 @@
|
||||||
<people-form ref="form" />
|
<people-form ref="form" />
|
||||||
</template>
|
</template>
|
||||||
</t-dialog>
|
</t-dialog>
|
||||||
|
<t-dialog
|
||||||
|
v-model:visible="showDeleteDialog"
|
||||||
|
header="你确定吗?"
|
||||||
|
width="40%"
|
||||||
|
:confirm-on-enter="true"
|
||||||
|
:on-confirm="deleteUser"
|
||||||
|
>
|
||||||
|
此操作将永久删除该人员,确定吗?
|
||||||
|
</t-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
await router.push('/base/home');
|
await router.push('/base/home');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
loginForm.value.usernameOrEmail = '';
|
||||||
|
loginForm.value.password = '';
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -47,7 +51,7 @@
|
||||||
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full border-4 border-gray-200 w-10 h-10 bg-loginBG"
|
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full border-4 border-gray-200 w-10 h-10 bg-loginBG"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-1"
|
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-1 dark:text-black"
|
||||||
>or
|
>or
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
:label-width="10"
|
:label-width="10"
|
||||||
:data="registerForm"
|
:data="registerForm"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
@submit="() => store.register()"
|
@submit="() => store.register(backToLogin)"
|
||||||
>
|
>
|
||||||
<t-form-item name="email">
|
<t-form-item name="email">
|
||||||
<div class="flex flex-row items-center gap-2">
|
<div class="flex flex-row items-center gap-2">
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
:data="resetForm"
|
:data="resetForm"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
class="flex flex-col items-center gap-4"
|
class="flex flex-col items-center gap-4"
|
||||||
@submit="store.reset()"
|
@submit="store.reset(backToLogin)"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex md:flex-row items-center md:justify-center w-full flex-col gap-4 md:gap-0"
|
class="flex md:flex-row items-center md:justify-center w-full flex-col gap-4 md:gap-0"
|
||||||
|
|
|
@ -67,6 +67,5 @@ export const $http: HTTP = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default defineNuxtPlugin((nuxtApp) => {
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
console.log('$http', $http);
|
|
||||||
nuxtApp.provide('http', $http);
|
nuxtApp.provide('http', $http);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
export type Article = {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
mainIdea: string;
|
||||||
|
content: string;
|
||||||
|
};
|
||||||
|
export type ArticleUser = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
amount: number;
|
||||||
|
};
|
||||||
|
type ArticleStore = {
|
||||||
|
articleList: ArticleUser[];
|
||||||
|
pagination: BasicPagination;
|
||||||
|
currentManageUser: UserInfo;
|
||||||
|
currentUserAvatar: string;
|
||||||
|
currentUserLastGetTime: Date;
|
||||||
|
currentUserArticleList: Article[];
|
||||||
|
currentUserPagination: BasicPagination;
|
||||||
|
currentArticle: Article;
|
||||||
|
};
|
||||||
|
export const useArticleStore = defineStore('Article', {
|
||||||
|
state: (): ArticleStore => ({
|
||||||
|
articleList: [],
|
||||||
|
pagination: {
|
||||||
|
current: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
defaultPageSize: 5,
|
||||||
|
total: 0,
|
||||||
|
defaultCurrent: 1,
|
||||||
|
},
|
||||||
|
currentManageUser: {
|
||||||
|
userId: '',
|
||||||
|
userName: '',
|
||||||
|
userEmail: '',
|
||||||
|
userAvatarPath: '',
|
||||||
|
userAmount: '',
|
||||||
|
userBirthday: '',
|
||||||
|
},
|
||||||
|
currentUserAvatar: '',
|
||||||
|
currentUserLastGetTime: new Date(),
|
||||||
|
currentUserArticleList: [],
|
||||||
|
currentUserPagination: {
|
||||||
|
current: 1,
|
||||||
|
pageSize: 5,
|
||||||
|
defaultPageSize: 5,
|
||||||
|
total: 0,
|
||||||
|
defaultCurrent: 1,
|
||||||
|
},
|
||||||
|
currentArticle: {
|
||||||
|
id: 0,
|
||||||
|
title: '',
|
||||||
|
mainIdea: '',
|
||||||
|
content: '',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
async modifyArticle() {
|
||||||
|
const { $http } = useNuxtApp();
|
||||||
|
try {
|
||||||
|
await $http.POST('/article/updateArticle', {
|
||||||
|
...this.currentArticle,
|
||||||
|
author: this.currentManageUser.userName,
|
||||||
|
});
|
||||||
|
this.getCurrentManageUserArticleList();
|
||||||
|
} catch (error) {
|
||||||
|
await MessagePlugin.error('Error adding article:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async deleteArticle(id: number) {
|
||||||
|
const { $http } = useNuxtApp();
|
||||||
|
try {
|
||||||
|
await $http.GET('/article/deleteArticle', {
|
||||||
|
id: '' + id,
|
||||||
|
});
|
||||||
|
this.getCurrentManageUserArticleList();
|
||||||
|
} catch (error) {
|
||||||
|
await MessagePlugin.error('Error deleting article:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async addNewArticle() {
|
||||||
|
const { $http } = useNuxtApp();
|
||||||
|
try {
|
||||||
|
await $http.POST('/article/addArticle', {
|
||||||
|
...this.currentArticle,
|
||||||
|
author: this.currentManageUser.userName,
|
||||||
|
});
|
||||||
|
this.getCurrentManageUserArticleList();
|
||||||
|
} catch (error) {
|
||||||
|
await MessagePlugin.error('Error adding article:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getCurrentManageUserArticleList() {
|
||||||
|
const { $http } = useNuxtApp();
|
||||||
|
try {
|
||||||
|
const res = await $http.GET<{ records: Article[] }>(
|
||||||
|
`/article/page/${this.currentManageUser.userName}`,
|
||||||
|
{
|
||||||
|
page: '' + this.pagination!.current,
|
||||||
|
size: '' + this.pagination!.pageSize,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
this.currentUserArticleList = res.data.records;
|
||||||
|
} catch (error) {
|
||||||
|
await MessagePlugin.error('Error fetching people list:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getCurrentManageUserArticleTotal() {
|
||||||
|
const { $http } = useNuxtApp();
|
||||||
|
try {
|
||||||
|
const res = await $http.GET<number>(
|
||||||
|
`/article/total/${this.currentManageUser.userName}`,
|
||||||
|
);
|
||||||
|
console.log(res.data);
|
||||||
|
this.currentUserPagination.total = res.data;
|
||||||
|
if (
|
||||||
|
(this.currentUserPagination!.current - 1) *
|
||||||
|
this.currentUserPagination!.pageSize >
|
||||||
|
this.currentUserPagination!.total
|
||||||
|
) {
|
||||||
|
this.currentUserPagination!.current = Math.ceil(
|
||||||
|
this.currentUserPagination!.total /
|
||||||
|
this.currentUserPagination!.pageSize,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
await MessagePlugin.error('Error fetching article total:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getCurrentManageUserAvatar(forceUpdate: boolean = false) {
|
||||||
|
const now = new Date();
|
||||||
|
if (
|
||||||
|
!forceUpdate &&
|
||||||
|
this.currentUserAvatar !== '' &&
|
||||||
|
now.getTime() - this.currentUserLastGetTime.getTime() < 1000 * 60 * 9
|
||||||
|
) {
|
||||||
|
return this.currentUserAvatar;
|
||||||
|
}
|
||||||
|
const { $http } = useNuxtApp();
|
||||||
|
try {
|
||||||
|
const res = await $http.GET<string>('/article/userAvatar', {
|
||||||
|
userId: this.currentManageUser.userId,
|
||||||
|
});
|
||||||
|
this.currentUserAvatar = res.data;
|
||||||
|
return this.currentUserAvatar;
|
||||||
|
} catch (error) {
|
||||||
|
await MessagePlugin.error(
|
||||||
|
'Error fetching article user avatar:' + error,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getCurrentManageUserInfo(userId: string) {
|
||||||
|
const { $http } = useNuxtApp();
|
||||||
|
try {
|
||||||
|
const res = await $http.GET<UserInfo>('/article/userInfo', {
|
||||||
|
userId: userId,
|
||||||
|
});
|
||||||
|
this.currentManageUser = res.data;
|
||||||
|
} catch (error) {
|
||||||
|
await MessagePlugin.error('Error fetching article user info:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getArticleList() {
|
||||||
|
const { $http } = useNuxtApp();
|
||||||
|
try {
|
||||||
|
const res = await $http.GET<{ records: ArticleUser[] }>(
|
||||||
|
'/article/page',
|
||||||
|
{
|
||||||
|
page: '' + this.pagination!.current,
|
||||||
|
size: '' + this.pagination!.pageSize,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
this.articleList = res.data.records;
|
||||||
|
} catch (error) {
|
||||||
|
await MessagePlugin.error('Error fetching article list:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getTotal() {
|
||||||
|
const { $http } = useNuxtApp();
|
||||||
|
try {
|
||||||
|
const res = await $http.GET<number>('/article/total');
|
||||||
|
this.pagination.total = res.data;
|
||||||
|
if (
|
||||||
|
(this.pagination!.current - 1) * this.pagination!.pageSize >
|
||||||
|
this.pagination!.total
|
||||||
|
) {
|
||||||
|
this.pagination!.current = Math.ceil(
|
||||||
|
this.pagination!.total / this.pagination!.pageSize,
|
||||||
|
);
|
||||||
|
this.getArticleList();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
await MessagePlugin.error('Error fetching article total:' + error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
|
@ -79,7 +79,7 @@ export const useLoginStore = defineStore('Login', {
|
||||||
email: email,
|
email: email,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
await MessagePlugin.error(e as string);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (result.code === 200) {
|
if (result.code === 200) {
|
||||||
|
@ -106,19 +106,20 @@ export const useLoginStore = defineStore('Login', {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
async register() {
|
async register(recallWhenSuccess: () => void) {
|
||||||
const { $http } = useNuxtApp();
|
const { $http } = useNuxtApp();
|
||||||
try {
|
try {
|
||||||
await $http.POST('/login/register', this.registerForm);
|
await $http.POST('/login/register', this.registerForm);
|
||||||
|
recallWhenSuccess();
|
||||||
} catch {
|
} catch {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async reset() {
|
async reset(recallWhenSuccess: () => void) {
|
||||||
console.log(this.resetForm);
|
|
||||||
const { $http } = useNuxtApp();
|
const { $http } = useNuxtApp();
|
||||||
try {
|
try {
|
||||||
await $http.POST('/login/passwordReset', this.resetForm);
|
await $http.POST('/login/passwordReset', this.resetForm);
|
||||||
|
recallWhenSuccess();
|
||||||
} catch {
|
} catch {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -144,7 +145,6 @@ export const useLoginStore = defineStore('Login', {
|
||||||
case PageType.reset:
|
case PageType.reset:
|
||||||
return '重置密码';
|
return '重置密码';
|
||||||
default:
|
default:
|
||||||
console.log('未知');
|
|
||||||
return '未知';
|
return '未知';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -58,9 +58,8 @@ export const usePeopleStore = defineStore('People', {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.peopleList = res.data.records;
|
this.peopleList = res.data.records;
|
||||||
console.log(this.peopleList);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching people list:', error);
|
await MessagePlugin.error('Error fetching people list:' + error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async getTotal() {
|
async getTotal() {
|
||||||
|
@ -79,12 +78,11 @@ export const usePeopleStore = defineStore('People', {
|
||||||
);
|
);
|
||||||
this.getPeopleList();
|
this.getPeopleList();
|
||||||
}
|
}
|
||||||
} catch {
|
} catch (error) {
|
||||||
return;
|
await MessagePlugin.error('Error fetching people total:' + error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async addPeople() {
|
async addPeople() {
|
||||||
console.log('add');
|
|
||||||
const { $http } = useNuxtApp();
|
const { $http } = useNuxtApp();
|
||||||
try {
|
try {
|
||||||
await $http.POST('/userManager/addUser', this.currentForm);
|
await $http.POST('/userManager/addUser', this.currentForm);
|
||||||
|
|
|
@ -2,36 +2,45 @@ export interface UserInfo {
|
||||||
userId: string;
|
userId: string;
|
||||||
userName: string;
|
userName: string;
|
||||||
userEmail: string;
|
userEmail: string;
|
||||||
userAvatar: string;
|
userAvatarPath: string;
|
||||||
userAmount: string;
|
userAmount: string;
|
||||||
userBirthday: string;
|
userBirthday: string;
|
||||||
lastGetTime: Date;
|
}
|
||||||
|
export class ExampleUserInfo implements UserInfo {
|
||||||
|
userId = '';
|
||||||
|
userName = '';
|
||||||
|
userEmail = '';
|
||||||
|
userAvatarPath = '';
|
||||||
|
userAmount = '0';
|
||||||
|
userBirthday = '';
|
||||||
}
|
}
|
||||||
export interface UserState extends UserInfo {
|
export interface UserState extends UserInfo {
|
||||||
|
lastGetTime: Date;
|
||||||
usernameOrEmail: string;
|
usernameOrEmail: string;
|
||||||
|
userAvatarUrl: string;
|
||||||
}
|
}
|
||||||
export const useUserStore = defineStore('User', {
|
export const useUserStore = defineStore('User', {
|
||||||
state: (): UserState => ({
|
state: (): UserState => ({
|
||||||
usernameOrEmail: '',
|
|
||||||
userId: '',
|
userId: '',
|
||||||
userName: '',
|
userName: '',
|
||||||
userEmail: '',
|
userEmail: '',
|
||||||
userAvatar: '',
|
userAvatarPath: '',
|
||||||
userAmount: '',
|
userAmount: '',
|
||||||
userBirthday: '',
|
userBirthday: '',
|
||||||
lastGetTime: new Date(),
|
lastGetTime: new Date(),
|
||||||
|
usernameOrEmail: '',
|
||||||
|
userAvatarUrl: '',
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
async getUserInfo() {
|
async getUserInfo() {
|
||||||
const { $http } = useNuxtApp();
|
const { $http } = useNuxtApp();
|
||||||
try {
|
try {
|
||||||
const res = await $http.GET<UserInfo>('/user/info');
|
const res = await $http.GET<UserInfo>('/user/info');
|
||||||
console.log(res.data);
|
|
||||||
this.userId = res.data.userId;
|
this.userId = res.data.userId;
|
||||||
this.userName = res.data.userName;
|
this.userName = res.data.userName;
|
||||||
this.userEmail = res.data.userEmail;
|
this.userEmail = res.data.userEmail;
|
||||||
this.userAvatar = res.data.userAvatar;
|
this.userAvatarPath = res.data.userAvatarPath;
|
||||||
this.userAmount = '500';
|
this.userAmount = res.data.userAmount;
|
||||||
this.userBirthday = res.data.userBirthday;
|
this.userBirthday = res.data.userBirthday;
|
||||||
this.lastGetTime = new Date();
|
this.lastGetTime = new Date();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -40,14 +49,23 @@ export const useUserStore = defineStore('User', {
|
||||||
},
|
},
|
||||||
async getAvatarURL() {
|
async getAvatarURL() {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
if (now.getTime() - this.lastGetTime.getTime() < 1000 * 60 * 9) {
|
console.log('Current time:', now);
|
||||||
return this.userAvatar;
|
if (
|
||||||
|
this.userAvatarUrl !== '' &&
|
||||||
|
now.getTime() - this.lastGetTime.getTime() < 1000 * 60 * 9
|
||||||
|
) {
|
||||||
|
console.log('Using cached avatar URL');
|
||||||
|
console.log('Cached avatar URL:', this.userAvatarUrl);
|
||||||
|
return this.userAvatarUrl;
|
||||||
}
|
}
|
||||||
|
console.log('Fetching new avatar URL');
|
||||||
this.lastGetTime = now;
|
this.lastGetTime = now;
|
||||||
const { $http } = useNuxtApp();
|
const { $http } = useNuxtApp();
|
||||||
try {
|
try {
|
||||||
const res = await $http.GET<string>('/user/avatar');
|
const res = await $http.GET<string>('/user/avatar');
|
||||||
this.userAvatar = res.data;
|
this.userAvatarUrl = res.data;
|
||||||
|
console.log('User avatar URL:', this.userAvatarUrl);
|
||||||
|
return this.userAvatarUrl;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching user avatar:', error);
|
console.error('Error fetching user avatar:', error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ export {}
|
||||||
declare global {
|
declare global {
|
||||||
const APIResponse: typeof import('../utils/APIResponse')['APIResponse']
|
const APIResponse: typeof import('../utils/APIResponse')['APIResponse']
|
||||||
const APIResponseErrorException: typeof import('../utils/APIResponse')['APIResponseErrorException']
|
const APIResponseErrorException: typeof import('../utils/APIResponse')['APIResponseErrorException']
|
||||||
|
const ExampleUserInfo: typeof import('../stores/user')['ExampleUserInfo']
|
||||||
const PageType: typeof import('../stores/login')['PageType']
|
const PageType: typeof import('../stores/login')['PageType']
|
||||||
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
|
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
|
||||||
const createPinia: typeof import('pinia')['createPinia']
|
const createPinia: typeof import('pinia')['createPinia']
|
||||||
|
@ -21,6 +22,7 @@ declare global {
|
||||||
const setActivePinia: typeof import('pinia')['setActivePinia']
|
const setActivePinia: typeof import('pinia')['setActivePinia']
|
||||||
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
|
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
|
||||||
const storeToRefs: typeof import('pinia')['storeToRefs']
|
const storeToRefs: typeof import('pinia')['storeToRefs']
|
||||||
|
const useArticleStore: typeof import('../stores/articleUser')['useArticleStore']
|
||||||
const useLoginStore: typeof import('../stores/login')['useLoginStore']
|
const useLoginStore: typeof import('../stores/login')['useLoginStore']
|
||||||
const usePeopleStore: typeof import('../stores/people')['usePeopleStore']
|
const usePeopleStore: typeof import('../stores/people')['usePeopleStore']
|
||||||
const useSystemStore: typeof import('../stores/system')['useSystemStore']
|
const useSystemStore: typeof import('../stores/system')['useSystemStore']
|
||||||
|
@ -29,6 +31,9 @@ declare global {
|
||||||
}
|
}
|
||||||
// for type re-export
|
// for type re-export
|
||||||
declare global {
|
declare global {
|
||||||
|
// @ts-ignore
|
||||||
|
export type { Article, ArticleUser } from '../stores/articleUser'
|
||||||
|
import('../stores/articleUser')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export type { PageType, LoginStore } from '../stores/login'
|
export type { PageType, LoginStore } from '../stores/login'
|
||||||
import('../stores/login')
|
import('../stores/login')
|
||||||
|
@ -39,7 +44,7 @@ declare global {
|
||||||
export type { SystemStore } from '../stores/system'
|
export type { SystemStore } from '../stores/system'
|
||||||
import('../stores/system')
|
import('../stores/system')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export type { UserInfo, UserState } from '../stores/user'
|
export type { ExampleUserInfo, UserInfo, UserState } from '../stores/user'
|
||||||
import('../stores/user')
|
import('../stores/user')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export type { APIResponse, APIResponseErrorException, IAPIResponse } from '../utils/APIResponse'
|
export type { APIResponse, APIResponseErrorException, IAPIResponse } from '../utils/APIResponse'
|
||||||
|
@ -53,6 +58,7 @@ declare module 'vue' {
|
||||||
interface ComponentCustomProperties {
|
interface ComponentCustomProperties {
|
||||||
readonly APIResponse: UnwrapRef<typeof import('../utils/APIResponse')['APIResponse']>
|
readonly APIResponse: UnwrapRef<typeof import('../utils/APIResponse')['APIResponse']>
|
||||||
readonly APIResponseErrorException: UnwrapRef<typeof import('../utils/APIResponse')['APIResponseErrorException']>
|
readonly APIResponseErrorException: UnwrapRef<typeof import('../utils/APIResponse')['APIResponseErrorException']>
|
||||||
|
readonly ExampleUserInfo: UnwrapRef<typeof import('../stores/user')['ExampleUserInfo']>
|
||||||
readonly PageType: UnwrapRef<typeof import('../stores/login')['PageType']>
|
readonly PageType: UnwrapRef<typeof import('../stores/login')['PageType']>
|
||||||
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
|
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
|
||||||
readonly createPinia: UnwrapRef<typeof import('pinia')['createPinia']>
|
readonly createPinia: UnwrapRef<typeof import('pinia')['createPinia']>
|
||||||
|
@ -66,6 +72,7 @@ declare module 'vue' {
|
||||||
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
|
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
|
||||||
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
|
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
|
||||||
readonly storeToRefs: UnwrapRef<typeof import('pinia')['storeToRefs']>
|
readonly storeToRefs: UnwrapRef<typeof import('pinia')['storeToRefs']>
|
||||||
|
readonly useArticleStore: UnwrapRef<typeof import('../stores/articleUser')['useArticleStore']>
|
||||||
readonly useLoginStore: UnwrapRef<typeof import('../stores/login')['useLoginStore']>
|
readonly useLoginStore: UnwrapRef<typeof import('../stores/login')['useLoginStore']>
|
||||||
readonly usePeopleStore: UnwrapRef<typeof import('../stores/people')['usePeopleStore']>
|
readonly usePeopleStore: UnwrapRef<typeof import('../stores/people')['usePeopleStore']>
|
||||||
readonly useSystemStore: UnwrapRef<typeof import('../stores/system')['useSystemStore']>
|
readonly useSystemStore: UnwrapRef<typeof import('../stores/system')['useSystemStore']>
|
||||||
|
|
|
@ -28,13 +28,15 @@
|
||||||
"@nuxtjs/tailwindcss": "^6.13.2",
|
"@nuxtjs/tailwindcss": "^6.13.2",
|
||||||
"@pinia/nuxt": "^0.10.1",
|
"@pinia/nuxt": "^0.10.1",
|
||||||
"@unhead/vue": "^2.0.5",
|
"@unhead/vue": "^2.0.5",
|
||||||
|
"echarts": "^5.6.0",
|
||||||
|
"md-editor-v3": "^5.5.0",
|
||||||
"nuxt": "^3.16.2",
|
"nuxt": "^3.16.2",
|
||||||
"pinia": "^3.0.2",
|
"pinia": "^3.0.2",
|
||||||
"tdesign-vue-next": "^1.11.5",
|
"tdesign-vue-next": "^1.11.5",
|
||||||
"unplugin-auto-import": "^19.1.2",
|
"unplugin-auto-import": "^19.1.2",
|
||||||
"unplugin-vue-components": "^28.4.1"
|
"unplugin-vue-components": "^28.4.1"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.9.0",
|
"packageManager": "pnpm@10.10.0",
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"onlyBuiltDependencies": [
|
"onlyBuiltDependencies": [
|
||||||
"@parcel/watcher",
|
"@parcel/watcher",
|
||||||
|
|
Loading…
Reference in New Issue