feat: 优化个人设置页面
parent
66ea7f5436
commit
b1600f6721
|
|
@ -133,7 +133,7 @@ export const FormModal = defineComponent({
|
|||
<Button type="primary">
|
||||
{{
|
||||
default: () => (typeof props.trigger === "string" ? props.trigger : "添加"),
|
||||
icon: () => <i class="icon-park-outline-plus" />,
|
||||
icon: () => <i class="icon-park-outline-add" />,
|
||||
}}
|
||||
</Button>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {
|
|||
Input,
|
||||
InputNumber,
|
||||
InputPassword,
|
||||
InputSearch,
|
||||
RadioGroup,
|
||||
RangePicker,
|
||||
Select,
|
||||
|
|
@ -49,6 +50,16 @@ export const nodeMap = {
|
|||
allowClear: true,
|
||||
} as InstanceType<typeof Input>["$props"],
|
||||
},
|
||||
/**
|
||||
* 搜索框
|
||||
*/
|
||||
search: {
|
||||
component: InputSearch,
|
||||
nodeProps: {
|
||||
placeholder: "请输入",
|
||||
allowClear: true,
|
||||
} as InstanceType<typeof InputSearch>["$props"],
|
||||
},
|
||||
/**
|
||||
* 文本域
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Button } from "@arco-design/web-vue";
|
||||
import { Button, Link } from "@arco-design/web-vue";
|
||||
import { IconRefresh, IconSearch } from "@arco-design/web-vue/es/icon";
|
||||
|
||||
export const config = {
|
||||
|
|
@ -11,20 +11,22 @@ export const config = {
|
|||
searchItemSubmit: {
|
||||
field: "id",
|
||||
type: "custom",
|
||||
label: ' ',
|
||||
itemProps: {
|
||||
class: "table-search-item col-start-4 !mr-0 grid grid-cols-[0_1fr]",
|
||||
hideLabel: true,
|
||||
// hideLabel: true,
|
||||
},
|
||||
component: () => {
|
||||
const tableRef = inject<any>("ref:table");
|
||||
return (
|
||||
<div class="w-full flex gap-x-2 justify-end">
|
||||
{/* <Link>收起 <i class="icon-park-outline-up"></i> </Link> */}
|
||||
{(tableRef.search?.items?.length || 0) > config.searchInlineCount && (
|
||||
<Button disabled={tableRef?.loading.value} onClick={() => tableRef?.reloadData()}>
|
||||
{{ icon: () => <IconRefresh></IconRefresh>, default: () => "重置" }}
|
||||
</Button>
|
||||
)}
|
||||
<Button type="primary" loading={tableRef?.loading.value} onClick={() => tableRef?.loadData()}>
|
||||
<Button type="outline" loading={tableRef?.loading.value} onClick={() => tableRef?.loadData()}>
|
||||
{{ icon: () => <IconSearch></IconSearch>, default: () => "查询" }}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -72,6 +74,6 @@ export const config = {
|
|||
},
|
||||
getApiErrorMessage(error: any): string {
|
||||
const message = error?.response?.data?.message || error?.message || "请求失败";
|
||||
return message;
|
||||
return '';
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -158,14 +158,14 @@ export const Table = defineComponent({
|
|||
render() {
|
||||
(this.columns as any).instance = this;
|
||||
return (
|
||||
<div class="bh-table w-full">
|
||||
<div class="table w-full">
|
||||
{!this.inlined && (
|
||||
<div class="pb-5 border-b border-slate-200 mb-5">
|
||||
<Form ref="searchRef" class="grid grid-cols-4 gap-x-4" {...this.search}></Form>
|
||||
<div class="border-b pb-2 border-slate-200 mb-5">
|
||||
<Form ref="searchRef" class="!grid grid-cols-4 gap-x-6" {...this.search}></Form>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div class={`mb-2 flex justify-between ${!this.inlined && "mt-2"}`}>
|
||||
<div class={`mb-3 flex justify-between ${!this.inlined && "mt-2"}`}>
|
||||
<div class="flex-1 flex gap-2">
|
||||
{this.create && (
|
||||
<FormModal ref="createRef" onSubmited={this.reloadData} {...(this.create as any)}></FormModal>
|
||||
|
|
|
|||
|
|
@ -167,11 +167,11 @@ export const useTable = (optionsOrFn: UseTableOptions | (() => UseTableOptions))
|
|||
if (item.extend) {
|
||||
const createItem = createItems.find((i) => i.field === item.extend);
|
||||
if (createItem) {
|
||||
searchItems.push(merge({}, createItem, item));
|
||||
searchItems.push(merge({ itemProps: { hideLabel: true } }, createItem, item));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
searchItems.push(item);
|
||||
searchItems.push(merge({ itemProps: { hideLabel: true } }, item));
|
||||
}
|
||||
searchItems.push(config.searchItemSubmit);
|
||||
options.search.items = searchItems;
|
||||
|
|
|
|||
|
|
@ -28,11 +28,11 @@ export default defineComponent({
|
|||
|
||||
renderItem(routes: MenuItem[], isTop = false) {
|
||||
return routes.map((route) => {
|
||||
const icon = route.icon && isTop ? () => <i class={route.icon} /> : null;
|
||||
const icon = route.icon ? () => <i class={route.icon} /> : null;
|
||||
const node = route.children?.length ? (
|
||||
<a-sub-menu key={route.path} v-slots={{ icon, title: () => route.title }}>
|
||||
<a-menu-item-group key={route.path} v-slots={{ icon, title: () => route.title }}>
|
||||
{this.renderItem(route?.children)}
|
||||
</a-sub-menu>
|
||||
</a-menu-item-group>
|
||||
) : (
|
||||
<a-menu-item key={route.path} v-slots={{ icon }} onClick={() => this.goto(route)}>
|
||||
{route.title}
|
||||
|
|
@ -51,6 +51,7 @@ export default defineComponent({
|
|||
breakpoint="xl"
|
||||
selectedKeys={this.selectedKeys}
|
||||
autoOpenSelected={true}
|
||||
levelIndent={0}
|
||||
>
|
||||
{this.renderItem(menus, true)}
|
||||
</a-menu>
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@
|
|||
>
|
||||
<div class="h-13 flex items-center border-b border-slate-200 dark:border-slate-800">
|
||||
<router-link to="/" class="ml-1 flex items-center gap-2 text-slate-700">
|
||||
<img src="/favicon.ico" alt="" width="20" height="20" />
|
||||
<h1 class="text-lg leading-[19px] dark:text-white m-0 p-0">
|
||||
<img src="/favicon.ico" alt="" width="22" height="22" class="" />
|
||||
<h1 class="relative text-lg font-semibold leading-[19px] dark:text-white m-0 p-0">
|
||||
{{ appStore.title }}
|
||||
<span v-if="isDev" class="absolute -right-14 -top-1 text-xs font-normal text-blue-500 bg-blue-50 px-2 rounded-full">开发版</span>
|
||||
</h1>
|
||||
</router-link>
|
||||
</div>
|
||||
|
|
@ -22,7 +23,7 @@
|
|||
<a-dropdown>
|
||||
<span class="cursor-pointer">
|
||||
<a-avatar :size="28">
|
||||
<img :src="userStore.avatar" :alt="userStore.nickname" />
|
||||
<img :src="userStore.avatar || 'https://github.com/juetan.png'" :alt="userStore.nickname" />
|
||||
</a-avatar>
|
||||
<span class="mx-2">
|
||||
{{ userStore.nickname }}
|
||||
|
|
@ -45,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="208"
|
||||
:width="224"
|
||||
:collapsed-width="52"
|
||||
:collapsible="true"
|
||||
:collapsed="isCollapsed"
|
||||
|
|
@ -86,6 +87,7 @@ const themeConfig = ref({ visible: false });
|
|||
const onCollapse = (val: boolean) => {
|
||||
isCollapsed.value = val;
|
||||
};
|
||||
const isDev = import.meta.env.DEV
|
||||
|
||||
const buttons = [
|
||||
{
|
||||
|
|
@ -109,7 +111,7 @@ const userButtons = [
|
|||
icon: "icon-park-outline-config",
|
||||
text: "个人设置",
|
||||
onClick: () => {
|
||||
console.log("个人设置");
|
||||
router.push('/my')
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
</div>
|
||||
<div class="flex items-center justify-center w-full overflow-hidden">
|
||||
<div
|
||||
class="login-box w-[960px] h-[560px] relative mx-8 grid md:grid-cols-2 rounded overflow-hidden border border-blue-100"
|
||||
class="login-box w-[960px] h-[560px] relative mx-4 grid md:grid-cols-2 rounded overflow-hidden border border-blue-100"
|
||||
>
|
||||
<div class="relative hidden md:block w-full h-full overflow-hidden bg-[#09f] px-4">
|
||||
<img src="@/assets/td.svg" :alt="appStore.title" class="w-full h-full select-none" />
|
||||
|
|
|
|||
|
|
@ -1,42 +1,30 @@
|
|||
<template>
|
||||
<bread-page class="">
|
||||
<div v-for="menu in state.menus" :key="menu.id" class="mt-8">
|
||||
<div class="flex justify-between pb-1.5 border-b">
|
||||
<a-checkbox v-model="menu.checked" :indeterminate="indeter(menu.children)">
|
||||
<span class="font-semibold">
|
||||
{{ menu.title }}
|
||||
</span>
|
||||
</a-checkbox>
|
||||
<a-link> 设置权限 </a-link>
|
||||
</div>
|
||||
<div class="flex gap-4 mt-4">
|
||||
<template v-if="menu.children">
|
||||
<a-checkbox
|
||||
v-model="item.checked"
|
||||
@change="onItemChange(item, menu)"
|
||||
v-for="item in menu.children || []"
|
||||
:key="item.id"
|
||||
>
|
||||
{{ item.title }}
|
||||
</a-checkbox>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="text-gray-400">暂无子项</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<a-card title="菜单权限">
|
||||
<a-tree :data="items" :field-names="{ title: 'title' }" checkable></a-tree>
|
||||
</a-card>
|
||||
</bread-page>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup lang="tsx">
|
||||
import { menus } from "@/router";
|
||||
import { cloneDeep } from "lodash-es";
|
||||
|
||||
const items = cloneDeep(menus) as any;
|
||||
for (const item of items) {
|
||||
item.checked = false;
|
||||
if (item.icon) {
|
||||
const icon = item.icon;
|
||||
item.icon = () => <i class={icon}></i>;
|
||||
|
||||
}
|
||||
item.switcherIcon = () => null;
|
||||
if (item.children) {
|
||||
for (const child of item.children) {
|
||||
if (child.icon) {
|
||||
const icon = child.icon;
|
||||
child.icon = () => <i class={icon}></i>;
|
||||
}
|
||||
child.checked = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<bread-page id="list-page">
|
||||
<template #default>
|
||||
<div class="flex justify-between gap-4">
|
||||
<div class="flex justify-between items-end gap-4">
|
||||
<div class="">
|
||||
<span class="text-base font-semibold text-gray-900">媒体素材</span>
|
||||
<div class="mt-1 text-gray-400">
|
||||
|
|
@ -9,14 +9,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-gray-400">
|
||||
<div>
|
||||
<a-button type="primary">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-plus"></i>
|
||||
</template>
|
||||
添加
|
||||
</a-button>
|
||||
</div>
|
||||
<a-button type="primary">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-add"></i>
|
||||
</template>
|
||||
添加
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<AList class="mt-4 bg-white" :bordered="true">
|
||||
|
|
@ -41,8 +39,8 @@
|
|||
</ADoption>
|
||||
<ADoption v-for="j in 10">
|
||||
<div class="flex items-center gap-1 w-48">
|
||||
<AAvatar :size="20" class="mr-1">
|
||||
<img src="https://picsum.photos/seed/picsum/200/300" alt="" />
|
||||
<AAvatar :size="20" class="mr-1 bg-slate-50">
|
||||
<img :src="`https://picsum.photo1s/seed/picsum/200/300?${Math.random()}`" alt="" />
|
||||
</AAvatar>
|
||||
绝弹土豆
|
||||
</div>
|
||||
|
|
@ -56,30 +54,23 @@
|
|||
</span>
|
||||
<template #content>
|
||||
<ADoption>
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-check"></i>
|
||||
</template>
|
||||
<div class="w-48">默认</div>
|
||||
</ADoption>
|
||||
<ADoption>
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-sort-amount-up"></i>
|
||||
</template>
|
||||
按创建时间升序
|
||||
</ADoption>
|
||||
<ADoption>
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-sort-amount-down"></i>
|
||||
</template>
|
||||
按创建时间降序
|
||||
</ADoption>
|
||||
<ADoption>
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-align-text-top"></i>
|
||||
</template>
|
||||
按文件大小升序
|
||||
</ADoption>
|
||||
<ADoption>
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-align-text-bottom"></i>
|
||||
</template>
|
||||
按文件大小降序
|
||||
</ADoption>
|
||||
</template>
|
||||
|
|
@ -108,7 +99,7 @@
|
|||
<AListItemMeta title="测试图片.png" description="image/png 1.2MB">
|
||||
<template #avatar>
|
||||
<ACheckbox class="mr-3"></ACheckbox>
|
||||
<AImage src="https://picsum.photos/seed/picsum/200/300?12" height="32" width="48">
|
||||
<AImage :src="`https://picsum.photos/200/300?${Math.random()}`" height="32" width="48" class="bg-slate-50">
|
||||
</AImage>
|
||||
</template>
|
||||
<template #title>
|
||||
|
|
@ -125,7 +116,7 @@
|
|||
</span>
|
||||
<span class="text-xs text-gray-400">2023-08-17 17:00:01</span>
|
||||
<ADropdown @select="onRowActionsSelect" position="br">
|
||||
<span class="inline-flex p-1 hover:bg-slate-100 rounded cursor-pointer">
|
||||
<span class="inline-flex p-1 hover:bg-slate-100 text-brand-500 rounded cursor-pointer">
|
||||
<i class="icon-park-outline-more"></i>
|
||||
</span>
|
||||
<template #content>
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ const form = useForm({
|
|||
<route lang="json">
|
||||
{
|
||||
"meta": {
|
||||
"sort": 10101,
|
||||
"sort": 20101,
|
||||
"title": "首页111",
|
||||
"icon": "icon-park-outline-home"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,9 +151,14 @@ const table = useTable({
|
|||
<route lang="json">
|
||||
{
|
||||
"meta": {
|
||||
"sort": 10101,
|
||||
"sort": 10301,
|
||||
"title": "首页",
|
||||
"icon": "icon-park-outline-home"
|
||||
},
|
||||
"parentMeta": {
|
||||
"title": "总览",
|
||||
"sort": 10000,
|
||||
"icon": "icon-park-outline-home"
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 381 KiB |
|
|
@ -1,14 +1,24 @@
|
|||
<template>
|
||||
<BreadPage>
|
||||
<template #content>
|
||||
<section class="my-page m-5 bg-white p-4">
|
||||
<div>
|
||||
<div class="font-semibold text-base flex items-center">个人设置</div>
|
||||
<div class="text-sm text-gray-400">此表情符号和消息会显示在您的个人资料和界面中。</div>
|
||||
<section class="my-page m-5 bg-white py-4 px-6 max-w-[980px] mx-auto">
|
||||
<div class="flex items-end justify-between gap-4 banner">
|
||||
<div>
|
||||
<div class="font-semibold text-xl flex items-center">个人设置</div>
|
||||
<div class="mt-1 text-sm text-gray-400">此表情符号和消息会显示在您的个人资料和界面中。</div>
|
||||
</div>
|
||||
<div class=" text-gray-500">
|
||||
<div class="text-right">绝弹 <span class="text-sm font-normal text-gray-500">(juetan)</span></div>
|
||||
<div class="mt-0.5 text-gray-400 text-xs">创建于 2023年08月18日 </div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="md:flex md:gap-4 mt-3 border-t pt-6">
|
||||
<div class="md:w-56 text-gray-400">基本信息</div>
|
||||
<!-- <div class="md:w-48 text-gray-400">基本信息</div> -->
|
||||
<!-- <div class="mb-2 md:w-64">
|
||||
<div class="text-base font-semibold">基本设置</div>
|
||||
<div class="text-gray-400 mt-1">设置你的基本信息,用于个性化显示</div>
|
||||
</div> -->
|
||||
<div class="flex-1 flex">
|
||||
<a-form :model="user" layout="vertical">
|
||||
<a-form-item label="个人头像">
|
||||
|
|
@ -18,19 +28,33 @@
|
|||
<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="user.nickname" placeholder="请输入" class="!w-[432px]"></a-input>
|
||||
<template #help> 用作系统内显示的名称,可在后台修改 </template>
|
||||
</a-form-item>
|
||||
<a-form-item label="个人描述">
|
||||
<a-textarea v-model="user.description" placeholder="请输入" class="!w-[580px] h-24"></a-textarea>
|
||||
<a-textarea v-model="user.description" placeholder="请输入" class="!w-[432px] h-24"></a-textarea>
|
||||
</a-form-item>
|
||||
<a-form-item label="密码">
|
||||
<a-button >修改密码</a-button>
|
||||
</a-form-item>
|
||||
<a-form-item label="性别">
|
||||
<a-radio-group v-model="user.gender" type="button">
|
||||
<a-radio :value="1">男</a-radio>
|
||||
<a-radio :value="2">女</a-radio>
|
||||
<a-radio :value="3">保密</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="出生日期">
|
||||
<a-date-picker v-model="user.birth"></a-date-picker>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md:flex md:gap-4 mt-6 pt-6 border-t">
|
||||
<div class="md:w-56 text-gray-400">联系方式</div>
|
||||
<div class="md:flex md:gap-4 mt-2 pt-6 border-t">
|
||||
<!-- <div class="md:w-48 text-gray-400">联系方式</div> -->
|
||||
<div class="flex-1">
|
||||
<a-form :model="user" layout="vertical">
|
||||
<a-form-item label="消息推送">
|
||||
|
|
@ -52,7 +76,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="md:flex md:gap-4 mt-6 pt-6 border-t">
|
||||
<div class="md:w-56 text-gray-400">偏好设置</div>
|
||||
<!-- <div class="md:w-48 text-gray-400">偏好设置</div> -->
|
||||
<div class="flex-1">
|
||||
<a-form :model="user" layout="vertical">
|
||||
<a-form-item label="主题">
|
||||
|
|
@ -73,15 +97,52 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="md:flex md:gap-4 mt-6 pt-6 border-t">
|
||||
<div class="md:w-56 text-gray-400">
|
||||
<!-- <div class="md:w-48 text-gray-400">
|
||||
其他功能
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="flex-1 grid">
|
||||
<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">
|
||||
<svg t="1692015760052" class="icon h-8 w-10" viewBox="0 0 1264 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7353" width="200" height="200"><path d="M0 333.884235a90.352941 90.352941 0 0 1 90.352941-90.352941h1084.235294a90.352941 90.352941 0 0 1 90.352941 90.352941v271.058824h-256a105.411765 105.411765 0 1 0 0 210.823529H1264.941176v90.352941a90.352941 90.352941 0 0 1-90.352941 90.352942H90.352941a90.352941 90.352941 0 0 1-90.352941-90.352942v-572.235294z m1008.941176 421.647059a45.176471 45.176471 0 1 0 0-90.352941 45.176471 45.176471 0 0 0 0 90.352941z" fill="#C1D0FF" p-id="7354"></path><path d="M90.352941 190.343529a60.235294 60.235294 0 0 1 66.861177-59.843764l963.764706 107.068235A60.235294 60.235294 0 0 1 1174.588235 297.441882v187.030589a60.235294 60.235294 0 0 1-60.235294 60.235294H150.588235a60.235294 60.235294 0 0 1-60.235294-60.235294V190.343529zM140.649412 83.275294A90.352941 90.352941 0 0 1 249.615059 13.251765l886.573176 205.914353L139.264 90.051765l1.385412-6.746353z" fill="#0B77FF" p-id="7355"></path><path d="M0 331.294118a90.352941 90.352941 0 0 1 90.352941-90.352942h1084.235294a90.352941 90.352941 0 0 1 90.352941 90.352942v271.058823h-256a105.411765 105.411765 0 1 0 0 210.82353H1264.941176v90.352941a90.352941 90.352941 0 0 1-90.352941 90.352941H90.352941a90.352941 90.352941 0 0 1-90.352941-90.352941V331.294118z" fill="#E8E8E8" fill-opacity=".1" p-id="7356"></path><path d="M90.352941 271.058824h1084.235294a60.235294 60.235294 0 0 1 60.235294 60.235294v240.941176h-225.882353a135.529412 135.529412 0 1 0 0 271.058824H1234.823529v60.235294a60.235294 60.235294 0 0 1-60.235294 60.235294H90.352941a60.235294 60.235294 0 0 1-60.235294-60.235294V331.294118a60.235294 60.235294 0 0 1 60.235294-60.235294z m1174.588235 60.235294a90.352941 90.352941 0 0 0-90.352941-90.352942H90.352941a90.352941 90.352941 0 0 0-90.352941 90.352942v572.235294a90.352941 90.352941 0 0 0 90.352941 90.352941h1084.235294a90.352941 90.352941 0 0 0 90.352941-90.352941v-90.352941h-256a105.411765 105.411765 0 1 1 0-210.82353H1264.941176v-271.058823z" fill="#FFFFFF" fill-opacity=".6" p-id="7357"></path><path d="M353.882353 424.237176H271.058824l82.823529 195.764706h-41.411765v39.152942h82.82353v39.152941h-82.82353v39.152941h82.82353v78.305882h82.823529v-78.305882h82.823529v-39.152941h-82.823529v-39.152941h82.823529v-39.152942H519.529412l82.823529-195.764706h-82.823529l-82.82353 195.764706-82.823529-195.764706z" fill="#FFFFFF" p-id="7358"></path></svg>
|
||||
<svg
|
||||
t="1692015760052"
|
||||
class="icon h-8 w-10"
|
||||
viewBox="0 0 1264 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="7353"
|
||||
width="200"
|
||||
height="200"
|
||||
>
|
||||
<path
|
||||
d="M0 333.884235a90.352941 90.352941 0 0 1 90.352941-90.352941h1084.235294a90.352941 90.352941 0 0 1 90.352941 90.352941v271.058824h-256a105.411765 105.411765 0 1 0 0 210.823529H1264.941176v90.352941a90.352941 90.352941 0 0 1-90.352941 90.352942H90.352941a90.352941 90.352941 0 0 1-90.352941-90.352942v-572.235294z m1008.941176 421.647059a45.176471 45.176471 0 1 0 0-90.352941 45.176471 45.176471 0 0 0 0 90.352941z"
|
||||
fill="#C1D0FF"
|
||||
p-id="7354"
|
||||
></path>
|
||||
<path
|
||||
d="M90.352941 190.343529a60.235294 60.235294 0 0 1 66.861177-59.843764l963.764706 107.068235A60.235294 60.235294 0 0 1 1174.588235 297.441882v187.030589a60.235294 60.235294 0 0 1-60.235294 60.235294H150.588235a60.235294 60.235294 0 0 1-60.235294-60.235294V190.343529zM140.649412 83.275294A90.352941 90.352941 0 0 1 249.615059 13.251765l886.573176 205.914353L139.264 90.051765l1.385412-6.746353z"
|
||||
fill="#0B77FF"
|
||||
p-id="7355"
|
||||
></path>
|
||||
<path
|
||||
d="M0 331.294118a90.352941 90.352941 0 0 1 90.352941-90.352942h1084.235294a90.352941 90.352941 0 0 1 90.352941 90.352942v271.058823h-256a105.411765 105.411765 0 1 0 0 210.82353H1264.941176v90.352941a90.352941 90.352941 0 0 1-90.352941 90.352941H90.352941a90.352941 90.352941 0 0 1-90.352941-90.352941V331.294118z"
|
||||
fill="#E8E8E8"
|
||||
fill-opacity=".1"
|
||||
p-id="7356"
|
||||
></path>
|
||||
<path
|
||||
d="M90.352941 271.058824h1084.235294a60.235294 60.235294 0 0 1 60.235294 60.235294v240.941176h-225.882353a135.529412 135.529412 0 1 0 0 271.058824H1234.823529v60.235294a60.235294 60.235294 0 0 1-60.235294 60.235294H90.352941a60.235294 60.235294 0 0 1-60.235294-60.235294V331.294118a60.235294 60.235294 0 0 1 60.235294-60.235294z m1174.588235 60.235294a90.352941 90.352941 0 0 0-90.352941-90.352942H90.352941a90.352941 90.352941 0 0 0-90.352941 90.352942v572.235294a90.352941 90.352941 0 0 0 90.352941 90.352941h1084.235294a90.352941 90.352941 0 0 0 90.352941-90.352941v-90.352941h-256a105.411765 105.411765 0 1 1 0-210.82353H1264.941176v-271.058823z"
|
||||
fill="#FFFFFF"
|
||||
fill-opacity=".6"
|
||||
p-id="7357"
|
||||
></path>
|
||||
<path
|
||||
d="M353.882353 424.237176H271.058824l82.823529 195.764706h-41.411765v39.152942h82.82353v39.152941h-82.82353v39.152941h82.82353v78.305882h82.823529v-78.305882h82.823529v-39.152941h-82.823529v-39.152941h82.823529v-39.152942H519.529412l82.823529-195.764706h-82.823529l-82.82353 195.764706-82.823529-195.764706z"
|
||||
fill="#FFFFFF"
|
||||
p-id="7358"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-gray-900">支付功能</div>
|
||||
|
|
@ -90,19 +151,15 @@
|
|||
</div>
|
||||
<div>
|
||||
<a-switch checked-color="#3c9">
|
||||
<template #checked>
|
||||
已启用
|
||||
</template>
|
||||
<template #unchecked>
|
||||
未启用
|
||||
</template>
|
||||
<template #checked> 已启用 </template>
|
||||
<template #unchecked> 未启用 </template>
|
||||
</a-switch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="md:flex md:gap-4 mt-6 pt-6 border-t">
|
||||
<div class="md:w-56 text-gray-400"></div>
|
||||
<!-- <div class="md:w-48 text-gray-400"></div> -->
|
||||
<div class="flex-1">
|
||||
<a-button type="primary">更新设置</a-button>
|
||||
</div>
|
||||
|
|
@ -114,7 +171,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { reactive } from 'vue';
|
||||
import { reactive } from "vue";
|
||||
|
||||
const emailOptions = [
|
||||
{
|
||||
|
|
@ -127,14 +184,15 @@ const emailOptions = [
|
|||
},
|
||||
];
|
||||
|
||||
const user =reactive({
|
||||
const user = reactive({
|
||||
nickname: "绝弹",
|
||||
description: "选择在公开个人资料中显示私有项目的贡献,但不显示任何项目,仓库或组织信息",
|
||||
theme: "dark",
|
||||
email: "810335188@qq.com",
|
||||
msg: [2],
|
||||
|
||||
})
|
||||
gender: 1,
|
||||
birth: '1988-12-18'
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="bg-white px-4 pt-2">
|
||||
<bread-crumb></bread-crumb>
|
||||
<div class="flex justify-between items-end gap-4 bg-white px-1 py-4">
|
||||
<div>
|
||||
<div class="text-lg font-semibold">新增文章</div>
|
||||
<div class="text-gray-400 mt-1">新增的文章需审核才能展现</div>
|
||||
</div>
|
||||
<div>
|
||||
<a-button class="mr-2">保存为草稿</a-button>
|
||||
<a-button type="primary">保存发布</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-4 mt-6 px-6">
|
||||
<div class="flex-1 bg-white p-4">
|
||||
<a-form :model="{}" layout="vertical">
|
||||
<a-form-item label="标题">
|
||||
<a-input placeholder="请输入标题" :max-length="120" :show-word-limit="true"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="文章内容">
|
||||
<a-textarea placeholder="说点啥" :max-length="1000" :show-word-limit="true"></a-textarea>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="w-64 bg-white p-4">
|
||||
<a-form :model="{}" layout="vertical">
|
||||
<a-form-item label="别名">
|
||||
<a-input placeholder="请输入"></a-input>
|
||||
<template #help>
|
||||
用作URL的别名, 只能包含字母、数字、下划线和破折号
|
||||
</template>
|
||||
</a-form-item>
|
||||
<a-form-item label="分类">
|
||||
<a-checkbox-group direction="vertical">
|
||||
<a-checkbox>开发工具</a-checkbox>
|
||||
<a-checkbox>日常记录</a-checkbox>
|
||||
<a-checkbox>心得体验</a-checkbox>
|
||||
</a-checkbox-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="封面图">
|
||||
<div class="h-24 rounded w-full flex items-center justify-center text-gray-500 bg-gray-100">
|
||||
从素材库中选择...
|
||||
</div>
|
||||
<template #help>
|
||||
推荐使用 600x400 的图片
|
||||
</template>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx" name="PostPage">
|
||||
import { api } from "@/api";
|
||||
import { Table, useTable } from "@/components";
|
||||
import { dayjs } from "@/plugins";
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.export-form {
|
||||
.arco-form-item-content {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<route lang="json">
|
||||
{
|
||||
"meta": {
|
||||
"sort": 10300,
|
||||
"title": "新增文章",
|
||||
"icon": "icon-park-outline-edit"
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
|
@ -1,6 +1,51 @@
|
|||
<template>
|
||||
<div class="m-4 p-4 bg-white">
|
||||
<Table v-bind="table" />
|
||||
<Table v-bind="table">
|
||||
<template #action>
|
||||
<a-button type="outline" @click="model.visible = true">
|
||||
<template #icon>
|
||||
<i class="icon-park-outline-export"></i>
|
||||
</template>
|
||||
导出
|
||||
</a-button>
|
||||
</template>
|
||||
</Table>
|
||||
<a-modal title="导出为文件" v-model:visible="model.visible" title-align="start">
|
||||
<a-form :model="{}" layout="vertical" class="export-form">
|
||||
<a-form-item label="文件名">
|
||||
<a-input v-model="model.filename" placeholder="请输入"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="导出类型">
|
||||
<div class="grid gap-2">
|
||||
<div
|
||||
v-for="item in exportTypes"
|
||||
@click="model.exportType = item.name"
|
||||
class="w-full flex justify-between items-center gap-4 rounded py-2 px-4 border border-transparent cursor-pointer"
|
||||
:class="{
|
||||
'!border-brand-500': model.exportType === item.name,
|
||||
}"
|
||||
>
|
||||
<div class="flex items-center gap-2 rounded">
|
||||
<div class="h-10 w-10 flex items-center justify-center rounded-full bg-brand-50">
|
||||
<i :class="item.icon" class="text-2xl text-brand-500"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-slate-900">
|
||||
{{ item.label }}
|
||||
</div>
|
||||
<div class="text-slate-400 text-xs">
|
||||
{{ item.description }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<a-radio v-model="model.exportType" :value="item.name" class="mt-1"></a-radio>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -62,6 +107,22 @@ const table = useTable({
|
|||
extend: "title",
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
extend: "title",
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
extend: "title",
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
extend: "title",
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
extend: "title",
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
create: {
|
||||
|
|
@ -108,9 +169,42 @@ const table = useTable({
|
|||
},
|
||||
},
|
||||
});
|
||||
|
||||
const exportTypes = [
|
||||
{
|
||||
name: "excel",
|
||||
icon: "icon-park-outline-file-excel",
|
||||
label: "Excel格式",
|
||||
description: "后缀: .xlsx, 可使用 office excel 2003 及以上版本打开",
|
||||
},
|
||||
{
|
||||
name: "csv",
|
||||
icon: "icon-park-outline-file-code",
|
||||
label: "CSV格式",
|
||||
description: "后缀: .csv, 可使用 excel 或 记事本等工具打开",
|
||||
},
|
||||
{
|
||||
name: "text",
|
||||
icon: "icon-park-outline-file-text",
|
||||
label: "TEXT格式",
|
||||
description: "后缀: .txt, 可使用 记事本 或 其他文本编辑器打开",
|
||||
},
|
||||
];
|
||||
|
||||
const model = reactive({
|
||||
visible: false,
|
||||
exportType: "excel",
|
||||
filename: dayjs().format("导出文件YYYYMMDDHHmmss"),
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style lang="less">
|
||||
.export-form {
|
||||
.arco-form-item-content {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<route lang="json">
|
||||
{
|
||||
|
|
@ -118,6 +212,11 @@ const table = useTable({
|
|||
"sort": 10300,
|
||||
"title": "文章管理",
|
||||
"icon": "icon-park-outline-document-folder"
|
||||
},
|
||||
"parentMeta": {
|
||||
"sort": 10300,
|
||||
"title": "内容管理",
|
||||
"icon": "icon-park-outline-document-folder"
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
|
|
|||
|
|
@ -14,9 +14,6 @@ const table = useTable({
|
|||
return api.permission.getPermissions();
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
type: "index",
|
||||
},
|
||||
{
|
||||
title: "权限名称",
|
||||
dataIndex: "username",
|
||||
|
|
@ -25,7 +22,7 @@ const table = useTable({
|
|||
return (
|
||||
<div class="flex flex-col overflow-hidden">
|
||||
<span>{record.name}</span>
|
||||
<span class="text-gray-400 text-xs truncate">标识:{record.slug}</span>
|
||||
<span class="text-gray-400 text-xs truncate">{record.slug}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
@ -43,12 +40,16 @@ const table = useTable({
|
|||
{
|
||||
title: "操作",
|
||||
type: "button",
|
||||
width: 70,
|
||||
width: 110,
|
||||
buttons: [
|
||||
{
|
||||
type: "modify",
|
||||
text: "修改",
|
||||
},
|
||||
{
|
||||
type: 'delete',
|
||||
text: '删除',
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -14,9 +14,6 @@ const table = useTable({
|
|||
return api.role.getRoles();
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
type: "index",
|
||||
},
|
||||
{
|
||||
title: "角色名称",
|
||||
dataIndex: "username",
|
||||
|
|
@ -25,7 +22,7 @@ const table = useTable({
|
|||
return (
|
||||
<div class="flex flex-col overflow-hidden">
|
||||
<span>{record.name}</span>
|
||||
<span class="text-gray-400 text-xs truncate">标识:{record.slug}</span>
|
||||
<span class="text-gray-400 text-xs truncate">{record.slug}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,9 +22,6 @@ const table = useTable({
|
|||
return api.user.getUsers({ ...model, ...paging });
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
type: "index",
|
||||
},
|
||||
{
|
||||
title: "用户昵称",
|
||||
dataIndex: "username",
|
||||
|
|
@ -36,7 +33,7 @@ const table = useTable({
|
|||
</Avatar>
|
||||
<span class="ml-2 flex-1 flex flex-col overflow-hidden">
|
||||
<span>{record.nickname}</span>
|
||||
<span class="text-gray-400 text-xs truncate">账号:{record.username}</span>
|
||||
<span class="text-gray-400 text-xs truncate">{record.username}</span>
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
|
|
@ -82,6 +79,9 @@ const table = useTable({
|
|||
itemProps: {
|
||||
hideLabel: true,
|
||||
},
|
||||
nodeProps: {
|
||||
placeholder: "输入用户昵称关键字",
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ body {
|
|||
display: none;
|
||||
}
|
||||
}
|
||||
.arco-form-item-layout-inline:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
.dark {
|
||||
.arco-menu-item.arco-menu-selected {
|
||||
|
|
|
|||
|
|
@ -10,3 +10,8 @@
|
|||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.table .arco-form-item-layout-inline {
|
||||
margin-right: 8px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,16 +8,18 @@ export {}
|
|||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
AAvatar: typeof import('@arco-design/web-vue')['Avatar']
|
||||
ABadge: typeof import('@arco-design/web-vue')['Badge']
|
||||
ABreadcrumb: typeof import('@arco-design/web-vue')['Breadcrumb']
|
||||
ABreadcrumbItem: typeof import('@arco-design/web-vue')['BreadcrumbItem']
|
||||
AButton: typeof import('@arco-design/web-vue')['Button']
|
||||
ACard: typeof import('@arco-design/web-vue')['Card']
|
||||
ACheckbox: typeof import('@arco-design/web-vue')['Checkbox']
|
||||
ACheckboxGroup: typeof import('@arco-design/web-vue')['CheckboxGroup']
|
||||
AConfigProvider: typeof import('@arco-design/web-vue')['ConfigProvider']
|
||||
ADatePicker: typeof import('@arco-design/web-vue')['DatePicker']
|
||||
ADoption: typeof import('@arco-design/web-vue')['Doption']
|
||||
ADrawer: typeof import('@arco-design/web-vue')['Drawer']
|
||||
ADropdown: typeof import('@arco-design/web-vue')['Dropdown']
|
||||
AEmpty: typeof import('@arco-design/web-vue')['Empty']
|
||||
AForm: typeof import('@arco-design/web-vue')['Form']
|
||||
AFormItem: typeof import('@arco-design/web-vue')['FormItem']
|
||||
AImage: typeof import('@arco-design/web-vue')['Image']
|
||||
|
|
@ -33,9 +35,12 @@ declare module '@vue/runtime-core' {
|
|||
AListItemMeta: typeof import('@arco-design/web-vue')['ListItemMeta']
|
||||
AMenu: typeof import('@arco-design/web-vue')['Menu']
|
||||
AMenuItem: typeof import('@arco-design/web-vue')['MenuItem']
|
||||
AMenuItemGroup: typeof import('@arco-design/web-vue')['MenuItemGroup']
|
||||
AModal: typeof import('@arco-design/web-vue')['Modal']
|
||||
APagination: typeof import('@arco-design/web-vue')['Pagination']
|
||||
ARadio: typeof import('@arco-design/web-vue')['Radio']
|
||||
ARadioGroup: typeof import('@arco-design/web-vue')['RadioGroup']
|
||||
ASelect: typeof import('@arco-design/web-vue')['Select']
|
||||
ASpace: typeof import('@arco-design/web-vue')['Space']
|
||||
ASubMenu: typeof import('@arco-design/web-vue')['SubMenu']
|
||||
ASwitch: typeof import('@arco-design/web-vue')['Switch']
|
||||
|
|
@ -44,6 +49,7 @@ declare module '@vue/runtime-core' {
|
|||
ATag: typeof import('@arco-design/web-vue')['Tag']
|
||||
ATextarea: typeof import('@arco-design/web-vue')['Textarea']
|
||||
ATooltip: typeof import('@arco-design/web-vue')['Tooltip']
|
||||
ATree: typeof import('@arco-design/web-vue')['Tree']
|
||||
BreadCrumb: typeof import('./../components/breadcrumb/bread-crumb.vue')['default']
|
||||
BreadPage: typeof import('./../components/breadcrumb/bread-page.vue')['default']
|
||||
Page403: typeof import('./../components/error/page-403.vue')['default']
|
||||
|
|
|
|||
|
|
@ -90,6 +90,22 @@ export default defineConfig(({ mode }) => {
|
|||
* @see https://github.com/unocss/unocss#readme
|
||||
*/
|
||||
Unocss({
|
||||
theme: {
|
||||
colors: {
|
||||
brand: {
|
||||
50: 'rgb(var(--primary-1))',
|
||||
100: 'rgb(var(--primary-2))',
|
||||
200: 'rgb(var(--primary-3))',
|
||||
300: 'rgb(var(--primary-4))',
|
||||
400: 'rgb(var(--primary-5))',
|
||||
500: 'rgb(var(--primary-6))',
|
||||
600: 'rgb(var(--primary-7))',
|
||||
700: 'rgb(var(--primary-8))',
|
||||
800: 'rgb(var(--primary-9))',
|
||||
900: 'rgb(var(--primary-10))',
|
||||
}
|
||||
}
|
||||
},
|
||||
include: ["src/**/*.{vue,ts,tsx,css,scss,sass,less,styl}"],
|
||||
presets: [presetUno(), presetIcons({ prefix: "" })],
|
||||
}),
|
||||
|
|
|
|||
Loading…
Reference in New Issue