feat: 优化弹窗样式
parent
2f127bac40
commit
5791478337
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="h-full grid grid-rows-[auto_1fr]">
|
||||||
<div class="bg-white px-4 py-2">
|
<div class="bg-white dark:bg-gray-800 px-4 py-2">
|
||||||
<div class="flex justify-between gap-4">
|
<div class="flex justify-between gap-4">
|
||||||
<BreadCrumb></BreadCrumb>
|
<BreadCrumb></BreadCrumb>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<slot name="content">
|
<slot name="content">
|
||||||
<div class="m-4 p-4 bg-white">
|
<div class="m-4 p-4 bg-white dark:bg-gray-700">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ export const Table = defineComponent({
|
||||||
|
|
||||||
<BaseTable
|
<BaseTable
|
||||||
row-key="id"
|
row-key="id"
|
||||||
bordered={true}
|
bordered={false}
|
||||||
{...this.tableProps}
|
{...this.tableProps}
|
||||||
loading={this.loading}
|
loading={this.loading}
|
||||||
pagination={this.pagination}
|
pagination={this.pagination}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import relativeTime from "dayjs/plugin/relativeTime";
|
||||||
*
|
*
|
||||||
* 默认日期时间格式
|
* 默认日期时间格式
|
||||||
*/
|
*/
|
||||||
const DATETIME = "YYYY-MM-DD HH:mm:ss";
|
const DATETIME = "YYYY-MM-DD HH:mm";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认日期格式
|
* 默认日期格式
|
||||||
|
|
@ -63,5 +63,5 @@ dayjs.prototype.format = function (format?: string) {
|
||||||
return this._format(dayjs.DATETIME);
|
return this._format(dayjs.DATETIME);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { dayjs, DATETIME, DATE, TIME };
|
export { DATE, DATETIME, TIME, dayjs };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ declare module 'dayjs' {
|
||||||
/**
|
/**
|
||||||
* 默认日期时间格式
|
* 默认日期时间格式
|
||||||
*/
|
*/
|
||||||
export var DATETIME: 'YYYY-MM-DD HH:mm:ss';
|
export var DATETIME: 'YYYY-MM-DD HH:mm';
|
||||||
|
|
||||||
export var DATE: 'YYYY-MM-DD';
|
export var DATE: 'YYYY-MM-DD';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,15 @@ export default defineComponent({
|
||||||
renderItem(routes: MenuItem[], isTop = false) {
|
renderItem(routes: MenuItem[], isTop = false) {
|
||||||
return routes.map((route) => {
|
return routes.map((route) => {
|
||||||
const icon = route.icon ? () => <i class={route.icon} /> : null;
|
const icon = route.icon ? () => <i class={route.icon} /> : null;
|
||||||
const node = route.children?.length ? (
|
const node: any = route.children?.length ? (
|
||||||
<a-menu-item-group key={route.path} v-slots={{ icon, title: () => route.title }}>
|
<>
|
||||||
|
<div class="px-2"><a-divider margin={6}></a-divider></div>
|
||||||
{this.renderItem(route?.children)}
|
{this.renderItem(route?.children)}
|
||||||
</a-menu-item-group>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<a-menu-item key={route.path} v-slots={{ icon }} onClick={() => this.goto(route)}>
|
<a-menu-item key={route.path} v-slots={{ icon }} onClick={() => this.goto(route)}>
|
||||||
{route.title}
|
{route.title}
|
||||||
{ false && <span class="text-xs text-slate-400 ml-2">({route.sort})</span>}
|
{false && <span class="text-xs text-slate-400 ml-2">({route.sort})</span>}
|
||||||
</a-menu-item>
|
</a-menu-item>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@
|
||||||
class="h-13 overflow-hidden flex justify-between items-center gap-4 px-2 pr-4 border-b border-slate-200 bg-white dark:bg-slate-800 dark:border-slate-700"
|
class="h-13 overflow-hidden flex justify-between items-center gap-4 px-2 pr-4 border-b border-slate-200 bg-white dark:bg-slate-800 dark:border-slate-700"
|
||||||
>
|
>
|
||||||
<div class="h-13 flex items-center border-b border-slate-200 dark:border-slate-800">
|
<div class="h-13 flex items-center border-b border-slate-200 dark:border-slate-800">
|
||||||
<router-link to="/" class="px-2 py-1 rounded flex items-center gap-2 text-slate-700 hover:bg-slate-100">
|
<router-link to="/" class="px-2 py-2 rounded flex items-center gap-2 text-slate-700">
|
||||||
<img src="/favicon.ico" alt="" width="22" height="22" class="" />
|
<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">
|
<h1 class="relative text-lg leading-[19px] dark:text-white m-0 p-0">
|
||||||
{{ appStore.title }}
|
{{ appStore.title }}
|
||||||
<span
|
<span
|
||||||
v-if="isDev"
|
v-if="isDev"
|
||||||
|
|
@ -41,11 +41,15 @@
|
||||||
:collapsible="true"
|
:collapsible="true"
|
||||||
:collapsed="isCollapsed"
|
:collapsed="isCollapsed"
|
||||||
:hide-trigger="false"
|
:hide-trigger="false"
|
||||||
|
:breakpoint="'lg'"
|
||||||
@collapse="onCollapse"
|
@collapse="onCollapse"
|
||||||
>
|
>
|
||||||
<a-scrollbar outer-class="h-full overflow-hidden" class="h-full overflow-hidden pt-2">
|
<a-scrollbar outer-class="h-full overflow-hidden" class="h-full overflow-hidden pt-2">
|
||||||
<Menu />
|
<Menu />
|
||||||
</a-scrollbar>
|
</a-scrollbar>
|
||||||
|
<template #trigger="{ collapsed }">
|
||||||
|
<i :class="`text-gray-400 text-base ${collapsed ? 'icon-park-outline-expand-left' : 'icon-park-outline-expand-right'}`"></i>
|
||||||
|
</template>
|
||||||
</a-layout-sider>
|
</a-layout-sider>
|
||||||
<a-layout class="layout-content flex-1">
|
<a-layout class="layout-content flex-1">
|
||||||
<a-layout-header class="h-8 bg-white border-b border-slate-200 dark:bg-slate-800 dark:border-slate-700">
|
<a-layout-header class="h-8 bg-white border-b border-slate-200 dark:bg-slate-800 dark:border-slate-700">
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ import { reactive } from "vue";
|
||||||
const meridiem = dayjs.localeData().meridiem(dayjs().hour(), dayjs().minute());
|
const meridiem = dayjs.localeData().meridiem(dayjs().hour(), dayjs().minute());
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const model = reactive({ username: "juetan", password: "juetan" });
|
const model = reactive({ username: "", password: "" });
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<template>
|
||||||
|
<bread-page>
|
||||||
|
<template #content>
|
||||||
|
<iframe
|
||||||
|
src="https://apifox.com/apidoc/shared-f1ea65e6-cee8-4fe3-949f-288a7cd1af49"
|
||||||
|
frameborder="0"
|
||||||
|
class="w-full h-full"
|
||||||
|
></iframe>
|
||||||
|
</template>
|
||||||
|
</bread-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts"></script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
|
|
||||||
|
<route lang="json">
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"sort": 20010,
|
||||||
|
"title": "接口文档",
|
||||||
|
"icon": "icon-park-outline-api"
|
||||||
|
},
|
||||||
|
"parentMeta": {
|
||||||
|
"sort": 20010,
|
||||||
|
"title": "开发相关",
|
||||||
|
"icon": "icon-park-outline-home"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</route>
|
||||||
|
|
@ -63,7 +63,7 @@ for (const item of items) {
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
menus: items,
|
menus: items,
|
||||||
visible: true
|
visible: false
|
||||||
});
|
});
|
||||||
|
|
||||||
const indeter = (items: any[]) => {
|
const indeter = (items: any[]) => {
|
||||||
|
|
@ -200,11 +200,6 @@ const table = useTable({
|
||||||
"sort": 10201,
|
"sort": 10201,
|
||||||
"title": "表格组件",
|
"title": "表格组件",
|
||||||
"icon": "icon-park-outline-add-subtract"
|
"icon": "icon-park-outline-add-subtract"
|
||||||
},
|
|
||||||
"parentMeta": {
|
|
||||||
"sort": 10201,
|
|
||||||
"title": "内置组件",
|
|
||||||
"icon": "icon-park-outline-add-subtract"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</route>
|
</route>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<div class="m-4">
|
||||||
|
<a-card :bordered="false">
|
||||||
|
<template #title>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<i class="icon-park-outline-config mr-2"></i>
|
||||||
|
系统参数
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="tsx"></script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
|
|
||||||
|
<route lang="json">
|
||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"sort": 10001,
|
||||||
|
"title": "首页",
|
||||||
|
"icon": "icon-park-outline-home"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</route>
|
||||||
|
|
@ -1,164 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="m-4 p-4 bg-white dark:bg-gray-700">
|
|
||||||
<Form v-bind="form"></Form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="tsx">
|
|
||||||
import { Form, useForm } from "@/components";
|
|
||||||
|
|
||||||
const sleep = (wait: number) => new Promise((res) => setTimeout(res, wait));
|
|
||||||
|
|
||||||
const form = useForm({
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
field: "username",
|
|
||||||
label: "姓名",
|
|
||||||
type: "input",
|
|
||||||
required: true,
|
|
||||||
itemProps: {
|
|
||||||
hideLabel: false,
|
|
||||||
},
|
|
||||||
rules: ["password"],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "nickname",
|
|
||||||
label: "昵称",
|
|
||||||
type: "input",
|
|
||||||
disable: ({ model }) => !model.username,
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
message: "昵称不能超过 10 个字符",
|
|
||||||
required: true,
|
|
||||||
disable: ({ model }) => !model.username,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "password",
|
|
||||||
label: "密码",
|
|
||||||
type: "password",
|
|
||||||
visible: ({ model }) => model.username,
|
|
||||||
nodeProps: {
|
|
||||||
class: "w-full",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "gender",
|
|
||||||
label: "性别",
|
|
||||||
type: "select",
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: "男",
|
|
||||||
value: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "女",
|
|
||||||
value: 2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "startTime:endTime",
|
|
||||||
label: "时间",
|
|
||||||
type: "time",
|
|
||||||
nodeProps: {
|
|
||||||
type: "time-range",
|
|
||||||
},
|
|
||||||
help: "时间段",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "startDate:endDate",
|
|
||||||
label: "日期",
|
|
||||||
type: "dateRange",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "checkbox",
|
|
||||||
label: "多选",
|
|
||||||
type: "checkbox",
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: "选项1",
|
|
||||||
value: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "选项2",
|
|
||||||
value: 2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "radio",
|
|
||||||
label: "单选",
|
|
||||||
type: "radio",
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: "选项1",
|
|
||||||
value: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "选项2",
|
|
||||||
value: 2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "slider",
|
|
||||||
label: "音量",
|
|
||||||
type: "slider",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "provice:city:town",
|
|
||||||
label: "城市",
|
|
||||||
type: "cascader",
|
|
||||||
nodeProps: {
|
|
||||||
checkStrictly: true,
|
|
||||||
pathMode: true,
|
|
||||||
},
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: "广西",
|
|
||||||
value: "gx",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
label: "南宁",
|
|
||||||
value: "nn",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "桂林",
|
|
||||||
value: "gl",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
label: "阳朔",
|
|
||||||
value: "ys",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "临桂",
|
|
||||||
value: "lg",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
submit: async ({ model }) => {
|
|
||||||
await sleep(3000);
|
|
||||||
console.log("submit", model);
|
|
||||||
return { message: "操作成功" };
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
|
|
||||||
<route lang="json">
|
|
||||||
{
|
|
||||||
"meta": {
|
|
||||||
"sort": 10001,
|
|
||||||
"title": "首页111",
|
|
||||||
"icon": "icon-park-outline-home"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</route>
|
|
||||||
|
|
@ -1,159 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="m-4 p-4 bg-white">
|
|
||||||
<Table v-bind="table"></Table>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="tsx">
|
|
||||||
import { ContentType, api } from "@/api";
|
|
||||||
import { Table, useTable } from "@/components";
|
|
||||||
import { dayjs } from "@/libs/dayjs";
|
|
||||||
import { Avatar } from "@arco-design/web-vue";
|
|
||||||
|
|
||||||
const url = ref<any>(null);
|
|
||||||
|
|
||||||
const table = useTable({
|
|
||||||
data: async () => {
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
type: "index",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "姓名",
|
|
||||||
dataIndex: "username",
|
|
||||||
width: 200,
|
|
||||||
render: ({ record }) => {
|
|
||||||
return (
|
|
||||||
<div class="flex items-center gap-2 w-full">
|
|
||||||
<div>
|
|
||||||
<Avatar size={32}>
|
|
||||||
<img src={record.avatar} width={32} height={32} />
|
|
||||||
</Avatar>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 overflow-hidden">
|
|
||||||
<span class="ml-0">{record.nickname}</span>
|
|
||||||
<div class="text-xs text-gray-400 mt-1 truncate">{record.description}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "昵称",
|
|
||||||
dataIndex: "username",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "昵称",
|
|
||||||
dataIndex: "username",
|
|
||||||
width: 200,
|
|
||||||
render: ({ record }) => {
|
|
||||||
return (
|
|
||||||
<div class="">
|
|
||||||
<span class="ml-0">{record.username}</span>
|
|
||||||
<div class="text-xs text-gray-400 mt-1 truncate">创建于 {dayjs(record.createAt).format()}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "操作",
|
|
||||||
type: "button",
|
|
||||||
width: 70,
|
|
||||||
buttons: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
search: {
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
field: "username",
|
|
||||||
label: "姓名",
|
|
||||||
type: "input",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
title: "新建用户",
|
|
||||||
modalProps: {
|
|
||||||
width: 432,
|
|
||||||
maskClosable: false,
|
|
||||||
},
|
|
||||||
formProps: {
|
|
||||||
layout: "vertical",
|
|
||||||
},
|
|
||||||
model: {
|
|
||||||
avatar: "11",
|
|
||||||
},
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
field: "username",
|
|
||||||
label: "姓名",
|
|
||||||
type: "input",
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "nickname",
|
|
||||||
label: "昵称",
|
|
||||||
type: "input",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: "password",
|
|
||||||
label: "密码",
|
|
||||||
type: "password",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "头像",
|
|
||||||
field: "avatar",
|
|
||||||
type: "input",
|
|
||||||
component: ({ model, field }) => {
|
|
||||||
const onInputChange = (e: Event) => {
|
|
||||||
const target = e.target as HTMLInputElement;
|
|
||||||
const file = target.files?.[0];
|
|
||||||
if (!file) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
model[field] = file;
|
|
||||||
console.log(file);
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = (e) => {
|
|
||||||
url.value = e.target?.result;
|
|
||||||
};
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div class="w-full h-12 flex gap-4 items-center justify-between">
|
|
||||||
<input type="file" onChange={onInputChange} class="flex-1" />
|
|
||||||
{url.value && (
|
|
||||||
<a-avatar size={40}>
|
|
||||||
<img src={url.value} />
|
|
||||||
</a-avatar>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
submit: ({ model }) => {
|
|
||||||
return api.user.addUser(model as any, {
|
|
||||||
type: ContentType.FormData,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
modify: {
|
|
||||||
title: "修改用户",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
|
|
||||||
<route lang="json">
|
|
||||||
{
|
|
||||||
"meta": {
|
|
||||||
"sort": 10001,
|
|
||||||
"title": "首页",
|
|
||||||
"icon": "icon-park-outline-home"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</route>
|
|
||||||
|
|
@ -2,20 +2,14 @@
|
||||||
<bread-page id="list-page">
|
<bread-page id="list-page">
|
||||||
<template #default>
|
<template #default>
|
||||||
<div class="flex justify-between items-end gap-4">
|
<div class="flex justify-between items-end gap-4">
|
||||||
<div class="">
|
<a-button type="primary" @click="visible = true">
|
||||||
<span class="text-lg font-bold text-gray-900">媒体素材</span>
|
<template #icon>
|
||||||
<div class="mt-1 text-gray-400">用户上传的图片、视频、音频等素材,可用于文章、图文、视频等内容的编辑。</div>
|
<i class="icon-park-outline-add"></i>
|
||||||
</div>
|
</template>
|
||||||
<div class="text-sm text-gray-400">
|
添加
|
||||||
<a-button type="primary" @click="visible = true">
|
</a-button>
|
||||||
<template #icon>
|
|
||||||
<i class="icon-park-outline-add"></i>
|
|
||||||
</template>
|
|
||||||
添加
|
|
||||||
</a-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<AList class="mt-4 bg-white" :bordered="true">
|
<AList class="mt-2 bg-white" :bordered="true">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex gap-2 items-center justify-between text-sm bg-[#fbfbfc] px-5 py-2">
|
<div class="flex gap-2 items-center justify-between text-sm bg-[#fbfbfc] px-5 py-2">
|
||||||
<div class="flex gap-4 my-1.5">
|
<div class="flex gap-4 my-1.5">
|
||||||
|
|
@ -159,7 +153,7 @@
|
||||||
<script setup lang="tsx">
|
<script setup lang="tsx">
|
||||||
import { Modal } from "@arco-design/web-vue";
|
import { Modal } from "@arco-design/web-vue";
|
||||||
|
|
||||||
const visible = ref(false)
|
const visible = ref(false);
|
||||||
|
|
||||||
const onRowActionsSelect = () => {
|
const onRowActionsSelect = () => {
|
||||||
Modal.open({
|
Modal.open({
|
||||||
|
|
@ -8,9 +8,8 @@
|
||||||
import { api } from "@/api";
|
import { api } from "@/api";
|
||||||
import { RequestOption } from "@arco-design/web-vue";
|
import { RequestOption } from "@arco-design/web-vue";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { reactive } from "vue";
|
|
||||||
|
|
||||||
const modal = reactive({
|
const modal = ref({
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -50,7 +49,7 @@ const upload = (option: RequestOption) => {
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open: () => {
|
open: () => {
|
||||||
modal.visible = true;
|
modal.value.visible = true;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,13 @@
|
||||||
<div>
|
<div>
|
||||||
<Table v-bind="table">
|
<Table v-bind="table">
|
||||||
<template #action>
|
<template #action>
|
||||||
<a-button type="primary">
|
<a-button type="primary" @click="uploadRef?.open()">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<i class="icon-park-outline-upload"></i>
|
<i class="icon-park-outline-upload"></i>
|
||||||
</template>
|
</template>
|
||||||
上传
|
上传
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<ani-upload ref="uploadRef"></ani-upload>
|
||||||
</template>
|
</template>
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -50,6 +51,9 @@ import { api } from "@/api";
|
||||||
import { Table, useTable } from "@/components";
|
import { Table, useTable } from "@/components";
|
||||||
import { dayjs } from "@/libs/dayjs";
|
import { dayjs } from "@/libs/dayjs";
|
||||||
import numeral from "numeral";
|
import numeral from "numeral";
|
||||||
|
import AniUpload from './components/upload.vue';
|
||||||
|
|
||||||
|
const uploadRef = ref<InstanceType<typeof AniUpload>>()
|
||||||
|
|
||||||
const getIcon = (mimetype: string) => {
|
const getIcon = (mimetype: string) => {
|
||||||
if (mimetype.startsWith("image")) {
|
if (mimetype.startsWith("image")) {
|
||||||
|
|
|
||||||
|
|
@ -68,14 +68,28 @@ const table = useTable({
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
search: {
|
search: {
|
||||||
|
button: true,
|
||||||
items: [
|
items: [
|
||||||
|
{
|
||||||
|
field: "[startDate, endDate]",
|
||||||
|
label: "登陆账号",
|
||||||
|
type: "dateRange",
|
||||||
|
required: false,
|
||||||
|
nodeProps: {
|
||||||
|
showTime: true,
|
||||||
|
timePickerProps: { defaultValue: ["23:59:59", "00:00:00"] },
|
||||||
|
},
|
||||||
|
itemProps: {
|
||||||
|
hideLabel: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: "nickname",
|
field: "nickname",
|
||||||
label: "登陆账号",
|
label: "登陆账号",
|
||||||
type: "search",
|
type: "input",
|
||||||
required: false,
|
required: false,
|
||||||
nodeProps: {
|
nodeProps: {
|
||||||
// placeholder: "请输入登陆账号",
|
placeholder: "请输入登陆账号",
|
||||||
},
|
},
|
||||||
itemProps: {
|
itemProps: {
|
||||||
hideLabel: true,
|
hideLabel: true,
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ const table = useTable({
|
||||||
return (
|
return (
|
||||||
<div class="flex flex-col overflow-hidden">
|
<div class="flex flex-col overflow-hidden">
|
||||||
<span>{record.name}</span>
|
<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>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
@ -97,11 +97,6 @@ const table = useTable({
|
||||||
label: "角色标识",
|
label: "角色标识",
|
||||||
type: "input",
|
type: "input",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
field: "description",
|
|
||||||
label: "个人描述",
|
|
||||||
type: "textarea",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
field: "permissionIds",
|
field: "permissionIds",
|
||||||
label: "关联权限",
|
label: "关联权限",
|
||||||
|
|
@ -111,6 +106,11 @@ const table = useTable({
|
||||||
multiple: true,
|
multiple: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: "description",
|
||||||
|
label: "个人描述",
|
||||||
|
type: "textarea",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
submit: ({ model }) => {
|
submit: ({ model }) => {
|
||||||
return api.role.addRole(model);
|
return api.role.addRole(model);
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<BreadPage>
|
<BreadPage>
|
||||||
<Table v-bind="table">
|
<Table v-bind="table"> </Table>
|
||||||
<template #action>
|
|
||||||
<a-button status="danger" :disabled="true">
|
|
||||||
<template #icon>
|
|
||||||
<i class="icon-park-outline-delete"></i>
|
|
||||||
</template>
|
|
||||||
删除
|
|
||||||
</a-button>
|
|
||||||
</template>
|
|
||||||
</Table>
|
|
||||||
</BreadPage>
|
</BreadPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -18,26 +9,19 @@ import { api } from "@/api";
|
||||||
import { Table, useTable } from "@/components";
|
import { Table, useTable } from "@/components";
|
||||||
import { dayjs } from "@/libs/dayjs";
|
import { dayjs } from "@/libs/dayjs";
|
||||||
|
|
||||||
const type = ref("all");
|
|
||||||
|
|
||||||
const table = useTable({
|
const table = useTable({
|
||||||
data: async (model, paging) => {
|
data: async (model, paging) => {
|
||||||
return api.user.getUsers({ ...model, ...paging });
|
return api.user.getUsers({ ...model, ...paging });
|
||||||
},
|
},
|
||||||
tableProps: {
|
|
||||||
rowSelection: {
|
|
||||||
showCheckedAll: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
columns: [
|
columns: [
|
||||||
{
|
{
|
||||||
title: "用户昵称",
|
title: "用户昵称",
|
||||||
dataIndex: "username",
|
dataIndex: "username",
|
||||||
width: 240,
|
width: 180,
|
||||||
render: ({ record }) => (
|
render: ({ record }) => (
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<a-avatar size={40}>
|
<a-avatar size={32}>
|
||||||
<img src={record.avatar || "https://github.com/juetan.png"} alt="" />
|
<img src={`https://picsum.photos/200?${Math.random()}`} alt="" />
|
||||||
</a-avatar>
|
</a-avatar>
|
||||||
<span class="ml-2 flex-1 flex flex-col overflow-hidden">
|
<span class="ml-2 flex-1 flex flex-col overflow-hidden">
|
||||||
<span>{record.nickname}</span>
|
<span>{record.nickname}</span>
|
||||||
|
|
@ -84,15 +68,18 @@ const table = useTable({
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
search: {
|
search: {
|
||||||
|
button: false,
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
extend: "nickname",
|
extend: "nickname",
|
||||||
required: false,
|
required: false,
|
||||||
|
type: 'search',
|
||||||
|
enableLoad: true,
|
||||||
itemProps: {
|
itemProps: {
|
||||||
hideLabel: true,
|
hideLabel: true,
|
||||||
},
|
},
|
||||||
nodeProps: {
|
nodeProps: {
|
||||||
placeholder: "输入用户昵称关键字",
|
placeholder: "用户昵称",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -100,7 +87,7 @@ const table = useTable({
|
||||||
create: {
|
create: {
|
||||||
title: "新建用户",
|
title: "新建用户",
|
||||||
modalProps: {
|
modalProps: {
|
||||||
width: 772,
|
width: 732,
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
},
|
},
|
||||||
formProps: {
|
formProps: {
|
||||||
|
|
@ -119,14 +106,6 @@ const table = useTable({
|
||||||
label: "用户昵称",
|
label: "用户昵称",
|
||||||
type: "input",
|
type: "input",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
field: "description",
|
|
||||||
label: "个人描述",
|
|
||||||
type: "textarea",
|
|
||||||
itemProps: {
|
|
||||||
class: "col-span-2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
field: "password",
|
field: "password",
|
||||||
label: "密码",
|
label: "密码",
|
||||||
|
|
@ -142,16 +121,15 @@ const table = useTable({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "头像",
|
field: "description",
|
||||||
field: "avatarId",
|
label: "个人描述",
|
||||||
type: "custom",
|
type: "textarea",
|
||||||
component: ({ field, model }) => {
|
itemProps: {
|
||||||
return (
|
class: "col-span-2",
|
||||||
<a-avatar size={40}>
|
|
||||||
<img src={model?.[field]} alt="" />
|
|
||||||
</a-avatar>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
nodeProps: {
|
||||||
|
class: 'h-[96px]'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
submit: ({ model }) => {
|
submit: ({ model }) => {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ export const router = createRouter({
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
redirect: "/home",
|
redirect: "/home/home",
|
||||||
},
|
},
|
||||||
...routes,
|
...routes,
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@
|
||||||
@arcoblue-6: #08f;
|
@arcoblue-6: #08f;
|
||||||
|
|
||||||
body {
|
body {
|
||||||
--border-radius-small: 4px;
|
// --border-radius-small: 4px;
|
||||||
|
|
||||||
li.arco-dropdown-option {
|
li.arco-dropdown-option {
|
||||||
line-height: 28px;
|
line-height: 32px;
|
||||||
width: calc(100% - 8px);
|
width: calc(100% - 8px);
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
|
|
@ -14,6 +15,21 @@ body {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.arco-table-td {
|
||||||
|
color: rgb(var(--gray-8));
|
||||||
|
}
|
||||||
|
.arco-modal {
|
||||||
|
border-radius: var(--border-radius-small);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.arco-modal-header {
|
||||||
|
background: var(--color-fill-2);
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.arco-modal-footer {
|
||||||
|
padding-top: 0;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
.arco-layout-sider {
|
.arco-layout-sider {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
@ -52,10 +68,10 @@ body {
|
||||||
background-color: var(--color-neutral-2);
|
background-color: var(--color-neutral-2);
|
||||||
}
|
}
|
||||||
&.arco-menu-selected {
|
&.arco-menu-selected {
|
||||||
// color: @arcoblue-6;
|
color: @arcoblue-6;
|
||||||
// background-color: @arcoblue-1;
|
background-color: @arcoblue-1;
|
||||||
color: #fff;
|
// color: #fff;
|
||||||
background-color: @arcoblue-6;
|
// background-color: @arcoblue-6;
|
||||||
.arco-menu-icon {
|
.arco-menu-icon {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,10 @@ declare module 'vue-router/auto/routes' {
|
||||||
'/_layout/': RouteRecordInfo<'/_layout/', '/_layout', Record<never, never>, Record<never, never>>,
|
'/_layout/': RouteRecordInfo<'/_layout/', '/_layout', Record<never, never>, Record<never, never>>,
|
||||||
'/_login/': RouteRecordInfo<'/_login/', '/_login', Record<never, never>, Record<never, never>>,
|
'/_login/': RouteRecordInfo<'/_login/', '/_login', Record<never, never>, Record<never, never>>,
|
||||||
'/[..._all]/': RouteRecordInfo<'/[..._all]/', '/:_all(.*)', { _all: ParamValue<true> }, { _all: ParamValue<false> }>,
|
'/[..._all]/': RouteRecordInfo<'/[..._all]/', '/:_all(.*)', { _all: ParamValue<true> }, { _all: ParamValue<false> }>,
|
||||||
'/demo/': RouteRecordInfo<'/demo/', '/demo', Record<never, never>, Record<never, never>>,
|
'/dev/openapi': RouteRecordInfo<'/dev/openapi', '/dev/openapi', Record<never, never>, Record<never, never>>,
|
||||||
'/demo/test': RouteRecordInfo<'/demo/test', '/demo/test', Record<never, never>, Record<never, never>>,
|
'/home/demo': RouteRecordInfo<'/home/demo', '/home/demo', Record<never, never>, Record<never, never>>,
|
||||||
'/home/': RouteRecordInfo<'/home/', '/home', Record<never, never>, Record<never, never>>,
|
'/home/home': RouteRecordInfo<'/home/home', '/home/home', Record<never, never>, Record<never, never>>,
|
||||||
|
'/home/test': RouteRecordInfo<'/home/test', '/home/test', Record<never, never>, Record<never, never>>,
|
||||||
'/my/': RouteRecordInfo<'/my/', '/my', Record<never, never>, Record<never, never>>,
|
'/my/': RouteRecordInfo<'/my/', '/my', Record<never, never>, Record<never, never>>,
|
||||||
'/post/': RouteRecordInfo<'/post/', '/post', Record<never, never>, Record<never, never>>,
|
'/post/': RouteRecordInfo<'/post/', '/post', Record<never, never>, Record<never, never>>,
|
||||||
'/post/category/': RouteRecordInfo<'/post/category/', '/post/category', Record<never, never>, Record<never, never>>,
|
'/post/category/': RouteRecordInfo<'/post/category/', '/post/category', Record<never, never>, Record<never, never>>,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ const delOptions = {
|
||||||
title: "提示",
|
title: "提示",
|
||||||
titleAlign: "start",
|
titleAlign: "start",
|
||||||
width: 432,
|
width: 432,
|
||||||
content: "危险操作!确定删除该数据吗?",
|
content: "危险操作,确定删除该数据吗?",
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
closable: false,
|
closable: false,
|
||||||
okText: "确定",
|
okText: "确定",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue