mirror of
https://github.com/Tencent/tdesign-vue-next-starter.git
synced 2024-11-10 07:28:24 +08:00
enhance/router (#23)
* style: ui edit。 * feat: ui edit complete * style: ui edit * chore: update style import path * feat: update import path * chore: lint fix * feat: add package.lok * chore: update node version * chore: update actions * chore: remove lock file * fix: node version update * fix: revert preview actiion * fix: tdesign-wrapper classname fix * feat: add router permission * feat: enhance router * feat: optimize header icon Co-authored-by: pengYYY <pengyue970715@gmail.com>
This commit is contained in:
parent
15e8f72117
commit
baf43fb503
|
@ -53,7 +53,7 @@
|
||||||
"stylelint-order": "^4.1.0",
|
"stylelint-order": "^4.1.0",
|
||||||
"stylelint-scss": "^4.0.0",
|
"stylelint-scss": "^4.0.0",
|
||||||
"typescript": "^4.4.3",
|
"typescript": "^4.4.3",
|
||||||
"vite": "^2.4.4",
|
"vite": "^2.7.1",
|
||||||
"vite-plugin-mock": "^2.9.6",
|
"vite-plugin-mock": "^2.9.6",
|
||||||
"vite-plugin-svg-sprite-component": "^1.0.10",
|
"vite-plugin-svg-sprite-component": "^1.0.10",
|
||||||
"vite-svg-loader": "^3.1.0",
|
"vite-svg-loader": "^3.1.0",
|
||||||
|
|
|
@ -19,3 +19,10 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="less">
|
||||||
|
@import '@/style/variables.less';
|
||||||
|
|
||||||
|
#nprogress .bar {
|
||||||
|
background: @brand-color !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
export const PREFIX = 'tdesign-starter';
|
export const PREFIX = 'tdesign-starter';
|
||||||
export const THEME = 'light';
|
export const THEME = 'light';
|
||||||
|
|
||||||
export const AUTHENTICATION_METHOD = 'customize';
|
export const AUTHENTICATION_METHOD = 'customize';
|
||||||
|
export const TOKEN_NAME = 'tdesign-starter';
|
||||||
export default {
|
|
||||||
PREFIX,
|
|
||||||
THEME,
|
|
||||||
AUTHENTICATION_METHOD,
|
|
||||||
};
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ export interface MenuRoute {
|
||||||
path: string;
|
path: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
redirect?: string;
|
||||||
children: MenuRoute[];
|
children: MenuRoute[];
|
||||||
meta: any;
|
meta: any;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="tdesign-wrapper">
|
<div class="tdesign-wrapper">
|
||||||
<router-view />
|
<router-view />
|
||||||
<tdesign-setting />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import TdesignSetting from './setting.vue';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {},
|
||||||
TdesignSetting,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
|
25
src/layouts/components/Content.vue
Normal file
25
src/layouts/components/Content.vue
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<template>
|
||||||
|
<router-view v-slot="{ Component }">
|
||||||
|
<transition name="fade" mode="out-in">
|
||||||
|
<component :is="Component" />
|
||||||
|
</transition>
|
||||||
|
</router-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({});
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@import '@/style/variables';
|
||||||
|
|
||||||
|
.fade-leave-active,
|
||||||
|
.fade-enter-active {
|
||||||
|
transition: opacity @anim-duration-slow @anim-time-fn-easing;
|
||||||
|
}
|
||||||
|
.fade-enter,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -2,9 +2,6 @@ import { defineComponent, PropType, computed } from 'vue';
|
||||||
import { PREFIX as prefix } from '@/config/global';
|
import { PREFIX as prefix } from '@/config/global';
|
||||||
import { MenuRoute } from '@/interface';
|
import { MenuRoute } from '@/interface';
|
||||||
|
|
||||||
// utils
|
|
||||||
const isSingleNav = (list: Array<MenuRoute>) => list.every((item) => !item.children || item.children.length === 0);
|
|
||||||
|
|
||||||
const getMenuList = (list: MenuRoute[], basePath?: string): MenuRoute[] => {
|
const getMenuList = (list: MenuRoute[], basePath?: string): MenuRoute[] => {
|
||||||
if (!list) {
|
if (!list) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -13,55 +10,39 @@ const getMenuList = (list: MenuRoute[], basePath?: string): MenuRoute[] => {
|
||||||
const path = basePath ? `${basePath}/${item.path}` : item.path;
|
const path = basePath ? `${basePath}/${item.path}` : item.path;
|
||||||
return {
|
return {
|
||||||
path,
|
path,
|
||||||
title: item.title,
|
title: item.meta?.title,
|
||||||
icon: item.icon || '',
|
icon: item.meta?.icon || '',
|
||||||
children: getMenuList(item.children, path),
|
children: getMenuList(item.children, path),
|
||||||
meta: item.meta || {},
|
meta: item.meta,
|
||||||
|
redirect: item.redirect,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const useRenderNav = (list: Array<MenuRoute>, deep = 0, maxLevel = 2) => {
|
const useRenderNav = (list: Array<MenuRoute>) => {
|
||||||
if (isSingleNav(list)) {
|
|
||||||
return list.map((item) => (
|
|
||||||
<t-menu-item
|
|
||||||
key={item.path}
|
|
||||||
value={item.path}
|
|
||||||
to={item.path}
|
|
||||||
icon={() => item.icon && <t-icon name={item.icon} />}
|
|
||||||
>
|
|
||||||
{item.title}
|
|
||||||
</t-menu-item>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return list.map((item) => {
|
return list.map((item) => {
|
||||||
if (deep < maxLevel) {
|
if (!item.children || !item.children.length || item.meta?.single) {
|
||||||
if (deep === 0) {
|
|
||||||
return (
|
|
||||||
<t-submenu
|
|
||||||
name={item.path}
|
|
||||||
value={item.path}
|
|
||||||
title={item.title}
|
|
||||||
icon={() => item.icon && <t-icon name={item.icon} />}
|
|
||||||
>
|
|
||||||
{item.children && useRenderNav(item.children, deep + 1)}
|
|
||||||
</t-submenu>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<t-menu-item
|
<t-menu-item
|
||||||
name={item.path}
|
name={item.path}
|
||||||
value={item.path}
|
value={item.meta?.single ? item.redirect : item.path}
|
||||||
to={item.path}
|
to={item.path}
|
||||||
icon={() => item.icon && <t-icon name={item.icon} />}
|
icon={() => item.icon && <t-icon name={item.icon} />}
|
||||||
>
|
>
|
||||||
{item.title}
|
{item.title}
|
||||||
{item.children && useRenderNav(item.children, deep + 1)}
|
|
||||||
</t-menu-item>
|
</t-menu-item>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return '';
|
return (
|
||||||
|
<t-submenu
|
||||||
|
name={item.path}
|
||||||
|
value={item.path}
|
||||||
|
title={item.title}
|
||||||
|
icon={() => item.icon && <t-icon name={item.icon} />}
|
||||||
|
>
|
||||||
|
{item.children && useRenderNav(item.children)}
|
||||||
|
</t-submenu>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
import TdesignHeader from './header/index.vue';
|
import TdesignHeader from './components/Header.vue';
|
||||||
import TdesignBreadcrumb from './components/Breadcrumb.vue';
|
import TdesignBreadcrumb from './components/Breadcrumb.vue';
|
||||||
import TdesignFooter from './components/Footer.vue';
|
import TdesignFooter from './components/Footer.vue';
|
||||||
import TdesignSideNav from './components/SideNav';
|
import TdesignSideNav from './components/SideNav';
|
||||||
|
import TdesignContent from './components/Content.vue';
|
||||||
|
|
||||||
import { PREFIX } from '@/config/global';
|
import { PREFIX } from '@/config/global';
|
||||||
import TdesignSetting from './setting.vue';
|
import TdesignSetting from './setting.vue';
|
||||||
|
@ -20,6 +21,7 @@ export default defineComponent({
|
||||||
TdesignSideNav,
|
TdesignSideNav,
|
||||||
TdesignSetting,
|
TdesignSetting,
|
||||||
TdesignBreadcrumb,
|
TdesignBreadcrumb,
|
||||||
|
TdesignContent,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
|
@ -27,10 +29,9 @@ export default defineComponent({
|
||||||
showHeader: 'setting/showHeader',
|
showHeader: 'setting/showHeader',
|
||||||
showHeaderLogo: 'setting/showHeaderLogo',
|
showHeaderLogo: 'setting/showHeaderLogo',
|
||||||
showSidebarLogo: 'setting/showSidebarLogo',
|
showSidebarLogo: 'setting/showSidebarLogo',
|
||||||
headerMenu: 'setting/headerMenu',
|
|
||||||
sideMenu: 'setting/sideMenu',
|
|
||||||
showFooter: 'setting/showFooter',
|
showFooter: 'setting/showFooter',
|
||||||
mode: 'setting/mode',
|
mode: 'setting/mode',
|
||||||
|
menuRouters: 'permission/routers',
|
||||||
}),
|
}),
|
||||||
setting(): SettingType {
|
setting(): SettingType {
|
||||||
return this.$store.state.setting;
|
return this.$store.state.setting;
|
||||||
|
@ -42,6 +43,34 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
headerMenu() {
|
||||||
|
const { layout, splitMenu } = this.$store.state.setting;
|
||||||
|
const { menuRouters } = this;
|
||||||
|
if (layout === 'mix') {
|
||||||
|
if (splitMenu) {
|
||||||
|
return menuRouters.map((menu) => ({
|
||||||
|
...menu,
|
||||||
|
children: [],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return menuRouters;
|
||||||
|
},
|
||||||
|
sideMenu() {
|
||||||
|
const { layout, splitMenu } = this.$store.state.setting;
|
||||||
|
const { menuRouters } = this;
|
||||||
|
if (layout === 'mix' && splitMenu) {
|
||||||
|
let index;
|
||||||
|
for (index = 0; index < menuRouters.length; index++) {
|
||||||
|
const item = menuRouters[index];
|
||||||
|
if (item.children && item.children.length > 0) {
|
||||||
|
return item.children.map((menuRouter) => ({ ...menuRouter, path: `${item.path}/${menuRouter.path}` }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return menuRouters;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getNavTheme(mode: ModeType, layout: string, type: string): string {
|
getNavTheme(mode: ModeType, layout: string, type: string): string {
|
||||||
|
@ -90,10 +119,10 @@ export default defineComponent({
|
||||||
const { showBreadcrumb } = this.setting;
|
const { showBreadcrumb } = this.setting;
|
||||||
const { showFooter } = this;
|
const { showFooter } = this;
|
||||||
return (
|
return (
|
||||||
<t-layout>
|
<t-layout class={[`${PREFIX}-layout`, 'narrow-scrollbar']}>
|
||||||
<t-content class={`${PREFIX}-content-layout`}>
|
<t-content class={`${PREFIX}-content-layout`}>
|
||||||
{showBreadcrumb && <tdesign-breadcrumb />}
|
{showBreadcrumb && <tdesign-breadcrumb />}
|
||||||
<router-view />
|
<TdesignContent />
|
||||||
</t-content>
|
</t-content>
|
||||||
{showFooter && this.renderFooter()}
|
{showFooter && this.renderFooter()}
|
||||||
</t-layout>
|
</t-layout>
|
||||||
|
@ -120,7 +149,7 @@ export default defineComponent({
|
||||||
<div class={`${PREFIX}-wrapper`}>
|
<div class={`${PREFIX}-wrapper`}>
|
||||||
{layout === 'side' ? (
|
{layout === 'side' ? (
|
||||||
<t-layout class={this.mainLayoutCls} key="side">
|
<t-layout class={this.mainLayoutCls} key="side">
|
||||||
<t-aside style={{ width: 'fit-content' }}>{sidebar}</t-aside>
|
<t-aside>{sidebar}</t-aside>
|
||||||
<t-layout>{[header, content]}</t-layout>
|
<t-layout>{[header, content]}</t-layout>
|
||||||
</t-layout>
|
</t-layout>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { store } from './store';
|
||||||
import router from './router';
|
import router from './router';
|
||||||
|
|
||||||
import '@/style/index.less';
|
import '@/style/index.less';
|
||||||
|
import './permission';
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,7 @@ export const SALE_COLUMNS: TdBaseTableProps['columns'] = [
|
||||||
colKey: 'index',
|
colKey: 'index',
|
||||||
title: '排名',
|
title: '排名',
|
||||||
width: 80,
|
width: 80,
|
||||||
|
fixed: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -156,7 +157,8 @@ export const SALE_COLUMNS: TdBaseTableProps['columns'] = [
|
||||||
align: 'center',
|
align: 'center',
|
||||||
colKey: 'operation',
|
colKey: 'operation',
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 100,
|
width: 80,
|
||||||
|
fixed: 'right',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -166,6 +168,7 @@ export const BUY_COLUMNS: TdBaseTableProps['columns'] = [
|
||||||
colKey: 'index',
|
colKey: 'index',
|
||||||
title: '排名',
|
title: '排名',
|
||||||
width: 80,
|
width: 80,
|
||||||
|
fixed: 'left',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -196,6 +199,7 @@ export const BUY_COLUMNS: TdBaseTableProps['columns'] = [
|
||||||
align: 'center',
|
align: 'center',
|
||||||
colKey: 'operation',
|
colKey: 'operation',
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 100,
|
width: 80,
|
||||||
|
fixed: 'right',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -32,7 +32,7 @@ export function getColorFromTheme(theme: string) {
|
||||||
/** 图表颜色 */
|
/** 图表颜色 */
|
||||||
function chartListColor(): Array<string> {
|
function chartListColor(): Array<string> {
|
||||||
const colorList: Array<string> = ['#0052D9', '#BCC4D0', '#7D46BD', '#0594FA', '#ED7B2F'];
|
const colorList: Array<string> = ['#0052D9', '#BCC4D0', '#7D46BD', '#0594FA', '#ED7B2F'];
|
||||||
const { setting } = state;
|
const { setting } = state as any;
|
||||||
|
|
||||||
return getColorFromTheme(setting.brandTheme) || colorList;
|
return getColorFromTheme(setting.brandTheme) || colorList;
|
||||||
}
|
}
|
||||||
|
@ -1020,13 +1020,16 @@ export function getPieChartDataSet(radius = 42) {
|
||||||
return {
|
return {
|
||||||
color: chartListColor(),
|
color: chartListColor(),
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
show: false,
|
||||||
|
trigger: 'axis',
|
||||||
|
position: null,
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: '0',
|
top: '0',
|
||||||
right: '0',
|
right: '0',
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
|
selectedMode: false,
|
||||||
itemWidth: 12,
|
itemWidth: 12,
|
||||||
itemHeight: 4,
|
itemHeight: 4,
|
||||||
textStyle: {
|
textStyle: {
|
||||||
|
@ -1042,7 +1045,10 @@ export function getPieChartDataSet(radius = 42) {
|
||||||
name: '销售渠道',
|
name: '销售渠道',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: ['48%', '60%'],
|
radius: ['48%', '60%'],
|
||||||
avoidLabelOverlap: false,
|
avoidLabelOverlap: true,
|
||||||
|
selectedMode: true,
|
||||||
|
hoverAnimation: true,
|
||||||
|
silent: true,
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
position: 'center',
|
position: 'center',
|
||||||
|
@ -1050,13 +1056,13 @@ export function getPieChartDataSet(radius = 42) {
|
||||||
rich: {
|
rich: {
|
||||||
value: {
|
value: {
|
||||||
color: '#303133',
|
color: '#303133',
|
||||||
fontSize: 36,
|
fontSize: 28,
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal',
|
||||||
lineHeight: 46,
|
lineHeight: 46,
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
color: '#909399',
|
color: '#909399',
|
||||||
fontSize: 14,
|
fontSize: 12,
|
||||||
lineHeight: 14,
|
lineHeight: 14,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1068,7 +1074,7 @@ export function getPieChartDataSet(radius = 42) {
|
||||||
rich: {
|
rich: {
|
||||||
value: {
|
value: {
|
||||||
color: '#303133',
|
color: '#303133',
|
||||||
fontSize: 36,
|
fontSize: 28,
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal',
|
||||||
lineHeight: 46,
|
lineHeight: 46,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,204 +1,205 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- 顶部 card -->
|
<div>
|
||||||
<t-row :gutter="[16, 16]">
|
<t-row :gutter="[16, 16]">
|
||||||
<t-col v-for="(item, index) in PANE_LIST" :key="item.title" :xs="6" :xl="3">
|
<t-col v-for="(item, index) in PANE_LIST" :key="item.title" :xs="6" :xl="3">
|
||||||
<card :subtitle="item.title" :style="{ height: '168px' }" :class="{ 'main-color': index == 0 }" size="small">
|
<card :subtitle="item.title" :style="{ height: '168px' }" :class="{ 'main-color': index == 0 }" size="small">
|
||||||
<div class="dashboard-item">
|
<div class="dashboard-item">
|
||||||
<div class="dashboard-item-top">
|
<div class="dashboard-item-top">
|
||||||
<span>{{ item.number }}</span>
|
<span>{{ item.number }}</span>
|
||||||
</div>
|
|
||||||
<div class="dashboard-item-left">
|
|
||||||
<div v-if="index === 0">
|
|
||||||
<div
|
|
||||||
id="moneyContainer"
|
|
||||||
class="dashboard-chart-container"
|
|
||||||
style="width: 96px; height: 40px; margin-top: 36px"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="index === 1">
|
<div class="dashboard-item-left">
|
||||||
<div
|
<div v-if="index === 0">
|
||||||
id="refundContainer"
|
<div
|
||||||
class="dashboard-chart-container"
|
id="moneyContainer"
|
||||||
style="width: 120px; height: 42px; margin-top: 24px"
|
class="dashboard-chart-container"
|
||||||
/>
|
style="width: 96px; height: 40px; margin-top: 36px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="index === 1">
|
||||||
|
<div
|
||||||
|
id="refundContainer"
|
||||||
|
class="dashboard-chart-container"
|
||||||
|
style="width: 120px; height: 42px; margin-top: 24px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span v-else-if="index === 2">
|
||||||
|
<t-icon name="usergroup" />
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
<t-icon name="file" />
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="dashboard-item-bottom">
|
||||||
<span v-else-if="index === 2">
|
<div class="dashboard-item-block">
|
||||||
<t-icon name="usergroup" />
|
自从上周以来
|
||||||
</span>
|
<trend
|
||||||
<span v-else>
|
class="dashboard-item-trend"
|
||||||
<t-icon name="file" />
|
:type="item.upTrend ? 'up' : 'down'"
|
||||||
</span>
|
:is-reverse-color="index === 0"
|
||||||
</div>
|
:describe="item.upTrend || item.downTrend"
|
||||||
<div class="dashboard-item-bottom">
|
/>
|
||||||
<div class="dashboard-item-block">
|
</div>
|
||||||
自从上周以来
|
<t-icon name="chevron-right" />
|
||||||
<trend
|
|
||||||
class="dashboard-item-trend"
|
|
||||||
:type="item.upTrend ? 'up' : 'down'"
|
|
||||||
:is-reverse-color="index === 0"
|
|
||||||
:describe="item.upTrend || item.downTrend"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<t-icon name="chevron-right" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</card>
|
||||||
</card>
|
</t-col>
|
||||||
</t-col>
|
</t-row>
|
||||||
</t-row>
|
|
||||||
|
|
||||||
<!-- 中部图表 -->
|
<!-- 中部图表 -->
|
||||||
<t-row :gutter="16" class="row-container">
|
<t-row :gutter="16" class="row-container">
|
||||||
<t-col :xs="12" :xl="9">
|
|
||||||
<card title="统计数据" :describe="`(万元)${currentMonth}`">
|
|
||||||
<template #option>
|
|
||||||
<div class="dashboard-chart-title-container">
|
|
||||||
<t-date-picker
|
|
||||||
class="card-date-picker-container"
|
|
||||||
theme="primary"
|
|
||||||
mode="date"
|
|
||||||
range
|
|
||||||
:default-value="LAST_7_DAYS"
|
|
||||||
@change="onCurrencyChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div
|
|
||||||
id="monitorContainer"
|
|
||||||
ref="monitorContainer"
|
|
||||||
class="dashboard-chart-container"
|
|
||||||
style="width: 100%; height: 326px"
|
|
||||||
/>
|
|
||||||
</card>
|
|
||||||
</t-col>
|
|
||||||
<t-col :xs="12" :xl="3">
|
|
||||||
<card title="销售渠道" :describe="currentMonth">
|
|
||||||
<div
|
|
||||||
id="countContainer"
|
|
||||||
ref="countContainer"
|
|
||||||
style="width: 100%; height: 326px"
|
|
||||||
class="dashboard-chart-container"
|
|
||||||
/>
|
|
||||||
</card>
|
|
||||||
</t-col>
|
|
||||||
</t-row>
|
|
||||||
|
|
||||||
<!-- 列表排名 -->
|
|
||||||
<t-row :gutter="16" class="row-container">
|
|
||||||
<t-col :xs="12" :xl="6">
|
|
||||||
<card title="销售订单排名">
|
|
||||||
<template #option>
|
|
||||||
<t-radio-group default-value="dateVal">
|
|
||||||
<t-radio-button value="dateVal"> 月份 </t-radio-button>
|
|
||||||
<t-radio-button value="monthVal"> 季度 </t-radio-button>
|
|
||||||
</t-radio-group>
|
|
||||||
</template>
|
|
||||||
<t-table :data="SALE_TEND_LIST" :columns="SALE_COLUMNS" row-key="productName" :style="{ overflow: 'scroll' }">
|
|
||||||
<template #index="{ rowIndex }">
|
|
||||||
<span :class="getRankClass(rowIndex)">
|
|
||||||
{{ rowIndex + 1 }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #growUp="{ row }">
|
|
||||||
<span>
|
|
||||||
<trend :type="row.growUp > 0 ? 'up' : 'down'" :describe="Math.abs(row.growUp)" />
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #operation="slotProps">
|
|
||||||
<a class="t-button-link" @click="rehandleClickOp(slotProps)">操作</a>
|
|
||||||
</template>
|
|
||||||
</t-table>
|
|
||||||
</card>
|
|
||||||
</t-col>
|
|
||||||
<t-col :xs="12" :xl="6">
|
|
||||||
<card title="采购订单排名">
|
|
||||||
<template #option>
|
|
||||||
<t-radio-group default-value="dateVal">
|
|
||||||
<t-radio-button value="dateVal"> 月份 </t-radio-button>
|
|
||||||
<t-radio-button value="monthVal"> 季度 </t-radio-button>
|
|
||||||
</t-radio-group>
|
|
||||||
</template>
|
|
||||||
<t-table :data="BUY_TEND_LIST" :columns="BUY_COLUMNS" row-key="productName" :style="{ overflow: 'scroll' }">
|
|
||||||
<template #index="{ rowIndex }">
|
|
||||||
<span :class="getRankClass(rowIndex)">
|
|
||||||
{{ rowIndex + 1 }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #growUp="{ row }">
|
|
||||||
<trend :type="row.growUp > 0 ? 'up' : 'down'" :describe="Math.abs(row.growUp)" />
|
|
||||||
</template>
|
|
||||||
<template #operation="slotProps">
|
|
||||||
<a class="t-button-link" @click="rehandleClickOp(slotProps)">操作</a>
|
|
||||||
</template>
|
|
||||||
</t-table>
|
|
||||||
</card>
|
|
||||||
</t-col>
|
|
||||||
</t-row>
|
|
||||||
|
|
||||||
<!-- 出入库概览 -->
|
|
||||||
<div class="row-container overview-panel">
|
|
||||||
<t-row>
|
|
||||||
<t-col :xs="12" :xl="9">
|
<t-col :xs="12" :xl="9">
|
||||||
<card title="出入库概览" describe="(件)">
|
<card title="统计数据" :describe="`(万元)${currentMonth}`">
|
||||||
<template #option>
|
<template #option>
|
||||||
<t-date-picker
|
<div class="dashboard-chart-title-container">
|
||||||
class="card-date-picker-container"
|
<t-date-picker
|
||||||
theme="primary"
|
class="card-date-picker-container"
|
||||||
mode="date"
|
theme="primary"
|
||||||
range
|
mode="date"
|
||||||
:default-value="LAST_7_DAYS"
|
range
|
||||||
@change="onWharehouseChange"
|
:default-value="LAST_7_DAYS"
|
||||||
/>
|
@change="onCurrencyChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div
|
<div
|
||||||
id="stokeContainer"
|
id="monitorContainer"
|
||||||
ref="stokeContainer"
|
ref="monitorContainer"
|
||||||
style="width: 100%; height: 351px"
|
|
||||||
class="dashboard-chart-container"
|
class="dashboard-chart-container"
|
||||||
|
style="width: 100%; height: 326px"
|
||||||
/>
|
/>
|
||||||
</card>
|
</card>
|
||||||
</t-col>
|
</t-col>
|
||||||
<t-col :xs="12" :xl="3">
|
<t-col :xs="12" :xl="3">
|
||||||
<card>
|
<card title="销售渠道" :describe="currentMonth">
|
||||||
<template #option>
|
<div
|
||||||
<t-button>导出数据</t-button>
|
id="countContainer"
|
||||||
</template>
|
ref="countContainer"
|
||||||
<t-row>
|
style="width: 100%; height: 326px"
|
||||||
<t-col :xs="6" :xl="12">
|
class="dashboard-chart-container"
|
||||||
<card describe="本月出库总计(件)" class="inner-card" size="small">
|
/>
|
||||||
<div class="dashboard-item">
|
|
||||||
<div class="dashboard-item-top">
|
|
||||||
<span>1726</span>
|
|
||||||
</div>
|
|
||||||
<div class="dashboard-item-bottom">
|
|
||||||
<div class="dashboard-item-block">
|
|
||||||
自从上周以来
|
|
||||||
<trend class="dashboard-item-trend" type="down" :is-reverse-color="false" describe="20.3%" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</card>
|
|
||||||
</t-col>
|
|
||||||
|
|
||||||
<t-col :xs="6" :xl="12">
|
|
||||||
<card describe="本月入库总计(件)" class="inner-card" size="small">
|
|
||||||
<div class="dashboard-item">
|
|
||||||
<div class="dashboard-item-top">
|
|
||||||
<span>226</span>
|
|
||||||
</div>
|
|
||||||
<div class="dashboard-item-bottom">
|
|
||||||
<div class="dashboard-item-block">
|
|
||||||
自从上周以来
|
|
||||||
<trend class="dashboard-item-trend" type="down" :is-reverse-color="false" describe="20.3%" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</card>
|
|
||||||
</t-col>
|
|
||||||
</t-row>
|
|
||||||
</card>
|
</card>
|
||||||
</t-col>
|
</t-col>
|
||||||
</t-row>
|
</t-row>
|
||||||
|
|
||||||
|
<!-- 列表排名 -->
|
||||||
|
<t-row :gutter="16" class="row-container">
|
||||||
|
<t-col :xs="12" :xl="6">
|
||||||
|
<card title="销售订单排名">
|
||||||
|
<template #option>
|
||||||
|
<t-radio-group default-value="dateVal">
|
||||||
|
<t-radio-button value="dateVal"> 月份 </t-radio-button>
|
||||||
|
<t-radio-button value="monthVal"> 季度 </t-radio-button>
|
||||||
|
</t-radio-group>
|
||||||
|
</template>
|
||||||
|
<t-table :data="SALE_TEND_LIST" :columns="SALE_COLUMNS" row-key="productName">
|
||||||
|
<template #index="{ rowIndex }">
|
||||||
|
<span :class="getRankClass(rowIndex)">
|
||||||
|
{{ rowIndex + 1 }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #growUp="{ row }">
|
||||||
|
<span>
|
||||||
|
<trend :type="row.growUp > 0 ? 'up' : 'down'" :describe="Math.abs(row.growUp)" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #operation="slotProps">
|
||||||
|
<a class="t-button-link" @click="rehandleClickOp(slotProps)">操作</a>
|
||||||
|
</template>
|
||||||
|
</t-table>
|
||||||
|
</card>
|
||||||
|
</t-col>
|
||||||
|
<t-col :xs="12" :xl="6">
|
||||||
|
<card title="采购订单排名">
|
||||||
|
<template #option>
|
||||||
|
<t-radio-group default-value="dateVal">
|
||||||
|
<t-radio-button value="dateVal"> 月份 </t-radio-button>
|
||||||
|
<t-radio-button value="monthVal"> 季度 </t-radio-button>
|
||||||
|
</t-radio-group>
|
||||||
|
</template>
|
||||||
|
<t-table :data="BUY_TEND_LIST" :columns="BUY_COLUMNS" row-key="productName">
|
||||||
|
<template #index="{ rowIndex }">
|
||||||
|
<span :class="getRankClass(rowIndex)">
|
||||||
|
{{ rowIndex + 1 }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #growUp="{ row }">
|
||||||
|
<trend :type="row.growUp > 0 ? 'up' : 'down'" :describe="Math.abs(row.growUp)" />
|
||||||
|
</template>
|
||||||
|
<template #operation="slotProps">
|
||||||
|
<a class="t-button-link" @click="rehandleClickOp(slotProps)">操作</a>
|
||||||
|
</template>
|
||||||
|
</t-table>
|
||||||
|
</card>
|
||||||
|
</t-col>
|
||||||
|
</t-row>
|
||||||
|
|
||||||
|
<!-- 出入库概览 -->
|
||||||
|
<div class="row-container overview-panel">
|
||||||
|
<t-row>
|
||||||
|
<t-col :xs="12" :xl="9">
|
||||||
|
<card title="出入库概览" describe="(件)">
|
||||||
|
<template #option>
|
||||||
|
<t-date-picker
|
||||||
|
class="card-date-picker-container"
|
||||||
|
theme="primary"
|
||||||
|
mode="date"
|
||||||
|
range
|
||||||
|
:default-value="LAST_7_DAYS"
|
||||||
|
@change="onWharehouseChange"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<div
|
||||||
|
id="stokeContainer"
|
||||||
|
ref="stokeContainer"
|
||||||
|
style="width: 100%; height: 351px"
|
||||||
|
class="dashboard-chart-container"
|
||||||
|
/>
|
||||||
|
</card>
|
||||||
|
</t-col>
|
||||||
|
<t-col :xs="12" :xl="3">
|
||||||
|
<card>
|
||||||
|
<template #option>
|
||||||
|
<t-button>导出数据</t-button>
|
||||||
|
</template>
|
||||||
|
<t-row>
|
||||||
|
<t-col :xs="6" :xl="12">
|
||||||
|
<card describe="本月出库总计(件)" class="inner-card" size="small">
|
||||||
|
<div class="dashboard-item">
|
||||||
|
<div class="dashboard-item-top">
|
||||||
|
<span>1726</span>
|
||||||
|
</div>
|
||||||
|
<div class="dashboard-item-bottom">
|
||||||
|
<div class="dashboard-item-block">
|
||||||
|
自从上周以来
|
||||||
|
<trend class="dashboard-item-trend" type="down" :is-reverse-color="false" describe="20.3%" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</card>
|
||||||
|
</t-col>
|
||||||
|
|
||||||
|
<t-col :xs="6" :xl="12">
|
||||||
|
<card describe="本月入库总计(件)" class="inner-card" size="small">
|
||||||
|
<div class="dashboard-item">
|
||||||
|
<div class="dashboard-item-top">
|
||||||
|
<span>226</span>
|
||||||
|
</div>
|
||||||
|
<div class="dashboard-item-bottom">
|
||||||
|
<div class="dashboard-item-block">
|
||||||
|
自从上周以来
|
||||||
|
<trend class="dashboard-item-trend" type="down" :is-reverse-color="false" describe="20.3%" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</card>
|
||||||
|
</t-col>
|
||||||
|
</t-row>
|
||||||
|
</card>
|
||||||
|
</t-col>
|
||||||
|
</t-row>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
@ -311,24 +312,24 @@ export default defineComponent({
|
||||||
@import '@/style/variables.less';
|
@import '@/style/variables.less';
|
||||||
|
|
||||||
.card-container.main-color {
|
.card-container.main-color {
|
||||||
background: @brand-color;
|
background: @brand-color !important;
|
||||||
color: @text-color-primary;
|
color: @text-color-primary !important;
|
||||||
|
|
||||||
.card-describe {
|
.card-describe {
|
||||||
color: @text-color-anti;
|
color: @text-color-anti !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-item-top span {
|
.dashboard-item-top span {
|
||||||
color: @text-color-anti;
|
color: @text-color-anti !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-item-block {
|
.dashboard-item-block {
|
||||||
color: @text-color-anti;
|
color: @text-color-anti !important;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-item-bottom {
|
.dashboard-item-bottom {
|
||||||
color: @text-color-anti;
|
color: @text-color-anti !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
@change="onMaterialChange"
|
@change="onMaterialChange"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div id="lineContainer" style="width: 100%; height: 416px" />
|
<div id="lineContainer" style="width: 100%; height: 406px" />
|
||||||
</card>
|
</card>
|
||||||
</t-col>
|
</t-col>
|
||||||
<t-col :xs="12" :xl="3">
|
<t-col :xs="12" :xl="3">
|
||||||
|
|
|
@ -1,96 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<card title="基本信息">
|
<div>
|
||||||
<div class="info-block">
|
<card title="基本信息">
|
||||||
<div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
|
<div class="info-block">
|
||||||
<h1>{{ item.name }}</h1>
|
|
||||||
<span
|
|
||||||
:class="{
|
|
||||||
['inProgress']: item.type && item.type.value === 'inProgress',
|
|
||||||
['pdf']: item.type && item.type.value === 'pdf',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<i v-if="item.type && item.type.key === 'contractStatus'" />
|
|
||||||
{{ item.value }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</card>
|
|
||||||
|
|
||||||
<!-- 发票进度 -->
|
|
||||||
<card title="发票进度" class="container-base-margin-top">
|
|
||||||
<t-row justify="space-between">
|
|
||||||
<t-steps :current="updateCurrent">
|
|
||||||
<t-step-item title="申请提交" content="已于12月21日提交" />
|
|
||||||
<t-step-item title="电子发票" content="预计1~3个工作日" />
|
|
||||||
<t-step-item title="发票已邮寄" content="电子发票开出后7个工作日联系" />
|
|
||||||
<t-step-item title="完成" content />
|
|
||||||
</t-steps>
|
|
||||||
</t-row>
|
|
||||||
</card>
|
|
||||||
|
|
||||||
<!-- 产品目录 -->
|
|
||||||
<card title="产品目录" class="container-base-margin-top">
|
|
||||||
<template #option>
|
|
||||||
<t-radio-group default-value="dateVal">
|
|
||||||
<t-radio-button value="dateVal"> 季度 </t-radio-button>
|
|
||||||
<t-radio-button value="monthVal"> 月份 </t-radio-button>
|
|
||||||
</t-radio-group>
|
|
||||||
</template>
|
|
||||||
<t-row class="product-block-container">
|
|
||||||
<t-col :flex="1">
|
|
||||||
<div class="product-add">
|
|
||||||
<div class="product-sub">
|
|
||||||
<t-icon name="add" class="product-sub-icon" />
|
|
||||||
<span>新增产品</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</t-col>
|
|
||||||
<t-col v-for="(item, index) in PRODUCT_LIST" :key="index" :flex="1">
|
|
||||||
<product :data="item" />
|
|
||||||
</t-col>
|
|
||||||
</t-row>
|
|
||||||
</card>
|
|
||||||
|
|
||||||
<!-- 产品采购明细 -->
|
|
||||||
<card title="产品采购明细" class="container-base-margin-top">
|
|
||||||
<t-table
|
|
||||||
:columns="columns"
|
|
||||||
:data="data"
|
|
||||||
:pagination="pagination"
|
|
||||||
:hover="true"
|
|
||||||
row-key="index"
|
|
||||||
size="large"
|
|
||||||
@sort-change="sortChange"
|
|
||||||
@change="rehandleChange"
|
|
||||||
>
|
|
||||||
<template #pdName="{ row }">
|
|
||||||
<span>
|
|
||||||
{{ row.pdName }}
|
|
||||||
<t-tag v-if="row.pdType" size="small">{{ row.pdType }}</t-tag>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #purchaseNum="{ row }">
|
|
||||||
<span>
|
|
||||||
{{ row.purchaseNum }}
|
|
||||||
<t-tag v-if="row.purchaseNum > 50" theme="danger" variant="light" size="small">超预算</t-tag>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #op="slotProps">
|
|
||||||
<a :class="PREFIX + '-link'" @click="listClick()">管理</a>
|
|
||||||
<a :class="PREFIX + '-link'" @click="deleteClickOp(slotProps)">删除</a>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #op-column>
|
|
||||||
<t-icon name="descending-order" />
|
|
||||||
</template>
|
|
||||||
</t-table>
|
|
||||||
</card>
|
|
||||||
|
|
||||||
<t-dialog v-model:visible="visible" header="基本信息" @confirm="onConfirm">
|
|
||||||
<template #body>
|
|
||||||
<div class="dialog-info-block">
|
|
||||||
<div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
|
<div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
|
||||||
<h1>{{ item.name }}</h1>
|
<h1>{{ item.name }}</h1>
|
||||||
<span
|
<span
|
||||||
|
@ -104,8 +15,99 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</card>
|
||||||
</t-dialog>
|
|
||||||
|
<!-- 发票进度 -->
|
||||||
|
<card title="发票进度" class="container-base-margin-top">
|
||||||
|
<t-row justify="space-between">
|
||||||
|
<t-steps :current="updateCurrent">
|
||||||
|
<t-step-item title="申请提交" content="已于12月21日提交" />
|
||||||
|
<t-step-item title="电子发票" content="预计1~3个工作日" />
|
||||||
|
<t-step-item title="发票已邮寄" content="电子发票开出后7个工作日联系" />
|
||||||
|
<t-step-item title="完成" content />
|
||||||
|
</t-steps>
|
||||||
|
</t-row>
|
||||||
|
</card>
|
||||||
|
|
||||||
|
<!-- 产品目录 -->
|
||||||
|
<card title="产品目录" class="container-base-margin-top">
|
||||||
|
<template #option>
|
||||||
|
<t-radio-group default-value="dateVal">
|
||||||
|
<t-radio-button value="dateVal"> 季度 </t-radio-button>
|
||||||
|
<t-radio-button value="monthVal"> 月份 </t-radio-button>
|
||||||
|
</t-radio-group>
|
||||||
|
</template>
|
||||||
|
<t-row class="product-block-container">
|
||||||
|
<t-col :flex="1">
|
||||||
|
<div class="product-add">
|
||||||
|
<div class="product-sub">
|
||||||
|
<t-icon name="add" class="product-sub-icon" />
|
||||||
|
<span>新增产品</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</t-col>
|
||||||
|
<t-col v-for="(item, index) in PRODUCT_LIST" :key="index" :flex="1">
|
||||||
|
<product :data="item" />
|
||||||
|
</t-col>
|
||||||
|
</t-row>
|
||||||
|
</card>
|
||||||
|
|
||||||
|
<!-- 产品采购明细 -->
|
||||||
|
<card title="产品采购明细" class="container-base-margin-top">
|
||||||
|
<t-table
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:pagination="pagination"
|
||||||
|
:hover="true"
|
||||||
|
row-key="index"
|
||||||
|
size="large"
|
||||||
|
@sort-change="sortChange"
|
||||||
|
@change="rehandleChange"
|
||||||
|
>
|
||||||
|
<template #pdName="{ row }">
|
||||||
|
<span>
|
||||||
|
{{ row.pdName }}
|
||||||
|
<t-tag v-if="row.pdType" size="small">{{ row.pdType }}</t-tag>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #purchaseNum="{ row }">
|
||||||
|
<span>
|
||||||
|
{{ row.purchaseNum }}
|
||||||
|
<t-tag v-if="row.purchaseNum > 50" theme="danger" variant="light" size="small">超预算</t-tag>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #op="slotProps">
|
||||||
|
<a :class="PREFIX + '-link'" @click="listClick()">管理</a>
|
||||||
|
<a :class="PREFIX + '-link'" @click="deleteClickOp(slotProps)">删除</a>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #op-column>
|
||||||
|
<t-icon name="descending-order" />
|
||||||
|
</template>
|
||||||
|
</t-table>
|
||||||
|
</card>
|
||||||
|
|
||||||
|
<t-dialog v-model:visible="visible" header="基本信息" @confirm="onConfirm">
|
||||||
|
<template #body>
|
||||||
|
<div class="dialog-info-block">
|
||||||
|
<div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
|
||||||
|
<h1>{{ item.name }}</h1>
|
||||||
|
<span
|
||||||
|
:class="{
|
||||||
|
['inProgress']: item.type && item.type.value === 'inProgress',
|
||||||
|
['pdf']: item.type && item.type.value === 'pdf',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<i v-if="item.type && item.type.key === 'contractStatus'" />
|
||||||
|
{{ item.value }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</t-dialog>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, onMounted } from 'vue';
|
import { defineComponent, ref, onMounted } from 'vue';
|
||||||
|
|
|
@ -1,28 +1,30 @@
|
||||||
<template>
|
<template>
|
||||||
<card title="基本信息">
|
<div>
|
||||||
<div class="info-block">
|
<card title="基本信息">
|
||||||
<div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
|
<div class="info-block">
|
||||||
<h1>{{ item.name }}</h1>
|
<div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
|
||||||
<span
|
<h1>{{ item.name }}</h1>
|
||||||
:class="{
|
<span
|
||||||
['inProgress']: item.type && item.type.value === 'inProgress',
|
:class="{
|
||||||
['pdf']: item.type && item.type.value === 'pdf',
|
['inProgress']: item.type && item.type.value === 'inProgress',
|
||||||
}"
|
['pdf']: item.type && item.type.value === 'pdf',
|
||||||
>
|
}"
|
||||||
<i v-if="item.type && item.type.key === 'contractStatus'" />
|
>
|
||||||
{{ item.value }}
|
<i v-if="item.type && item.type.key === 'contractStatus'" />
|
||||||
</span>
|
{{ item.value }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</card>
|
||||||
</card>
|
|
||||||
|
|
||||||
<card title="变更记录">
|
<card title="变更记录" class="container-base-margin-top">
|
||||||
<t-steps class="detail-base-info-steps" layout="vertical" theme="dot" :current="1">
|
<t-steps class="detail-base-info-steps" layout="vertical" theme="dot" :current="1">
|
||||||
<t-step-item title="上传合同附件" content="这里是提示文字" />
|
<t-step-item title="上传合同附件" content="这里是提示文字" />
|
||||||
<t-step-item title="修改合同金额" content="这里是提示文字" />
|
<t-step-item title="修改合同金额" content="这里是提示文字" />
|
||||||
<t-step-item title="新建合同" content="2020-12-01 15:00:00 管理员-李川操作" />
|
<t-step-item title="新建合同" content="2020-12-01 15:00:00 管理员-李川操作" />
|
||||||
</t-steps>
|
</t-steps>
|
||||||
</card>
|
</card>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
|
|
@ -1,70 +1,72 @@
|
||||||
<template>
|
<template>
|
||||||
<t-row :gutter="16">
|
<div>
|
||||||
<t-col :span="6">
|
<t-row :gutter="16">
|
||||||
<card title="部署趋势">
|
<t-col :span="6">
|
||||||
<div class="deploy-panel-left">
|
<card title="部署趋势">
|
||||||
<div id="monitorContainer" style="width: 100%; height: 265px" />
|
<div class="deploy-panel-left">
|
||||||
</div>
|
<div id="monitorContainer" style="width: 100%; height: 265px" />
|
||||||
</card>
|
</div>
|
||||||
</t-col>
|
</card>
|
||||||
<t-col :span="6">
|
</t-col>
|
||||||
<card title="告警情况">
|
<t-col :span="6">
|
||||||
<template #option>
|
<card title="告警情况">
|
||||||
<t-radio-group default-value="dateVal" @change="onAlertChange">
|
<template #option>
|
||||||
<t-radio-button value="dateVal"> 本周 </t-radio-button>
|
<t-radio-group default-value="dateVal" @change="onAlertChange">
|
||||||
<t-radio-button value="monthVal"> 本月 </t-radio-button>
|
<t-radio-button value="dateVal"> 本周 </t-radio-button>
|
||||||
</t-radio-group>
|
<t-radio-button value="monthVal"> 本月 </t-radio-button>
|
||||||
|
</t-radio-group>
|
||||||
|
</template>
|
||||||
|
<div id="dataContainer" style="width: 100%; height: 265px" />
|
||||||
|
</card>
|
||||||
|
</t-col>
|
||||||
|
</t-row>
|
||||||
|
|
||||||
|
<!-- 项目列表 -->
|
||||||
|
<card title="项目列表" class="container-base-margin-top">
|
||||||
|
<t-table
|
||||||
|
:columns="columns"
|
||||||
|
:data="data"
|
||||||
|
:pagination="pagination"
|
||||||
|
:hover="true"
|
||||||
|
row-key="index"
|
||||||
|
@sort-change="sortChange"
|
||||||
|
@change="rehandleChange"
|
||||||
|
>
|
||||||
|
<template #adminName="{ row }">
|
||||||
|
<span>
|
||||||
|
{{ row.adminName }}
|
||||||
|
<t-tag v-if="row.adminPhone" size="small">{{ row.adminPhone }}</t-tag>
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<div id="dataContainer" style="width: 100%; height: 265px" />
|
<template #op="slotProps">
|
||||||
</card>
|
<a :class="PREFIX + '-link'" @click="listClick()">管理</a>
|
||||||
</t-col>
|
<a :class="PREFIX + '-link'" @click="deleteClickOp(slotProps)">删除</a>
|
||||||
</t-row>
|
</template>
|
||||||
|
<template #op-column>
|
||||||
|
<t-icon name="descending-order" />
|
||||||
|
</template>
|
||||||
|
</t-table>
|
||||||
|
</card>
|
||||||
|
|
||||||
<!-- 项目列表 -->
|
<t-dialog v-model:visible="visible" header="基本信息" @confirm="onConfirm">
|
||||||
<card title="项目列表" class="container-base-margin-top">
|
<template #body>
|
||||||
<t-table
|
|
||||||
:columns="columns"
|
|
||||||
:data="data"
|
|
||||||
:pagination="pagination"
|
|
||||||
:hover="true"
|
|
||||||
row-key="index"
|
|
||||||
@sort-change="sortChange"
|
|
||||||
@change="rehandleChange"
|
|
||||||
>
|
|
||||||
<template #adminName="{ row }">
|
|
||||||
<span>
|
|
||||||
{{ row.adminName }}
|
|
||||||
<t-tag v-if="row.adminPhone" size="small">{{ row.adminPhone }}</t-tag>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #op="slotProps">
|
|
||||||
<a :class="PREFIX + '-link'" @click="listClick()">管理</a>
|
|
||||||
<a :class="PREFIX + '-link'" @click="deleteClickOp(slotProps)">删除</a>
|
|
||||||
</template>
|
|
||||||
<template #op-column>
|
|
||||||
<t-icon name="descending-order" />
|
|
||||||
</template>
|
|
||||||
</t-table>
|
|
||||||
</card>
|
|
||||||
|
|
||||||
<t-dialog v-model:visible="visible" header="基本信息" @confirm="onConfirm">
|
|
||||||
<template #body>
|
|
||||||
<div class="dialog-info-block">
|
|
||||||
<div class="dialog-info-block">
|
<div class="dialog-info-block">
|
||||||
<div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
|
<div class="dialog-info-block">
|
||||||
<h1>{{ item.name }}</h1>
|
<div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
|
||||||
<span
|
<h1>{{ item.name }}</h1>
|
||||||
:class="{
|
<span
|
||||||
['green']: item.type && item.type.value === 'green',
|
:class="{
|
||||||
['blue']: item.type && item.type.value === 'blue',
|
['green']: item.type && item.type.value === 'green',
|
||||||
}"
|
['blue']: item.type && item.type.value === 'blue',
|
||||||
>{{ item.value }}</span
|
}"
|
||||||
>
|
>{{ item.value }}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
</t-dialog>
|
||||||
</t-dialog>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, onMounted, onUnmounted, ref, watch } from 'vue';
|
import { defineComponent, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||||
|
|
|
@ -1,51 +1,53 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="secondary-notification">
|
<div>
|
||||||
<t-tabs v-model="tabValue">
|
<div class="secondary-notification">
|
||||||
<t-tab-panel v-for="(tab, tabIndex) in TAB_LIST" :key="tabIndex" :value="tab.value" :label="tab.label">
|
<t-tabs v-model="tabValue">
|
||||||
<t-list v-if="msgDataList.length > 0" class="secondary-msg-list" :split="true">
|
<t-tab-panel v-for="(tab, tabIndex) in TAB_LIST" :key="tabIndex" :value="tab.value" :label="tab.label">
|
||||||
<t-list-item v-for="(item, index) in msgDataList" :key="index">
|
<t-list v-if="msgDataList.length > 0" class="secondary-msg-list" :split="true">
|
||||||
<p :class="['content', { unread: item.status }]" @click="setReadStatus(item)">
|
<t-list-item v-for="(item, index) in msgDataList" :key="index">
|
||||||
<t-tag size="small" :theme="NOTIFICATION_TYPES[item.quality]" variant="light">
|
<p :class="['content', { unread: item.status }]" @click="setReadStatus(item)">
|
||||||
{{ item.type }}
|
<t-tag size="small" :theme="NOTIFICATION_TYPES[item.quality]" variant="light">
|
||||||
</t-tag>
|
{{ item.type }}
|
||||||
{{ item.content }}
|
</t-tag>
|
||||||
</p>
|
{{ item.content }}
|
||||||
<template #action>
|
</p>
|
||||||
<span class="msg-date">{{ item.date }}</span>
|
<template #action>
|
||||||
|
<span class="msg-date">{{ item.date }}</span>
|
||||||
|
|
||||||
<div class="msg-action">
|
<div class="msg-action">
|
||||||
<t-tooltip
|
<t-tooltip
|
||||||
class="set-read-icon"
|
class="set-read-icon"
|
||||||
:overlay-style="{ margin: '6px' }"
|
:overlay-style="{ margin: '6px' }"
|
||||||
:content="item.status ? '设为已读' : '设为未读'"
|
:content="item.status ? '设为已读' : '设为未读'"
|
||||||
>
|
>
|
||||||
<span class="msg-action-icon" @click="setReadStatus(item)">
|
<span class="msg-action-icon" @click="setReadStatus(item)">
|
||||||
<t-icon v-if="!!item.status" name="queue" size="16px" />
|
<t-icon v-if="!!item.status" name="queue" size="16px" />
|
||||||
<t-icon v-else name="chat" />
|
<t-icon v-else name="chat" />
|
||||||
</span>
|
</span>
|
||||||
</t-tooltip>
|
</t-tooltip>
|
||||||
<t-tooltip content="删除通知" :overlay-style="{ margin: '6px' }">
|
<t-tooltip content="删除通知" :overlay-style="{ margin: '6px' }">
|
||||||
<span @click="handleClickDeleteBtn(item)">
|
<span @click="handleClickDeleteBtn(item)">
|
||||||
<t-icon name="delete" size="16px" />
|
<t-icon name="delete" size="16px" />
|
||||||
</span>
|
</span>
|
||||||
</t-tooltip>
|
</t-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</t-list-item>
|
</t-list-item>
|
||||||
</t-list>
|
</t-list>
|
||||||
<div v-else class="secondary-msg-list__empty-list">
|
<div v-else class="secondary-msg-list__empty-list">
|
||||||
<img src="https://tdesign.gtimg.com/pro-template/personal/nothing.png" alt="空" />
|
<img src="https://tdesign.gtimg.com/pro-template/personal/nothing.png" alt="空" />
|
||||||
<p>暂无通知</p>
|
<p>暂无通知</p>
|
||||||
</div>
|
</div>
|
||||||
</t-tab-panel>
|
</t-tab-panel>
|
||||||
</t-tabs>
|
</t-tabs>
|
||||||
|
</div>
|
||||||
|
<t-dialog
|
||||||
|
v-model:visible="visible"
|
||||||
|
header="删除通知"
|
||||||
|
:body="`确认删除通知:${selectedItem && selectedItem.content}吗?`"
|
||||||
|
:on-confirm="deleteMsg"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<t-dialog
|
|
||||||
v-model:visible="visible"
|
|
||||||
header="删除通知"
|
|
||||||
:body="`确认删除通知:${selectedItem && selectedItem.content}吗?`"
|
|
||||||
:on-confirm="deleteMsg"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, computed, ComputedRef } from 'vue';
|
import { defineComponent, ref, computed, ComputedRef } from 'vue';
|
||||||
|
|
|
@ -1,162 +1,174 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="form-basic-container">
|
<div>
|
||||||
<div class="form-basic-item">
|
<div class="form-basic-container">
|
||||||
<div class="form-basic-container-title">合同信息</div>
|
<div class="form-basic-item">
|
||||||
<!-- 表单内容 -->
|
<div class="form-basic-container-title">合同信息</div>
|
||||||
<t-form
|
<!-- 表单内容 -->
|
||||||
ref="form"
|
<t-form
|
||||||
class="base-form"
|
ref="form"
|
||||||
:data="formData"
|
class="base-form"
|
||||||
:rules="FORM_RULES"
|
:data="formData"
|
||||||
label-align="top"
|
:rules="FORM_RULES"
|
||||||
:label-width="100"
|
label-align="top"
|
||||||
@reset="onReset"
|
:label-width="100"
|
||||||
@submit="onSubmit"
|
@reset="onReset"
|
||||||
>
|
@submit="onSubmit"
|
||||||
<!-- 合同名称,合同类型 -->
|
|
||||||
<t-row class="row-gap" :gutter="[16, 24]">
|
|
||||||
<t-col :span="6">
|
|
||||||
<t-form-item label="合同名称" name="name">
|
|
||||||
<t-input v-model="formData.name" :style="{ width: '322px' }" placeholder="请输入内容" />
|
|
||||||
</t-form-item>
|
|
||||||
</t-col>
|
|
||||||
<t-col :span="6">
|
|
||||||
<t-form-item label="合同类型" name="type">
|
|
||||||
<t-select
|
|
||||||
v-model="formData.type"
|
|
||||||
:style="{ width: '322px' }"
|
|
||||||
placeholder="请选择类型"
|
|
||||||
class="demo-select-base"
|
|
||||||
clearable
|
|
||||||
>
|
|
||||||
<t-option v-for="(item, index) in TYPE_OPTIONS" :key="index" :value="item.value" :label="item.label">
|
|
||||||
{{ item.label }}
|
|
||||||
</t-option>
|
|
||||||
</t-select>
|
|
||||||
</t-form-item>
|
|
||||||
</t-col>
|
|
||||||
|
|
||||||
<!-- 合同收付类型 -->
|
|
||||||
<t-col :span="8">
|
|
||||||
<t-form-item label="合同收付类型" name="payment">
|
|
||||||
<t-radio-group v-model="formData.payment">
|
|
||||||
<t-radio value="1"> 收款 </t-radio>
|
|
||||||
<t-radio value="2"> 付款 </t-radio>
|
|
||||||
</t-radio-group>
|
|
||||||
<span class="space-item" />
|
|
||||||
<t-input placeholder="请输入金额" :style="{ width: '160px' }" />
|
|
||||||
</t-form-item>
|
|
||||||
</t-col>
|
|
||||||
|
|
||||||
<t-col :span="6">
|
|
||||||
<t-form-item label="甲方" name="partyA">
|
|
||||||
<t-select
|
|
||||||
v-model="formData.partyA"
|
|
||||||
:style="{ width: '322px' }"
|
|
||||||
class="demo-select-base"
|
|
||||||
placeholder="请选择类型"
|
|
||||||
clearable
|
|
||||||
>
|
|
||||||
<t-option v-for="(item, index) in PARTY_A_OPTIONS" :key="index" :value="item.value" :label="item.label">
|
|
||||||
{{ item.label }}
|
|
||||||
</t-option>
|
|
||||||
</t-select>
|
|
||||||
</t-form-item>
|
|
||||||
</t-col>
|
|
||||||
<t-col :span="6">
|
|
||||||
<t-form-item label="乙方" name="partyB">
|
|
||||||
<t-select
|
|
||||||
v-model="formData.partyB"
|
|
||||||
:style="{ width: '322px' }"
|
|
||||||
placeholder="请选择类型"
|
|
||||||
class="demo-select-base"
|
|
||||||
clearable
|
|
||||||
>
|
|
||||||
<t-option v-for="(item, index) in PARTY_B_OPTIONS" :key="index" :value="item.value" :label="item.label">
|
|
||||||
{{ item.label }}
|
|
||||||
</t-option>
|
|
||||||
</t-select>
|
|
||||||
</t-form-item>
|
|
||||||
</t-col>
|
|
||||||
<t-col :span="6">
|
|
||||||
<t-form-item label="合同签订日期" name="signDate">
|
|
||||||
<t-date-picker
|
|
||||||
v-model="formData.signDate"
|
|
||||||
:style="{ width: '322px' }"
|
|
||||||
theme="primary"
|
|
||||||
mode="date"
|
|
||||||
separator="/"
|
|
||||||
/>
|
|
||||||
</t-form-item>
|
|
||||||
</t-col>
|
|
||||||
<t-col :span="6">
|
|
||||||
<t-form-item label="合同生效日期" name="startDate">
|
|
||||||
<t-date-picker
|
|
||||||
v-model="formData.startDate"
|
|
||||||
:style="{ width: '322px' }"
|
|
||||||
theme="primary"
|
|
||||||
mode="date"
|
|
||||||
separator="/"
|
|
||||||
/>
|
|
||||||
</t-form-item>
|
|
||||||
</t-col>
|
|
||||||
<t-col :span="6">
|
|
||||||
<t-form-item label="合同结束日期" name="endDate">
|
|
||||||
<t-date-picker
|
|
||||||
v-model="formData.endDate"
|
|
||||||
:style="{ width: '322px' }"
|
|
||||||
theme="primary"
|
|
||||||
mode="date"
|
|
||||||
separator="/"
|
|
||||||
/>
|
|
||||||
</t-form-item>
|
|
||||||
</t-col>
|
|
||||||
</t-row>
|
|
||||||
</t-form>
|
|
||||||
|
|
||||||
<div class="form-basic-container-title form-title-gap">其它信息</div>
|
|
||||||
<t-form
|
|
||||||
ref="form"
|
|
||||||
class="base-form"
|
|
||||||
:data="formData"
|
|
||||||
:rules="FORM_RULES"
|
|
||||||
label-align="top"
|
|
||||||
:label-width="100"
|
|
||||||
@reset="onReset"
|
|
||||||
@submit="onSubmit"
|
|
||||||
>
|
|
||||||
<t-form-item label="备注" name="comment">
|
|
||||||
<t-textarea v-model="formData.comment" :height="124" placeholder="请输入备注" />
|
|
||||||
</t-form-item>
|
|
||||||
<t-form-item label="公证人">
|
|
||||||
<t-avatar-group>
|
|
||||||
<t-avatar>D</t-avatar>
|
|
||||||
<t-avatar>S</t-avatar>
|
|
||||||
<t-avatar>+</t-avatar>
|
|
||||||
</t-avatar-group>
|
|
||||||
</t-form-item>
|
|
||||||
</t-form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-submit-container">
|
|
||||||
<div class="form-submit-sub">
|
|
||||||
<div class="form-submit-left">
|
|
||||||
<t-upload
|
|
||||||
v-model="files"
|
|
||||||
action=""
|
|
||||||
placeholder="支持批量上传文件,文 件格式不限,最多只能上传 10 份文件"
|
|
||||||
:format-response="formatResponse"
|
|
||||||
:before-upload="beforeUpload"
|
|
||||||
@fail="handleFail"
|
|
||||||
>
|
>
|
||||||
<t-button class="form-submit-upload-btn" variant="outline"> 上传合同文件 </t-button>
|
<!-- 合同名称,合同类型 -->
|
||||||
</t-upload>
|
<t-row class="row-gap" :gutter="[16, 24]">
|
||||||
<span class="form-submit-upload-span">请上传pdf文件,大小在60M以内</span>
|
<t-col :span="6">
|
||||||
|
<t-form-item label="合同名称" name="name">
|
||||||
|
<t-input v-model="formData.name" :style="{ width: '322px' }" placeholder="请输入内容" />
|
||||||
|
</t-form-item>
|
||||||
|
</t-col>
|
||||||
|
<t-col :span="6">
|
||||||
|
<t-form-item label="合同类型" name="type">
|
||||||
|
<t-select
|
||||||
|
v-model="formData.type"
|
||||||
|
:style="{ width: '322px' }"
|
||||||
|
placeholder="请选择类型"
|
||||||
|
class="demo-select-base"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<t-option v-for="(item, index) in TYPE_OPTIONS" :key="index" :value="item.value" :label="item.label">
|
||||||
|
{{ item.label }}
|
||||||
|
</t-option>
|
||||||
|
</t-select>
|
||||||
|
</t-form-item>
|
||||||
|
</t-col>
|
||||||
|
|
||||||
|
<!-- 合同收付类型 -->
|
||||||
|
<t-col :span="8">
|
||||||
|
<t-form-item label="合同收付类型" name="payment">
|
||||||
|
<t-radio-group v-model="formData.payment">
|
||||||
|
<t-radio value="1"> 收款 </t-radio>
|
||||||
|
<t-radio value="2"> 付款 </t-radio>
|
||||||
|
</t-radio-group>
|
||||||
|
<span class="space-item" />
|
||||||
|
<t-input placeholder="请输入金额" :style="{ width: '160px' }" />
|
||||||
|
</t-form-item>
|
||||||
|
</t-col>
|
||||||
|
|
||||||
|
<t-col :span="6">
|
||||||
|
<t-form-item label="甲方" name="partyA">
|
||||||
|
<t-select
|
||||||
|
v-model="formData.partyA"
|
||||||
|
:style="{ width: '322px' }"
|
||||||
|
class="demo-select-base"
|
||||||
|
placeholder="请选择类型"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<t-option
|
||||||
|
v-for="(item, index) in PARTY_A_OPTIONS"
|
||||||
|
:key="index"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</t-option>
|
||||||
|
</t-select>
|
||||||
|
</t-form-item>
|
||||||
|
</t-col>
|
||||||
|
<t-col :span="6">
|
||||||
|
<t-form-item label="乙方" name="partyB">
|
||||||
|
<t-select
|
||||||
|
v-model="formData.partyB"
|
||||||
|
:style="{ width: '322px' }"
|
||||||
|
placeholder="请选择类型"
|
||||||
|
class="demo-select-base"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<t-option
|
||||||
|
v-for="(item, index) in PARTY_B_OPTIONS"
|
||||||
|
:key="index"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</t-option>
|
||||||
|
</t-select>
|
||||||
|
</t-form-item>
|
||||||
|
</t-col>
|
||||||
|
<t-col :span="6">
|
||||||
|
<t-form-item label="合同签订日期" name="signDate">
|
||||||
|
<t-date-picker
|
||||||
|
v-model="formData.signDate"
|
||||||
|
:style="{ width: '322px' }"
|
||||||
|
theme="primary"
|
||||||
|
mode="date"
|
||||||
|
separator="/"
|
||||||
|
/>
|
||||||
|
</t-form-item>
|
||||||
|
</t-col>
|
||||||
|
<t-col :span="6">
|
||||||
|
<t-form-item label="合同生效日期" name="startDate">
|
||||||
|
<t-date-picker
|
||||||
|
v-model="formData.startDate"
|
||||||
|
:style="{ width: '322px' }"
|
||||||
|
theme="primary"
|
||||||
|
mode="date"
|
||||||
|
separator="/"
|
||||||
|
/>
|
||||||
|
</t-form-item>
|
||||||
|
</t-col>
|
||||||
|
<t-col :span="6">
|
||||||
|
<t-form-item label="合同结束日期" name="endDate">
|
||||||
|
<t-date-picker
|
||||||
|
v-model="formData.endDate"
|
||||||
|
:style="{ width: '322px' }"
|
||||||
|
theme="primary"
|
||||||
|
mode="date"
|
||||||
|
separator="/"
|
||||||
|
/>
|
||||||
|
</t-form-item>
|
||||||
|
</t-col>
|
||||||
|
</t-row>
|
||||||
|
</t-form>
|
||||||
|
|
||||||
|
<div class="form-basic-container-title form-title-gap">其它信息</div>
|
||||||
|
<t-form
|
||||||
|
ref="form"
|
||||||
|
class="base-form"
|
||||||
|
:data="formData"
|
||||||
|
:rules="FORM_RULES"
|
||||||
|
label-align="top"
|
||||||
|
:label-width="100"
|
||||||
|
@reset="onReset"
|
||||||
|
@submit="onSubmit"
|
||||||
|
>
|
||||||
|
<t-form-item label="备注" name="comment">
|
||||||
|
<t-textarea v-model="formData.comment" :height="124" placeholder="请输入备注" />
|
||||||
|
</t-form-item>
|
||||||
|
<t-form-item label="公证人">
|
||||||
|
<t-avatar-group>
|
||||||
|
<t-avatar>D</t-avatar>
|
||||||
|
<t-avatar>S</t-avatar>
|
||||||
|
<t-avatar>+</t-avatar>
|
||||||
|
</t-avatar-group>
|
||||||
|
</t-form-item>
|
||||||
|
</t-form>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-submit-right">
|
</div>
|
||||||
<t-button type="reset" class="form-submit-cancel" theme="default" variant="base"> 取消 </t-button>
|
|
||||||
<t-button theme="primary" class="form-submit-confirm" type="submit"> 提交 </t-button>
|
<div class="form-submit-container">
|
||||||
|
<div class="form-submit-sub">
|
||||||
|
<div class="form-submit-left">
|
||||||
|
<t-upload
|
||||||
|
v-model="files"
|
||||||
|
action=""
|
||||||
|
placeholder="支持批量上传文件,文 件格式不限,最多只能上传 10 份文件"
|
||||||
|
:format-response="formatResponse"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
@fail="handleFail"
|
||||||
|
>
|
||||||
|
<t-button class="form-submit-upload-btn" variant="outline"> 上传合同文件 </t-button>
|
||||||
|
</t-upload>
|
||||||
|
<span class="form-submit-upload-span">请上传pdf文件,大小在60M以内</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-submit-right">
|
||||||
|
<t-button type="reset" class="form-submit-cancel" theme="default" variant="base"> 取消 </t-button>
|
||||||
|
<t-button theme="primary" class="form-submit-confirm" type="submit"> 提交 </t-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,138 +1,140 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="form-step-container">
|
<div>
|
||||||
<!-- 简单步骤条 -->
|
<div class="form-step-container">
|
||||||
<card title="基本信息">
|
<!-- 简单步骤条 -->
|
||||||
<t-steps class="step-container" :current="activeForm" status="process">
|
<card title="基本信息">
|
||||||
<t-step-item title="提交开票申请" />
|
<t-steps class="step-container" :current="activeForm" status="process">
|
||||||
<t-step-item title="填写发票信息" />
|
<t-step-item title="提交开票申请" />
|
||||||
<t-step-item title="确认邮寄地址" />
|
<t-step-item title="填写发票信息" />
|
||||||
<t-step-item title="完成" />
|
<t-step-item title="确认邮寄地址" />
|
||||||
</t-steps>
|
<t-step-item title="完成" />
|
||||||
</card>
|
</t-steps>
|
||||||
|
</card>
|
||||||
|
|
||||||
<!-- 分步表单1 -->
|
<!-- 分步表单1 -->
|
||||||
<div v-show="activeForm === 0" class="rule-tips">
|
<div v-show="activeForm === 0" class="rule-tips">
|
||||||
<t-alert theme="info" title="发票开具规则:" :close="true">
|
<t-alert theme="info" title="发票开具规则:" :close="true">
|
||||||
<template #message>
|
<template #message>
|
||||||
<p>
|
<p>
|
||||||
1、申请开票后,电子发票在1~3个工作日内开具;增值税专用发票(纸质)如资质审核通过,将在电子发票开具后10个工作日内为您寄出;
|
1、申请开票后,电子发票在1~3个工作日内开具;增值税专用发票(纸质)如资质审核通过,将在电子发票开具后10个工作日内为您寄出;
|
||||||
</p>
|
</p>
|
||||||
<p>2、开票金额为您实际支付金额;</p>
|
<p>2、开票金额为您实际支付金额;</p>
|
||||||
<p>3、如有疑问请直接联系:13300001111。</p>
|
<p>3、如有疑问请直接联系:13300001111。</p>
|
||||||
</template>
|
</template>
|
||||||
</t-alert>
|
</t-alert>
|
||||||
</div>
|
</div>
|
||||||
<t-form
|
<t-form
|
||||||
v-show="activeForm === 0"
|
v-show="activeForm === 0"
|
||||||
class="step-form"
|
class="step-form"
|
||||||
:data="formData1"
|
:data="formData1"
|
||||||
:rules="FORM_RULES"
|
:rules="FORM_RULES"
|
||||||
label-align="right"
|
label-align="right"
|
||||||
@submit="(result) => onSubmit(result, 1)"
|
@submit="(result) => onSubmit(result, 1)"
|
||||||
>
|
>
|
||||||
<t-form-item label="合同名称" name="name">
|
<t-form-item label="合同名称" name="name">
|
||||||
<t-select v-model="formData1.name" :style="{ width: '480px' }" class="demo-select-base" clearable>
|
<t-select v-model="formData1.name" :style="{ width: '480px' }" class="demo-select-base" clearable>
|
||||||
<t-option v-for="(item, index) in NAME_OPTIONS" :key="index" :value="item.value" :label="item.label">
|
<t-option v-for="(item, index) in NAME_OPTIONS" :key="index" :value="item.value" :label="item.label">
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</t-option>
|
</t-option>
|
||||||
</t-select>
|
</t-select>
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="发票类型" name="type">
|
<t-form-item label="发票类型" name="type">
|
||||||
<t-select v-model="formData1.type" :style="{ width: '480px' }" class="demo-select-base" clearable>
|
<t-select v-model="formData1.type" :style="{ width: '480px' }" class="demo-select-base" clearable>
|
||||||
<t-option v-for="(item, index) in TYPE_OPTIONS" :key="index" :value="item.value" :label="item.label">
|
<t-option v-for="(item, index) in TYPE_OPTIONS" :key="index" :value="item.value" :label="item.label">
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</t-option>
|
</t-option>
|
||||||
</t-select>
|
</t-select>
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="开票金额"> {{ amount }} 元 </t-form-item>
|
<t-form-item label="开票金额"> {{ amount }} 元 </t-form-item>
|
||||||
<t-form-item>
|
<t-form-item>
|
||||||
<t-button theme="primary" type="submit"> 提交申请 </t-button>
|
<t-button theme="primary" type="submit"> 提交申请 </t-button>
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
</t-form>
|
</t-form>
|
||||||
|
|
||||||
<!-- 分步表单2 -->
|
<!-- 分步表单2 -->
|
||||||
<t-form
|
<t-form
|
||||||
v-show="activeForm === 1"
|
v-show="activeForm === 1"
|
||||||
class="step-form"
|
class="step-form"
|
||||||
:data="formData2"
|
:data="formData2"
|
||||||
:rules="FORM_RULES"
|
:rules="FORM_RULES"
|
||||||
label-align="left"
|
label-align="left"
|
||||||
@reset="onReset(0)"
|
@reset="onReset(0)"
|
||||||
@submit="(result) => onSubmit(result, 2)"
|
@submit="(result) => onSubmit(result, 2)"
|
||||||
>
|
>
|
||||||
<t-form-item label="发票抬头" name="title">
|
<t-form-item label="发票抬头" name="title">
|
||||||
<t-input v-model="formData2.title" :style="{ width: '480px' }" placeholder="请输入发票抬头" />
|
<t-input v-model="formData2.title" :style="{ width: '480px' }" placeholder="请输入发票抬头" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="纳税人识别号" name="taxNum">
|
<t-form-item label="纳税人识别号" name="taxNum">
|
||||||
<t-input v-model="formData2.taxNum" :style="{ width: '480px' }" placeholder="请输入纳税人识别号" />
|
<t-input v-model="formData2.taxNum" :style="{ width: '480px' }" placeholder="请输入纳税人识别号" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="单位地址" name="address">
|
<t-form-item label="单位地址" name="address">
|
||||||
<t-input v-model="formData2.address" :style="{ width: '480px' }" placeholder="请输入单位地址" />
|
<t-input v-model="formData2.address" :style="{ width: '480px' }" placeholder="请输入单位地址" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="开户行" name="bank">
|
<t-form-item label="开户行" name="bank">
|
||||||
<t-input v-model="formData2.bank" :style="{ width: '480px' }" placeholder="请输入开户行" />
|
<t-input v-model="formData2.bank" :style="{ width: '480px' }" placeholder="请输入开户行" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="银行账号" name="bankAccount">
|
<t-form-item label="银行账号" name="bankAccount">
|
||||||
<t-input v-model="formData2.bankAccount" :style="{ width: '480px' }" placeholder="请输入银行账号" />
|
<t-input v-model="formData2.bankAccount" :style="{ width: '480px' }" placeholder="请输入银行账号" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="通知邮箱" name="email">
|
<t-form-item label="通知邮箱" name="email">
|
||||||
<t-input v-model="formData2.email" :style="{ width: '480px' }" placeholder="请输入通知邮箱" />
|
<t-input v-model="formData2.email" :style="{ width: '480px' }" placeholder="请输入通知邮箱" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="通知手机" name="tel">
|
<t-form-item label="通知手机" name="tel">
|
||||||
<t-input v-model="formData2.tel" :style="{ width: '480px' }" placeholder="请输入通知手机" />
|
<t-input v-model="formData2.tel" :style="{ width: '480px' }" placeholder="请输入通知手机" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item>
|
<t-form-item>
|
||||||
<t-button type="reset" theme="default" variant="base"> 上一步 </t-button>
|
<t-button type="reset" theme="default" variant="base"> 上一步 </t-button>
|
||||||
<t-button theme="primary" type="submit"> 下一步 </t-button>
|
<t-button theme="primary" type="submit"> 下一步 </t-button>
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
</t-form>
|
</t-form>
|
||||||
|
|
||||||
<!-- 分步表单3 -->
|
<!-- 分步表单3 -->
|
||||||
<t-form
|
<t-form
|
||||||
v-show="activeForm === 2"
|
v-show="activeForm === 2"
|
||||||
class="step-form"
|
class="step-form"
|
||||||
:data="formData3"
|
:data="formData3"
|
||||||
:rules="FORM_RULES"
|
:rules="FORM_RULES"
|
||||||
label-align="left"
|
label-align="left"
|
||||||
@reset="onReset(1)"
|
@reset="onReset(1)"
|
||||||
@submit="(result) => onSubmit(result, 6)"
|
@submit="(result) => onSubmit(result, 6)"
|
||||||
>
|
>
|
||||||
<t-form-item label="收货人" name="consignee">
|
<t-form-item label="收货人" name="consignee">
|
||||||
<t-input v-model="formData3.consignee" :style="{ width: '480px' }" placeholder="请输入收货人" />
|
<t-input v-model="formData3.consignee" :style="{ width: '480px' }" placeholder="请输入收货人" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="手机号码" name="mobileNum">
|
<t-form-item label="手机号码" name="mobileNum">
|
||||||
<t-input v-model="formData3.mobileNum" :style="{ width: '480px' }" placeholder="请输入手机号码" />
|
<t-input v-model="formData3.mobileNum" :style="{ width: '480px' }" placeholder="请输入手机号码" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="收货地址" name="deliveryAddress">
|
<t-form-item label="收货地址" name="deliveryAddress">
|
||||||
<t-select
|
<t-select
|
||||||
v-model="formData3.deliveryAddress"
|
v-model="formData3.deliveryAddress"
|
||||||
:style="{ width: '480px' }"
|
:style="{ width: '480px' }"
|
||||||
placeholder="请选择收货地址"
|
placeholder="请选择收货地址"
|
||||||
class="demo-select-base"
|
class="demo-select-base"
|
||||||
clearable
|
clearable
|
||||||
>
|
>
|
||||||
<t-option v-for="(item, index) in ADDRESS_OPTIONS" :key="index" :value="item.value" :label="item.label">
|
<t-option v-for="(item, index) in ADDRESS_OPTIONS" :key="index" :value="item.value" :label="item.label">
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</t-option>
|
</t-option>
|
||||||
</t-select>
|
</t-select>
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item label="详细地址" name="fullAddress">
|
<t-form-item label="详细地址" name="fullAddress">
|
||||||
<t-textarea v-model="formData3.fullAddress" :style="{ width: '480px' }" placeholder="请输入详细地址" />
|
<t-textarea v-model="formData3.fullAddress" :style="{ width: '480px' }" placeholder="请输入详细地址" />
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
<t-form-item>
|
<t-form-item>
|
||||||
<t-button type="reset" theme="default" variant="base"> 上一步 </t-button>
|
<t-button type="reset" theme="default" variant="base"> 上一步 </t-button>
|
||||||
<t-button theme="primary" type="submit"> 下一步 </t-button>
|
<t-button theme="primary" type="submit"> 下一步 </t-button>
|
||||||
</t-form-item>
|
</t-form-item>
|
||||||
</t-form>
|
</t-form>
|
||||||
|
|
||||||
<!-- 分步表单4 -->
|
<!-- 分步表单4 -->
|
||||||
<div v-show="activeForm === 6" class="step-form-4">
|
<div v-show="activeForm === 6" class="step-form-4">
|
||||||
<t-icon name="check-circle-filled" style="color: green" size="52px" />
|
<t-icon name="check-circle-filled" style="color: green" size="52px" />
|
||||||
<p class="text">完成开票申请</p>
|
<p class="text">完成开票申请</p>
|
||||||
<p class="tips">预计1~3个工作日会将电子发票发至邮箱,发票邮寄请耐心等待</p>
|
<p class="tips">预计1~3个工作日会将电子发票发至邮箱,发票邮寄请耐心等待</p>
|
||||||
<div class="button-group">
|
<div class="button-group">
|
||||||
<t-button theme="primary" @click="onReset(0)"> 再次申请 </t-button>
|
<t-button theme="primary" @click="onReset(0)"> 再次申请 </t-button>
|
||||||
<t-button variant="base" theme="default" @click="complete"> 查看进度 </t-button>
|
<t-button variant="base" theme="default" @click="complete"> 查看进度 </t-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,66 +1,68 @@
|
||||||
<template>
|
<template>
|
||||||
<card class="list-card-container">
|
<div>
|
||||||
<t-row justify="space-between">
|
<card class="list-card-container">
|
||||||
<div class="left-operation-container">
|
<t-row justify="space-between">
|
||||||
<t-button @click="handleSetupContract"> 新建合同 </t-button>
|
<div class="left-operation-container">
|
||||||
<t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出合同 </t-button>
|
<t-button @click="handleSetupContract"> 新建合同 </t-button>
|
||||||
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
|
<t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出合同 </t-button>
|
||||||
</div>
|
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
|
||||||
<t-input v-model="searchValue" class="search-input" placeholder="请输入你需要搜索的内容" clearable>
|
</div>
|
||||||
<template #suffix-icon>
|
<t-input v-model="searchValue" class="search-input" placeholder="请输入你需要搜索的内容" clearable>
|
||||||
<search-icon size="20px" />
|
<template #suffix-icon>
|
||||||
|
<search-icon size="20px" />
|
||||||
|
</template>
|
||||||
|
</t-input>
|
||||||
|
</t-row>
|
||||||
|
|
||||||
|
<t-table
|
||||||
|
:data="data"
|
||||||
|
:columns="COLUMNS"
|
||||||
|
:row-key="rowKey"
|
||||||
|
vertical-align="top"
|
||||||
|
:hover="true"
|
||||||
|
:pagination="pagination"
|
||||||
|
:selected-row-keys="selectedRowKeys"
|
||||||
|
:loading="dataLoading"
|
||||||
|
@page-change="rehandlePageChange"
|
||||||
|
@change="rehandleChange"
|
||||||
|
@select-change="rehandleSelectChange"
|
||||||
|
>
|
||||||
|
<template #status="{ row }">
|
||||||
|
<t-tag v-if="row.status === CONTRACT_STATUS.FAIL" theme="danger" variant="light"> 审核失败 </t-tag>
|
||||||
|
<t-tag v-if="row.status === CONTRACT_STATUS.AUDIT_PENDING" theme="warning" variant="light"> 待审核 </t-tag>
|
||||||
|
<t-tag v-if="row.status === CONTRACT_STATUS.EXEC_PENDING" theme="warning" variant="light"> 待履行 </t-tag>
|
||||||
|
<t-tag v-if="row.status === CONTRACT_STATUS.EXECUTING" theme="success" variant="light"> 履行中 </t-tag>
|
||||||
|
<t-tag v-if="row.status === CONTRACT_STATUS.FINISH" theme="success" variant="light"> 已完成 </t-tag>
|
||||||
|
</template>
|
||||||
|
<template #contractType="{ row }">
|
||||||
|
<p v-if="row.contractType === CONTRACT_TYPES.MAIN">审核失败</p>
|
||||||
|
<p v-if="row.contractType === CONTRACT_TYPES.SUB">待审核</p>
|
||||||
|
<p v-if="row.contractType === CONTRACT_TYPES.SUPPLEMENT">待履行</p>
|
||||||
|
</template>
|
||||||
|
<template #paymentType="{ row }">
|
||||||
|
<div v-if="row.paymentType === CONTRACT_PAYMENT_TYPES.PAYMENT" class="payment-col">
|
||||||
|
付款<trend class="dashboard-item-trend" type="up" />
|
||||||
|
</div>
|
||||||
|
<div v-if="row.paymentType === CONTRACT_PAYMENT_TYPES.RECIPT" class="payment-col">
|
||||||
|
收款<trend class="dashboard-item-trend" type="down" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</t-input>
|
|
||||||
</t-row>
|
|
||||||
|
|
||||||
<t-table
|
<template #op="slotProps">
|
||||||
:data="data"
|
<a class="t-button-link" @click="handleClickDetail()">详情</a>
|
||||||
:columns="COLUMNS"
|
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
|
||||||
:row-key="rowKey"
|
</template>
|
||||||
vertical-align="top"
|
</t-table>
|
||||||
:hover="true"
|
</card>
|
||||||
:pagination="pagination"
|
|
||||||
:selected-row-keys="selectedRowKeys"
|
|
||||||
:loading="dataLoading"
|
|
||||||
@page-change="rehandlePageChange"
|
|
||||||
@change="rehandleChange"
|
|
||||||
@select-change="rehandleSelectChange"
|
|
||||||
>
|
|
||||||
<template #status="{ row }">
|
|
||||||
<t-tag v-if="row.status === CONTRACT_STATUS.FAIL" theme="danger" variant="light"> 审核失败 </t-tag>
|
|
||||||
<t-tag v-if="row.status === CONTRACT_STATUS.AUDIT_PENDING" theme="warning" variant="light"> 待审核 </t-tag>
|
|
||||||
<t-tag v-if="row.status === CONTRACT_STATUS.EXEC_PENDING" theme="warning" variant="light"> 待履行 </t-tag>
|
|
||||||
<t-tag v-if="row.status === CONTRACT_STATUS.EXECUTING" theme="success" variant="light"> 履行中 </t-tag>
|
|
||||||
<t-tag v-if="row.status === CONTRACT_STATUS.FINISH" theme="success" variant="light"> 已完成 </t-tag>
|
|
||||||
</template>
|
|
||||||
<template #contractType="{ row }">
|
|
||||||
<p v-if="row.contractType === CONTRACT_TYPES.MAIN">审核失败</p>
|
|
||||||
<p v-if="row.contractType === CONTRACT_TYPES.SUB">待审核</p>
|
|
||||||
<p v-if="row.contractType === CONTRACT_TYPES.SUPPLEMENT">待履行</p>
|
|
||||||
</template>
|
|
||||||
<template #paymentType="{ row }">
|
|
||||||
<div v-if="row.paymentType === CONTRACT_PAYMENT_TYPES.PAYMENT" class="payment-col">
|
|
||||||
付款<trend class="dashboard-item-trend" type="up" />
|
|
||||||
</div>
|
|
||||||
<div v-if="row.paymentType === CONTRACT_PAYMENT_TYPES.RECIPT" class="payment-col">
|
|
||||||
收款<trend class="dashboard-item-trend" type="down" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #op="slotProps">
|
<t-dialog
|
||||||
<a class="t-button-link" @click="handleClickDetail()">详情</a>
|
v-model:visible="confirmVisible"
|
||||||
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
|
header="是否确认删除"
|
||||||
</template>
|
:body="confirmBody"
|
||||||
</t-table>
|
:on-cancel="onCancel"
|
||||||
</card>
|
@confirm="onConfirmDelete"
|
||||||
|
/>
|
||||||
<t-dialog
|
</div>
|
||||||
v-model:visible="confirmVisible"
|
|
||||||
header="是否确认删除"
|
|
||||||
:body="confirmBody"
|
|
||||||
:on-cancel="onCancel"
|
|
||||||
@confirm="onConfirmDelete"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, onMounted, computed } from 'vue';
|
import { defineComponent, ref, onMounted, computed } from 'vue';
|
||||||
|
|
|
@ -1,59 +1,62 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="list-card-operation">
|
<div>
|
||||||
<t-button @click="formDialogVisible = true"> 新建产品 </t-button>
|
<div class="list-card-operation">
|
||||||
<t-input v-model="searchValue" class="search-input" placeholder="请输入你需要搜索的内容" clearable>
|
<t-button @click="formDialogVisible = true"> 新建产品 </t-button>
|
||||||
<template #suffix-icon>
|
<t-input v-model="searchValue" class="search-input" placeholder="请输入你需要搜索的内容" clearable>
|
||||||
<search-icon v-if="searchValue === ''" size="20px" />
|
<template #suffix-icon>
|
||||||
</template>
|
<search-icon v-if="searchValue === ''" size="20px" />
|
||||||
</t-input>
|
</template>
|
||||||
</div>
|
</t-input>
|
||||||
|
|
||||||
<dialog-form v-model:visible="formDialogVisible" :data="formData" />
|
|
||||||
|
|
||||||
<template v-if="pagination.total > 0 && !dataLoading">
|
|
||||||
<div class="list-card-items">
|
|
||||||
<t-row :gutter="[16, 12]">
|
|
||||||
<t-col
|
|
||||||
v-for="product in productList.slice(
|
|
||||||
pagination.pageSize * (pagination.current - 1),
|
|
||||||
pagination.pageSize * pagination.current,
|
|
||||||
)"
|
|
||||||
:key="product.index"
|
|
||||||
:lg="4"
|
|
||||||
:xs="6"
|
|
||||||
:xl="3"
|
|
||||||
>
|
|
||||||
<card
|
|
||||||
class="list-card-item"
|
|
||||||
:product="product"
|
|
||||||
@delete-item="handleDeleteItem"
|
|
||||||
@manage-product="handleManageProduct"
|
|
||||||
/>
|
|
||||||
</t-col>
|
|
||||||
</t-row>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="list-card-pagination">
|
|
||||||
<t-pagination
|
|
||||||
v-model="pagination.current"
|
|
||||||
v-model:page-size="pagination.pageSize"
|
|
||||||
:total="pagination.total"
|
|
||||||
:page-size-options="[12, 24, 36]"
|
|
||||||
@page-size-change="onPageSizeChange"
|
|
||||||
@current-change="onCurrentChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div v-else-if="dataLoading" class="list-card-loading">
|
|
||||||
<t-loading size="large" text="加载数据中..." />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<t-dialog
|
<dialog-form v-model:visible="formDialogVisible" :data="formData" />
|
||||||
v-model:visible="confirmVisible"
|
|
||||||
header="是否确认删除产品"
|
<template v-if="pagination.total > 0 && !dataLoading">
|
||||||
:body="confirmBody"
|
<div class="list-card-items">
|
||||||
:on-cancel="onCancel"
|
<t-row :gutter="[16, 12]">
|
||||||
@confirm="onConfirmDelete"
|
<t-col
|
||||||
/>
|
v-for="product in productList.slice(
|
||||||
|
pagination.pageSize * (pagination.current - 1),
|
||||||
|
pagination.pageSize * pagination.current,
|
||||||
|
)"
|
||||||
|
:key="product.index"
|
||||||
|
:lg="4"
|
||||||
|
:xs="6"
|
||||||
|
:xl="3"
|
||||||
|
>
|
||||||
|
<card
|
||||||
|
class="list-card-item"
|
||||||
|
:product="product"
|
||||||
|
@delete-item="handleDeleteItem"
|
||||||
|
@manage-product="handleManageProduct"
|
||||||
|
/>
|
||||||
|
</t-col>
|
||||||
|
</t-row>
|
||||||
|
</div>
|
||||||
|
<div class="list-card-pagination">
|
||||||
|
<t-pagination
|
||||||
|
v-model="pagination.current"
|
||||||
|
v-model:page-size="pagination.pageSize"
|
||||||
|
:total="pagination.total"
|
||||||
|
:page-size-options="[12, 24, 36]"
|
||||||
|
@page-size-change="onPageSizeChange"
|
||||||
|
@current-change="onCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div v-else-if="dataLoading" class="list-card-loading">
|
||||||
|
<t-loading size="large" text="加载数据中..." />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<t-dialog
|
||||||
|
v-model:visible="confirmVisible"
|
||||||
|
header="是否确认删除产品"
|
||||||
|
:body="confirmBody"
|
||||||
|
:on-cancel="onCancel"
|
||||||
|
@confirm="onConfirmDelete"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, ref, computed, onMounted } from 'vue';
|
import { defineComponent, ref, computed, onMounted } from 'vue';
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
>
|
>
|
||||||
<template v-if="type == 'password'">
|
<template v-if="type == 'password'">
|
||||||
<t-form-item name="account">
|
<t-form-item name="account">
|
||||||
<t-input v-model="formData.account" size="large" placeholder="请输入您的邮箱/手机号">
|
<t-input v-model="formData.account" size="large" placeholder="请输入您的账号:td">
|
||||||
<template #prefix-icon>
|
<template #prefix-icon>
|
||||||
<t-icon name="user" />
|
<t-icon name="user" />
|
||||||
</template>
|
</template>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
size="large"
|
size="large"
|
||||||
:type="showPsw ? 'text' : 'password'"
|
:type="showPsw ? 'text' : 'password'"
|
||||||
clearable
|
clearable
|
||||||
placeholder="请输入登录密码"
|
placeholder="请输入登录密码:main_/dev_"
|
||||||
>
|
>
|
||||||
<template #prefix-icon>
|
<template #prefix-icon>
|
||||||
<t-icon name="lock-on" />
|
<t-icon name="lock-on" />
|
||||||
|
@ -50,14 +50,6 @@
|
||||||
|
|
||||||
<!-- 手机号登陆 -->
|
<!-- 手机号登陆 -->
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<t-form-item name="phone">
|
|
||||||
<t-input v-model="formData.phone" size="large" placeholder="请输入您的手机号">
|
|
||||||
<template #prefix-icon>
|
|
||||||
<t-icon name="user" />
|
|
||||||
</template>
|
|
||||||
</t-input>
|
|
||||||
</t-form-item>
|
|
||||||
|
|
||||||
<t-form-item class="verification-code" name="verifyCode">
|
<t-form-item class="verification-code" name="verifyCode">
|
||||||
<t-input v-model="formData.verifyCode" size="large" placeholder="请输入验证码" />
|
<t-input v-model="formData.verifyCode" size="large" placeholder="请输入验证码" />
|
||||||
<t-button variant="outline" :disabled="countDown > 0" @click="handleCounter">
|
<t-button variant="outline" :disabled="countDown > 0" @click="handleCounter">
|
||||||
|
@ -97,8 +89,11 @@ const INITIAL_DATA = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const FORM_RULES = {
|
const FORM_RULES = {
|
||||||
phone: [{ required: true, message: '手机号必填', type: 'error' }],
|
|
||||||
account: [{ required: true, message: '账号必填', type: 'error' }],
|
account: [{ required: true, message: '账号必填', type: 'error' }],
|
||||||
|
phone: [
|
||||||
|
{ required: true, message: '手机号必填', type: 'error' },
|
||||||
|
{ telnumber: true, message: '请输入正确的手机号', type: 'warning' },
|
||||||
|
],
|
||||||
password: [{ required: true, message: '密码必填', type: 'error' }, { validator: passwordValidator }],
|
password: [{ required: true, message: '密码必填', type: 'error' }, { validator: passwordValidator }],
|
||||||
verifyCode: [{ required: true, message: '验证码必填', type: 'error' }],
|
verifyCode: [{ required: true, message: '验证码必填', type: 'error' }],
|
||||||
};
|
};
|
||||||
|
@ -120,15 +115,18 @@ export default defineComponent({
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
|
|
||||||
const onSubmit = ({ validateResult }) => {
|
const onSubmit = async ({ validateResult }) => {
|
||||||
if (validateResult === true) {
|
if (validateResult === true) {
|
||||||
store.commit('user/SET_USER_INFO', formData.value);
|
try {
|
||||||
|
await store.dispatch('user/login', formData.value);
|
||||||
MessagePlugin.success('登录成功');
|
MessagePlugin.success('登陆成功');
|
||||||
|
router.push({
|
||||||
router.push({
|
path: '/dashboard/base',
|
||||||
path: '/',
|
});
|
||||||
});
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
MessagePlugin.error(e.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
@import '@/style/variables.less';
|
@import '@/style/variables.less';
|
||||||
|
|
||||||
&.light {
|
.light {
|
||||||
.login-wrapper {
|
&.login-wrapper {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
background-image: url('@/assets/assets-login-bg-white.png');
|
background-image: url('@/assets/assets-login-bg-white.png');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.dark {
|
.dark {
|
||||||
.login-wrapper {
|
&.login-wrapper {
|
||||||
background-color: @bg-color-page;
|
background-color: @bg-color-page;
|
||||||
background-image: url('@/assets/assets-login-bg-black.png');
|
background-image: url('@/assets/assets-login-bg-black.png');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-wrapper {
|
.login-wrapper {
|
||||||
width: 100%;
|
height: 100vh;
|
||||||
height: 100%;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: 50%;
|
background-position: 50%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
<login v-if="type === 'login'" />
|
<login v-if="type === 'login'" />
|
||||||
<register v-else @register-success="switchType('login')" />
|
<register v-else @register-success="switchType('login')" />
|
||||||
|
<tdesign-setting />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -26,6 +27,7 @@ import { useStore } from 'vuex';
|
||||||
import Login from './components/Login.vue';
|
import Login from './components/Login.vue';
|
||||||
import Register from './components/Register.vue';
|
import Register from './components/Register.vue';
|
||||||
import LoginHeader from './components/Header.vue';
|
import LoginHeader from './components/Header.vue';
|
||||||
|
import TdesignSetting from '@/layouts/setting.vue';
|
||||||
|
|
||||||
/** 高级详情 */
|
/** 高级详情 */
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -34,6 +36,7 @@ export default defineComponent({
|
||||||
Login,
|
Login,
|
||||||
Register,
|
Register,
|
||||||
LoginHeader,
|
LoginHeader,
|
||||||
|
TdesignSetting,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const type = ref('login');
|
const type = ref('login');
|
||||||
|
|
56
src/permission.ts
Normal file
56
src/permission.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import { MessagePlugin } from 'tdesign-vue-next';
|
||||||
|
import NProgress from 'nprogress'; // progress bar
|
||||||
|
import 'nprogress/nprogress.css'; // progress bar style
|
||||||
|
|
||||||
|
import store from '@/store';
|
||||||
|
import router from '@/router';
|
||||||
|
|
||||||
|
NProgress.configure({ showSpinner: false });
|
||||||
|
|
||||||
|
const whiteListRouters = store.getters['permission/whiteListRouters'];
|
||||||
|
|
||||||
|
router.beforeEach(async (to, from, next) => {
|
||||||
|
NProgress.start();
|
||||||
|
|
||||||
|
const token = store.getters['user/token'];
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
if (to.path === '/login') {
|
||||||
|
store.dispatch('user/logout');
|
||||||
|
store.dispatch('permission/restore');
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const roles = store.getters['user/roles'];
|
||||||
|
if (roles && roles.length > 0) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
await store.dispatch('user/getUserInfo');
|
||||||
|
|
||||||
|
await store.dispatch('permission/initRoutes', store.getters['user/roles']);
|
||||||
|
|
||||||
|
next({ ...to });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
MessagePlugin.error(error);
|
||||||
|
await store.commit('user/removeToken');
|
||||||
|
next(`/login?redirect=${to.path}`);
|
||||||
|
NProgress.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* white list router */
|
||||||
|
if (whiteListRouters.indexOf(to.path) !== -1) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
next(`/login?redirect=${to.path}`);
|
||||||
|
}
|
||||||
|
NProgress.done();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.afterEach(() => {
|
||||||
|
NProgress.done();
|
||||||
|
});
|
|
@ -1,38 +1,35 @@
|
||||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
|
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
|
||||||
import routeConfig from '@/config/routes';
|
|
||||||
|
|
||||||
const layoutModules = import.meta.glob('../layout/*');
|
import baseRouters from './modules/base';
|
||||||
const pagesModules = import.meta.glob('../pages/**/*.vue');
|
import componentsRouters from './modules/components';
|
||||||
const fristPagesModules = import.meta.glob('../pages/*.vue');
|
import othersRouters from './modules/others';
|
||||||
const modules = { ...layoutModules, ...fristPagesModules, ...pagesModules };
|
|
||||||
|
|
||||||
const getMenuRoutes = (list) => {
|
// 存放动态路由
|
||||||
if (!list) {
|
export const asyncRouterList: Array<RouteRecordRaw> = [...baseRouters, ...componentsRouters, ...othersRouters];
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return list.map((item) => {
|
|
||||||
const { path = '', component, meta = { title: item.title }, redirect = '' } = item;
|
|
||||||
return {
|
|
||||||
path,
|
|
||||||
component: modules[component],
|
|
||||||
children: getMenuRoutes(item.children),
|
|
||||||
meta,
|
|
||||||
redirect,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
// 存放固定的路由
|
||||||
...getMenuRoutes(routeConfig),
|
const defaultRouterList: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '/login',
|
||||||
redirect: '/login/index',
|
name: 'login',
|
||||||
|
component: () => import('@/pages/login/index.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
redirect: '/login',
|
||||||
|
component: () => import('@/layouts/blank.vue'),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const page404 = {
|
||||||
|
path: '/:w+',
|
||||||
|
name: '404Page',
|
||||||
|
redirect: '/result/404',
|
||||||
|
};
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHashHistory(),
|
history: createWebHashHistory(),
|
||||||
routes,
|
routes: defaultRouterList,
|
||||||
scrollBehavior() {
|
scrollBehavior() {
|
||||||
return {
|
return {
|
||||||
el: '#app',
|
el: '#app',
|
||||||
|
@ -41,4 +38,5 @@ const router = createRouter({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
25
src/router/modules/base.ts
Normal file
25
src/router/modules/base.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import Layout from '@/layouts';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
path: '/dashboard',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/dashboard/base',
|
||||||
|
name: 'dashboard',
|
||||||
|
meta: { title: '仪表盘', icon: 'dashboard' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'base',
|
||||||
|
name: 'dashboardBase',
|
||||||
|
component: () => import('@/pages/dashboard/base/index.vue'),
|
||||||
|
meta: { title: '概览仪表盘' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'detail',
|
||||||
|
name: 'dashboardDetail',
|
||||||
|
component: () => import('@/pages/dashboard/detail/index.vue'),
|
||||||
|
meta: { title: '统计报表' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
151
src/router/modules/components.ts
Normal file
151
src/router/modules/components.ts
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
import Layout from '@/layouts';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
path: '/list',
|
||||||
|
name: 'list',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/list/base',
|
||||||
|
meta: { title: '列表页', icon: 'view-module' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'base',
|
||||||
|
name: 'listBase',
|
||||||
|
component: () => import('@/pages/list/base/index.vue'),
|
||||||
|
meta: { title: '基础列表页' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'card',
|
||||||
|
name: 'listCard',
|
||||||
|
component: () => import('@/pages/list/card/index.vue'),
|
||||||
|
meta: { title: '卡片列表页' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'filter',
|
||||||
|
name: 'listFilter',
|
||||||
|
component: () => import('@/pages/list/filter/index.vue'),
|
||||||
|
meta: { title: '筛选列表页' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'tree',
|
||||||
|
name: 'listTree',
|
||||||
|
component: () => import('@/pages/list/tree/index.vue'),
|
||||||
|
meta: { title: '树状筛选列表页' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/form',
|
||||||
|
name: 'form',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/form/base',
|
||||||
|
meta: { title: '表单页', icon: 'queue' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'base',
|
||||||
|
name: 'formBase',
|
||||||
|
component: () => import('@/pages/form/base/index.vue'),
|
||||||
|
meta: { title: '基础表单页' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'step',
|
||||||
|
name: 'formStep',
|
||||||
|
component: () => import('@/pages/form/step/index.vue'),
|
||||||
|
meta: { title: '分步表单页' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/detail',
|
||||||
|
name: 'detail',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/detail/base',
|
||||||
|
meta: { title: '详情页', icon: 'layers' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'base',
|
||||||
|
name: 'detailBase',
|
||||||
|
component: () => import('@/pages/detail/base/index.vue'),
|
||||||
|
meta: { title: '基础详情页' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'advanced',
|
||||||
|
name: 'detailAdvanced',
|
||||||
|
component: () => import('@/pages/detail/advanced/index.vue'),
|
||||||
|
meta: { title: '多卡片详情页' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'deploy',
|
||||||
|
name: 'detailDeploy',
|
||||||
|
component: () => import('@/pages/detail/deploy/index.vue'),
|
||||||
|
meta: { title: '数据详情页' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'secondary',
|
||||||
|
name: 'detailDeploy',
|
||||||
|
component: () => import('@/pages/detail/secondary/index.vue'),
|
||||||
|
meta: { title: '二级详情页' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/result',
|
||||||
|
name: 'result',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/result/success',
|
||||||
|
meta: { title: '结果页', icon: 'check-circle' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'success',
|
||||||
|
name: 'resultSuccess',
|
||||||
|
component: () => import('@/pages/result/success/index.vue'),
|
||||||
|
meta: { title: '成功页' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'fail',
|
||||||
|
name: 'resultFail',
|
||||||
|
component: () => import('@/pages/result/fail/index.vue'),
|
||||||
|
meta: { title: '失败页' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/warning',
|
||||||
|
name: 'warning',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/warning/success',
|
||||||
|
meta: { title: '异常页', icon: 'error-circle' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'network-error',
|
||||||
|
name: 'warningNetworkError',
|
||||||
|
component: () => import('@/pages/result/network-error/index.vue'),
|
||||||
|
meta: { title: '网络异常' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '403',
|
||||||
|
name: 'warning403',
|
||||||
|
component: () => import('@/pages/result/403/index.vue'),
|
||||||
|
meta: { title: '无权限' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '404',
|
||||||
|
name: 'warning404',
|
||||||
|
component: () => import('@/pages/result/404/index.vue'),
|
||||||
|
meta: { title: '访问页面不存在页' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '500',
|
||||||
|
name: 'warning500',
|
||||||
|
component: () => import('@/pages/result/500/index.vue'),
|
||||||
|
meta: { title: '服务器出错页' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'browser-incompatible',
|
||||||
|
name: 'warningBrowserIncompatible',
|
||||||
|
component: () => import('@/pages/result/browser-incompatible/index.vue'),
|
||||||
|
meta: { title: '浏览器不兼容页' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
33
src/router/modules/others.ts
Normal file
33
src/router/modules/others.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import Layout from '@/layouts';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
path: '/user',
|
||||||
|
name: 'user',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/user/index',
|
||||||
|
meta: { title: '个人页', icon: 'user-circle' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
name: 'userIndex',
|
||||||
|
component: () => import('@/pages/user/index.vue'),
|
||||||
|
meta: { title: '个人中心' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/loginRedirect',
|
||||||
|
name: 'loginRedirect',
|
||||||
|
meta: { title: '登录页', icon: 'chevron-right-rectangle' },
|
||||||
|
component: () => import('@/layouts/blank.vue'),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'index',
|
||||||
|
redirect: '/login',
|
||||||
|
component: () => import('@/layouts/blank.vue'),
|
||||||
|
meta: { title: '登陆页' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
|
@ -2,12 +2,14 @@ import { createStore } from 'vuex';
|
||||||
import user from './modules/user';
|
import user from './modules/user';
|
||||||
import notification from './modules/notification';
|
import notification from './modules/notification';
|
||||||
import setting from './modules/setting';
|
import setting from './modules/setting';
|
||||||
|
import permission from './modules/permission';
|
||||||
|
|
||||||
export const store = createStore({
|
export const store = createStore({
|
||||||
modules: {
|
modules: {
|
||||||
user,
|
user,
|
||||||
setting,
|
setting,
|
||||||
notification,
|
notification,
|
||||||
|
permission,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
74
src/store/modules/permission.ts
Normal file
74
src/store/modules/permission.ts
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import router, { asyncRouterList, page404 } from '@/router';
|
||||||
|
|
||||||
|
function filterPermissionsRouters(routes, roles) {
|
||||||
|
const res = [];
|
||||||
|
routes.forEach((route) => {
|
||||||
|
const children = [];
|
||||||
|
route.children?.forEach((childRouter) => {
|
||||||
|
const roleCode = childRouter.meta?.roleCode || childRouter.name;
|
||||||
|
if (roles.indexOf(roleCode) !== -1) {
|
||||||
|
children.push(childRouter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (children.length > 0) {
|
||||||
|
route.children = children;
|
||||||
|
res.push(route);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
whiteListRouters: ['/login'],
|
||||||
|
routers: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const mutations = {
|
||||||
|
setRouters: (state, routers) => {
|
||||||
|
state.routers = routers;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const getters = {
|
||||||
|
routers: (state) => {
|
||||||
|
return state.routers;
|
||||||
|
},
|
||||||
|
whiteListRouters: (state) => {
|
||||||
|
return state.whiteListRouters;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
async initRoutes({ commit }, roles) {
|
||||||
|
let accessedRouters;
|
||||||
|
|
||||||
|
// special token
|
||||||
|
if (roles.includes('ALL_ROUTERS')) {
|
||||||
|
accessedRouters = asyncRouterList;
|
||||||
|
} else {
|
||||||
|
accessedRouters = filterPermissionsRouters(asyncRouterList, roles);
|
||||||
|
}
|
||||||
|
|
||||||
|
commit('setRouters', accessedRouters);
|
||||||
|
|
||||||
|
// register routers
|
||||||
|
state.routers.concat(page404).forEach((item) => {
|
||||||
|
router.addRoute(item);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async restore({ commit, state }) {
|
||||||
|
// remove routers
|
||||||
|
state.routers.concat(page404).forEach((item) => {
|
||||||
|
router.removeRoute(item.name);
|
||||||
|
});
|
||||||
|
commit('setRouters', []);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
namespaced: true,
|
||||||
|
state,
|
||||||
|
mutations,
|
||||||
|
actions,
|
||||||
|
getters,
|
||||||
|
};
|
|
@ -1,5 +1,4 @@
|
||||||
import STYLE_CONFIG from '@/config/style';
|
import STYLE_CONFIG from '@/config/style';
|
||||||
import MENU_CONFIG from '@/config/routes';
|
|
||||||
|
|
||||||
// 定义的state初始值
|
// 定义的state初始值
|
||||||
const state = {
|
const state = {
|
||||||
|
@ -37,32 +36,6 @@ const getters = {
|
||||||
showSidebar: (state) => state.layout !== 'top',
|
showSidebar: (state) => state.layout !== 'top',
|
||||||
showSidebarLogo: (state) => state.layout === 'side',
|
showSidebarLogo: (state) => state.layout === 'side',
|
||||||
showHeaderLogo: (state) => state.layout !== 'side',
|
showHeaderLogo: (state) => state.layout !== 'side',
|
||||||
headerMenu: (state) => {
|
|
||||||
if (state.layout === 'mix') {
|
|
||||||
if (state.splitMenu) {
|
|
||||||
return MENU_CONFIG.map((menu) => ({
|
|
||||||
...menu,
|
|
||||||
children: [],
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return MENU_CONFIG;
|
|
||||||
},
|
|
||||||
sideMenu: (state, getters, rootState) => {
|
|
||||||
if (state.layout === 'mix' && state.splitMenu) {
|
|
||||||
let index;
|
|
||||||
for (index = 0; index < MENU_CONFIG.length; index++) {
|
|
||||||
const item = MENU_CONFIG[index];
|
|
||||||
if (item.children && item.children.length > 0) {
|
|
||||||
if (rootState.route.path.indexOf(item.path) === 0) {
|
|
||||||
return item.children.map((menuRouter) => ({ ...menuRouter, path: `${item.path}/${menuRouter.path}` }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return MENU_CONFIG;
|
|
||||||
},
|
|
||||||
showFooter: (state) => state.showFooter,
|
showFooter: (state) => state.showFooter,
|
||||||
showSettingBtn: (state) => !state.showHeader,
|
showSettingBtn: (state) => !state.showHeader,
|
||||||
mode: (state) => {
|
mode: (state) => {
|
||||||
|
|
|
@ -1,42 +1,94 @@
|
||||||
import request from '@/utils/request';
|
import { TOKEN_NAME } from '@/config/global';
|
||||||
|
|
||||||
|
const InitUserInfo = {
|
||||||
|
roles: [],
|
||||||
|
};
|
||||||
|
|
||||||
// 定义的state初始值
|
// 定义的state初始值
|
||||||
const state = {
|
const state = {
|
||||||
loginName: '',
|
token: localStorage.getItem(TOKEN_NAME),
|
||||||
deptNameString: '',
|
userInfo: InitUserInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
SET_USER_INFO(state, userInfo) {
|
setToken(state, token) {
|
||||||
state.loginName = userInfo.EngName;
|
localStorage.setItem(TOKEN_NAME, token);
|
||||||
state.deptNameString = userInfo.DeptNameString;
|
state.token = token;
|
||||||
|
},
|
||||||
|
removeToken(state) {
|
||||||
|
localStorage.removeItem(TOKEN_NAME);
|
||||||
|
state.token = '';
|
||||||
|
},
|
||||||
|
setUserInfo(state, userInfo) {
|
||||||
|
state.userInfo = userInfo;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const getters = {
|
||||||
|
token: (state) => {
|
||||||
|
return state.token;
|
||||||
|
},
|
||||||
|
roles: (state) => {
|
||||||
|
return state.userInfo?.roles;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
async getUserInfo(context) {
|
async login({ commit }, userInfo) {
|
||||||
try {
|
const mockLogin = async (userInfo) => {
|
||||||
console.log('当前编译环境');
|
const { account, password } = userInfo;
|
||||||
console.log(process.env.NODE_ENV);
|
if (account !== 'td') {
|
||||||
|
return {
|
||||||
if (process.env.NODE_ENV === 'development') {
|
code: 401,
|
||||||
context.commit('SET_USER_INFO', {
|
message: '账号不存在',
|
||||||
EngName: 'user_test',
|
};
|
||||||
DeptNameString: '虚拟部门test',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
request({
|
|
||||||
method: 'get',
|
|
||||||
url: '/ts:auth/tauth/info.ashx',
|
|
||||||
baseURL: '',
|
|
||||||
}).then((res) => {
|
|
||||||
context.commit('SET_USER_INFO', res.data);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
if (['main_', 'dev_'].indexOf(password) === -1) {
|
||||||
console.log(`智能网关获取用户信息错误:${err.message}`);
|
return {
|
||||||
|
code: 401,
|
||||||
|
message: '密码错误',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const token = {
|
||||||
|
main_: 'main_token',
|
||||||
|
dev_: 'dev_token',
|
||||||
|
}[password];
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
message: '登陆成功',
|
||||||
|
data: token,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await mockLogin(userInfo);
|
||||||
|
if (res.code === 200) {
|
||||||
|
commit('setToken', res.data);
|
||||||
|
} else {
|
||||||
|
throw res;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async getUserInfo({ commit, state }) {
|
||||||
|
const mockRemoteUserInfo = async (token) => {
|
||||||
|
if (token === 'main_token') {
|
||||||
|
return {
|
||||||
|
name: 'td_main',
|
||||||
|
roles: ['ALL_ROUTERS'],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: 'td_dev',
|
||||||
|
roles: ['userIndex', 'dashboardBase', 'login'],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await mockRemoteUserInfo(state.token);
|
||||||
|
|
||||||
|
commit('setUserInfo', res);
|
||||||
|
},
|
||||||
|
async logout({ commit }) {
|
||||||
|
commit('removeToken');
|
||||||
|
commit('setUserInfo', InitUserInfo);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -44,4 +96,5 @@ export default {
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
actions,
|
actions,
|
||||||
|
getters,
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
> .t-layout {
|
> .t-layout {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 760px; // 992 - 232
|
min-width: 760px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,11 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-main-wrapper{
|
||||||
|
height: 500px;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
&-side-nav-layout {
|
&-side-nav-layout {
|
||||||
&-relative {
|
&-relative {
|
||||||
|
@ -35,8 +40,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-layout{
|
||||||
|
height: calc(100vh - 64px);
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
&-content-layout {
|
&-content-layout {
|
||||||
margin: @spacer-3;
|
padding: @spacer-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-footer-layout {
|
&-footer-layout {
|
||||||
|
|
|
@ -26,5 +26,8 @@ export default defineConfig({
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
port: 3002,
|
port: 3002,
|
||||||
|
proxy: {
|
||||||
|
'/api': 'http://127.0.0.1:3000/',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user