feat: update list, form, detail

This commit is contained in:
pengYYYYY 2021-11-16 19:01:03 +08:00
parent d32ac9e722
commit d9ff532fdb
29 changed files with 1164 additions and 1053 deletions

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TDesign Pro Vue3</title> <title>TDesign Starter Vue Next</title>
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View File

@ -3,10 +3,7 @@
<div :class="titleCls"> <div :class="titleCls">
<span :class="titleTextCls"> <span :class="titleTextCls">
{{ title }} {{ title }}
<span <span v-if="describe" class="card-describe">{{ describe }}</span>
v-if="describe"
class="card-describe"
>{{ describe }}</span>
</span> </span>
<span class="card-option"> <span class="card-option">
<slot name="option" /> <slot name="option" />
@ -15,10 +12,7 @@
<div class="card-content"> <div class="card-content">
<slot /> <slot />
</div> </div>
<div <div v-if="size !== 'small'" class="card-spacer-bottom" />
v-if="size !== 'small'"
class="card-spacer-bottom"
/>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -87,7 +81,6 @@ export default defineComponent({
} }
.card { .card {
&-option { &-option {
display: flex; display: flex;
align-items: center; align-items: center;
@ -138,7 +131,7 @@ export default defineComponent({
&-describe { &-describe {
font-size: 14px; font-size: 14px;
color: rgba(0, 0, 0, .6); color: rgba(0, 0, 0, 0.6);
line-height: 22px; line-height: 22px;
} }

View File

@ -1,8 +1,5 @@
<template> <template>
<div <div :style="style" class="color-container" />
:style="style"
class="color-container"
/>
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent, PropType } from 'vue'; import { computed, defineComponent, PropType } from 'vue';
@ -37,4 +34,3 @@ export default defineComponent({
display: inline-block; display: inline-block;
} }
</style> </style>

View File

@ -1,22 +1,13 @@
<template> <template>
<card> <card>
<div class="result-container"> <div class="result-container">
<img <img class="result-bg-img" :src="bgUrl">
class="result-bg-img"
:src="bgUrl"
>
<div class="result-tip"> <div class="result-tip">
{{ tip }} {{ tip }}
</div> </div>
<div> <div>
<router-link <router-link class="tdesign-pro-main-link" to="/">
class="tdesign-pro-main-link" <t-button theme="primary" variant="text">
to="/"
>
<t-button
theme="primary"
variant="text"
>
返回首页 返回首页
</t-button> </t-button>
</router-link> </router-link>
@ -47,7 +38,6 @@ export default defineComponent({
@import url('@/style/index.less'); @import url('@/style/index.less');
.result { .result {
&-link { &-link {
color: @brand-color; color: @brand-color;
text-decoration: none; text-decoration: none;

View File

@ -1,8 +1,5 @@
<template> <template>
<img <img :class="className" :src="url">
:class="className"
:src="url"
>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, computed, PropType } from 'vue'; import { defineComponent, computed, PropType } from 'vue';
@ -38,7 +35,6 @@ export default defineComponent({
@import url('@/style/index.less'); @import url('@/style/index.less');
.thumbnail { .thumbnail {
&-container { &-container {
display: inline-block; display: inline-block;
} }

View File

@ -9,16 +9,8 @@
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<path <path d="M11.5 8L8 11.5L4.5 8" stroke="currentColor" stroke-width="1.5" />
d="M11.5 8L8 11.5L4.5 8" <path d="M8 11L8 4" stroke="currentColor" stroke-width="1.5" />
stroke="currentColor"
stroke-width="1.5"
/>
<path
d="M8 11L8 4"
stroke="currentColor"
stroke-width="1.5"
/>
</svg> </svg>
<svg <svg
v-else v-else
@ -28,16 +20,8 @@
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<path <path d="M4.5 8L8 4.5L11.5 8" stroke="currentColor" stroke-width="1.5" />
d="M4.5 8L8 4.5L11.5 8" <path d="M8 5V12" stroke="currentColor" stroke-width="1.5" />
stroke="currentColor"
stroke-width="1.5"
/>
<path
d="M8 5V12"
stroke="currentColor"
stroke-width="1.5"
/>
</svg> </svg>
</span> </span>
<span>{{ describe }}</span> <span>{{ describe }}</span>
@ -87,9 +71,7 @@ export default defineComponent({
<style lang="less" scoped> <style lang="less" scoped>
.trend { .trend {
&-container { &-container {
&__up { &__up {
color: #e34d59 !important; color: #e34d59 !important;
display: inline-flex; display: inline-flex;

4
src/interface.ts Normal file
View File

@ -0,0 +1,4 @@
export interface ResDataType {
code: number,
data: any
}

View File

@ -0,0 +1,60 @@
<template>
<div class="operater-block operater-gap">
<div class="operater-content">
<div class="operater-title">
<t-icon name="cart" class="operater-title-icon" />
<h1>{{ data.name }}</h1>
<div class="operater-title-subtitle">
{{ data.subtitle }}
</div>
<div class="operater-title-tags">
<t-tag class="operater-title-tag" theme="success" size="small">
{{ data.size }}
</t-tag>
<t-tag class="operater-title-tag" size="small">
{{ data.cpu }}
</t-tag>
<t-tag class="operater-title-tag" size="small">
{{ data.memory }}
</t-tag>
</div>
</div>
<div class="operater-item">
<span class="operater-item-info">{{ data.info }}</span>
<t-icon
class="operater-item-icon"
name="chevron-right"
size="small"
style="color: rgba(0, 0, 0, 0.26)"
/>
</div>
</div>
<div class="operater-footer">
<span class="operater-footer-percentage">{{ data.use }} / {{ data.stock }}</span>
<t-progress
class="operater-progress"
theme="line"
:percentage="(data.use / data.stock) * 100"
:label="false"
:color="(data.use / data.stock) < 0.5 ? '#E24D59' : ''"
:track-color="(data.use / data.stock) < 0.5 ? '#FCD4D4' : '#D4E3FC'"
/>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
props: {
data: {
type: Object,
},
},
});
</script>
<style lang="less" scoped>
@import url('../index.less');
</style>

View File

@ -0,0 +1,154 @@
export const BASE_INFO_DATA = [
{
name: '合同名称',
value: '总部办公用品采购项目',
type: null,
},
{
name: '合同状态',
value: '履行中',
type: {
key: 'contractStatus',
value: 'inProgress',
},
},
{
name: '合同编号',
value: 'BH00010',
type: null,
},
{
name: '合同类型',
value: '主合同',
type: null,
},
{
name: '合同收付类型',
value: '付款',
type: null,
},
{
name: '合同金额',
value: '5,000,000元',
type: null,
},
{
name: '甲方',
value: '腾讯科技(深圳)有限公司',
type: null,
},
{
name: '乙方',
value: '欧尚',
type: null,
},
{
name: '合同签订日期',
value: '2020-12-20',
type: null,
},
{
name: '合同生效日期',
value: '2021-01-20',
type: null,
},
{
name: '合同结束日期',
value: '2022-12-20',
type: null,
},
{
name: '合同附件',
value: '总部办公用品采购项目合同.pdf',
type: {
key: 'contractAnnex',
value: 'pdf',
},
},
{
name: '备注',
value: '--',
type: null,
},
{
name: '创建时间',
value: '2020-12-22 10:00:00',
type: null,
},
];
export const TABLE_COLUMNS_DATA = [
{
align: 'center',
minWidth: '250',
ellipsis: true,
colKey: 'index',
title: '申请号',
sorter: (a, b) => a.index.substr(3) - b.index.substr(3),
},
{
minWidth: '100',
ellipsis: true,
colKey: 'pdName',
title: '产品名称',
sorter: (a, b) => a.pdName.length - b.pdName.length,
},
{
minWidth: '250',
ellipsis: true,
colKey: 'pdNum',
title: '产品编号',
},
{
minWidth: '100',
ellipsis: true,
colKey: 'purchaseNum',
title: '采购数量',
sorter: (a, b) => a.purchaseNum - b.purchaseNum,
},
{
minWidth: '100',
ellipsis: true,
colKey: 'adminName',
title: '申请部门',
},
{
minWidth: '250',
className: 'test',
ellipsis: true,
colKey: 'updateTime',
title: '创建时间',
sorter: (a, b) => Date.parse(a.updateTime) - Date.parse(b.updateTime),
},
{
align: 'left',
width: 200,
className: 'test2',
ellipsis: true,
colKey: 'op',
title: '操作',
},
];
export const PRODUCT_LIST = [
{
name: 'Macbook Pro 2021',
subTitle: 'Macbook Pro 2021',
size: '13.3 英寸',
cpu: 'Apple M1',
memory: 'RAM 16GB',
info: '最高可选配 16GB 内存 · 最高可选配 2TB 存储设备 电池续航最长达 18 小时',
use: 1420,
stock: 1500
},
{
name: 'Surface Laptop Go',
subTitle: '微软Microsoft Corporation',
size: '12.4 英寸',
cpu: 'Core i7',
memory: 'RAM 16GB',
info: '常规使用 Surface续航时间最长可达13小时 随时伴您工作',
use: 120,
stock: 2000
}
]

View File

@ -8,13 +8,19 @@
color: rgba(0, 0, 0, .6) !important; color: rgba(0, 0, 0, .6) !important;
} }
.t-table.t-size-l th,
.t-table.t-size-l td {
padding: 13px 13px 12px 24px;
line-height: 22px;
}
.row-padding { .row-padding {
padding-top: 30px; padding-top: 30px;
padding-left: 20px; padding-left: 20px;
} }
.operater-block-container { .t-tag.t-size-s {
padding: 10px 0 30px; margin-left: 8px;
} }
.operater-add { .operater-add {
@ -27,6 +33,14 @@
border: dashed 1px #dedede; border: dashed 1px #dedede;
border-radius: 3px; border-radius: 3px;
.operater-sub-icon {
background: #ecf2fe;
color: @brand-color;
font-size: 33px;
padding: 8px;
border-radius: 100%;
}
.operater-sub { .operater-sub {
font-size: 14px; font-size: 14px;
color: @text-color-secondary; color: @text-color-secondary;
@ -41,7 +55,7 @@
svg { svg {
rect { rect {
fill: @brand-color-2; fill: @brand-color-1;
} }
path { path {
@ -69,6 +83,14 @@
padding: 20px 32px 24px 32px; padding: 20px 32px 24px 32px;
height: 256px; height: 256px;
.operater-title-icon {
background: #ecf2fe;
color: @brand-color;
font-size: 56px;
padding: 14px;
border-radius: 100%;
}
.operater-title { .operater-title {
margin-bottom: 25px; margin-bottom: 25px;
position: relative; position: relative;
@ -88,7 +110,10 @@
} }
&-tag { &-tag {
margin-right: 8px; margin-right: 4px;
margin-top: 8px;
margin-left: unset;
border: unset
} }
&-icon { &-icon {
@ -124,7 +149,7 @@
&-icon { &-icon {
position: absolute; position: absolute;
bottom: 0; bottom: 8px;
right: 0; right: 0;
} }
} }
@ -134,6 +159,7 @@
position: absolute; position: absolute;
width: 100%; width: 100%;
bottom: 0px; bottom: 0px;
left: 0;
.t-progress--thin { .t-progress--thin {
display: unset; display: unset;
@ -152,9 +178,8 @@
&-panel { &-panel {
background-color: white; background-color: white;
padding: @spacer-3; padding: @spacer-3 @spacer-4 @spacer-4 @spacer-4;
border-radius: @border-radius; border-radius: @border-radius;
margin-top: 16px;
} }
&-search-input { &-search-input {
@ -163,13 +188,12 @@
} }
&-operater-row { &-operater-row {
margin-bottom: 12px; margin-bottom: 32px;
} }
&-operater-title { &-operater-title {
font-size: 20px; font-size: 20px;
color: rgba(0, 0, 0, .9); color: rgba(0, 0, 0, .9);
font-weight: bold;
} }
&-operater-label { &-operater-label {
@ -178,8 +202,17 @@
} }
} }
.advanced-card {
margin-top: 0 !important;
.card-title-default {
margin-bottom: 12px;
}
}
.info-block { .info-block {
column-count: 2; column-count: 2;
margin-bottom: 12px;
.info-item { .info-item {
padding: 12px 0; padding: 12px 0;

View File

@ -1,21 +1,8 @@
<template> <template>
<div> <div>
<div :class="prefix + '-panel'"> <card title="基本信息" class="advanced-card">
<div class="base-info">
<t-row
:class="prefix + '-operater-row'"
justify="space-between"
>
<p :class="prefix + '-operater-title'">
基本信息
</p>
</t-row>
<div class="info-block"> <div class="info-block">
<div <div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
v-for="(item, index) in baseInfoData"
:key="index"
class="info-item"
>
<h1>{{ item.name }}</h1> <h1>{{ item.name }}</h1>
<span <span
:class="{ :class="{
@ -28,259 +15,54 @@
</span> </span>
</div> </div>
</div> </div>
</div> </card>
</div>
<!-- 发票进度 --> <!-- 发票进度 -->
<div :class="prefix + '-panel'"> <card title="发票进度">
<t-row <t-row :class="PREFIX + '-operater-row row-padding'" justify="space-between">
:class="prefix + '-operater-row'" <t-steps theme="dot" :current="updateCurrent">
justify="space-between" <t-step-item title="申请提交" content="已于12月21日提交" />
> <t-step-item title="电子发票" content="预计13个工作日" />
<p :class="prefix + '-operater-title'"> <t-step-item title="发票已邮寄" content="电子发票开出后7个工作日内联系" />
发票进度 <t-step-item title="完成" content />
</p>
</t-row>
<t-row
:class="prefix + '-operater-row row-padding'"
justify="space-between"
>
<t-steps
theme="dot"
:current="updateCurrent"
>
<t-step-item
title="申请提交"
content="已于12月21日提交"
/>
<t-step-item
title="电子发票"
content="预计13个工作日"
/>
<t-step-item
title="发票已邮寄"
content="电子发票开出后7个工作日内联系"
/>
<t-step-item
title="完成"
content
/>
</t-steps> </t-steps>
</t-row> </t-row>
</div> </card>
<!-- 产品目录 --> <!-- 产品目录 -->
<div :class="prefix + '-panel'"> <card title="产品目录">
<t-row <template #option>
:class="prefix + '-operater-row'" <t-radio-group default-value="dateVal">
justify="space-between" <t-radio-button value="dateVal">
> 季度
<p :class="prefix + '-operater-title'"> </t-radio-button>
产品目录 <t-radio-button value="monthVal">
</p> 月份
</t-row> </t-radio-button>
</t-radio-group>
</template>
<t-row class="operater-block-container"> <t-row class="operater-block-container">
<t-col :flex="1"> <t-col :flex="1">
<div class="operater-add"> <div class="operater-add">
<div class="operater-sub"> <div class="operater-sub">
<svg <t-icon name="add" class="operater-sub-icon" />
width="34"
height="34"
viewBox="0 0 34 34"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect
x="0.5"
y="0.5"
width="33"
height="33"
rx="16.5"
stroke="white"
/>
<path d="M16.35 17.6501V21.5H17.65V17.6501H21.5V16.3501H17.65V12.5H16.35V16.3501H12.5V17.6501H16.35Z" />
</svg>
<span>新增产品</span> <span>新增产品</span>
</div> </div>
</div> </div>
</t-col> </t-col>
<t-col :flex="1"> <t-col v-for="(item, index) in PRODUCT_LIST" :key="index" :flex="1">
<div class="operater-block operater-gap"> <product :data="item" />
<div class="operater-content">
<div class="operater-title">
<svg
class="operater-title-icon"
width="56"
height="56"
viewBox="0 0 56 56"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="28"
cy="28"
r="28"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M14 18H17.1529L19.93 34.663C20.0586 35.4345 20.7261 36 21.5083 36H40V34H21.8471L21.1805 30H38.4478C39.182 30 39.8219 29.5003 40 28.7881L41.7 21.9881C41.9525 20.9782 41.1887 20 40.1478 20H19.5138L19.07 17.337C18.9414 16.5655 18.2739 16 17.4917 16H14V18ZM38.1355 28H20.8471L19.8471 22H39.6355L38.1355 28Z"
/>
<path
d="M21.5 41C22.3284 41 23 40.3284 23 39.5C23 38.6716 22.3284 38 21.5 38C20.6716 38 20 38.6716 20 39.5C20 40.3284 20.6716 41 21.5 41Z"
/>
<path
d="M37.6259 41C38.4543 41 39.1259 40.3284 39.1259 39.5C39.1259 38.6716 38.4543 38 37.6259 38C36.7975 38 36.1259 38.6716 36.1259 39.5C36.1259 40.3284 36.7975 41 37.6259 41Z"
/>
</svg>
<h1>Macbook Pro 2021</h1>
<div class="operater-title-subtitle">
Macbook Pro 2021
</div>
<div class="operater-title-tags">
<t-tag
class="operater-title-tag"
theme="success"
size="small"
>
13.3 英寸
</t-tag>
<t-tag
class="operater-title-tag"
size="small"
>
Apple M1
</t-tag>
<t-tag
class="operater-title-tag"
size="small"
>
RAM 16GB
</t-tag>
</div>
</div>
<div class="operater-item">
<span
class="operater-item-info"
>最高可选配 16GB 内存 · 最高可选配 2TB 存储设备 电池续航最长达 18 小时</span>
<t-icon
class="operater-item-icon"
name="chevron-right"
size="small"
style="color: rgba(0, 0, 0, .26)"
/>
</div>
<div class="operater-footer">
<span class="operater-footer-percentage">1420 / 1500</span>
<t-progress
class="operater-progress"
theme="line"
:percentage="(1420 / 1500) * 100"
:label="false"
track-color="#D4E3FC"
/>
</div>
</div>
</div>
</t-col>
<t-col :flex="1">
<div class="operater-block operater-gap">
<div class="operater-content">
<div class="operater-title">
<svg
class="operater-title-icon"
width="56"
height="56"
viewBox="0 0 56 56"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle
cx="28"
cy="28"
r="28"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M14 18H17.1529L19.93 34.663C20.0586 35.4345 20.7261 36 21.5083 36H40V34H21.8471L21.1805 30H38.4478C39.182 30 39.8219 29.5003 40 28.7881L41.7 21.9881C41.9525 20.9782 41.1887 20 40.1478 20H19.5138L19.07 17.337C18.9414 16.5655 18.2739 16 17.4917 16H14V18ZM38.1355 28H20.8471L19.8471 22H39.6355L38.1355 28Z"
/>
<path
d="M21.5 41C22.3284 41 23 40.3284 23 39.5C23 38.6716 22.3284 38 21.5 38C20.6716 38 20 38.6716 20 39.5C20 40.3284 20.6716 41 21.5 41Z"
/>
<path
d="M37.6259 41C38.4543 41 39.1259 40.3284 39.1259 39.5C39.1259 38.6716 38.4543 38 37.6259 38C36.7975 38 36.1259 38.6716 36.1259 39.5C36.1259 40.3284 36.7975 41 37.6259 41Z"
/>
</svg>
<h1>Surface Laptop Go</h1>
<div class="operater-title-subtitle">
微软Microsoft Corporation
</div>
<div class="operater-title-tags">
<t-tag
class="operater-title-tag"
theme="success"
size="small"
>
12.4 英寸
</t-tag>
<t-tag
class="operater-title-tag"
size="small"
>
Core i7
</t-tag>
<t-tag
class="operater-title-tag"
size="small"
>
RAM 16GB
</t-tag>
</div>
</div>
<div class="operater-item">
<span class="operater-item-info">常规使用 Surface续航时间最长可达13小时 随时伴您工作</span>
<t-icon
class="operater-item-icon"
name="chevron-right"
size="small"
style="color: rgba(0, 0, 0, .26)"
/>
</div>
</div>
<div class="operater-footer">
<span class="operater-footer-percentage">120 / 2000</span>
<t-progress
class="operater-progress"
theme="line"
:percentage="(120 / 2000) * 100"
:label="false"
color="#E24D59"
track-color="#FCD4D4"
/>
</div>
</div>
</t-col> </t-col>
</t-row> </t-row>
</div> </card>
<!-- 产品采购明细 --> <!-- 产品采购明细 -->
<div :class="prefix + '-panel'"> <card title="产品采购明细">
<t-row
:class="prefix + '-operater-row'"
justify="space-between"
>
<p :class="prefix + '-operater-title'">
产品采购明细
</p>
</t-row>
<t-table <t-table
:columns="columns" :columns="columns"
:data="data" :data="data"
:pagination="pagination" :pagination="pagination"
:hover="hover" :hover="true"
row-key="index" row-key="index"
size="large" size="large"
@sort-change="sortChange" @sort-change="sortChange"
@ -289,53 +71,32 @@
<template #pdName="{ row }"> <template #pdName="{ row }">
<span> <span>
{{ row.pdName }} {{ row.pdName }}
<t-tag <t-tag v-if="row.pdType" size="small">{{ row.pdType }}</t-tag>
v-if="row.pdType"
size="small"
>{{ row.pdType }}</t-tag>
</span> </span>
</template> </template>
<template #purchaseNum="{ row }"> <template #purchaseNum="{ row }">
<span> <span>
{{ row.purchaseNum }} {{ row.purchaseNum }}
<t-tag <t-tag v-if="row.purchaseNum > 50" theme="danger" variant="light" size="small">超预算</t-tag>
v-if="row.purchaseNum > 50"
theme="danger"
variant="light"
size="small"
>超预算</t-tag>
</span> </span>
</template> </template>
<template #op="slotProps"> <template #op="slotProps">
<a <a :class="PREFIX + '-link'" @click="listClick()">管理</a>
:class="prefix + '-link'" <a :class="PREFIX + '-link'" @click="deleteClickOp(slotProps)">删除</a>
@click="listClick(slotProps)"
>管理</a>
<a
:class="prefix + '-link'"
@click="deleteClickOp(slotProps)"
>删除</a>
</template> </template>
<template #op-column> <template #op-column>
<t-icon name="descending-order" /> <t-icon name="descending-order" />
</template> </template>
</t-table> </t-table>
</div> </card>
<t-dialog
v-model:visible="visible" <t-dialog v-model:visible="visible" header="基本信息" @confirm="onConfirm">
header="基本信息"
@confirm="onConfirm"
>
<template #body> <template #body>
<div class="dialog-info-block"> <div class="dialog-info-block">
<div <div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
v-for="(item, index) in baseInfoData"
:key="index"
class="info-item"
>
<h1>{{ item.name }}</h1> <h1>{{ item.name }}</h1>
<span <span
:class="{ :class="{
@ -353,78 +114,91 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent, ref, onMounted } from 'vue';
import { PREFIX as prefix } from '@/config/global'; import { PREFIX } from '@/config/global';
import model from './index'; import { BASE_INFO_DATA, TABLE_COLUMNS_DATA, PRODUCT_LIST } from './constants';
import request from '@/utils/request';
import { ResDataType } from '@/interface';
// import Card from '@/components/card/index.vue';
import './index.less'; import Product from './components/Product.vue';
export default defineComponent({ export default defineComponent({
name: 'DetailAdvanced', name: 'DetailAdvanced',
data() { components: {
return { Card,
data: [], Product,
prefix, },
updateCurrent: 0, setup() {
columns: model.getTableColumns(), const data = ref([]);
baseInfoData: model.getBaseInfoData(), const pagination = ref({
bordered: true,
hover: true,
visible: false,
pagination: {
defaultPageSize: 10, defaultPageSize: 10,
total: 100, total: 100,
defaultCurrent: 1, defaultCurrent: 1,
}, });
};
},
async mounted() {
//
setInterval(() => {
if (this.updateCurrent > 5) {
this.updateCurrent = -1;
}
this.updateCurrent = this.updateCurrent + 1;
}, 2000);
this.$request const updateCurrent = ref(0);
.get('/api/get-purchase-list')
.then((res) => { const setpUpdate = () => {
setInterval(() => {
if (updateCurrent.value > 5) {
updateCurrent.value = -1;
}
updateCurrent.value += 1;
}, 2000);
};
const fetchData = async () => {
try {
const res:ResDataType = await request.get('/api/get-purchase-list');
if (res.code === 0) { if (res.code === 0) {
const { list = [] } = res.data; const { list = [] } = res.data;
this.data = list; data.value = list;
this.pagination = { pagination.value = {
...this.pagination, ...pagination.value,
total: list.length, total: list.length,
}; };
} }
}) } catch (e) {
.catch((e) => {
console.log(e); console.log(e);
}
};
onMounted(() => {
setpUpdate();
fetchData();
}); });
},
methods: { const visible = ref(false);
return {
BASE_INFO_DATA,
PREFIX,
PRODUCT_LIST,
columns: TABLE_COLUMNS_DATA,
data,
pagination,
visible,
updateCurrent,
sortChange(val) { sortChange(val) {
console.log(val); console.log(val);
}, },
rehandleChange(changeParams, triggerAndData) { rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData); console.log('统一Change', changeParams, triggerAndData);
}, },
listClick(e) { listClick() {
console.log(e); visible.value = true;
this.visible = true;
}, },
deleteClickOp(e) { deleteClickOp(columns) {
this.data.splice(e.index, 1); data.value.splice(columns.index, 1);
}, },
onConfirm() { onConfirm() {
this.visible = false; visible.value = false;
}, },
};
}, },
}); });
</script> </script>
<style> <style lang="less" scoped>
@import url('./index.less');
</style> </style>

View File

@ -0,0 +1,78 @@
export const BASE_INFO_DATA = [
{
name: '合同名称',
value: '总部办公用品采购项目',
type: null,
},
{
name: '合同状态',
value: '履行中',
type: {
key: 'contractStatus',
value: 'inProgress',
},
},
{
name: '合同编号',
value: 'BH00010',
type: null,
},
{
name: '合同类型',
value: '主合同',
type: null,
},
{
name: '合同收付类型',
value: '付款',
type: null,
},
{
name: '合同金额',
value: '5,000,000元',
type: null,
},
{
name: '甲方',
value: '腾讯科技(深圳)有限公司',
type: null,
},
{
name: '乙方',
value: '欧尚',
type: null,
},
{
name: '合同签订日期',
value: '2020-12-20',
type: null,
},
{
name: '合同生效日期',
value: '2021-01-20',
type: null,
},
{
name: '合同结束日期',
value: '2022-12-20',
type: null,
},
{
name: '合同附件',
value: '总部办公用品采购项目合同.pdf',
type: {
key: 'contractAnnex',
value: 'pdf',
},
},
{
name: '备注',
value: '--',
type: null,
},
{
name: '创建时间',
value: '2020-12-22 10:00:00',
type: null,
},
]

View File

@ -4,27 +4,44 @@
padding-top: @spacer-3; padding-top: @spacer-3;
} }
.@{prefix} { .t-steps .t-steps-item-title {
font-size: @font-size-base;
}
&-panel { .@{prefix} {
background-color: white;
padding: @spacer-4;
border-radius: @border-radius;
}
&-operater-row { &-operater-row {
margin-bottom: 12px; margin-bottom: 12px;
} }
}
&-operater-title { .detail-base-panel {
font-weight: 400; background-color: white;
padding: @spacer-3 @spacer-4 @spacer-4 @spacer-4;
border-radius: @border-radius;
margin-top: 0;
&-row {
margin-bottom: 12px;
}
}
.detail-base-info {
margin-bottom: 12px;
}
.detail-base-info-title {
margin: @spacer-1 0;
font-size: @font-size-xl;
font-weight: 500;
line-height: 28px;
color: @text-color-primary; color: @text-color-primary;
font-family: PingFangSC-Medium; font-family: PingFangSC-Regular;
}
.t-steps-item-title { .detail-base-info-steps {
font-size: @font-size-base; padding-top: 12px;
}
}
} }
.info-block { .info-block {

View File

@ -1,21 +1,13 @@
<template> <template>
<div> <div>
<div :class="prefix + '-panel'"> <div class="detail-base-panel">
<div class="base-info"> <t-row class="detail-base-info" justify="space-between">
<t-row <p class="detail-base-info-title">
:class="prefix + '-operater-row'"
justify="space-between"
>
<p :class="prefix + '-operater-title'">
基本信息 基本信息
</p> </p>
</t-row> </t-row>
<div class="info-block"> <div class="info-block">
<div <div v-for="(item, index) in BASE_INFO_DATA" :key="index" class="info-item">
v-for="(item, index) in baseInfoData"
:key="index"
class="info-item"
>
<h1>{{ item.name }}</h1> <h1>{{ item.name }}</h1>
<span <span
:class="{ :class="{
@ -28,34 +20,17 @@
</span> </span>
</div> </div>
</div> </div>
</div> <t-divider style="margin-top: 24px; margin-bottom: 23px; border-top-color: rgba(255, 255, 255, 0)" />
<t-divider style="margin-top: 12px" />
<div class="update-history"> <div class="update-history">
<t-row <t-row class="detail-base-info" justify="space-between">
:class="prefix + '-operater-row'" <p class="detail-base-info-title">
justify="space-between"
>
<p :class="prefix + '-operater-title'">
变更记录 变更记录
</p> </p>
</t-row> </t-row>
<t-steps <t-steps class="detail-base-info-steps" direction="vertical" theme="dot" :current="1">
direction="vertical" <t-step-item title="上传合同附件" content="这里是提示文字" />
theme="dot" <t-step-item title="修改合同金额" content="这里是提示文字" />
:current="1" <t-step-item title="新建合同" content="2020-12-01 15:00:00 管理员-李川操作" />
>
<t-step-item
title="上传合同附件"
content="这里是提示文字"
/>
<t-step-item
title="修改合同金额"
content="这里是提示文字"
/>
<t-step-item
title="新建合同"
content="2020-12-01 15:00:00 管理员-李川操作"
/>
</t-steps> </t-steps>
</div> </div>
</div> </div>
@ -63,21 +38,17 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { PREFIX as prefix } from '@/config/global'; import { BASE_INFO_DATA } from './constants';
import model from './index';
import './index.less';
export default defineComponent({ export default defineComponent({
name: 'ListBase', name: 'ListBase',
data() { data() {
return { return {
prefix, BASE_INFO_DATA,
baseInfoData: model.getBaseInfoData(),
}; };
}, },
}); });
</script> </script>
<style> <style lang="less" scoped>
@import url('./index.less');
</style> </style>

View File

@ -0,0 +1,115 @@
export const BASE_INFO_DATA = [
{
name: '集群名',
value: 'helloworld',
type: null,
},
{
name: '集群ID',
value: 'cls - 2ntelvxw',
type: {
key: 'color',
value: 'blue',
},
},
{
name: '状态',
value: '运行中',
type: {
key: 'color',
value: 'green',
},
},
{
name: 'K8S版本',
value: '1.7.8',
type: null,
},
{
name: '配置',
value: '6.73 核 10.30 GB',
type: null,
},
{
name: '所在地域',
value: '广州',
type: null,
},
{
name: '新增资源所属项目',
value: '默认项目',
type: null,
},
{
name: '节点数量',
value: '4 个',
type: null,
},
{
name: '节点网络',
value: 'vpc - 5frmkm1x',
type: {
key: 'color',
value: 'blue',
},
},
{
name: '容器网络',
value: '172.16.0.0 / 16',
type: null,
},
{
name: '集群凭证',
value: '显示凭证',
type: {
key: 'color',
value: 'blue',
},
},
{
name: '创建/更新',
value: '2018-05-31 22:11:44 2018-05-31 22:11:44',
type: {
key: 'contractAnnex',
value: 'pdf',
},
},
{
name: '描述',
value: 'istio_test',
type: null,
},
];
export const TABLE_COLUMNS = [
{
minWidth: '250',
ellipsis: true,
colKey: 'name',
title: '项目名称',
sorter: (a, b) => a.name.substr(10) - b.name.substr(10),
},
{
minWidth: '200',
ellipsis: true,
colKey: 'adminName',
title: '管理员',
},
{
minWidth: '100',
className: 'test',
ellipsis: true,
colKey: 'updateTime',
title: '创建时间',
sorter: (a, b) => Date.parse(a.updateTime) - Date.parse(b.updateTime),
},
{
align: 'left',
width: 200,
className: 'test2',
ellipsis: true,
colKey: 'op',
title: '操作',
},
];

View File

@ -3,8 +3,7 @@
.secondary-notification { .secondary-notification {
background-color: white; background-color: white;
border-radius: @border-radius; border-radius: @border-radius;
margin-top: 16px; padding: @spacer-3 @spacer-4;
padding: 32px;
.t-tabs__content { .t-tabs__content {
padding-top: 0; padding-top: 0;
@ -12,12 +11,11 @@
} }
.secondary-msg-list { .secondary-msg-list {
min-height: 443px; height: 70vh;
max-height: calc(100vh - 400px);
.t-list-item { .t-list-item {
cursor: pointer; cursor: pointer;
padding: 16px 24px 16px 0; padding: 13px 24px 13px 0;
&:hover { &:hover {
background-color: @bg-color-container-hover; background-color: @bg-color-container-hover;
@ -36,6 +34,11 @@
} }
} }
} }
.t-tag.t-size-s {
margin-right: @spacer-1;
margin-left: 0;
}
} }
.content { .content {

View File

@ -1,30 +1,11 @@
<template> <template>
<t-page-header> 通知中心 </t-page-header>
<div class="secondary-notification"> <div class="secondary-notification">
<t-tabs v-model="value"> <t-tabs v-model="tabValue">
<t-tab-panel <t-tab-panel v-for="(tab, tabIndex) in TAB_LIST" :key="tabIndex" :value="tab.value" :label="tab.label">
value="frist" <t-list v-if="msgDataList.length > 0" class="secondary-msg-list" :split="true">
label="全部通知" <t-list-item v-for="(item, index) in msgDataList" :key="index">
> <p :class="['content', { unread: item.status }]" @click="setReadStatus(item)">
<t-list <t-tag class="operater-title-tag" size="small" :theme="NOTIFICATION_TYPES[item.priorty]" variant="light">
v-if="msgData.length > 0"
class="secondary-msg-list"
:split="true"
>
<t-list-item
v-for="(item, index) in msgData"
:key="index"
>
<p
:class="['content', { unread: item.status }]"
@click="setReadStatus(item)"
>
<t-tag
class="operater-title-tag"
size="small"
:theme="NOTIFICATION_TYPES[item.priorty]"
variant="light"
>
{{ item.type }} {{ item.type }}
</t-tag> </t-tag>
{{ item.content }} {{ item.content }}
@ -38,212 +19,25 @@
:overlay-style="{ margin: '6px' }" :overlay-style="{ margin: '6px' }"
:content="item.status ? '设为已读' : '设为未读'" :content="item.status ? '设为已读' : '设为未读'"
> >
<span <span class="msg-action-icon" @click="setReadStatus(item)">
class="msg-action-icon" <t-icon v-if="!!item.status" name="queue" size="16px" />
@click="setReadStatus(item)" <read-icon v-else />
>
<t-icon
v-if="!!item.status"
name="queue"
size="16px"
/>
<svg
v-else
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.63795 11.4471H8.5V12.4471H5L2.49205 14.537C2.29666 14.6999 2 14.5609 2 14.3066V4.94708C2 4.3948 2.44772 3.94708 3 3.94708H13C13.5523 3.94708 14 4.3948 14 4.94708V10H13V4.94708H3V12.812L4.63795 11.4471Z"
fill="black"
/>
<path
d="M11.7786 14.9286L15.3536 11.3535L14.6464 10.6465L11.7786 13.5144L10.1318 11.8677L9.42471 12.5748L11.7786 14.9286Z"
fill="black"
/>
</svg>
</span> </span>
</t-tooltip> </t-tooltip>
<t-tooltip <t-tooltip content="删除通知" :overlay-style="{ margin: '6px' }">
content="删除通知"
:overlay-style="{ margin: '6px' }"
>
<span @click="handleClickDeleteBtn(item)"> <span @click="handleClickDeleteBtn(item)">
<t-icon <t-icon name="delete" size="16px" />
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 <div v-else class="secondary-msg-list__empty-list">
v-else <img src="https://tdesign.gtimg.com/pro-template/personal/nothing.png" alt="空">
class="secondary-msg-list__empty-list"
>
<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-tab-panel
value="second"
label="未读通知"
>
<t-list
v-if="unreadMsg.length > 0"
class="secondary-msg-list"
:split="true"
>
<t-list-item
v-for="(item, index) in unreadMsg"
:key="index"
>
<p
:class="['content', { unread: item.status }]"
@click="setReadStatus(item)"
>
<t-tag
class="operater-title-tag"
size="small"
:theme="NOTIFICATION_TYPES[item.priorty]"
variant="light"
>
{{ item.type }}
</t-tag>
{{ item.content }}
</p>
<template #action>
<p class="msg-date">
{{ item.date }}
</p>
<div class="msg-action">
<t-tooltip
class="set-read-icon"
:overlay-style="{ margin: '6px' }"
:content="item.status ? '设为已读' : '设为未读'"
>
<span @click="setReadStatus(item)">
<t-icon
name="queue"
size="16px"
/>
</span>
</t-tooltip>
<t-tooltip
content="删除通知"
:overlay-style="{ margin: '6px' }"
>
<span @click="handleClickDeleteBtn(item)">
<t-icon
name="delete"
size="16px"
/>
</span>
</t-tooltip>
</div>
</template>
</t-list-item>
</t-list>
<div
v-else
class="secondary-msg-list__empty-list"
>
<img
src="https://tdesign.gtimg.com/pro-template/personal/nothing.png"
alt="空"
>
<p>暂无未读通知</p>
</div>
</t-tab-panel>
<t-tab-panel
value="third"
label="已读通知"
>
<t-list
v-if="readMsg.length > 0"
class="secondary-msg-list"
:split="true"
>
<t-list-item
v-for="(item, index) in readMsg"
:key="index"
>
<p :class="['content', { unread: item.status }]">
<t-tag
class="operater-title-tag"
size="small"
:theme="NOTIFICATION_TYPES[item.priorty]"
variant="light"
>
{{ item.type }}
</t-tag>
{{ item.content }}
</p>
<template #action>
<p class="msg-date">
{{ item.date }}
</p>
<div class="msg-action">
<t-tooltip
class="set-read-icon"
:overlay-style="{ margin: '6px' }"
:content="item.status ? '设为已读' : '设为未读'"
>
<span
class="msg-action-icon"
@click="setReadStatus(item)"
>
<svg
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.63795 11.4471H8.5V12.4471H5L2.49205 14.537C2.29666 14.6999 2 14.5609 2 14.3066V4.94708C2 4.3948 2.44772 3.94708 3 3.94708H13C13.5523 3.94708 14 4.3948 14 4.94708V10H13V4.94708H3V12.812L4.63795 11.4471Z"
fill="black"
/>
<path
d="M11.7786 14.9286L15.3536 11.3535L14.6464 10.6465L11.7786 13.5144L10.1318 11.8677L9.42471 12.5748L11.7786 14.9286Z"
fill="black"
/>
</svg>
</span>
</t-tooltip>
<t-tooltip
content="删除通知"
:overlay-style="{ margin: '6px' }"
>
<span @click="handleClickDeleteBtn(item)">
<t-icon
name="delete"
size="16px"
/>
</span>
</t-tooltip>
</div>
</template>
</t-list-item>
</t-list>
<div
v-else
class="secondary-msg-list__empty-list"
>
<img
src="https://tdesign.gtimg.com/pro-template/personal/nothing.png"
alt="空"
>
<p>暂无已读通知</p>
</div>
</t-tab-panel>
</t-tabs> </t-tabs>
</div> </div>
<t-dialog <t-dialog
@ -254,56 +48,87 @@
/> />
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent, ref, computed } from 'vue';
import { mapState, mapGetters } from 'vuex'; import { useStore } from 'vuex';
import { PREFIX as prefix } from '@/config/global';
import { NOTIFICATION_TYPES } from '@/constants'; import { NOTIFICATION_TYPES } from '@/constants';
import ReadIcon from '@/assets/read.svg?component';
// const TAB_LIST = [
import './index.less'; {
label: '全部通知',
value: 'msgData',
},
{
label: '未读通知',
value: 'unreadMsg',
},
{
label: '已读通知',
value: 'readMsg',
},
];
export default defineComponent({ export default defineComponent({
name: 'DetailSecondary', name: 'DetailSecondary',
components: {}, components: { ReadIcon },
data() { setup() {
return { const tabValue = ref('msgData');
NOTIFICATION_TYPES,
prefix, const visible = ref(false);
data: [], const selectedItem = ref(undefined);
value: 'frist',
visible: false, const store = useStore();
selectedItem: undefined,
const { msgData } = store.state.notification;
const msgDataList = computed(() => {
if (tabValue.value === 'msgData') return msgData;
if (tabValue.value === 'unreadMsg') return store.getters['notification/unreadMsg'];
if (tabValue.value === 'readMsg') return store.getters['notification/readMsg'];
return [];
});
const handleClickDeleteBtn = (item) => {
visible.value = true;
selectedItem.value = item;
}; };
},
computed: { const setReadStatus = (item) => {
...mapState('notification', ['msgData']), const changeMsg = msgData;
...mapGetters('notification', ['unreadMsg', 'readMsg']),
},
methods: {
handleClickDeleteBtn(item) {
this.visible = true;
this.selectedItem = item;
},
setReadStatus(item) {
const changeMsg = this.msgData;
changeMsg.forEach((e) => { changeMsg.forEach((e) => {
if (e.id === item.id) { if (e.id === item.id) {
e.status = !e.status; e.status = !e.status;
} }
}); });
this.$store.commit('notification/setMsgData', changeMsg); store.commit('notification/setMsgData', changeMsg);
}, };
deleteMsg() {
const item = this.selectedItem; const deleteMsg = () => {
const changeMsg = this.msgData; const item = selectedItem.value;
const changeMsg = msgData;
changeMsg.forEach((e, index) => { changeMsg.forEach((e, index) => {
if (e.id === item.id) { if (e.id === item.id) {
changeMsg.splice(index, 1); changeMsg.splice(index, 1);
} }
}); });
this.visible = false; visible.value = false;
this.$store.commit('notification/setMsgData', changeMsg); store.commit('notification/setMsgData', changeMsg);
}, };
return {
TAB_LIST,
NOTIFICATION_TYPES,
visible,
selectedItem,
tabValue,
msgDataList,
handleClickDeleteBtn,
setReadStatus,
deleteMsg,
};
}, },
}); });
</script> </script>
<style lang="less" scoped>
@import url('./index.less');
</style>

View File

@ -0,0 +1,42 @@
export const FORM_RULES = {
name: [{ required: true, message: '请输入合同名称', type: 'error' }],
type: [{ required: true, message: '请选择合同类型', type: 'error' }],
payment: [{ required: true, message: '请选择合同收付类型', type: 'error' }],
amount: [{ required: true, message: '请输入合同金额', type: 'error' }],
partyA: [{ required: true, message: '请选择甲方', type: 'error' }],
partyB: [{ required: true, message: '请选择乙方', type: 'error' }],
signDate: [{ required: true, message: '请选择日期', type: 'error' }],
startDate: [{ required: true, message: '请选择日期', type: 'error' }],
endDate: [{ required: true, message: '请选择日期', type: 'error' }],
}
export const INITIAL_DATA = {
name: '',
type: '',
partyA: '',
partyB: '',
signDate: '',
startDate: '',
endDate: '',
payment: '1',
amount: 0,
comment: ''
};
export const TYPE_OPTIONS = [
{ label: '类型A', value: '1' },
{ label: '类型B', value: '2' },
{ label: '类型C', value: '3' },
]
export const PARTY_A_OPTIONS = [
{ label: '公司A', value: '1' },
{ label: '公司B', value: '2' },
{ label: '公司C', value: '3' },
]
export const PARTY_B_OPTIONS = [
{ label: '公司A', value: '1' },
{ label: '公司B', value: '2' },
{ label: '公司C', value: '3' },
]

View File

@ -25,3 +25,154 @@
color: @text-color-secondary; color: @text-color-secondary;
line-height: 20px; line-height: 20px;
} }
.form-item-container {
display: flex;
// align-items: center;
justify-content: center;
}
.form-basic-container {
display: flex;
align-items: center;
justify-content: center;
border-bottom-left-radius: 0 !important;
border-bottom-right-radius: 0 !important;
.span-item {
width: 12px;
}
.form-gap {
padding-left: 32px;
}
.row-gap {
padding-bottom: 24px;
}
.form-basic-item {
// padding: 0 60px 0 160px;
.form-basic-container-title {
font-style: normal;
font-weight: normal;
font-size: 20px;
line-height: 22px;
color: rgba(0, 0, 0, .9);
padding: 64px 0 32px 0;
}
// .t-size-m {
// width: 100% !important;
// min-width: 280px;
// }
// .t-form-item__type {
// // width: 100% !important;
// min-width: 280px;
// }
}
.tdesign-pro-panel {
margin-top: 0px !important;
}
.t-textarea__inner {
height: 124px !important;
}
.form-cretifier {
font-size: 14px;
color: #000000;
padding-top: 24px;
padding-bottom: 130px;
.form-cretifier-container {
padding-top: 12px;
.form-cretifier-circle {
background: #0052d9;
border: 1px solid #a7a4a4;
border-radius: 40px;
width: 32px;
height: 32px;
color: #ffffff;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
text-align: center;
line-height: 22px;
font-weight: 500;
position: absolute;
}
.form-cretifier-gap1 {
margin-left: 25px;
}
.form-cretifier-gap2 {
margin-left: 50px;
}
.form-cretifier-blure {
background: #d4e3fc;
color: #0052d9;
}
}
}
}
.form-submit-container {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding-top: 30px;
padding-bottom: 28px;
background-color: #e3e6eb;
border-bottom: solid 1px #d8dadf;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
.form-submint-sub {
width: 676px;
display: flex;
align-items: center;
justify-content: space-between;
.form-submit-left {
.form-submit-upload-span {
font-size: 14px;
line-height: 22px;
color: rgba(0, 0, 0, .4);
padding-top: 8px;
display: inline-block;
}
}
.form-submit-upload-btn {
width: 144px;
height: 40px;
}
.form-submit-right {
.form-submit-cancel {
font-size: 16px !important;
color: #0052d9 !important;
background-color: #ebedf100 !important;
}
.form-submit-confirm {
font-size: 16px !important;
background: #0052d9 !important;
border-radius: 3px !important;
width: 80px !important;
height: 40px !important;
}
}
}
}

View File

@ -0,0 +1,53 @@
export const FORM_RULES = {
name: [{ required: true, message: '请选择合同名称', type: 'error' }],
type: [{ required: true, message: '请选择发票类型', type: 'error' }],
title: [{ required: true, message: '请输入发票抬头', type: 'error' }],
taxNum: [{ required: true, message: '请输入纳税人识别号', type: 'error' }],
consignee: [{ required: true, message: '请输入收货人', type: 'error' }],
mobileNum: [{ required: true, message: '请输入手机号码', type: 'error' }],
deliveryAddress: [{ required: true, message: '请选择收货地址', type: 'error' }],
fullAddress: [{ required: true, message: '请输入详细地址', type: 'error' }],
};
export const NAME_OPTIONS = [
{ label: '合同A', value: '1' },
{ label: '合同B', value: '2' },
{ label: '合同C', value: '3' },
];
export const TYPE_OPTIONS = [
{ label: '类型A', value: '1' },
{ label: '类型B', value: '2' },
{ label: '类型C', value: '3' },
];
export const ADDRESS_OPTIONS = [
{ label: '广东省深圳市南山区', value: '1' },
{ label: '北京市海淀区', value: '2' },
{ label: '上海市徐汇区', value: '3' },
{ label: '四川省成都市高新区', value: '4' },
{ label: '广东省广州市天河区', value: '5' },
{ label: '陕西省西安市高新区', value: '6' },
];
export const INITIAL_DATA1 = {
name: '',
type: '',
};
export const INITIAL_DATA2 = {
title: '',
taxNum: '',
address: '',
bank: '',
bankAccount: '',
email: '',
tel: '',
};
export const INITIAL_DATA3 = {
consignee: '',
mobileNum: '',
deliveryAddress: '',
fullAddress: '',
};

View File

@ -1,12 +1,8 @@
<template> <template>
<t-page-header>分步表单页</t-page-header> <div :class="`${PREFIX}-panel ${PREFIX}-step-panel`">
<div :class="`${prefix}-panel ${prefix}-step-panel`">
<!-- 简单步骤条 --> <!-- 简单步骤条 -->
<div :class="`${prefix}-step step-top`"> <div :class="`${PREFIX}-step step-top`">
<t-steps <t-steps :current="activeForm" status="process">
: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="确认邮寄地址" />
@ -15,15 +11,8 @@
</div> </div>
<!-- 分步表单1 --> <!-- 分步表单1 -->
<div <div v-show="activeForm === 0" class="rule-tips">
v-show="activeForm === 0" <t-alert theme="info" title="发票开具规则:" :close="true">
class="rule-tips"
>
<t-alert
theme="info"
title="发票开具规则:"
:close="true"
>
<template #message> <template #message>
<p> <p>
1申请开票后电子发票在13个工作日内开具增值税专用发票纸质如资质审核通过将在电子发票开具后10个工作日内为您寄出 1申请开票后电子发票在13个工作日内开具增值税专用发票纸质如资质审核通过将在电子发票开具后10个工作日内为您寄出
@ -37,46 +26,20 @@
v-show="activeForm === 0" v-show="activeForm === 0"
class="step-form" class="step-form"
:data="formData1" :data="formData1"
:rules="rules" :rules="FORM_RULES"
label-align="left" label-align="left"
@submit="onSubmit1" @submit="({ validateResult }) => onSubmit({ validateResult }, 1)"
>
<t-form-item
label="合同名称"
name="name"
>
<t-select
v-model="formData1.name"
:style="{ width: '480px' }"
class="demo-select-base"
clearable
>
<t-option
v-for="(item, index) in nameOptions"
:key="index"
:value="item.value"
:label="item.label"
> >
<t-form-item label="合同名称" name="name">
<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">
{{ item.label }} {{ item.label }}
</t-option> </t-option>
</t-select> </t-select>
</t-form-item> </t-form-item>
<t-form-item <t-form-item label="发票类型" name="type">
label="发票类型" <t-select v-model="formData1.type" :style="{ width: '480px' }" class="demo-select-base" clearable>
name="type" <t-option v-for="(item, index) in TYPE_OPTIONS" :key="index" :value="item.value" :label="item.label">
>
<t-select
v-model="formData1.type"
:style="{ width: '480px' }"
class="demo-select-base"
clearable
>
<t-option
v-for="(item, index) in typeOptions"
:key="index"
:value="item.value"
:label="item.label"
>
{{ item.label }} {{ item.label }}
</t-option> </t-option>
</t-select> </t-select>
@ -85,10 +48,7 @@
{{ amount }} {{ amount }}
</t-form-item> </t-form-item>
<t-form-item> <t-form-item>
<t-button <t-button theme="primary" type="submit">
theme="primary"
type="submit"
>
提交申请 提交申请
</t-button> </t-button>
</t-form-item> </t-form-item>
@ -99,93 +59,37 @@
v-show="activeForm === 1" v-show="activeForm === 1"
class="step-form" class="step-form"
:data="formData2" :data="formData2"
:rules="rules" :rules="FORM_RULES"
label-align="left" label-align="left"
@reset="onReset2" @reset="onReset(0)"
@submit="onSubmit2" @submit="({ validateResult }) => onSubmit({ validateResult }, 2)"
> >
<t-form-item <t-form-item label="发票抬头" name="title">
label="发票抬头" <t-input v-model="formData2.title" :style="{ width: '480px' }" placeholder="请输入发票抬头" />
name="title"
>
<t-input
v-model="formData2.title"
:style="{ width: '480px' }"
placeholder="请输入发票抬头"
/>
</t-form-item> </t-form-item>
<t-form-item <t-form-item label="纳税人识别号" name="taxNum">
label="纳税人识别号" <t-input v-model="formData2.taxNum" :style="{ width: '480px' }" placeholder="请输入纳税人识别号" />
name="taxNum"
>
<t-input
v-model="formData2.taxNum"
:style="{ width: '480px' }"
placeholder="请输入纳税人识别号"
/>
</t-form-item> </t-form-item>
<t-form-item <t-form-item label="单位地址" name="address">
label="单位地址" <t-input v-model="formData2.address" :style="{ width: '480px' }" placeholder="请输入单位地址" />
name="address"
>
<t-input
v-model="formData2.address"
:style="{ width: '480px' }"
placeholder="请输入单位地址"
/>
</t-form-item> </t-form-item>
<t-form-item <t-form-item label="开户行" name="bank">
label="开户行" <t-input v-model="formData2.bank" :style="{ width: '480px' }" placeholder="请输入开户行" />
name="bank"
>
<t-input
v-model="formData2.bank"
:style="{ width: '480px' }"
placeholder="请输入开户行"
/>
</t-form-item> </t-form-item>
<t-form-item <t-form-item label="银行账号" name="bankAccount">
label="银行账号" <t-input v-model="formData2.bankAccount" :style="{ width: '480px' }" placeholder="请输入银行账号" />
name="bankAccount"
>
<t-input
v-model="formData2.bankAccount"
:style="{ width: '480px' }"
placeholder="请输入银行账号"
/>
</t-form-item> </t-form-item>
<t-form-item <t-form-item label="通知邮箱" name="email">
label="通知邮箱" <t-input v-model="formData2.email" :style="{ width: '480px' }" placeholder="请输入通知邮箱" />
name="email"
>
<t-input
v-model="formData2.email"
:style="{ width: '480px' }"
placeholder="请输入通知邮箱"
/>
</t-form-item> </t-form-item>
<t-form-item <t-form-item label="通知手机" name="tel">
label="通知手机" <t-input v-model="formData2.tel" :style="{ width: '480px' }" placeholder="请输入通知手机" />
name="tel"
>
<t-input
v-model="formData2.tel"
:style="{ width: '480px' }"
placeholder="请输入通知手机"
/>
</t-form-item> </t-form-item>
<t-form-item> <t-form-item>
<t-button <t-button type="reset" theme="default" variant="base">
type="reset"
theme="default"
variant="base"
>
上一步 上一步
</t-button> </t-button>
<t-button <t-button theme="primary" type="submit">
theme="primary"
type="submit"
>
下一步 下一步
</t-button> </t-button>
</t-form-item> </t-form-item>
@ -196,35 +100,18 @@
v-show="activeForm === 2" v-show="activeForm === 2"
class="step-form" class="step-form"
:data="formData3" :data="formData3"
:rules="rules" :rules="FORM_RULES"
label-align="left" label-align="left"
@reset="onReset3" @reset="onReset(1)"
@submit="onSubmit3" @submit="({ validateResult }) => onSubmit({ validateResult }, 6)"
> >
<t-form-item <t-form-item label="收货人" name="consignee">
label="收货人" <t-input v-model="formData3.consignee" :style="{ width: '480px' }" placeholder="请输入收货人" />
name="consignee"
>
<t-input
v-model="formData3.consignee"
:style="{ width: '480px' }"
placeholder="请输入收货人"
/>
</t-form-item> </t-form-item>
<t-form-item <t-form-item label="手机号码" name="mobileNum">
label="手机号码" <t-input v-model="formData3.mobileNum" :style="{ width: '480px' }" placeholder="请输入手机号码" />
name="mobileNum"
>
<t-input
v-model="formData3.mobileNum"
:style="{ width: '480px' }"
placeholder="请输入手机号码"
/>
</t-form-item> </t-form-item>
<t-form-item <t-form-item label="收货地址" name="deliveryAddress">
label="收货地址"
name="deliveryAddress"
>
<t-select <t-select
v-model="formData3.deliveryAddress" v-model="formData3.deliveryAddress"
:style="{ width: '480px' }" :style="{ width: '480px' }"
@ -232,53 +119,27 @@
class="demo-select-base" class="demo-select-base"
clearable clearable
> >
<t-option <t-option v-for="(item, index) in ADDRESS_OPTIONS" :key="index" :value="item.value" :label="item.label">
v-for="(item, index) in addressOptions"
: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 <t-form-item label="详细地址" name="fullAddress">
label="详细地址" <t-textarea v-model="formData3.fullAddress" :style="{ width: '480px' }" placeholder="请输入详细地址" />
name="fullAddress"
>
<t-textarea
v-model="formData3.fullAddress"
:style="{ width: '480px' }"
placeholder="请输入详细地址"
/>
</t-form-item> </t-form-item>
<t-form-item> <t-form-item>
<t-button <t-button type="reset" theme="default" variant="base">
type="reset"
theme="default"
variant="base"
>
上一步 上一步
</t-button> </t-button>
<t-button <t-button theme="primary" type="submit">
theme="primary"
type="submit"
>
下一步 下一步
</t-button> </t-button>
</t-form-item> </t-form-item>
</t-form> </t-form>
<!-- 分步表单4 --> <!-- 分步表单4 -->
<div <div v-show="activeForm === 6" class="step-form-4">
v-show="activeForm === 6" <t-icon name="check-circle-filled" style="color: green" size="52px" />
class="step-form-4"
>
<t-icon
name="check-circle-filled"
style="color: green"
size="52px"
/>
<p class="text"> <p class="text">
完成开票申请 完成开票申请
</p> </p>
@ -286,17 +147,10 @@
预计13个工作日会将电子发票发至邮箱发票邮寄请耐心等待 预计13个工作日会将电子发票发至邮箱发票邮寄请耐心等待
</p> </p>
<div class="button-group"> <div class="button-group">
<t-button <t-button theme="primary" @click="onReset(0)">
theme="primary"
@click="onReset4"
>
再次申请 再次申请
</t-button> </t-button>
<t-button <t-button variant="base" theme="default" @click="complete">
variant="base"
theme="default"
@click="onSubmit4"
>
查看进度 查看进度
</t-button> </t-button>
</div> </div>
@ -304,117 +158,62 @@
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent, ref, computed } from 'vue';
import { useRouter } from 'vue-router';
import { PREFIX as prefix } from '@/config/global'; import { PREFIX } from '@/config/global';
import { FORM_RULES, NAME_OPTIONS, TYPE_OPTIONS, ADDRESS_OPTIONS, INITIAL_DATA1, INITIAL_DATA2, INITIAL_DATA3 } from './constants';
// //
import './index.less'; import './index.less';
const INITIAL_DATA1 = {
name: '',
type: '',
};
const INITIAL_DATA2 = {
title: '',
taxNum: '',
address: '',
bank: '',
bankAccount: '',
email: '',
tel: '',
};
const INITIAL_DATA3 = {
consignee: '',
mobileNum: '',
deliveryAddress: '',
fullAddress: '',
};
export default defineComponent({ export default defineComponent({
name: 'FormStep', name: 'FormStep',
data() { setup() {
return { const formData1 = ref({ ...INITIAL_DATA1 });
prefix, const formData2 = ref({ ...INITIAL_DATA2 });
formData1: { ...INITIAL_DATA1 }, const formData3 = ref({ ...INITIAL_DATA3 });
formData2: { ...INITIAL_DATA2 }, const activeForm = ref(0);
formData3: { ...INITIAL_DATA3 },
nameOptions: [ const amount = computed(() => {
{ label: '合同A', value: '1' }, if (formData1.value.name === '1') {
{ label: '合同B', value: '2' },
{ label: '合同C', value: '3' },
],
typeOptions: [
{ label: '类型A', value: '1' },
{ label: '类型B', value: '2' },
{ label: '类型C', value: '3' },
],
addressOptions: [
{ label: '广东省深圳市南山区', value: '1' },
{ label: '北京市海淀区', value: '2' },
{ label: '上海市徐汇区', value: '3' },
{ label: '四川省成都市高新区', value: '4' },
{ label: '广东省广州市天河区', value: '5' },
{ label: '陕西省西安市高新区', value: '6' },
],
rules: {
name: [{ required: true, message: '请选择合同名称', type: 'error' }],
type: [{ required: true, message: '请选择发票类型', type: 'error' }],
title: [{ required: true, message: '请输入发票抬头', type: 'error' }],
taxNum: [{ required: true, message: '请输入纳税人识别号', type: 'error' }],
consignee: [{ required: true, message: '请输入收货人', type: 'error' }],
mobileNum: [{ required: true, message: '请输入手机号码', type: 'error' }],
deliveryAddress: [{ required: true, message: '请选择收货地址', type: 'error' }],
fullAddress: [{ required: true, message: '请输入详细地址', type: 'error' }],
},
activeForm: 0,
};
},
computed: {
amount() {
if (this.formData1.name === '1') {
return '565421'; return '565421';
} }
if (this.formData1.name === '2') { if (formData1.value.name === '2') {
return '278821'; return '278821';
} }
if (this.formData1.name === '3') { if (formData1.value.name === '3') {
return '109824'; return '109824';
} }
return '--'; return '--';
}, });
},
methods: { return {
onSubmit1({ validateResult }) { PREFIX,
NAME_OPTIONS,
TYPE_OPTIONS,
ADDRESS_OPTIONS,
FORM_RULES,
formData1,
formData2,
formData3,
activeForm,
amount,
onSubmit({ validateResult }, val) {
if (validateResult === true) { if (validateResult === true) {
this.activeForm = 1; activeForm.value = val;
} }
}, },
onSubmit2({ validateResult }) { onReset(val) {
if (validateResult === true) { activeForm.value = val;
this.activeForm = 2;
}
}, },
onReset2() { complete() {
this.activeForm = 0; const router = useRouter();
}, router.replace({ path: '/detail/advanced' });
onSubmit3({ validateResult }) {
if (validateResult === true) {
this.activeForm = 6;
}
},
onReset3() {
this.activeForm = 1;
},
onSubmit4() {
this.$router.replace({ path: '/detail/advanced' });
},
onReset4() {
this.activeForm = 0;
}, },
};
}, },
}); });
</script> </script>
<style> <style lang="less" scoped>
@import url('./index.less');
</style> </style>

View File

@ -0,0 +1,48 @@
export const COLUMNS = [
{ colKey: 'row-select', type: 'multiple', width: '50' },
{
title: '合同名称',
minWidth: '200',
width: 200,
align: 'left',
ellipsis: true,
colKey: 'name',
},
{ title: '合同状态', colKey: 'status', width: 150, cell: { col: 'status' } },
{
title: '合同编号',
minWidth: '100',
width: 100,
ellipsis: true,
colKey: 'no',
},
{
title: '合同类型',
width: 150,
minWidth: '150',
ellipsis: true,
colKey: 'contractType',
},
{
title: '合同收付类型',
width: 200,
minWidth: '200',
ellipsis: true,
colKey: 'paymentType',
},
{
title: '合同金额 (元)',
width: 300,
minWidth: '300',
ellipsis: true,
colKey: 'amount',
},
{
align: 'left',
fixed: 'right',
width: 200,
ellipsis: true,
colKey: 'op',
title: '操作',
},
]

View File

@ -11,12 +11,10 @@ export default defineComponent({
ListCommonTable, ListCommonTable,
}, },
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/index'; @import '@/style/index';
.@{prefix} { .@{prefix} {
&-panel { &-panel {
background-color: white; background-color: white;
padding: @spacer-3; padding: @spacer-3;

View File

@ -1,10 +1,7 @@
<template> <template>
<card> <card>
<div class="result-success"> <div class="result-success">
<t-icon <t-icon class="result-success-icon" name="close-circle-filled" />
class="result-success-icon"
name="close-circle-filled"
/>
<div class="result-success-title"> <div class="result-success-title">
项目创建失败 项目创建失败
</div> </div>

View File

@ -1,10 +1,7 @@
<template> <template>
<card> <card>
<div class="result-success"> <div class="result-success">
<t-icon <t-icon class="result-success-icon" name="check-circle-filled" />
class="result-success-icon"
name="check-circle-filled"
/>
<div class="result-success-title"> <div class="result-success-title">
项目已创建成功 项目已创建成功
</div> </div>
@ -12,10 +9,7 @@
可以联系负责人分发应用 可以联系负责人分发应用
</div> </div>
<div> <div>
<t-button <t-button theme="default" @click="() => $router.push('/detail/advanced')">
theme="default"
@click="() => $router.push('/detail/advanced')"
>
查看进度 查看进度
</t-button> </t-button>
<t-button @click="() => $router.push('/form/base')"> <t-button @click="() => $router.push('/form/base')">
@ -54,7 +48,7 @@ export default defineComponent({
&-title { &-title {
margin-top: 16px; margin-top: 16px;
font-size: 20px; font-size: 20px;
color: rgba(0, 0, 0, .9); color: rgba(0, 0, 0, 0.9);
text-align: center; text-align: center;
line-height: 22px; line-height: 22px;
} }
@ -62,7 +56,7 @@ export default defineComponent({
&-describe { &-describe {
margin: 8px 0 32px; margin: 8px 0 32px;
font-size: 14px; font-size: 14px;
color: rgba(0, 0, 0, .6); color: rgba(0, 0, 0, 0.6);
line-height: 22px; line-height: 22px;
} }
} }

View File

@ -1,5 +1,4 @@
import { InjectionKey } from 'vue'; import { createStore } from 'vuex';
import { createStore, Store } 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';

View File

@ -6,42 +6,54 @@ const state = {
content: '腾讯大厦一楼改造施工项目 已通过审核!', content: '腾讯大厦一楼改造施工项目 已通过审核!',
type: '合同动态', type: '合同动态',
status: true, status: true,
collected: false,
date: '2021-01-01 08:00', date: '2021-01-01 08:00',
priorty: 'high',
}, },
{ {
id: '124', id: '124',
content: '三季度生产原材料采购项目 开票成功!', content: '三季度生产原材料采购项目 开票成功!',
type: '票务动态', type: '票务动态',
status: true, status: true,
collected: false,
date: '2021-01-01 08:00', date: '2021-01-01 08:00',
priorty: 'low',
}, },
{ {
id: '125', id: '125',
content: '2021-01-01 10:00的【国家电网线下签约】会议即将开始请提前10分钟前往 会议室1 进行签到!', content: '2021-01-01 10:00的【国家电网线下签约】会议即将开始请提前10分钟前往 会议室1 进行签到!',
type: '会议通知', type: '会议通知',
status: true, status: true,
collected: false,
date: '2021-01-01 08:00', date: '2021-01-01 08:00',
priorty: 'middle',
}, },
{ {
id: '126', id: '126',
content: '一季度生产原材料采购项目 开票成功!', content: '一季度生产原材料采购项目 开票成功!',
type: '票务动态', type: '票务动态',
status: true, status: true,
collected: false,
date: '2021-01-01 08:00', date: '2021-01-01 08:00',
priorty: 'low',
}, },
{ {
id: '127', id: '127',
content: '二季度生产原材料采购项目 开票成功!', content: '二季度生产原材料采购项目 开票成功!',
type: '票务动态', type: '票务动态',
status: true, status: true,
collected: false,
date: '2021-01-01 08:00', date: '2021-01-01 08:00',
priorty: 'low',
}, },
{ {
id: '128', id: '128',
content: '三季度生产原材料采购项目 开票成功!', content: '三季度生产原材料采购项目 开票成功!',
type: '票务动态', type: '票务动态',
status: true, status: true,
collected: false,
date: '2021-01-01 08:00', date: '2021-01-01 08:00',
priorty: 'low',
}, },
], ],
}; };

27
src/utils/hooks.ts Normal file
View File

@ -0,0 +1,27 @@
import { Ref, onUnmounted, onMounted } from 'vue';
import * as echarts from 'echarts/core';
export const useChart = (domId: string, chart: Ref) => {
let chartContainer: HTMLCanvasElement;
const selfChart = chart;
const updateContainer = () => {
selfChart.value.resize({
width: chartContainer.clientWidth,
height: chartContainer.clientHeight,
});
};
onMounted(() => {
if (!chartContainer) {
chartContainer = document.getElementById(domId) as HTMLCanvasElement;
}
selfChart.value = echarts.init(chartContainer);
});
window.addEventListener('resize', updateContainer, false);
onUnmounted(() => {
window.removeEventListener('resize', updateContainer);
});
};

View File

@ -2,8 +2,8 @@ import { defineConfig } from 'vite';
import { viteMockServe } from 'vite-plugin-mock'; import { viteMockServe } from 'vite-plugin-mock';
import { viteThemePlugin } from 'vite-plugin-theme'; import { viteThemePlugin } from 'vite-plugin-theme';
import createVuePlugin from '@vitejs/plugin-vue'; import createVuePlugin from '@vitejs/plugin-vue';
import svgLoader from 'vite-svg-loader'
import vueJsx from '@vitejs/plugin-vue-jsx'; import vueJsx from '@vitejs/plugin-vue-jsx';
import svgLoader from 'vite-svg-loader'
// import HttpProxyAgent from 'http-proxy-agent'; // import HttpProxyAgent from 'http-proxy-agent';
import path from 'path'; import path from 'path';
@ -44,7 +44,7 @@ export default defineConfig({
viteThemePlugin({ viteThemePlugin({
colorVariables: getColorList([getGreyColor(backgroundTheme), getBrandColor(brandTheme)]), colorVariables: getColorList([getGreyColor(backgroundTheme), getBrandColor(brandTheme)]),
}), }),
svgLoader() svgLoader(),
], ],
server: { server: {