first commit

This commit is contained in:
ye1023
2026-04-09 15:09:34 +08:00
commit d8e3a63df1
2246 changed files with 352109 additions and 0 deletions
@@ -0,0 +1,88 @@
<template>
<List :class="prefixCls">
<a-row :gutter="16">
<template v-for="item in list" :key="item.title">
<a-col :span="6">
<ListItem>
<Card :hoverable="true" :class="`${prefixCls}__card`">
<div :class="`${prefixCls}__card-title`">
<Icon class="icon" v-if="item.icon" :icon="item.icon" :color="item.color" />
{{ item.title }}
</div>
<div :class="`${prefixCls}__card-num`">
活跃用户<span>{{ item.active }}</span>
</div>
<div :class="`${prefixCls}__card-num`">
新增用户<span>{{ item.new }}</span>
</div>
<Icon :class="`${prefixCls}__card-download`" v-if="item.download" :icon="item.download" />
</Card>
</ListItem>
</a-col>
</template>
</a-row>
</List>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { List, Card, Row, Col } from 'ant-design-vue';
import Icon from '/@/components/Icon/index';
import { applicationList } from './data';
export default defineComponent({
components: {
List,
ListItem: List.Item,
Card,
Icon,
[Row.name]: Row,
[Col.name]: Col,
},
setup() {
return {
prefixCls: 'account-center-application',
list: applicationList,
};
},
});
</script>
<style lang="less">
.account-center-application {
&__card {
width: 100%;
margin-bottom: -12px;
.ant-card-body {
padding: 16px;
}
&-title {
margin-bottom: 5px;
font-size: 16px;
font-weight: 500;
.icon {
margin-top: -5px;
font-size: 22px;
}
}
&-num {
margin-left: 24px;
line-height: 36px;
color: @text-color-secondary;
span {
margin-left: 5px;
font-size: 18px;
}
}
&-download {
float: right;
font-size: 20px !important;
color: @primary-color;
}
}
}
</style>
@@ -0,0 +1,92 @@
<template>
<List item-layout="vertical" :class="prefixCls">
<template v-for="item in list" :key="item.title">
<ListItem>
<ListItemMeta>
<template #description>
<div :class="`${prefixCls}__content`">
{{ item.content }}
</div>
</template>
<template #title>
<p :class="`${prefixCls}__title`">
{{ item.title }}
</p>
<div>
<template v-for="tag in item.description" :key="tag">
<Tag class="mb-2">
{{ tag }}
</Tag>
</template>
</div>
</template>
</ListItemMeta>
<div>
<template v-for="action in actions" :key="action.text">
<div :class="`${prefixCls}__action`">
<Icon v-if="action.icon" :class="`${prefixCls}__action-icon`" :icon="action.icon" :color="action.color" />
{{ action.text }}
</div>
</template>
<span :class="`${prefixCls}__time`">{{ item.time }}</span>
</div>
</ListItem>
</template>
</List>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { List, Tag } from 'ant-design-vue';
import Icon from '/@/components/Icon/index';
import { actions, articleList } from './data';
export default defineComponent({
components: {
List,
ListItem: List.Item,
ListItemMeta: List.Item.Meta,
Tag,
Icon,
},
setup() {
return {
prefixCls: 'account-center-article',
list: articleList,
actions,
};
},
});
</script>
<style lang="less" scoped>
.account-center-article {
&__title {
margin-bottom: 12px;
font-size: 18px;
}
&__content {
color: rgba(0, 0, 0, 0.65);
}
&__action {
display: inline-block;
padding: 0 16px;
color: rgba(0, 0, 0, 0.45);
&:nth-child(1),
&:nth-child(2) {
border-right: 1px solid rgba(206, 206, 206, 0.4);
}
&-icon {
margin-right: 3px;
}
}
&__time {
position: absolute;
right: 20px;
color: rgba(0, 0, 0, 0.45);
}
}
</style>
@@ -0,0 +1,71 @@
<template>
<List :class="prefixCls">
<a-row :gutter="16">
<template v-for="item in list" :key="item.title">
<a-col :span="6">
<ListItem>
<Card :hoverable="true" :class="`${prefixCls}__card`">
<img :src="demoImg" />
<div :class="`${prefixCls}__card-title`">
{{ item.title }}
</div>
<div :class="`${prefixCls}__card-content`">
{{ item.content }}
</div>
</Card>
</ListItem>
</a-col>
</template>
</a-row>
</List>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { List, Card, Row, Col } from 'ant-design-vue';
import demoImg from '/@/assets/images/demo.png';
import { projectList } from './data';
export default defineComponent({
components: {
List,
ListItem: List.Item,
Card,
[Row.name]: Row,
[Col.name]: Col,
},
setup() {
return {
prefixCls: 'account-center-project',
list: projectList,
demoImg,
};
},
});
</script>
<style lang="less">
.account-center-project {
&__card {
width: 100%;
.ant-card-body {
padding: 0 0 24px 0;
}
img {
width: 100%;
height: 130px;
}
&-title {
margin: 5px 10px;
font-size: 16px;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
&-content {
margin: 5px 10px;
}
}
}
</style>
+124
View File
@@ -0,0 +1,124 @@
export interface ListItem {
title: string;
icon: string;
color?: string;
}
export interface TabItem {
key: string;
name: string;
component: string;
}
export const tags: string[] = ['很有想法的', '专注设计', '川妹子', '大长腿', '海纳百川', '前端开发', 'vue3'];
<span class="iconify" data-icon="jam:codepen-circle" data-inline="false"></span>;
export const teams: ListItem[] = [
{
icon: 'ri:alipay-fill',
title: '科学搬砖组',
color: '#ff4000',
},
{
icon: 'emojione-monotone:letter-a',
title: '中二少年团',
color: '#7c51b8',
},
{
icon: 'ri:alipay-fill',
title: '高逼格设计',
color: '#00adf7',
},
{
icon: 'jam:codepen-circle',
title: '程序员日常',
color: '#00adf7',
},
{
icon: 'fa:behance-square',
title: '科学搬砖组',
color: '#7c51b8',
},
{
icon: 'jam:codepen-circle',
title: '程序员日常',
color: '#ff4000',
},
];
export const details: ListItem[] = [
{
icon: 'ic:outline-contacts',
title: '交互专家',
},
{
icon: 'grommet-icons:cluster',
title: '某某某事业群',
},
{
icon: 'bx:bx-home-circle',
title: '福建省厦门市',
},
];
export const achieveList: TabItem[] = [
{
key: '1',
name: '文章',
component: 'Article',
},
{
key: '2',
name: '应用',
component: 'Application',
},
{
key: '3',
name: '项目',
component: 'Project',
},
];
export const actions: any[] = [
{ icon: 'clarity:star-line', text: '156', color: '#018ffb' },
{ icon: 'bx:bxs-like', text: '156', color: '#459ae8' },
{ icon: 'bx:bxs-message-dots', text: '2', color: '#42d27d' },
];
export const articleList = (() => {
const result: any[] = [];
for (let i = 0; i < 4; i++) {
result.push({
title: 'Jeecg Admin',
description: ['Jeecg', '设计语言', 'Typescript'],
content: '基于Vue Next, TypeScript, Ant Design实现的一套完整的企业级后台管理系统。',
time: '2020-11-14 11:20',
});
}
return result;
})();
export const applicationList = (() => {
const result: any[] = [];
for (let i = 0; i < 8; i++) {
result.push({
title: 'Jeecg Admin',
icon: 'emojione-monotone:letter-a',
color: '#1890ff',
active: '100',
new: '1,799',
download: 'bx:bx-download',
});
}
return result;
})();
export const projectList = (() => {
const result: any[] = [];
for (let i = 0; i < 8; i++) {
result.push({
title: 'Jeecg Admin',
content: '基于Vue Next, TypeScript, Ant Design实现的一套完整的企业级后台管理系统。',
});
}
return result;
})();
@@ -0,0 +1,155 @@
<template>
<div :class="prefixCls">
<a-row :class="`${prefixCls}-top`">
<a-col :span="9" :class="`${prefixCls}-col`">
<a-row>
<a-col :span="8">
<div :class="`${prefixCls}-top__avatar`">
<img width="70" :src="avatar" />
<span>Jeecg</span>
<div>海纳百川有容乃大</div>
</div>
</a-col>
<a-col :span="16">
<div :class="`${prefixCls}-top__detail`">
<template v-for="detail in details" :key="detail.title">
<p>
<Icon :icon="detail.icon" />
{{ detail.title }}
</p>
</template>
</div>
</a-col>
</a-row>
</a-col>
<a-col :span="7" :class="`${prefixCls}-col`">
<CollapseContainer title="标签" :canExpan="false">
<template v-for="tag in tags" :key="tag">
<Tag class="mb-2">
{{ tag }}
</Tag>
</template>
</CollapseContainer>
</a-col>
<a-col :span="8" :class="`${prefixCls}-col`">
<CollapseContainer :class="`${prefixCls}-top__team`" title="团队" :canExpan="false">
<div v-for="(team, index) in teams" :key="index" :class="`${prefixCls}-top__team-item`">
<Icon :icon="team.icon" :color="team.color" />
<span>{{ team.title }}</span>
</div>
</CollapseContainer>
</a-col>
</a-row>
<div :class="`${prefixCls}-bottom`">
<Tabs>
<template v-for="item in achieveList" :key="item.key">
<TabPane :tab="item.name">
<component :is="item.component" />
</TabPane>
</template>
</Tabs>
</div>
</div>
</template>
<script lang="ts">
import { Tag, Tabs, Row, Col } from 'ant-design-vue';
import { defineComponent, computed } from 'vue';
import { CollapseContainer } from '/@/components/Container/index';
import Icon from '/@/components/Icon/index';
import Article from './Article.vue';
import Application from './Application.vue';
import Project from './Project.vue';
import headerImg from '/@/assets/images/header.jpg';
import { tags, teams, details, achieveList } from './data';
import { useUserStore } from '/@/store/modules/user';
export default defineComponent({
components: {
CollapseContainer,
Icon,
Tag,
Tabs,
TabPane: Tabs.TabPane,
Article,
Application,
Project,
[Row.name]: Row,
[Col.name]: Col,
},
setup() {
const userStore = useUserStore();
const avatar = computed(() => userStore.getUserInfo.avatar || headerImg);
return {
prefixCls: 'account-center',
avatar,
tags,
teams,
details,
achieveList,
};
},
});
</script>
<style lang="less" scoped>
.account-center {
&-col:not(:last-child) {
padding: 0 10px;
&:not(:last-child) {
border-right: 1px dashed rgb(206, 206, 206, 0.5);
}
}
&-top {
padding: 10px;
margin: 16px 16px 12px 16px;
background-color: @component-background;
border-radius: 3px;
&__avatar {
text-align: center;
img {
margin: auto;
border-radius: 50%;
}
span {
display: block;
font-size: 20px;
font-weight: 500;
}
div {
margin-top: 3px;
font-size: 12px;
}
}
&__detail {
padding-left: 20px;
margin-top: 15px;
}
&__team {
&-item {
display: inline-block;
padding: 4px 24px;
}
span {
margin-left: 3px;
}
}
}
&-bottom {
padding: 10px;
margin: 0 16px 16px 16px;
background-color: @component-background;
border-radius: 3px;
}
}
</style>
@@ -0,0 +1,59 @@
<template>
<CollapseContainer title="账号绑定" :canExpan="false">
<List>
<template v-for="item in list" :key="item.key">
<ListItem>
<ListItemMeta>
<template #avatar>
<Icon v-if="item.avatar" class="avatar" :icon="item.avatar" :color="item.color" />
</template>
<template #title>
{{ item.title }}
<a-button type="link" size="small" v-if="item.extra" class="extra">
{{ item.extra }}
</a-button>
</template>
<template #description>
<div>{{ item.description }} </div>
</template>
</ListItemMeta>
</ListItem>
</template>
</List>
</CollapseContainer>
</template>
<script lang="ts">
import { List } from 'ant-design-vue';
import { defineComponent } from 'vue';
import { CollapseContainer } from '/@/components/Container/index';
import Icon from '/@/components/Icon/index';
import { accountBindList } from './data';
export default defineComponent({
components: {
CollapseContainer,
List,
ListItem: List.Item,
ListItemMeta: List.Item.Meta,
Icon,
},
setup() {
return {
list: accountBindList,
};
},
});
</script>
<style lang="less" scoped>
.avatar {
font-size: 40px !important;
}
.extra {
float: right;
margin-top: 10px;
margin-right: 30px;
cursor: pointer;
}
</style>
@@ -0,0 +1,119 @@
<template>
<CollapseContainer title="基本设置" :canExpan="false">
<a-row :gutter="24">
<a-col :span="14">
<BasicForm @register="register" />
</a-col>
<a-col :span="10">
<div class="change-avatar">
<div class="mb-2"> 头像 </div>
<CropperAvatar
:uploadApi="uploadImg"
:value="avatar"
btnText="更换头像"
:btnProps="{ preIcon: 'ant-design:cloud-upload-outlined' }"
@change="updateAvatar"
width="150"
/>
</div>
</a-col>
</a-row>
<Button type="primary" @click="handleSubmit"> 更新基本信息 </Button>
</CollapseContainer>
</template>
<script lang="ts">
import { Button, Row, Col } from 'ant-design-vue';
import { computed, defineComponent, onMounted } from 'vue';
import { BasicForm, useForm } from '/@/components/Form/index';
import { CollapseContainer } from '/@/components/Container';
import { CropperAvatar } from '/@/components/Cropper';
import { useMessage } from '/@/hooks/web/useMessage';
import headerImg from '/@/assets/images/header.jpg';
import { defHttp } from '/@/utils/http/axios';
import { baseSetschemas } from './data';
import { useUserStore } from '/@/store/modules/user';
import { uploadImg } from '/@/api/sys/upload';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
export default defineComponent({
components: {
BasicForm,
CollapseContainer,
Button,
ARow: Row,
ACol: Col,
CropperAvatar,
},
setup() {
const { createMessage } = useMessage();
const userStore = useUserStore();
const [register, { setFieldsValue, validate }] = useForm({
labelWidth: 120,
schemas: baseSetschemas,
showActionButtonGroup: false,
});
onMounted(async () => {
//const data = await accountInfoApi();
const userInfo = userStore.getUserInfo;
setFieldsValue(userInfo);
});
const avatar = computed(() => {
const { avatar } = userStore.getUserInfo;
return getFileAccessHttpUrl(avatar) || headerImg;
});
function updateAvatar(src: string, data: string) {
console.log('data====》', data);
const userinfo = userStore.getUserInfo;
userinfo.avatar = data;
userStore.setUserInfo(userinfo);
//update-begin---author:wangshuai ---date:20220909 for[VUEN-2161]用户设置上传头像成功之后直接保存------------
if(data){
defHttp.post({ url: '/sys/user/appEdit', params:{avatar:data} });
}
//update-end---author:wangshuai ---date:20220909 for[VUEN-2161]用户设置上传头像成功之后直接保存--------------
}
/**
*更新基本信息
* */
async function handleSubmit() {
try {
let values = await validate();
values.avatar = userStore.getUserInfo.avatar
console.log('values', values);
//提交表单
defHttp.post({ url: '/sys/user/appEdit', params: values });
const userinfo = userStore.getUserInfo;
Object.assign(userinfo, values);
userStore.setUserInfo(userinfo);
createMessage.success('更新成功');
} catch (e) {
console.log('e', e);
}
}
return {
avatar,
register,
uploadImg,
updateAvatar,
handleSubmit,
};
},
});
</script>
<style lang="less" scoped>
.change-avatar {
img {
display: block;
margin-bottom: 15px;
border-radius: 50%;
}
}
</style>
@@ -0,0 +1,48 @@
<template>
<CollapseContainer title="新消息通知" :canExpan="false">
<List>
<template v-for="item in list" :key="item.key">
<ListItem>
<ListItemMeta>
<template #title>
{{ item.title }}
<Switch class="extra" checked-children="" un-checked-children="" default-checked />
</template>
<template #description>
<div>{{ item.description }} </div>
</template>
</ListItemMeta>
</ListItem>
</template>
</List>
</CollapseContainer>
</template>
<script lang="ts">
import { List, Switch } from 'ant-design-vue';
import { defineComponent } from 'vue';
import { CollapseContainer } from '/@/components/Container/index';
import { msgNotifyList } from './data';
export default defineComponent({
components: {
CollapseContainer,
List,
ListItem: List.Item,
ListItemMeta: List.Item.Meta,
Switch,
},
setup() {
return {
list: msgNotifyList,
};
},
});
</script>
<style lang="less" scoped>
.extra {
float: right;
margin-top: 10px;
margin-right: 30px;
}
</style>
@@ -0,0 +1,68 @@
<template>
<CollapseContainer title="安全设置" :canExpan="false">
<List>
<template v-for="item in list" :key="item.key">
<ListItem>
<ListItemMeta>
<template #title>
{{ item.title }}
<div class="extra" v-if="item.extra" @click="extraClick(item.key)">
{{ item.extra }}
</div>
</template>
<template #description>
<div>{{ item.description }} </div>
</template>
</ListItemMeta>
</ListItem>
</template>
</List>
</CollapseContainer>
<UpdatePassword ref="updatePasswordRef" />
</template>
<script lang="ts">
import { List } from 'ant-design-vue';
import { defineComponent, ref } from 'vue';
import { CollapseContainer } from '/@/components/Container/index';
import { secureSettingList } from './data';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import { useUserStore } from '/@/store/modules/user';
import { useMessage } from '/@/hooks/web/useMessage';
export default defineComponent({
components: {
CollapseContainer,
List,
ListItem: List.Item,
ListItemMeta: List.Item.Meta,
UpdatePassword: createAsyncComponent(() => import('/@/layouts/default/header/components/user-dropdown/UpdatePassword.vue')),
},
setup() {
const { createMessage } = useMessage();
const userStore = useUserStore();
const updatePasswordRef = ref();
function extraClick(key) {
if (key == '1') {
updatePasswordRef.value.show(userStore.getUserInfo.username);
} else {
createMessage.warning('暂不支持');
}
}
return {
updatePasswordRef,
extraClick,
list: secureSettingList,
};
},
});
</script>
<style lang="less" scoped>
.extra {
float: right;
margin-top: 10px;
margin-right: 30px;
font-weight: normal;
color: #1890ff;
cursor: pointer;
}
</style>
+167
View File
@@ -0,0 +1,167 @@
import { FormSchema } from '/@/components/Form/index';
import { rules } from '/@/utils/helper/validator';
export interface ListItem {
key: string;
title: string;
description: string;
extra?: string;
avatar?: string;
color?: string;
}
// tab的list
export const settingList = [
{
key: '1',
name: '基本设置',
component: 'BaseSetting',
},
{
key: '2',
name: '安全设置',
component: 'SecureSetting',
},
/* {
key: '3',
name: '账号绑定',
component: 'AccountBind',
},
{
key: '4',
name: '新消息通知',
component: 'MsgNotify',
},*/
];
// 基础设置 form
export const baseSetschemas: FormSchema[] = [
{
label: '',
field: 'id',
component: 'Input',
show: false,
},
{
field: 'realname',
component: 'Input',
label: '昵称',
colProps: { span: 18 },
},
{
field: 'sex',
label: '性别',
component: 'JDictSelectTag',
componentProps: {
dictCode: 'sex',
placeholder: '请选择性别',
stringToNumber: true,
},
colProps: { span: 18 },
},
{
label: '生日',
field: 'birthday',
component: 'DatePicker',
colProps: { span: 18 },
},
{
field: 'email',
component: 'Input',
label: '邮箱',
colProps: { span: 18 },
},
{
field: 'phone',
component: 'Input',
label: '联系电话',
dynamicRules: ({ model, schema }) => {
return [
{ ...rules.duplicateCheckRule('sys_user', 'phone', model, schema, false)[0] },
{ pattern: /^1[3456789]\d{9}$/, message: '手机号码格式有误' },
];
},
colProps: { span: 18 },
},
];
// 安全设置 list
export const secureSettingList: ListItem[] = [
{
key: '1',
title: '账户密码',
description: '当前密码强度::强',
extra: '修改',
},
{
key: '2',
title: '密保手机',
description: '已绑定手机::138****8293',
extra: '修改',
},
{
key: '3',
title: '密保问题',
description: '未设置密保问题,密保问题可有效保护账户安全',
extra: '修改',
},
{
key: '4',
title: '备用邮箱',
description: '已绑定邮箱::ant***sign.com',
extra: '修改',
},
{
key: '5',
title: 'MFA 设备',
description: '未绑定 MFA 设备,绑定后,可以进行二次确认',
extra: '修改',
},
];
// 账号绑定 list
export const accountBindList: ListItem[] = [
{
key: '1',
title: '绑定淘宝',
description: '当前未绑定淘宝账号',
extra: '绑定',
avatar: 'ri:taobao-fill',
color: '#ff4000',
},
{
key: '2',
title: '绑定支付宝',
description: '当前未绑定支付宝账号',
extra: '绑定',
avatar: 'fa-brands:alipay',
color: '#2eabff',
},
{
key: '3',
title: '绑定钉钉',
description: '当前未绑定钉钉账号',
extra: '绑定',
avatar: 'ri:dingding-fill',
color: '#2eabff',
},
];
// 新消息通知 list
export const msgNotifyList: ListItem[] = [
{
key: '1',
title: '账户密码',
description: '其他用户的消息将以站内信的形式通知',
},
{
key: '2',
title: '系统消息',
description: '系统消息将以站内信的形式通知',
},
{
key: '3',
title: '待办任务',
description: '待办任务将以站内信的形式通知',
},
];
@@ -0,0 +1,62 @@
<template>
<ScrollContainer>
<div ref="wrapperRef" :class="prefixCls">
<Tabs tab-position="left" :tabBarStyle="tabBarStyle">
<template v-for="item in settingList" :key="item.key">
<TabPane :tab="item.name">
<component :is="item.component" />
</TabPane>
</template>
</Tabs>
</div>
</ScrollContainer>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Tabs } from 'ant-design-vue';
import { ScrollContainer } from '/@/components/Container/index';
import { settingList } from './data';
import BaseSetting from './BaseSetting.vue';
import SecureSetting from './SecureSetting.vue';
import AccountBind from './AccountBind.vue';
import MsgNotify from './MsgNotify.vue';
export default defineComponent({
components: {
ScrollContainer,
Tabs,
TabPane: Tabs.TabPane,
BaseSetting,
SecureSetting,
AccountBind,
MsgNotify,
},
setup() {
return {
prefixCls: 'account-setting',
settingList,
tabBarStyle: {
width: '220px',
marginBottom: '200px',
},
};
},
});
</script>
<style lang="less">
.account-setting {
margin: 12px;
background-color: @component-background;
.base-title {
padding-left: 0;
}
.ant-tabs-tab-active {
background-color: @item-active-bg;
}
}
</style>
+196
View File
@@ -0,0 +1,196 @@
import { DescItem } from '/@/components/Description/index';
import { BasicColumn } from '/@/components/Table/src/types/table';
import { Button } from '/@/components/Button';
import { Badge } from 'ant-design-vue';
export const refundData = {
a1: '1000000000',
a2: '已取货',
a3: '1234123421',
a4: '3214321432',
};
export const personData = {
b1: '付小小',
b2: '18100000000',
b3: '菜鸟仓储',
b4: '浙江省杭州市西湖区万塘路18号',
b5: '无',
};
export const refundSchema: DescItem[] = [
{
field: 'a1',
label: '取货单号',
},
{
field: 'a2',
label: '状态',
},
{
field: 'a3',
label: '销售单号',
},
{
field: 'a4',
label: '子订单',
},
];
export const personSchema: DescItem[] = [
{
field: 'b1',
label: '用户姓名',
},
{
field: 'b2',
label: '联系电话',
},
{
field: 'b3',
label: '常用快递',
},
{
field: 'b4',
label: '取货地址',
},
{
field: 'b5',
label: '备注',
},
];
export const refundTableSchema: BasicColumn[] = [
{
title: '商品编号',
width: 150,
dataIndex: 't1',
customRender: ({ record }) => {
return (
<Button type="link" size="small">
{() => record.t1}
</Button>
);
},
},
{
title: '商品名称',
width: 150,
dataIndex: 't2',
},
{
title: '商品条码',
width: 150,
dataIndex: 't3',
},
{
title: '单价 ',
width: 150,
dataIndex: 't4',
},
{
title: '数量(件) ',
width: 150,
dataIndex: 't5',
},
{
title: '金额',
width: 150,
dataIndex: 't6',
},
];
export const refundTimeTableSchema: BasicColumn[] = [
{
title: '时间',
width: 150,
dataIndex: 't1',
},
{
title: '当前进度',
width: 150,
dataIndex: 't2',
},
{
title: '状态',
width: 150,
dataIndex: 't3',
customRender: ({ record }) => {
return <Badge status="success" text={record.t3} />;
},
},
{
title: '操作员ID ',
width: 150,
dataIndex: 't4',
},
{
title: '耗时',
width: 150,
dataIndex: 't5',
},
];
export const refundTableData: any[] = [
{
t1: 1234561,
t2: '矿泉水 550ml',
t3: '12421432143214321',
t4: '2.00',
t5: 1,
t6: 2.0,
},
{
t1: 1234562,
t2: '矿泉水 550ml',
t3: '12421432143214321',
t4: '2.00',
t5: 2,
t6: 2.0,
},
{
t1: 1234562,
t2: '矿泉水 550ml',
t3: '12421432143214321',
t4: '2.00',
t5: 2,
t6: 2.0,
},
{
t1: 1234562,
t2: '矿泉水 550ml',
t3: '12421432143214321',
t4: '2.00',
t5: 2,
t6: 2.0,
},
];
export const refundTimeTableData: any[] = [
{
t1: '2017-10-01 14:10',
t2: '联系客户',
t3: '进行中',
t4: '取货员 ID1234',
t5: '5mins',
},
{
t1: '2017-10-01 14:10',
t2: '取货员出发',
t3: '成功',
t4: '取货员 ID1234',
t5: '5mins',
},
{
t1: '2017-10-01 14:10',
t2: '取货员接单',
t3: '成功',
t4: '系统',
t5: '5mins',
},
{
t1: '2017-10-01 14:10',
t2: '申请审批通过',
t3: '成功',
t4: '用户',
t5: '1h',
},
];
+84
View File
@@ -0,0 +1,84 @@
<template>
<PageWrapper title="基础详情页" contentBackground>
<Description size="middle" title="退款申请" :bordered="false" :column="3" :data="refundData" :schema="refundSchema" />
<a-divider />
<Description size="middle" title="用户信息" :bordered="false" :column="3" :data="personData" :schema="personSchema" />
<a-divider />
<BasicTable @register="registerRefundTable" />
<a-divider />
<BasicTable @register="registerTimeTable" />
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Description } from '/@/components/Description/index';
import { BasicTable, useTable } from '/@/components/Table';
import { PageWrapper } from '/@/components/Page';
import { Divider } from 'ant-design-vue';
import {
refundSchema,
refundData,
personSchema,
personData,
refundTableSchema,
refundTimeTableSchema,
refundTableData,
refundTimeTableData,
} from './data';
export default defineComponent({
components: { Description, BasicTable, PageWrapper, [Divider.name]: Divider },
setup() {
const [registerRefundTable] = useTable({
title: '退货商品',
dataSource: refundTableData,
columns: refundTableSchema,
pagination: false,
showIndexColumn: false,
scroll: { y: 300 },
showSummary: true,
summaryFunc: handleSummary,
});
const [registerTimeTable] = useTable({
title: '退货进度',
columns: refundTimeTableSchema,
pagination: false,
dataSource: refundTimeTableData,
showIndexColumn: false,
scroll: { y: 300 },
});
function handleSummary(tableData: any[]) {
let totalT5 = 0;
let totalT6 = 0;
tableData.forEach((item) => {
totalT5 += item.t5;
totalT6 += item.t6;
});
return [
{
t1: '总计',
t5: totalT5,
t6: totalT6,
},
];
}
return {
registerRefundTable,
registerTimeTable,
refundSchema,
refundData,
personSchema,
personData,
};
},
});
</script>
<style lang="less" scoped>
.desc-wrap {
padding: 16px;
background-color: @component-background;
}
</style>
+65
View File
@@ -0,0 +1,65 @@
import { BasicColumn } from '/@/components/Table/src/types/table';
import { Badge } from 'ant-design-vue';
export const refundTimeTableSchema: BasicColumn[] = [
{
title: '时间',
width: 150,
dataIndex: 't1',
},
{
title: '当前进度',
width: 150,
dataIndex: 't2',
},
{
title: '状态',
width: 150,
dataIndex: 't3',
customRender: ({ record }) => {
return <Badge status="success" text={record.t3} />;
},
},
{
title: '操作员ID ',
width: 150,
dataIndex: 't4',
},
{
title: '耗时',
width: 150,
dataIndex: 't5',
},
];
export const refundTimeTableData: any[] = [
{
t1: '2017-10-01 14:10',
t2: '联系客户',
t3: '进行中',
t4: '取货员 ID1234',
t5: '5mins',
},
{
t1: '2017-10-01 14:10',
t2: '取货员出发',
t3: '成功',
t4: '取货员 ID1234',
t5: '5mins',
},
{
t1: '2017-10-01 14:10',
t2: '取货员接单',
t3: '成功',
t4: '系统',
t5: '5mins',
},
{
t1: '2017-10-01 14:10',
t2: '申请审批通过',
t3: '成功',
t4: '用户',
t5: '1h',
},
];
+123
View File
@@ -0,0 +1,123 @@
<template>
<PageWrapper title="单号:234231029431" contentBackground>
<template #extra>
<a-button> 操作一 </a-button>
<a-button> 操作二 </a-button>
<a-button type="primary"> 主操作 </a-button>
</template>
<template #footer>
<a-tabs default-active-key="1">
<a-tab-pane key="1" tab="详情" />
<a-tab-pane key="2" tab="规则" />
</a-tabs>
</template>
<div class="pt-4 m-4 desc-wrap">
<a-descriptions size="small" :column="2">
<a-descriptions-item label="创建人"> 曲丽丽 </a-descriptions-item>
<a-descriptions-item label="订购产品"> XX 服务 </a-descriptions-item>
<a-descriptions-item label="创建时间"> 2017-01-10 </a-descriptions-item>
<a-descriptions-item label="关联单据">
<a>12421</a>
</a-descriptions-item>
<a-descriptions-item label="生效日期"> 2017-07-07 ~ 2017-08-08 </a-descriptions-item>
<a-descriptions-item label="备注"> 请于两个工作日内确认 </a-descriptions-item>
</a-descriptions>
<a-card title="流程进度" :bordered="false">
<a-steps :current="1" progress-dot size="small">
<a-step title="创建项目">
<template #description> <div>Jeecg</div> <p>2016-12-12 12:32</p> </template>
</a-step>
<a-step title="部门初审">
<template #description>
<p>Chad</p>
</template>
</a-step>
<a-step title="财务复核" />
<a-step title="完成" />
</a-steps>
</a-card>
<a-card title="用户信息" :bordered="false" class="mt-5">
<a-descriptions :column="3">
<a-descriptions-item label="用户姓名"> 付小小 </a-descriptions-item>
<a-descriptions-item label="会员卡号"> XX 32943898021309809423 </a-descriptions-item>
<a-descriptions-item label="身份证"> 3321944288191034921 </a-descriptions-item>
<a-descriptions-item label="联系方式"> 18100000000 </a-descriptions-item>
<a-descriptions-item label="联系地址" :span="2"> 曲丽丽 18100000000 浙江省杭州市西湖区黄姑山路工专路交叉路口 </a-descriptions-item>
</a-descriptions>
<a-descriptions title="信息组" :column="3">
<a-descriptions-item label="某某数据"> 111 </a-descriptions-item>
<a-descriptions-item label="该数据更新时间"> 2017-08-08 </a-descriptions-item>
<a-descriptions-item label="某某数据"> 725 </a-descriptions-item>
<a-descriptions-item label="该数据更新时间"> 2017-08-08 </a-descriptions-item>
</a-descriptions>
<h4>信息组</h4>
<a-card title="多层级信息组">
<a-descriptions title="组名称" :column="3">
<a-descriptions-item label="负责人"> 林东东 </a-descriptions-item>
<a-descriptions-item label="角色码"> 1234567 </a-descriptions-item>
<a-descriptions-item label="所属部门"> XX公司 - YY部 </a-descriptions-item>
<a-descriptions-item label="过期时间"> 2017-08-08 </a-descriptions-item>
<a-descriptions-item label="描述" :span="2"> 这段描述很长很长很长很长很长很长很长很长很长很长很长很长很长很长... </a-descriptions-item>
</a-descriptions>
<a-divider />
<a-descriptions title="组名称" :column="1">
<a-descriptions-item label="学名">
Citrullus lanatus (Thunb.) Matsum. et Nakai一年生蔓生藤本枝粗壮具明显的棱卷须较粗..
</a-descriptions-item>
</a-descriptions>
<a-divider />
<a-descriptions title="组名称" :column="1">
<a-descriptions-item label="负责人"> 付小小 </a-descriptions-item>
<a-descriptions-item label="角色码"> 1234568 </a-descriptions-item>
</a-descriptions>
</a-card>
</a-card>
<a-card title="用户近半年来电记录" class="my-5">
<Empty />
</a-card>
<BasicTable @register="registerTimeTable" />
</div>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicTable, useTable } from '/@/components/Table';
import { PageWrapper } from '/@/components/Page';
import { Divider, Card, Empty, Descriptions, Steps, Tabs } from 'ant-design-vue';
import { refundTimeTableSchema, refundTimeTableData } from './data';
export default defineComponent({
components: {
BasicTable,
PageWrapper,
[Divider.name]: Divider,
[Card.name]: Card,
Empty,
[Descriptions.name]: Descriptions,
[Descriptions.Item.name]: Descriptions.Item,
[Steps.name]: Steps,
[Steps.Step.name]: Steps.Step,
[Tabs.name]: Tabs,
[Tabs.TabPane.name]: Tabs.TabPane,
},
setup() {
const [registerTimeTable] = useTable({
title: '退货进度',
columns: refundTimeTableSchema,
pagination: false,
dataSource: refundTimeTableData,
showIndexColumn: false,
scroll: { y: 300 },
});
return {
registerTimeTable,
};
},
});
</script>
+119
View File
@@ -0,0 +1,119 @@
import { FormSchema } from '/@/components/Form';
export const schemas: FormSchema[] = [
{
field: 'title',
component: 'Input',
label: '标题',
componentProps: {
placeholder: '给目标起个名字',
},
required: true,
},
{
field: 'time',
component: 'RangePicker',
label: '起止日期',
required: true,
},
{
field: 'target',
component: 'InputTextArea',
label: '目标描述',
componentProps: {
placeholder: '请输入你的阶段性工作目标',
rows: 4,
},
required: true,
},
{
field: 'metrics',
component: 'InputTextArea',
label: '衡量标准',
componentProps: {
placeholder: '请输入衡量标准',
rows: 4,
},
required: true,
},
{
field: 'client',
component: 'Input',
label: '客户',
helpMessage: '目标的服务对象',
subLabel: '( 选填 )',
componentProps: {
placeholder: '请描述你服务的客户,内部客户直接 @姓名/工号',
},
},
{
field: 'inviteer',
component: 'Input',
label: '邀评人',
subLabel: '( 选填 )',
componentProps: {
placeholder: '请直接 @姓名/工号,最多可邀请 5 人',
},
},
{
field: 'weights',
component: 'InputNumber',
label: '权重',
subLabel: '( 选填 )',
componentProps: {
formatter: (value: string) => (value ? `${value}%` : ''),
parser: (value: string) => value.replace('%', ''),
placeholder: '请输入',
},
},
{
field: 'disclosure',
component: 'RadioGroup',
label: '目标公开',
itemProps: {
extra: '客户、邀评人默认被分享',
},
componentProps: {
options: [
{
label: '公开',
value: '1',
},
{
label: '部分公开',
value: '2',
},
{
label: '不公开',
value: '3',
},
],
},
},
{
field: 'disclosurer',
component: 'Select',
label: ' ',
show: ({ model }) => {
return model.disclosure === '2';
},
componentProps: {
placeholder: '公开给',
mode: 'multiple',
options: [
{
label: '同事1',
value: '1',
},
{
label: '同事2',
value: '2',
},
{
label: '同事3',
value: '3',
},
],
},
},
];
+64
View File
@@ -0,0 +1,64 @@
<template>
<PageWrapper title="基础表单" contentBackground content=" 表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。" contentClass="p-4">
<BasicForm @register="register" />
</PageWrapper>
</template>
<script lang="ts">
import { BasicForm, useForm } from '/@/components/Form';
import { defineComponent } from 'vue';
import { schemas } from './data';
import { useMessage } from '/@/hooks/web/useMessage';
import { PageWrapper } from '/@/components/Page';
export default defineComponent({
name: 'FormBasicPage',
components: { BasicForm, PageWrapper },
setup() {
const { createMessage } = useMessage();
const [register, { validate, setProps }] = useForm({
labelCol: {
span: 8,
},
wrapperCol: {
span: 10,
},
schemas: schemas,
actionColOptions: {
offset: 8,
span: 12,
},
submitButtonOptions: {
text: '提交',
},
submitFunc: customSubmitFunc,
});
async function customSubmitFunc() {
try {
await validate();
setProps({
submitButtonOptions: {
loading: true,
},
});
setTimeout(() => {
setProps({
submitButtonOptions: {
loading: false,
},
});
createMessage.success('提交成功!');
}, 2000);
} catch (error) {}
}
return { register };
},
});
</script>
<style lang="less" scoped>
.form-wrap {
padding: 24px;
background-color: @component-background;
}
</style>
@@ -0,0 +1,137 @@
<template>
<div>
<BasicTable @register="registerTable" @edit-change="handleEditChange">
<template #action="{ record, column }">
<TableAction :actions="createActions(record, column)" />
</template>
</BasicTable>
<a-button block class="mt-5" type="dashed" @click="handleAdd"> 新增成员 </a-button>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicTable, useTable, TableAction, BasicColumn, ActionItem, EditRecordRow } from '/@/components/Table';
const columns: BasicColumn[] = [
{
title: '成员姓名',
dataIndex: 'name',
editRow: true,
},
{
title: '工号',
dataIndex: 'no',
editRow: true,
},
{
title: '所属部门',
dataIndex: 'dept',
editRow: true,
},
];
const data: any[] = [
{
name: 'John Brown',
no: '00001',
dept: 'New York No. 1 Lake Park',
},
{
name: 'John Brown2',
no: '00002',
dept: 'New York No. 2 Lake Park',
},
{
name: 'John Brown3',
no: '00003',
dept: 'New York No. 3Lake Park',
},
];
export default defineComponent({
components: { BasicTable, TableAction },
setup() {
const [registerTable, { getDataSource }] = useTable({
columns: columns,
showIndexColumn: false,
dataSource: data,
actionColumn: {
width: 160,
title: '操作',
dataIndex: 'action',
slots: { customRender: 'action' },
},
pagination: false,
});
function handleEdit(record: EditRecordRow) {
record.onEdit?.(true);
}
function handleCancel(record: EditRecordRow) {
record.onEdit?.(false);
if (record.isNew) {
const data = getDataSource();
const index = data.findIndex((item) => item.key === record.key);
data.splice(index, 1);
}
}
function handleSave(record: EditRecordRow) {
record.onEdit?.(false, true);
}
function handleEditChange(data: Recordable) {
console.log(data);
}
function handleAdd() {
const data = getDataSource();
const addRow: EditRecordRow = {
name: '',
no: '',
dept: '',
editable: true,
isNew: true,
key: `${Date.now()}`,
};
data.push(addRow);
}
function createActions(record: EditRecordRow, column: BasicColumn): ActionItem[] {
if (!record.editable) {
return [
{
label: '编辑',
onClick: handleEdit.bind(null, record),
},
{
label: '删除',
},
];
}
return [
{
label: '保存',
onClick: handleSave.bind(null, record, column),
},
{
label: '取消',
popConfirm: {
title: '是否取消编辑',
confirm: handleCancel.bind(null, record, column),
},
},
];
}
return {
registerTable,
handleEdit,
createActions,
handleAdd,
getDataSource,
handleEditChange,
};
},
});
</script>
+149
View File
@@ -0,0 +1,149 @@
import { FormSchema } from '/@/components/Form';
const basicOptions: LabelValueOptions = [
{
label: '付晓晓',
value: '1',
},
{
label: '周毛毛',
value: '2',
},
];
const storeTypeOptions: LabelValueOptions = [
{
label: '私密',
value: '1',
},
{
label: '公开',
value: '2',
},
];
export const schemas: FormSchema[] = [
{
field: 'f1',
component: 'Input',
label: '仓库名',
required: true,
},
{
field: 'f2',
component: 'Input',
label: '仓库域名',
required: true,
componentProps: {
addonBefore: 'http://',
addonAfter: 'com',
},
colProps: {
offset: 2,
},
},
{
field: 'f3',
component: 'Select',
label: '仓库管理员',
componentProps: {
options: basicOptions,
},
required: true,
colProps: {
offset: 2,
},
},
{
field: 'f4',
component: 'Select',
label: '审批人',
componentProps: {
options: basicOptions,
},
required: true,
},
{
field: 'f5',
component: 'RangePicker',
label: '生效日期',
required: true,
colProps: {
offset: 2,
},
},
{
field: 'f6',
component: 'Select',
label: '仓库类型',
componentProps: {
options: storeTypeOptions,
},
required: true,
colProps: {
offset: 2,
},
},
];
export const taskSchemas: FormSchema[] = [
{
field: 't1',
component: 'Input',
label: '任务名',
required: true,
},
{
field: 't2',
component: 'Input',
label: '任务描述',
required: true,
colProps: {
offset: 2,
},
},
{
field: 't3',
component: 'Select',
label: '执行人',
componentProps: {
options: basicOptions,
},
required: true,
colProps: {
offset: 2,
},
},
{
field: 't4',
component: 'Select',
label: '责任人',
componentProps: {
options: basicOptions,
},
required: true,
},
{
field: 't5',
component: 'TimePicker',
label: '生效日期',
required: true,
componentProps: {
style: { width: '100%' },
},
colProps: {
offset: 2,
},
},
{
field: 't6',
component: 'Select',
label: '任务类型',
componentProps: {
options: storeTypeOptions,
},
required: true,
colProps: {
offset: 2,
},
},
];
+77
View File
@@ -0,0 +1,77 @@
<template>
<PageWrapper class="high-form" title="高级表单" content=" 高级表单常见于一次性输入和提交大批量数据的场景。">
<a-card title="仓库管理" :bordered="false">
<BasicForm @register="register" />
</a-card>
<a-card title="任务管理" :bordered="false" class="!mt-5">
<BasicForm @register="registerTask" />
</a-card>
<a-card title="成员管理" :bordered="false">
<PersonTable ref="tableRef" />
</a-card>
<template #rightFooter>
<a-button type="primary" @click="submitAll"> 提交 </a-button>
</template>
</PageWrapper>
</template>
<script lang="ts">
import { BasicForm, useForm } from '/@/components/Form';
import { defineComponent, ref } from 'vue';
import PersonTable from './PersonTable.vue';
import { PageWrapper } from '/@/components/Page';
import { schemas, taskSchemas } from './data';
import { Card } from 'ant-design-vue';
export default defineComponent({
name: 'FormHightPage',
components: { BasicForm, PersonTable, PageWrapper, [Card.name]: Card },
setup() {
const tableRef = ref<{ getDataSource: () => any } | null>(null);
const [register, { validate }] = useForm({
baseColProps: {
span: 6,
},
labelWidth: 200,
layout: 'vertical',
schemas: schemas,
showActionButtonGroup: false,
});
const [registerTask, { validate: validateTaskForm }] = useForm({
baseColProps: {
span: 6,
},
labelWidth: 200,
layout: 'vertical',
schemas: taskSchemas,
showActionButtonGroup: false,
});
async function submitAll() {
try {
if (tableRef.value) {
console.log('table data:', tableRef.value.getDataSource());
}
const [values, taskValues] = await Promise.all([validate(), validateTaskForm()]);
console.log('form data:', values, taskValues);
} catch (error) {}
}
return { register, registerTask, submitAll, tableRef };
},
});
</script>
<style lang="less" scoped>
.high-form {
padding-bottom: 48px;
}
/** update-begin-author:taoyan date:2022-5-16 for:/issues/63 下拉框z-index问题 */
:deep(.ant-select-dropdown) {
z-index: 98 !important;
}
/** update-end-author:taoyan date:2022-5-16 for:/issues/63 下拉框z-index问题 */
</style>
+103
View File
@@ -0,0 +1,103 @@
<template>
<div class="step1">
<div class="step1-form">
<BasicForm @register="register">
<template #fac="{ model, field }">
<a-input-group compact>
<a-select v-model:value="model['pay']" class="pay-select">
<a-select-option value="zfb"> 支付宝 </a-select-option>
<a-select-option value="yl"> 银联 </a-select-option>
</a-select>
<a-input class="pay-input" v-model:value="model[field]" />
</a-input-group>
</template>
</BasicForm>
</div>
<a-divider />
<h3>说明</h3>
<h4>转账到支付宝账户</h4>
<p>
如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明
</p>
<h4>转账到银行卡</h4>
<p>
如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明如果需要这里可以放一些关于产品的常见问题说明
</p>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicForm, useForm } from '/@/components/Form';
import { step1Schemas } from './data';
import { Select, Input, Divider } from 'ant-design-vue';
export default defineComponent({
components: {
BasicForm,
[Select.name]: Select,
ASelectOption: Select.Option,
[Input.name]: Input,
[Input.Group.name]: Input.Group,
[Divider.name]: Divider,
},
emits: ['next'],
setup(_, { emit }) {
const [register, { validate }] = useForm({
labelWidth: 200,
schemas: step1Schemas,
actionColOptions: {
span: 14,
},
showResetButton: false,
submitButtonOptions: {
text: '下一步',
},
submitFunc: customSubmitFunc,
});
async function customSubmitFunc() {
try {
const values = await validate();
emit('next', values);
} catch (error) {}
}
return { register };
},
});
</script>
<style lang="less" scoped>
.step1 {
&-form {
width: 550px;
margin: 0 auto;
}
h3 {
margin: 0 0 12px;
font-size: 16px;
line-height: 32px;
color: @text-color;
}
h4 {
margin: 0 0 4px;
font-size: 14px;
line-height: 22px;
color: @text-color;
}
p {
color: @text-color;
}
}
.pay-select {
width: 20%;
}
.pay-input {
width: 70%;
}
</style>
+78
View File
@@ -0,0 +1,78 @@
<template>
<div class="step2">
<a-alert message="确认转账后,资金将直接打入对方账户,无法退回。" show-icon />
<a-descriptions :column="1" class="mt-5">
<a-descriptions-item label="付款账户"> ant-design@alipay.com </a-descriptions-item>
<a-descriptions-item label="收款账户"> test@example.com </a-descriptions-item>
<a-descriptions-item label="收款人姓名"> Jeecg </a-descriptions-item>
<a-descriptions-item label="转账金额"> 500 </a-descriptions-item>
</a-descriptions>
<a-divider />
<BasicForm @register="register" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { BasicForm, useForm } from '/@/components/Form';
import { step2Schemas } from './data';
import { Alert, Divider, Descriptions } from 'ant-design-vue';
export default defineComponent({
components: {
BasicForm,
[Alert.name]: Alert,
[Divider.name]: Divider,
[Descriptions.name]: Descriptions,
[Descriptions.Item.name]: Descriptions.Item,
},
emits: ['next', 'prev'],
setup(_, { emit }) {
const [register, { validate, setProps }] = useForm({
labelWidth: 120,
schemas: step2Schemas,
actionColOptions: {
span: 14,
},
resetButtonOptions: {
text: '上一步',
},
submitButtonOptions: {
text: '提交',
},
resetFunc: customResetFunc,
submitFunc: customSubmitFunc,
});
async function customResetFunc() {
emit('prev');
}
async function customSubmitFunc() {
try {
const values = await validate();
setProps({
submitButtonOptions: {
loading: true,
},
});
setTimeout(() => {
setProps({
submitButtonOptions: {
loading: false,
},
});
emit('next', values);
}, 1500);
} catch (error) {}
}
return { register };
},
});
</script>
<style lang="less" scoped>
.step2 {
width: 550px;
margin: 0 auto;
}
</style>
+49
View File
@@ -0,0 +1,49 @@
<template>
<div class="step3">
<a-result status="success" title="操作成功" sub-title="预计两小时内到账">
<template #extra>
<a-button type="primary" @click="redo"> 再转一笔 </a-button>
<a-button> 查看账单 </a-button>
</template>
</a-result>
<div class="desc-wrap">
<a-descriptions :column="1" class="mt-5">
<a-descriptions-item label="付款账户"> ant-design@alipay.com </a-descriptions-item>
<a-descriptions-item label="收款账户"> test@example.com </a-descriptions-item>
<a-descriptions-item label="收款人姓名"> Jeecg </a-descriptions-item>
<a-descriptions-item label="转账金额"> 500 </a-descriptions-item>
</a-descriptions>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Result, Descriptions } from 'ant-design-vue';
export default defineComponent({
components: {
[Result.name]: Result,
[Descriptions.name]: Descriptions,
[Descriptions.Item.name]: Descriptions.Item,
},
emits: ['redo'],
setup(_, { emit }) {
return {
redo: () => {
emit('redo');
},
};
},
});
</script>
<style lang="less" scoped>
.step3 {
width: 600px;
margin: 0 auto;
}
.desc-wrap {
padding: 24px 40px;
margin-top: 24px;
background-color: @background-color-light;
}
</style>
+63
View File
@@ -0,0 +1,63 @@
import { FormSchema } from '/@/components/Form';
export const step1Schemas: FormSchema[] = [
{
field: 'account',
component: 'Select',
label: '付款账户',
required: true,
defaultValue: '1',
componentProps: {
options: [
{
label: 'anncwb@126.com',
value: '1',
},
],
},
},
{
field: 'fac',
component: 'InputGroup',
label: '收款账户',
required: true,
defaultValue: 'test@example.com',
slot: 'fac',
},
{
field: 'pay',
component: 'Input',
label: '',
defaultValue: 'zfb',
show: false,
},
{
field: 'payeeName',
component: 'Input',
label: '收款人姓名',
defaultValue: 'Jeecg',
required: true,
},
{
field: 'money',
component: 'Input',
label: '转账金额',
defaultValue: '500',
required: true,
renderComponentContent: () => {
return {
prefix: () => '¥',
};
},
},
];
export const step2Schemas: FormSchema[] = [
{
field: 'pwd',
component: 'InputPassword',
label: '支付密码',
required: true,
defaultValue: '123456',
},
];
+86
View File
@@ -0,0 +1,86 @@
<template>
<PageWrapper title="分步表单" contentBackground content=" 将一个冗长或用户不熟悉的表单任务分成多个步骤,指导用户完成。" contentClass="p-4">
<div class="step-form-form">
<a-steps :current="current">
<a-step title="填写转账信息" />
<a-step title="确认转账信息" />
<a-step title="完成" />
</a-steps>
</div>
<div class="mt-5">
<Step1 @next="handleStep1Next" v-show="current === 0" />
<Step2 @prev="handleStepPrev" @next="handleStep2Next" v-show="current === 1" v-if="initSetp2" />
<Step3 v-show="current === 2" @redo="handleRedo" v-if="initSetp3" />
</div>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent, ref, reactive, toRefs } from 'vue';
import Step1 from './Step1.vue';
import Step2 from './Step2.vue';
import Step3 from './Step3.vue';
import { PageWrapper } from '/@/components/Page';
import { Steps } from 'ant-design-vue';
export default defineComponent({
name: 'FormStepPage',
components: {
Step1,
Step2,
Step3,
PageWrapper,
[Steps.name]: Steps,
[Steps.Step.name]: Steps.Step,
},
setup() {
const current = ref(0);
const state = reactive({
initSetp2: false,
initSetp3: false,
});
function handleStep1Next(step1Values: any) {
current.value++;
state.initSetp2 = true;
console.log(step1Values);
}
function handleStepPrev() {
current.value--;
}
function handleStep2Next(step2Values: any) {
current.value++;
state.initSetp3 = true;
console.log(step2Values);
}
function handleRedo() {
current.value = 0;
state.initSetp2 = false;
state.initSetp3 = false;
}
return {
current,
handleStep1Next,
handleStep2Next,
handleRedo,
handleStepPrev,
...toRefs(state),
};
},
});
</script>
<style lang="less" scoped>
.step-form-content {
padding: 24px;
background-color: @component-background;
}
.step-form-form {
width: 750px;
margin: 0 auto;
}
</style>
+17
View File
@@ -0,0 +1,17 @@
export const cardList = (() => {
const result: any[] = [];
for (let i = 0; i < 6; i++) {
result.push({
id: i,
title: 'Jeecg Admin',
description: '基于Vue Next, TypeScript, Ant Design Vue实现的一套完整的企业级后台管理系统',
datetime: '2020-11-26 17:39',
extra: '编辑',
icon: 'logos:vue',
color: '#1890ff',
author: 'Jeecg',
percent: 20 * (i + 1),
});
}
return result;
})();
+161
View File
@@ -0,0 +1,161 @@
<template>
<PageWrapper :class="prefixCls" title="标准列表">
<div :class="`${prefixCls}__top`">
<a-row :gutter="12">
<a-col :span="8" :class="`${prefixCls}__top-col`">
<div>我的待办</div>
<p>8个任务</p>
</a-col>
<a-col :span="8" :class="`${prefixCls}__top-col`">
<div>本周任务平均处理时间</div>
<p>32分钟</p>
</a-col>
<a-col :span="8" :class="`${prefixCls}__top-col`">
<div>本周完成任务数</div>
<p>24个任务</p>
</a-col>
</a-row>
</div>
<div :class="`${prefixCls}__content`">
<a-list :pagination="pagination">
<template v-for="item in list" :key="item.id">
<a-list-item class="list">
<a-list-item-meta>
<template #avatar>
<Icon class="icon" v-if="item.icon" :icon="item.icon" :color="item.color" />
</template>
<template #title>
<span>{{ item.title }}</span>
<div class="extra" v-if="item.extra">
{{ item.extra }}
</div>
</template>
<template #description>
<div class="description">
{{ item.description }}
</div>
<div class="info">
<div><span>Owner</span>{{ item.author }}</div>
<div><span>开始时间</span>{{ item.datetime }}</div>
</div>
<div class="progress">
<Progress :percent="item.percent" status="active" />
</div>
</template>
</a-list-item-meta>
</a-list-item>
</template>
</a-list>
</div>
</PageWrapper>
</template>
<script lang="ts">
import { Progress, Row, Col } from 'ant-design-vue';
import { defineComponent } from 'vue';
import Icon from '/@/components/Icon/index';
import { cardList } from './data';
import { PageWrapper } from '/@/components/Page';
import { List } from 'ant-design-vue';
export default defineComponent({
components: {
Icon,
Progress,
PageWrapper,
[List.name]: List,
[List.Item.name]: List.Item,
AListItemMeta: List.Item.Meta,
[Row.name]: Row,
[Col.name]: Col,
},
setup() {
return {
prefixCls: 'list-basic',
list: cardList,
pagination: {
show: true,
pageSize: 3,
},
};
},
});
</script>
<style lang="less" scoped>
.list-basic {
&__top {
padding: 24px;
text-align: center;
background-color: @component-background;
&-col {
&:not(:last-child) {
border-right: 1px dashed @border-color-base;
}
div {
margin-bottom: 12px;
font-size: 14px;
line-height: 22px;
color: @text-color;
}
p {
margin: 0;
font-size: 24px;
line-height: 32px;
color: @text-color;
}
}
}
&__content {
padding: 24px;
margin-top: 12px;
background-color: @component-background;
.list {
position: relative;
}
.icon {
font-size: 40px !important;
}
.extra {
position: absolute;
top: 20px;
right: 15px;
font-weight: normal;
color: @primary-color;
cursor: pointer;
}
.description {
display: inline-block;
width: 40%;
}
.info {
display: inline-block;
width: 30%;
text-align: center;
div {
display: inline-block;
padding: 0 20px;
span {
display: block;
}
}
}
.progress {
display: inline-block;
width: 15%;
vertical-align: top;
}
}
}
</style>
+14
View File
@@ -0,0 +1,14 @@
export const cardList = (() => {
const result: any[] = [];
for (let i = 0; i < 12; i++) {
result.push({
title: 'Jeecg Admin',
icon: 'logos:vue',
color: '#1890ff',
active: '100',
new: '1,799',
download: 'bx:bx-download',
});
}
return result;
})();
+102
View File
@@ -0,0 +1,102 @@
<template>
<PageWrapper :class="prefixCls" title="卡片列表">
<template #headerContent>
基于Vue Next, TypeScript, Ant Design Vue实现的一套完整的企业级后台管理系统
<div :class="`${prefixCls}__link`">
<a><Icon icon="bx:bx-paper-plane" color="#1890ff" /><span>开始</span></a>
<a><Icon icon="carbon:warning" color="#1890ff" /><span>简介</span></a>
<a><Icon icon="ion:document-text-outline" color="#1890ff" /><span>文档</span></a>
</div>
</template>
<div :class="`${prefixCls}__content`">
<a-list>
<a-row :gutter="16">
<template v-for="item in list" :key="item.title">
<a-col :span="6">
<a-list-item>
<a-card :hoverable="true" :class="`${prefixCls}__card`">
<div :class="`${prefixCls}__card-title`">
<Icon class="icon" v-if="item.icon" :icon="item.icon" :color="item.color" />
{{ item.title }}
</div>
<div :class="`${prefixCls}__card-detail`"> 基于Vue Next, TypeScript, Ant Design Vue实现的一套完整的企业级后台管理系统 </div>
</a-card>
</a-list-item>
</a-col>
</template>
</a-row>
</a-list>
</div>
</PageWrapper>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import Icon from '/@/components/Icon/index';
import { cardList } from './data';
import { PageWrapper } from '/@/components/Page';
import { Card, Row, Col, List } from 'ant-design-vue';
export default defineComponent({
components: {
Icon,
PageWrapper,
[Card.name]: Card,
[List.name]: List,
[List.Item.name]: List.Item,
[Row.name]: Row,
[Col.name]: Col,
},
setup() {
return {
prefixCls: 'list-card',
list: cardList,
};
},
});
</script>
<style lang="less" scoped>
.list-card {
&__link {
margin-top: 10px;
font-size: 14px;
a {
margin-right: 30px;
}
span {
margin-left: 5px;
}
}
&__card {
width: 100%;
margin-bottom: -8px;
.ant-card-body {
padding: 16px;
}
&-title {
margin-bottom: 5px;
font-size: 16px;
font-weight: 500;
color: @text-color;
.icon {
margin-top: -5px;
margin-right: 10px;
font-size: 38px !important;
}
}
&-detail {
padding-top: 10px;
padding-left: 30px;
font-size: 14px;
color: @text-color-secondary;
}
}
}
</style>
+37
View File
@@ -0,0 +1,37 @@
import { FormSchema } from '/@/components/Form/index';
export const searchList = (() => {
const result: any[] = [];
for (let i = 0; i < 6; i++) {
result.push({
id: i,
title: 'Jeecg Admin',
description: ['Jeecg', '设计语言', 'Typescript'],
content: '基于Vue Next, TypeScript, Ant Design实现的一套完整的企业级后台管理系统。',
time: '2020-11-14 11:20',
});
}
return result;
})();
export const actions: any[] = [
{ icon: 'clarity:star-line', text: '156', color: '#018ffb' },
{ icon: 'bx:bxs-like', text: '156', color: '#459ae8' },
{ icon: 'bx:bxs-message-dots', text: '2', color: '#42d27d' },
];
export const schemas: FormSchema[] = [
{
field: 'field1',
component: 'InputSearch',
label: '项目名',
colProps: {
span: 8,
},
componentProps: {
onChange: (e: any) => {
console.log(e);
},
},
},
];
+125
View File
@@ -0,0 +1,125 @@
<template>
<PageWrapper :class="prefixCls" title="搜索列表">
<template #headerContent>
<BasicForm :class="`${prefixCls}__header-form`" :labelWidth="100" :schemas="schemas" :showActionButtonGroup="false" />
</template>
<div :class="`${prefixCls}__container`">
<a-list>
<template v-for="item in list" :key="item.id">
<a-list-item>
<a-list-item-meta>
<template #description>
<div :class="`${prefixCls}__content`">
{{ item.content }}
</div>
<div :class="`${prefixCls}__action`">
<template v-for="action in actions" :key="action.icon">
<div :class="`${prefixCls}__action-item`">
<Icon v-if="action.icon" :class="`${prefixCls}__action-icon`" :icon="action.icon" :color="action.color" />
{{ action.text }}
</div>
</template>
<span :class="`${prefixCls}__time`">{{ item.time }}</span>
</div>
</template>
<template #title>
<p :class="`${prefixCls}__title`">
{{ item.title }}
</p>
<div>
<template v-for="tag in item.description" :key="tag">
<Tag class="mb-2">
{{ tag }}
</Tag>
</template>
</div>
</template>
</a-list-item-meta>
</a-list-item>
</template>
</a-list>
</div>
</PageWrapper>
</template>
<script lang="ts">
import { Tag } from 'ant-design-vue';
import { defineComponent } from 'vue';
import Icon from '/@/components/Icon/index';
import { BasicForm } from '/@/components/Form/index';
import { actions, searchList, schemas } from './data';
import { PageWrapper } from '/@/components/Page';
import { List } from 'ant-design-vue';
export default defineComponent({
components: {
Icon,
Tag,
BasicForm,
PageWrapper,
[List.name]: List,
[List.Item.name]: List.Item,
AListItemMeta: List.Item.Meta,
},
setup() {
return {
prefixCls: 'list-search',
list: searchList,
actions,
schemas,
};
},
});
</script>
<style lang="less" scoped>
.list-search {
&__header {
&-form {
margin-bottom: -16px;
}
}
&__container {
padding: 12px;
background-color: @component-background;
}
&__title {
margin-bottom: 12px;
font-size: 18px;
}
&__content {
color: @text-color-secondary;
}
&__action {
margin-top: 10px;
&-item {
display: inline-block;
padding: 0 16px;
color: @text-color-secondary;
&:nth-child(1) {
padding-left: 0;
}
&:nth-child(1),
&:nth-child(2) {
border-right: 1px solid @border-color-base;
}
}
&-icon {
margin-right: 3px;
}
}
&__time {
position: absolute;
right: 20px;
color: rgba(0, 0, 0, 0.45);
}
}
</style>
+54
View File
@@ -0,0 +1,54 @@
<template>
<div class="m-5 result-error">
<Result status="error" title="提交失败" sub-title="请核对并修改以下信息后再重新提交">
<template #extra>
<a-button key="console" type="primary"> 返回修改 </a-button>
</template>
</Result>
<div class="result-error__content">
<div class="result-error__content-title"> 您提交的内容有如下错误 </div>
<div class="mb-4">
<CloseCircleOutlined class="mr-2 result-error__content-icon" />
您的账户已被冻结
<a class="ml-4">立即解冻 ></a>
</div>
<div class="mb-4">
<CloseCircleOutlined class="mr-2 result-error__content-icon" />
您的账户还不具备申请资格
<a class="ml-4">立即解冻 ></a>
</div>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Result } from 'ant-design-vue';
import { CloseCircleOutlined } from '@ant-design/icons-vue';
export default defineComponent({
components: {
Result,
CloseCircleOutlined,
},
});
</script>
<style lang="less" scoped>
.result-error {
padding: 48px 32px;
background-color: @component-background;
&__content {
padding: 24px 40px;
background-color: @background-color-light;
&-title {
margin-bottom: 16px;
font-size: 16px;
font-weight: 500;
}
&-icon {
color: #ff4d4f;
}
}
}
</style>
@@ -0,0 +1,58 @@
<template>
<div class="m-5 result-success">
<Result
status="success"
title="提交成功"
sub-title="提交结果页用于反馈一系列操作任务的处理结果 如果仅是简单操作使用 Message 全局提示反馈即可 本文字区域可以展示简单的补充说明如果有类似展示 单据的需求下面这个灰色区域可以呈现比较复杂的内容"
>
<template #extra>
<a-button key="console" type="primary"> 返回列表 </a-button>
<a-button key="buy"> 查看项目 </a-button>
<a-button key="buy"> 打印 </a-button>
</template>
</Result>
<div class="result-success__content">
<Descriptions title="项目名称">
<DescriptionItem label="项目 ID"> 111222 </DescriptionItem>
<DescriptionItem label="负责人"> Jeecg </DescriptionItem>
<DescriptionItem label="生效时间"> 2016-12-12 ~ 2017-12-12 </DescriptionItem>
</Descriptions>
<Steps :current="1" progress-dot size="small">
<Step title="创建项目">
<template #description> <div>Jeecg</div> <p>2016-12-12 12:32</p> </template>
</Step>
<Step title="部门初审">
<template #description>
<p>Chad</p>
</template>
</Step>
<Step title="财务复核" />
<Step title="完成" />
</Steps>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { Result, Steps, Descriptions } from 'ant-design-vue';
export default defineComponent({
components: {
Result,
Steps,
Step: Steps.Step,
Descriptions,
DescriptionItem: Descriptions.Item,
},
});
</script>
<style lang="less" scoped>
.result-success {
padding: 48px 32px;
background-color: @component-background;
&__content {
padding: 24px 40px;
background-color: @background-color-light;
}
}
</style>