修改模板.
This commit is contained in:
@@ -120,6 +120,10 @@ body {
|
||||
color: rgb(var(--arcoblue-6));
|
||||
}
|
||||
|
||||
.span-red {
|
||||
color: rgb(var(--red-6));
|
||||
}
|
||||
|
||||
#app {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
@@ -75,9 +75,9 @@
|
||||
box-shadow: 2px 2px 12px rgba(0, 0, 0, .15);
|
||||
}
|
||||
|
||||
.card-descriptions {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
.card-extra-icon {
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.usn {
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
<div class="card-list-handler-left">
|
||||
<a-space>
|
||||
<!-- 创建 -->
|
||||
<div v-if="!handleVisible.disableAdd"
|
||||
<div v-permission="addPermission"
|
||||
v-if="!handleVisible.disableAdd"
|
||||
class="header-icon-wrapper"
|
||||
title="创建"
|
||||
@click="emits('add')">
|
||||
@@ -83,7 +84,9 @@
|
||||
<a-row v-if="list.length !== 0"
|
||||
:gutter="cardLayoutGutter">
|
||||
<!-- 添加卡片 -->
|
||||
<a-col v-if="createCardPosition === 'head'" v-bind="cardLayoutCols">
|
||||
<a-col v-permission="addPermission"
|
||||
v-if="createCardPosition === 'head'"
|
||||
v-bind="cardLayoutCols">
|
||||
<create-card :card-height="cardHeight"
|
||||
:create-card-description="createCardDescription"
|
||||
@click="emits('add')" />
|
||||
@@ -112,12 +115,58 @@
|
||||
<template #extra>
|
||||
<slot name="extra" :record="item" :index="index" :key="item[key]" />
|
||||
</template>
|
||||
<!-- 内容 -->
|
||||
<slot name="card" :record="item" :index="index" :key="item[key]" />
|
||||
<!-- 内容-字段 -->
|
||||
<template v-if="fieldConfig && fieldConfig.fields">
|
||||
<div :class="['fields-container', fieldConfig.bodyClass]">
|
||||
<template v-for="(field, index) in fieldConfig.fields">
|
||||
<a-row align="center"
|
||||
:style="{
|
||||
'margin-bottom': fieldConfig.rowGap || '10px'
|
||||
}">
|
||||
<!-- label -->
|
||||
<a-col :span="fieldConfig.labelSpan || 8" :offset="fieldConfig.labelOffset || 0"
|
||||
:style="{
|
||||
'text-align': fieldConfig.labelAlign || 'left'
|
||||
}"
|
||||
:class="[fieldConfig.labelClass,
|
||||
field.labelClass,
|
||||
'field-label'
|
||||
]">
|
||||
<span>{{ field.label + (fieldConfig.showColon ? ' :' : '') }}</span>
|
||||
</a-col>
|
||||
<!-- value -->
|
||||
<a-col :span="24 - (fieldConfig.labelSpan || 8) + (fieldConfig.labelOffset || 0)"
|
||||
:style="{
|
||||
'text-align': fieldConfig.valueAlign || 'left'
|
||||
}"
|
||||
:class="[fieldConfig.valueClass,
|
||||
field.valueClass,
|
||||
'field-value',
|
||||
field.ellipsis ? 'field-value-ellipsis' : ''
|
||||
]">
|
||||
<slot :name="field.slotName" :record="item" :index="index" :key="item[key]">
|
||||
<a-tooltip v-if="field.tooltip" :content="item[field.dataIndex]">
|
||||
<span>{{ item[field.dataIndex] }}</span>
|
||||
</a-tooltip>
|
||||
<template v-else>
|
||||
<span>{{ item[field.dataIndex] }}</span>
|
||||
</template>
|
||||
</slot>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 内容-自定义槽 -->
|
||||
<template v-else>
|
||||
<slot name="card" :record="item" :index="index" :key="item[key]" />
|
||||
</template>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<!-- 添加卡片 -->
|
||||
<a-col v-if="createCardPosition === 'tail'" v-bind="cardLayoutCols">
|
||||
<a-col v-permission="addPermission"
|
||||
v-if="createCardPosition === 'tail'"
|
||||
v-bind="cardLayoutCols">
|
||||
<create-card :card-height="cardHeight"
|
||||
:create-card-description="createCardDescription"
|
||||
@click="emits('add')" />
|
||||
@@ -128,12 +177,7 @@
|
||||
<a-card class="general-card empty-list-card"
|
||||
:style="{ height: `${cardHeight * 2 + 16}px` }"
|
||||
:body-style="{ height: '100%' }">
|
||||
<a-empty :class="{
|
||||
'empty-list-card-body': true,
|
||||
'empty-list-card-body-creatable': emptyToCreate
|
||||
}"
|
||||
:description="emptyDescription"
|
||||
@click="emits('add')" />
|
||||
<a-empty class="empty-list-card-body" description="暂无数据" />
|
||||
</a-card>
|
||||
</template>
|
||||
</a-spin>
|
||||
@@ -150,7 +194,7 @@
|
||||
import { compile, computed, h, PropType } from 'vue';
|
||||
import { useAppStore } from '@/store';
|
||||
import { PaginationProps, ResponsiveValue } from '@arco-design/web-vue';
|
||||
import { Position, CardRecord, ColResponsiveValue, HandleVisible } from '@/types/card';
|
||||
import { Position, CardRecord, ColResponsiveValue, HandleVisible, CardFieldConfig } from '@/types/card';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const headerWidth = computed(() => {
|
||||
@@ -189,6 +233,10 @@
|
||||
type: Boolean as PropType<Boolean>,
|
||||
default: () => false
|
||||
},
|
||||
fieldConfig: {
|
||||
type: Object as PropType<CardFieldConfig>,
|
||||
default: () => []
|
||||
},
|
||||
cardHeight: Number,
|
||||
searchInputWidth: {
|
||||
type: String,
|
||||
@@ -206,14 +254,6 @@
|
||||
type: String as PropType<Position>,
|
||||
default: () => '暂无数据 点击此处进行创建'
|
||||
},
|
||||
emptyToCreate: {
|
||||
type: Boolean,
|
||||
default: () => true
|
||||
},
|
||||
emptyDescription: {
|
||||
type: String,
|
||||
default: () => '暂无数据 点击此处进行创建'
|
||||
},
|
||||
cardLayoutGutter: {
|
||||
type: [Number, Array] as PropType<Number> |
|
||||
PropType<ResponsiveValue> |
|
||||
@@ -221,6 +261,10 @@
|
||||
PropType<Array<ResponsiveValue>>,
|
||||
default: () => [16, 16]
|
||||
},
|
||||
addPermission: {
|
||||
type: Array as PropType<String[]>,
|
||||
default: () => []
|
||||
},
|
||||
cardLayoutCols: {
|
||||
type: Object as PropType<ColResponsiveValue>,
|
||||
default: () => {
|
||||
@@ -382,8 +426,34 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&-body-creatable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fields-container {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
|
||||
.field-label {
|
||||
color: var(--color-text-3);
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
padding-right: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.field-value {
|
||||
color: var(--color-text-1);
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
padding-right: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.field-value.field-value-ellipsis {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: keep-all;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,46 @@
|
||||
import { DescData, PaginationProps, ResponsiveValue } from '@arco-design/web-vue';
|
||||
import { PaginationProps, ResponsiveValue } from '@arco-design/web-vue';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
/**
|
||||
* 卡片字段
|
||||
* 对齐方式
|
||||
*/
|
||||
export interface CardField {
|
||||
field: string;
|
||||
label: string;
|
||||
render: (record: CardRecord) => string;
|
||||
span?: number;
|
||||
}
|
||||
export type Align = 'left' | 'center' | 'right';
|
||||
|
||||
/**
|
||||
* 创建卡片位置
|
||||
*/
|
||||
export type Position = 'head' | 'tail' | false;
|
||||
|
||||
/**
|
||||
* 卡片字段配置
|
||||
*/
|
||||
export interface CardFieldConfig {
|
||||
rowGap?: string;
|
||||
bodyClass?: string;
|
||||
showColon?: boolean;
|
||||
labelSpan?: number;
|
||||
labelOffset?: number;
|
||||
labelAlign?: Align;
|
||||
valueAlign?: Align;
|
||||
labelClass?: string;
|
||||
valueClass?: string;
|
||||
|
||||
fields: CardField[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 卡片字段
|
||||
*/
|
||||
export interface CardField {
|
||||
label: string;
|
||||
dataIndex: string;
|
||||
slotName?: string;
|
||||
labelClass?: string;
|
||||
valueClass?: string;
|
||||
ellipsis?: boolean;
|
||||
tooltip?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 卡片实体
|
||||
*/
|
||||
@@ -72,17 +97,3 @@ export const usePagination = (): PaginationProps => {
|
||||
pageSizeOptions: [12, 18, 36, 48, 96]
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 转为卡片描述对象
|
||||
*/
|
||||
export const toCardDesc = (fields: CardField[], record: CardRecord): DescData[] => {
|
||||
return fields.map(s => {
|
||||
return {
|
||||
field: s.field,
|
||||
label: s.label,
|
||||
value: s.render(record),
|
||||
span: s.span || 3
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,40 +1,72 @@
|
||||
<template>
|
||||
<card-list ref="cardList"
|
||||
v-model:searchValue="formModel.name"
|
||||
<card-list v-model:searchValue="formModel.name"
|
||||
create-card-position="head"
|
||||
:card-height="180"
|
||||
:loading="loading"
|
||||
:fieldConfig="fieldConfig"
|
||||
:list="list"
|
||||
:pagination="pagination"
|
||||
:card-layout-cols="cardColLayout"
|
||||
@add="add"
|
||||
:add-permission="['asset:host:create']"
|
||||
@add="emits('openAdd')"
|
||||
@reset="reset"
|
||||
@search="fetchTableData"
|
||||
@page-change="fetchTableData">
|
||||
<!-- 标题 -->
|
||||
<template #title="{ record }">
|
||||
{{ record.id }}
|
||||
{{ record.name }}
|
||||
</template>
|
||||
<!-- 标题拓展 -->
|
||||
<template #extra="{ index }">
|
||||
{{ index }}
|
||||
<!-- 编码 -->
|
||||
<template #code="{ record }">
|
||||
<a-tag>{{ record.code }}</a-tag>
|
||||
</template>
|
||||
<!-- 卡片 -->
|
||||
<template #card="{ record }">
|
||||
<a-descriptions class="card-descriptions"
|
||||
:data="convert(record)"
|
||||
:column="1">
|
||||
<template #value="{ data }">
|
||||
{{ data.field }}
|
||||
<template v-if="data.field === 'id'">
|
||||
<a-tag>{{ data.value }}</a-tag>
|
||||
<!-- 地址 -->
|
||||
<template #address="{ record }">
|
||||
<a-tooltip content="点击复制">
|
||||
<span class="host-address" @click="copy(record.address)">
|
||||
<icon-copy class="mr4" />{{ record.address }}
|
||||
</span>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<!-- 标签 -->
|
||||
<template #tags="{ record }">
|
||||
<a-space v-if="record.tags" wrap>
|
||||
<a-tag v-for="tag in record.tags"
|
||||
:key="tag.id"
|
||||
:color="dataColor(tag.name, tagColor)">
|
||||
{{ tag.name }}
|
||||
</a-tag>
|
||||
</a-space>
|
||||
</template>
|
||||
<!-- 拓展操作 -->
|
||||
<template #extra="{ record }">
|
||||
<a-space>
|
||||
<!-- 更多操作 -->
|
||||
<a-dropdown trigger="hover">
|
||||
<icon-more class="card-extra-icon" />
|
||||
<template #content>
|
||||
<!-- 修改 -->
|
||||
<a-doption v-permission="['asset:host:update']"
|
||||
@click="emits('openUpdate', record)">
|
||||
<icon-edit />
|
||||
修改
|
||||
</a-doption>
|
||||
<!-- 配置 -->
|
||||
<a-doption v-permission="['asset:host:update-config']"
|
||||
@click="emits('openUpdateConfig', record)">
|
||||
<icon-settings />
|
||||
配置
|
||||
</a-doption>
|
||||
<!-- 删除 -->
|
||||
<a-doption class="span-red" @click="deleteRow(record.id)">
|
||||
<icon-delete />
|
||||
删除
|
||||
</a-doption>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ data.value }}
|
||||
</template>
|
||||
</template>
|
||||
</a-descriptions>
|
||||
</a-dropdown>
|
||||
</a-space>
|
||||
</template>
|
||||
<!-- 左侧条件 -->
|
||||
<template #leftHandle>
|
||||
<span>1</span>
|
||||
</template>
|
||||
@@ -51,58 +83,86 @@
|
||||
import { usePagination, useColLayout } from '@/types/card';
|
||||
import { reactive, ref } from 'vue';
|
||||
import useLoading from '@/hooks/loading';
|
||||
import { resetObject } from '@/utils';
|
||||
import { convert } from '../types/card.fields';
|
||||
|
||||
const formModel = reactive({
|
||||
name: undefined
|
||||
});
|
||||
import { dataColor, resetObject } from '@/utils';
|
||||
import fieldConfig from '../types/card.fields';
|
||||
import { deleteHost, getHostPage, HostQueryRequest, HostQueryResponse } from '@/api/asset/host';
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { tagColor } from '@/views/asset/host/types/const';
|
||||
import useCopy from '@/hooks/copy';
|
||||
|
||||
const { copy } = useCopy();
|
||||
const { loading, setLoading } = useLoading();
|
||||
const cardColLayout = useColLayout();
|
||||
const pagination = usePagination();
|
||||
const list = ref<Array<any>>([]);
|
||||
const list = ref<HostQueryResponse[]>([]);
|
||||
const emits = defineEmits(['openAdd', 'openUpdate', 'openUpdateConfig']);
|
||||
|
||||
// 切换页码
|
||||
const fetchTableData = (page = 1, limit = pagination.pageSize, form = formModel) => {
|
||||
console.log(page, limit, form);
|
||||
setLoading(true);
|
||||
setTimeout(() => {
|
||||
try {
|
||||
const t = 90;
|
||||
for (let i = 0; i < t; i++) {
|
||||
list.value.push({
|
||||
id: i + 1,
|
||||
name: `名称 ${i + 1}`,
|
||||
address: `192.168.1.${i}`,
|
||||
disabled: i === 0
|
||||
});
|
||||
}
|
||||
pagination.total = t;
|
||||
pagination.current = page;
|
||||
pagination.pageSize = limit;
|
||||
setLoading(false);
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, 300);
|
||||
};
|
||||
fetchTableData();
|
||||
const formModel = reactive<HostQueryRequest>({
|
||||
name: undefined,
|
||||
extra: true
|
||||
});
|
||||
|
||||
const add = () => {
|
||||
console.log('add');
|
||||
// 删除当前行
|
||||
const deleteRow = async (id: number) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
// 调用删除接口
|
||||
await deleteHost(id);
|
||||
Message.success('删除成功');
|
||||
// 重新加载数据
|
||||
await fetchTableData();
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 添加后回调
|
||||
const addedCallback = () => {
|
||||
fetchTableData();
|
||||
};
|
||||
|
||||
// 更新后回调
|
||||
const updatedCallback = () => {
|
||||
fetchTableData();
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
addedCallback, updatedCallback
|
||||
});
|
||||
|
||||
// 重置条件
|
||||
const reset = () => {
|
||||
console.log('reset');
|
||||
resetObject(formModel);
|
||||
fetchTableData();
|
||||
};
|
||||
|
||||
// 加载数据
|
||||
const doFetchTableData = async (request: HostQueryRequest) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const { data } = await getHostPage(request);
|
||||
list.value = data.rows;
|
||||
pagination.total = data.total;
|
||||
pagination.current = request.page;
|
||||
pagination.pageSize = request.limit;
|
||||
} catch (e) {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 切换页码
|
||||
const fetchTableData = (page = 1, limit = pagination.pageSize, form = formModel) => {
|
||||
doFetchTableData({ page, limit, ...form });
|
||||
};
|
||||
fetchTableData();
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
.host-address {
|
||||
cursor: pointer;
|
||||
color: rgb(var(--arcoblue-6))
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<a-input v-model="formModel.address" placeholder="请输入主机地址" allow-clear />
|
||||
</a-form-item>
|
||||
<!-- 主机标签 -->
|
||||
<a-form-item field="tags" label="主机地址" label-col-flex="50px">
|
||||
<a-form-item field="tags" label="主机标签" label-col-flex="50px">
|
||||
<tag-multi-selector v-model="formModel.tags"
|
||||
ref="tagSelector"
|
||||
:allowCreate="false"
|
||||
@@ -94,7 +94,7 @@
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<!-- 标签 -->
|
||||
<template #tag="{ record }">
|
||||
<template #tags="{ record }">
|
||||
<a-space v-if="record.tags">
|
||||
<a-tag v-for="tag in record.tags"
|
||||
:key="tag.id"
|
||||
@@ -279,7 +279,6 @@
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
|
||||
.host-favorite-choice {
|
||||
color: rgb(var(--yellow-6));
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
@openUpdateConfig="(e) => config.open(e)" />
|
||||
<!-- 列表-卡片 -->
|
||||
<host-card-list v-else
|
||||
ref="card" />
|
||||
<!-- @openAdd="() => modal.openAdd()"-->
|
||||
<!-- @openUpdate="(e) => modal.openUpdate(e)"-->
|
||||
<!-- @openUpdateConfig="(e) => config.open(e)" />-->
|
||||
ref="card"
|
||||
@openAdd="() => modal.openAdd()"
|
||||
@openUpdate="(e) => modal.openUpdate(e)"
|
||||
@openUpdateConfig="(e) => config.open(e)" />
|
||||
<!-- 添加修改模态框 -->
|
||||
<host-form-modal ref="modal"
|
||||
@added="() => table.addedCallback()"
|
||||
|
||||
@@ -1,30 +1,23 @@
|
||||
import { CardField, CardRecord, toCardDesc } from '@/types/card';
|
||||
|
||||
export const fields = [
|
||||
{
|
||||
field: 'id',
|
||||
label: 'id',
|
||||
render: r => r.id,
|
||||
}, {
|
||||
field: 'name',
|
||||
label: '主机名称',
|
||||
render: r => r.name,
|
||||
}, {
|
||||
field: 'code',
|
||||
label: '主机编码',
|
||||
render: r => 'code',
|
||||
}, {
|
||||
field: 'address',
|
||||
label: '主机地址',
|
||||
render: r => 'address',
|
||||
}, {
|
||||
field: 'tag',
|
||||
label: '标签',
|
||||
render: r => 'tag',
|
||||
},
|
||||
] as CardField[];
|
||||
|
||||
export const convert = (record: CardRecord) => {
|
||||
return toCardDesc(fields, record);
|
||||
};
|
||||
import { CardField, CardFieldConfig } from '@/types/card';
|
||||
|
||||
export const fieldConfig = {
|
||||
rowGap: '10px',
|
||||
labelSpan: 8,
|
||||
fields: [
|
||||
{
|
||||
label: '主机编码',
|
||||
dataIndex: 'code',
|
||||
slotName: 'code',
|
||||
}, {
|
||||
label: '主机地址',
|
||||
dataIndex: 'address',
|
||||
slotName: 'address',
|
||||
tooltip: true,
|
||||
}, {
|
||||
label: '主机标签',
|
||||
dataIndex: 'tags',
|
||||
slotName: 'tags',
|
||||
},
|
||||
] as CardField[]
|
||||
} as CardFieldConfig;
|
||||
export default fieldConfig;
|
||||
|
||||
@@ -24,9 +24,9 @@ const columns = [
|
||||
slotName: 'address',
|
||||
width: 260
|
||||
}, {
|
||||
title: '标签',
|
||||
dataIndex: 'tag',
|
||||
slotName: 'tag',
|
||||
title: '主机标签',
|
||||
dataIndex: 'tags',
|
||||
slotName: 'tags',
|
||||
align: 'left',
|
||||
}, {
|
||||
title: '操作',
|
||||
|
||||
Reference in New Issue
Block a user