fix: 临时提交

master
luoer 2024-01-10 17:39:52 +08:00
parent 9b15be521e
commit 3ae0869386
12 changed files with 371 additions and 316 deletions

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,7 @@
<div class="text-base flex items-center group">
<a-link @click="emit('exit')">
<template #icon>
<i class="icon-park-outline-left"></i>
<i class="icon-park-outline-back"></i>
</template>
返回
</a-link>

View File

@ -1,51 +1,42 @@
<template>
<span v-if="!descEditing" class="inline-block leading-[32px] h-8">
<span v-if="!descEditing" class="inline-block leading-[32px] h-8 cursor-text" @click="onDescEdit">
{{ modelValue }}
<a-button type="text" size="small" shape="round" class="!hidden !group-hover:inline-block !text-gray-500" @click="onDescEdit">
<template #icon>
<i class="icon-park-outline-edit"></i>
</template>
</a-button>
</span>
<span v-else class="inline-flex items-center">
<span v-else class="inline-flex items-center" ref="inputRef">
<a-input size="small" v-model="descContent" class="!w-96" v-bind="inputProps"></a-input>
<a-button type="text" size="small" @click="onDescEdited" class="ml-2">
<template #icon>
<i class="icon-park-outline-check"></i>
</template>
</a-button>
<a-button type="text" size="small" class="!text-gray-500" @click="descEditing = false">
<template #icon>
<i class="icon-park-outline-close"></i>
</template>
</a-button>
</span>
</template>
<script setup lang="ts">
import { Input } from "@arco-design/web-vue";
import { PropType } from "vue";
import { Input } from '@arco-design/web-vue';
import { onClickOutside } from '@vueuse/core';
import { PropType } from 'vue';
const props = defineProps({
modelValue: {
type: String,
default: "",
default: '',
},
inputProps: {
type: Object as PropType<Partial<InstanceType<typeof Input>["$props"]>>,
type: Object as PropType<Partial<InstanceType<typeof Input>['$props']>>,
default: () => ({}),
},
});
const emit = defineEmits(["update:modelValue"]);
const emit = defineEmits(['update:modelValue']);
const descEditing = ref(false);
const descContent = ref("");
const descContent = ref('');
const inputRef = ref<HTMLElement | null>(null);
const onDescEdited = () => {
emit("update:modelValue", descContent.value);
emit('update:modelValue', descContent.value);
descEditing.value = false;
};
onClickOutside(inputRef, () => {
onDescEdited();
});
const onDescEdit = () => {
descContent.value = props.modelValue;
descEditing.value = true;

View File

@ -1,5 +1,5 @@
<template>
<a-dropdown position="br">
<a-dropdown position="br" class="user-dropdown">
<span class="inline-flex items-center cursor-pointer rounded hover:bg-gray-100 px-2 py-1.5">
<a-avatar :size="24">
<img :src="userStore.avatar || 'https://github.com/juetan.png'" :alt="userStore.nickname" />
@ -36,12 +36,19 @@
</template>
账号信息
</a-doption>
<a-doption @click="router.push('/my')">
<a-divider :margin="4"></a-divider>
<a-doption @click="router.push('/user')">
<template #icon>
<i class="icon-park-outline-config"></i>
</template>
系统设置
</a-doption>
<a-doption @click="router.push('/user')">
<template #icon>
<i class="icon-park-outline-info"></i>
</template>
关于
</a-doption>
<a-divider :margin="4"></a-divider>
<a-doption @click="logout">
<template #icon>
@ -109,4 +116,10 @@ const { component: PasswordModal, open } = useFormModal({
});
</script>
<style scoped></style>
<style lang="less">
.user-dropdown {
.arco-dropdown-list-wrapper {
max-height: initial;
}
}
</style>

View File

@ -46,7 +46,7 @@
<a-layout class="flex flex-1 overflow-hidden">
<a-layout-sider
class="h-full overflow-hidden dark:bg-slate-800 border-r border-slate-200 dark:border-slate-700"
:width="224"
:width="208"
:collapsed-width="49"
:collapsible="true"
:collapsed="isCollapsed"
@ -81,7 +81,7 @@
</a-layout>
</template>
<script lang="ts" setup>
<script lang="tsx" setup>
import { useAppStore } from '@/store';
import { useMenuStore } from '@/store/menu';
import { Message } from '@arco-design/web-vue';
@ -96,6 +96,18 @@ const menuStore = useMenuStore();
const isCollapsed = ref(false);
const themeConfig = ref({ visible: false });
const ButtonWithTooltip = (props: { tooltip: string; icon: string; onClick: any }) => {
return (
<a-tooltip content={props.tooltip}>
<a-button onClick={props.onClick} class="!bg-transparent !hover:bg-gray-100">
{{
icon: () => <i class={`${props.icon} text-base`}></i>,
}}
</a-button>
</a-tooltip>
);
};
const buttons = [
{
icon: 'icon-park-outline-remind',
@ -197,7 +209,7 @@ const buttons = [
"meta": {
"name": "LayoutPage",
"sort": 101,
"title": "概览",
"title": "首页",
"icon": "icon-park-outline-home",
"keepAlive": true
}

View File

@ -1,5 +1,5 @@
<template>
<a-tabs class="tabs-page">
<a-tabs class="tabs-page" :destroy-on-hide="true">
<a-tab-pane key="1" title="全部素材">
<div class="overflow-hidden grid grid-cols-[auto_1fr] gap-2 m-4 mt-0">
<!-- <AnGroup class="bg-white p-4 w-[242px]" :current="current" @change="onCategoryChange"></AnGroup> -->
@ -205,14 +205,20 @@ const {
});
</script>
<style lang="less" scoped>
<style lang="less">
.tabs-page {
display: grid;
grid-template-rows: auto 1fr;
height: 100%;
:deep(.arco-tabs-content) {
.arco-tabs-content {
overflow: auto;
// padding-top: 0;
// padding: 16px;
}
// .arco-tabs-content-list {
// background-color: #fff;
// padding: 16px 20px;
// }
}
</style>

View File

@ -0,0 +1,64 @@
<template>
<a-form
:model="{}"
:label-col-props="{ span: 3 }"
label-align="left"
layout="vertical"
class="divide-y divide-gray-100"
>
<a-form-item label="站点LOGO">
<a-avatar :size="64">
<img :src="appStore.logo" alt="" />
<template #trigger-icon>
<i class="icon-park-outline-edit"></i>
</template>
</a-avatar>
<template #help>提示仅支持 5MB 以内大小, png jpg 格式的图片 </template>
</a-form-item>
<a-form-item label="站点名称">
<a-input
v-model="appStore.title"
placeholder="请输入"
class="!w-[432px]"
allow-clear
:max-length="24"
:show-word-limit="true"
></a-input>
<template #help> 用作系统内显示的名称可在后台修改 </template>
</a-form-item>
<a-form-item label="站点描述">
<a-textarea
v-model="appStore.subtitle"
placeholder="请输入"
class="!w-[432px] h-24"
:max-length="140"
:show-word-limit="true"
></a-textarea>
<template #help> 启用后消息通知将在左上角进行提示. </template>
</a-form-item>
<a-form-item label="站点URL">
<a-input v-model="appStore.title" placeholder="请输入" class="!w-[432px]" allow-clear></a-input>
<template #help> 示例https://www.juetan.cn </template>
</a-form-item>
<a-form-item>
<a-button type="primary">保存修改</a-button>
</a-form-item>
</a-form>
</template>
<script setup lang="ts">
import { useAppStore } from '@/store/app';
const appStore = useAppStore();
</script>
<style scoped></style>
<route lang="json">
{
"meta": {
"sort": 30401,
"title": "个人设置",
"icon": "icon-park-outline-config"
}
}
</route>

View File

@ -0,0 +1,99 @@
<template>
<div>
<!-- <div class="bg-white ">
<div v-for="t1 in types" :key="t1.label" class="flex items-center">
{{ t1.label }}
<div class="flex gap-2">
<a-tag
v-for="t2 in t1.children"
:key="t2.value"
:checked="search.bk === t2.value"
color="blue"
:bordered="true"
checkable
@check="search.bk = t2.value"
>
{{ t2.label }}
</a-tag>
</div>
</div>
</div> -->
</div>
</template>
<script setup lang="ts">
const search = reactive({ bk: undefined });
const types = [
{
label: '板块',
children: [
{
label: '全部',
value: undefined,
},
{
label: '电影',
value: 'fild',
},
{
label: '电视剧',
value: 'vs',
},
{
label: '综艺',
value: 'zy',
},
{
label: '动漫',
value: 'dm',
},
{
label: '短剧',
value: 'dj',
},
{
label: '体育',
value: 'ty',
},
{
label: '纪录片',
value: 'jlp',
},
{
label: '游戏',
value: 'yx',
},
{
label: '新闻',
value: 'xw',
},
{
label: '娱乐',
value: 'yl',
},
{
label: '生活',
value: 'sh',
},
{
label: '音乐',
value: 'yinyue',
},
{
label: '时尚',
value: 'shishang',
},
{
label: '科技',
value: 'keji',
},
{
label: '发现',
value: 'faxian',
},
],
},
];
</script>
<style scoped></style>

100
src/pages/user/TabMail.vue Normal file
View File

@ -0,0 +1,100 @@
<template>
<div class="flex">
<a-form
:model="{}"
:label-col-props="{ span: 3 }"
:disabled="!mail.enable"
layout="vertical"
label-align="left"
class="w-[580px]! divide-y divide-gray-100"
>
<a-form-item label="是否启用" :disabled="false">
<a-radio-group v-model="mail.enable">
<a-radio :value="true">启用</a-radio>
<a-radio :value="false">禁用</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="服务器和端口">
<a-input v-model="mail.smtpHost" allow-clear placeholder="请输入" class="!w-[314px]"></a-input>
<span class="inline-block px-2">:</span>
<a-input-number v-model="mail.smtpPort" :min="0" :max="65535" class="w-24!"></a-input-number>
<template #help>
示例: smtp.163.com:25国内常见有
<a target="_blank" class="mr-2" href="https://mail.163.com">网易邮箱</a>
<a target="_blank" class="mr-2" href="http://mail.aliyun.com/">阿里邮箱</a>
<a target="_blank" class="mr-2" href="https://mail.qq.com">QQ邮箱</a>
</template>
</a-form-item>
<a-form-item label="发信人地址">
<a-input v-model="mail.smtpFrom" placeholder="请输入" class="!w-[432px]"></a-input>
<template #help> 示例: example@mail.com仅作为发送邮件时的发送人标识与登陆无关</template>
</a-form-item>
<a-form-item label="是否需要验证">
<a-radio-group v-model="mail.smtpAuth">
<a-radio :value="true"></a-radio>
<a-radio :value="false"></a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="验证账号">
<a-input
:disabled="!mail.enable || !mail.smtpAuth"
v-model="mail.smtpUser"
placeholder="请输入"
class="!w-[432px]"
></a-input>
<template #help> 示例: example@mail.com企业邮箱请使用企业域名后缀</template>
</a-form-item>
<a-form-item label="验证密码">
<a-input
:disabled="!mail.enable || !mail.smtpAuth"
v-model="mail.smtpPass"
placeholder="请输入"
class="!w-[432px]"
></a-input>
<template #help> 示例AATOLARFABJKYWUY具体请在对应邮箱设置面板进行生成 </template>
</a-form-item>
<a-form-item :disabled="false">
<a-button type="primary"> 保存修改 </a-button>
</a-form-item>
</a-form>
<a-divider direction="vertical" :margin="32"></a-divider>
<div class="flex-1">
<div>
<div class="text-base font-semibold">配置测试</div>
<div class="text-gray-400 mt-1">
发送一封测试邮件检测邮件设置是否能正常工作
</div>
<div class="mt-6">
<a-input placeholder="接收人邮箱" class="w-[432px]!"></a-input>
</div>
<a-textarea placeholder="写点什么..." class="w-[432px]! h-24 mt-2"></a-textarea>
<div class="mt-2">
<a-button type="primary" :disabled="!mail.enable">发送邮件</a-button>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
const mail = reactive({
enable: true,
smtpHost: '10.10.10.30',
smtpPort: 25,
smtpFrom: 'no-reply@juetan.cn',
smtpAuth: true,
smtpUser: '952222@163.com',
smtpPass: 'FenZyealdsa@s92.',
});
</script>
<style scoped></style>
<route lang="json">
{
"meta": {
"sort": 30401,
"title": "个人设置",
"icon": "icon-park-outline-config"
}
}
</route>

View File

@ -1,291 +1,58 @@
<template>
<BreadPage :content-padding="false">
<template #content>
<section class="my-page m-4 bg-white rounded px-4">
<div class="bg-white py-4 px-5 mb-4">
<div v-for="t1 in types" :key="t1.label" class="flex items-center">
{{ t1.label }}
<div class="flex gap-2">
<a-tag
v-for="t2 in t1.children"
:key="t2.value"
:checked="search.bk === t2.value"
color="blue"
:bordered="true"
checkable
@check="search.bk = t2.value"
>
{{ t2.label }}
</a-tag>
<a-tabs
size="large"
class="tabs-page my-page"
:default-active-key="($route.query.tab as string)"
@change="onTabChange"
>
<a-tab-pane key="common" title="常规设置">
<div class="m-4 mt-0 py-4 px-5 bg-white rounded-sm">
<TabCommon></TabCommon>
</div>
</a-tab-pane>
<a-tab-pane key="mail" title="邮件设置">
<div class="m-4 mt-0 py-4 px-5 bg-white rounded-sm">
<TabMail></TabMail>
</div>
</a-tab-pane>
<a-tab-pane key="extra" title="额外功能">
<div class="m-4 mt-0 py-4 px-5 bg-white rounded-sm flex-1 grid px-6">
<div class="mb-3">功能列表</div>
<div v-for="i in 3" class="border-t py-4 flex justify-between items-center gap-4">
<div class="flex gap-3 items-center">
<div class="p-2 bg-slate-100 rounded">
<i class="icon-park-outline-mail"></i>
</div>
<div>
<div class="text-gray-900 text-base">支付功能</div>
<div class="text-gray-400 mt-2">通知管理员由企业互联的管理员来设置拥有通知业务的最大权限</div>
</div>
</div>
<div>
<a-switch checked-color="#3c9">
<template #checked> 已启用 </template>
<template #unchecked> 未启用 </template>
</a-switch>
</div>
</div>
<a-tabs size="large" class="h-full">
<a-tab-pane key="8" title="常规设置">
<a-form
:model="user"
:label-col-props="{ span: 3 }"
label-align="left"
layout="vertical"
class="px-6 divide-y divide-gray-100"
>
<a-form-item label="站点LOGO">
<a-avatar :size="64">
<img :src="appStore.logo" alt="" />
<template #trigger-icon>
<i class="icon-park-outline-edit"></i>
</template>
</a-avatar>
<template #help>提示仅支持 5MB 以内大小, png jpg 格式的图片 </template>
</a-form-item>
<a-form-item label="站点名称">
<a-input
v-model="appStore.title"
placeholder="请输入"
class="!w-[432px]"
allow-clear
:max-length="24"
:show-word-limit="true"
></a-input>
<template #help> 用作系统内显示的名称可在后台修改 </template>
</a-form-item>
<a-form-item label="站点描述">
<a-textarea
v-model="appStore.subtitle"
placeholder="请输入"
class="!w-[432px] h-24"
:max-length="140"
:show-word-limit="true"
></a-textarea>
<template #help> 启用后消息通知将在左上角进行提示. </template>
</a-form-item>
<a-form-item label="站点URL">
<a-input v-model="appStore.title" placeholder="请输入" class="!w-[432px]" allow-clear></a-input>
<template #help> 示例https://www.juetan.cn </template>
</a-form-item>
<a-form-item>
<a-button type="primary">保存修改</a-button>
</a-form-item>
</a-form>
</a-tab-pane>
<a-tab-pane key="5" title="邮件设置">
<!-- <div class="mb-6 px-6">
<div class="text-base font-semibold">邮件来源</div>
<label class="text-sm block mt-2">
目前仅支持 SMTP 协议用于发送验证码重置密码和消息通知等用途
</label>
</div> -->
<a-form
:model="user"
:label-col-props="{ span: 3 }"
:disabled="!mail.enable"
layout="vertical"
label-align="left"
class="px-6 divide-y divide-gray-100"
>
<a-form-item label="是否启用" :disabled="false">
<a-radio-group v-model="mail.enable" :type="'button'">
<a-radio :value="true">启用</a-radio>
<a-radio :value="false">禁用</a-radio>
</a-radio-group>
<template #help> 启用后对应时间触发后将会自动向用户发送邮件通知 </template>
</a-form-item>
<a-form-item label="服务器和端口">
<a-input v-model="mail.smtpHost" allow-clear placeholder="请输入" class="!w-[314px]"></a-input>
<span class="inline-block px-2">:</span>
<a-input-number v-model="mail.smtpPort" :min="0" :max="65535" class="w-24!"></a-input-number>
<template #help>
示例: smtp.163.com:25国内常见有
<a target="_blank" class="mr-2" href="https://mail.163.com">网易邮箱</a>
<a target="_blank" class="mr-2" href="http://mail.aliyun.com/">阿里邮箱</a>
<a target="_blank" class="mr-2" href="https://mail.qq.com">QQ邮箱</a>默认 25 端口
</template>
</a-form-item>
<a-form-item label="发信人地址">
<a-input v-model="mail.smtpFrom" placeholder="请输入" class="!w-[432px]"></a-input>
<template #help> 示例: example@mail.com仅作为发送邮件时的发送人标识与登陆无关</template>
</a-form-item>
<a-form-item label="是否需要验证">
<a-radio-group v-model="mail.smtpAuth" :type="'button'">
<a-radio :value="true"></a-radio>
<a-radio :value="false"></a-radio>
</a-radio-group>
<template #help> 可选 </template>
</a-form-item>
<a-form-item label="验证账号">
<a-input
:disabled="!mail.enable || !mail.smtpAuth"
v-model="mail.smtpUser"
placeholder="请输入"
class="!w-[432px]"
></a-input>
<template #help> 示例: example@mail.com企业邮箱请使用企业域名后缀</template>
</a-form-item>
<a-form-item label="验证密码">
<a-input
:disabled="!mail.enable || !mail.smtpAuth"
v-model="mail.smtpPass"
placeholder="请输入"
class="!w-[432px]"
></a-input>
<template #help> 示例AATOLARFABJKYWUY具体请在对应邮箱设置面板进行生成 </template>
</a-form-item>
<!-- <a-form-item label="发送测试邮件">
<div>
<a-textarea placeholder="写点什么..." class="w-[432px]!"></a-textarea>
<div class="mt-1">
<a-link :disabled="!mail.enable">发送</a-link>
</div>
</div>
<template #help> 测试邮箱配置是否正确 </template>
</a-form-item> -->
<a-form-item :disabled="false">
<a-button type="primary"> 保存修改 </a-button>
</a-form-item>
</a-form>
</a-tab-pane>
<a-tab-pane key="3" title="额外功能">
<div class="flex-1 grid px-6">
<div class="mb-3">功能列表</div>
<div v-for="i in 3" class="border-t py-4 flex justify-between items-center gap-4">
<div class="flex gap-3 items-center">
<div class="p-2 bg-slate-100 rounded">
<i class="icon-park-outline-mail"></i>
</div>
<div>
<div class="text-gray-900 text-base">支付功能</div>
<div class="text-gray-400 mt-2">通知管理员由企业互联的管理员来设置拥有通知业务的最大权限</div>
</div>
</div>
<div>
<a-switch checked-color="#3c9">
<template #checked> 已启用 </template>
<template #unchecked> 未启用 </template>
</a-switch>
</div>
</div>
</div>
</a-tab-pane>
</a-tabs>
</section>
</template>
</BreadPage>
</div>
</a-tab-pane>
</a-tabs>
</template>
<script setup lang="tsx">
import { useAppStore } from '@/store';
import { reactive } from 'vue';
import TabCommon from './TabCommon.vue';
import TabMail from './TabMail.vue';
const search = reactive({ bk: undefined });
const types = [
{
label: '板块',
children: [
{
label: '全部',
value: undefined,
},
{
label: '电影',
value: 'fild',
},
{
label: '电视剧',
value: 'vs',
},
{
label: '综艺',
value: 'zy',
},
{
label: '动漫',
value: 'dm',
},
{
label: '短剧',
value: 'dj',
},
{
label: '体育',
value: 'ty',
},
{
label: '纪录片',
value: 'jlp',
},
{
label: '游戏',
value: 'yx',
},
{
label: '新闻',
value: 'xw',
},
{
label: '娱乐',
value: 'yl',
},
{
label: '生活',
value: 'sh',
},
{
label: '音乐',
value: 'yinyue',
},
{
label: '时尚',
value: 'shishang',
},
{
label: '科技',
value: 'keji',
},
{
label: '发现',
value: 'faxian',
},
],
},
];
const appStore = useAppStore();
const mail = reactive({
enable: true,
smtpHost: '10.10.10.30',
smtpPort: 25,
smtpFrom: 'no-reply@juetan.cn',
smtpAuth: true,
smtpUser: '952222@163.com',
smtpPass: 'FenZyealdsa@s92.',
});
const user = reactive({
nickname: '绝弹',
description: '选择在公开个人资料中显示私有项目的贡献,但不显示任何项目,仓库或组织信息',
theme: 'dark',
email: '810335188@qq.com',
msg: [2],
gender: 1,
birth: '1988-12-18',
smtpPort: 25,
smtpIp: '10.10.10.30',
smtpUser: '952222@163.com',
smtpPass: 'xxxxx',
});
const route = useRoute();
const router = useRouter();
const onTabChange = (val: string | number) => {
router.replace({ query: { tab: val } });
};
</script>
<style lang="less">
.my-page {
.arco-form-item-wrapper-col {
display: grid;
grid-template-columns: min(432px) 1fr;
gap: 32px;
}
.arco-tabs-nav-type-line .arco-tabs-tab {
height: 52px;
}
.arco-form-item.arco-form-item-error,
.arco-form-item.arco-form-item-has-help {
margin-bottom: 20px;

View File

@ -78,10 +78,10 @@ body {
background-color: var(--color-neutral-1);
}
&.arco-menu-selected {
color: @arcoblue-6;
background-color: rgb(var(--primary-1));
// color: #fff;
// background-color: rgb(var(--primary-6));
// color: @arcoblue-6;
// background-color: rgb(var(--primary-1));
color: #fff;
background-color: rgb(var(--primary-6));
.arco-menu-icon {
color: inherit;
}

View File

@ -60,6 +60,9 @@ declare module 'vue-router/auto/routes' {
'/system/role/': RouteRecordInfo<'/system/role/', '/system/role', Record<never, never>, Record<never, never>>,
'/system/user/': RouteRecordInfo<'/system/user/', '/system/user', Record<never, never>, Record<never, never>>,
'/user/': RouteRecordInfo<'/user/', '/user', Record<never, never>, Record<never, never>>,
'/user/TabCommon': RouteRecordInfo<'/user/TabCommon', '/user/TabCommon', Record<never, never>, Record<never, never>>,
'/user/TabDemo': RouteRecordInfo<'/user/TabDemo', '/user/TabDemo', Record<never, never>, Record<never, never>>,
'/user/TabMail': RouteRecordInfo<'/user/TabMail', '/user/TabMail', Record<never, never>, Record<never, never>>,
}
}