效果
自定义组件模块
<template>
<div class="flex-1">
<div :style="{width: wrapWidth}" class="flex-margin mb8">
<OprateSteps :operateHtml="operateHtml" />
</div>
<ul class="datacollect-num-card color-f text-center font14 flex-margin" :style="style">
<li v-for="item of props.cardList" :key="item.key" :style="getSpanStyle(item)" :class="`datacollect-num-card-${item.type}`" class="flex-h-center">
<div class="w100" :style="{fontSize: fontSize}">
<label class="mb4">{{ item.label }}</label>
<span>{{ item.num }}</span>
</div>
</li>
</ul>
</div>
</template>
<script lang="ts" setup name="mesDatacollectCommonNumCard">
import { computed } from 'vue';
import { getAPI } from '/@/utils/axios-utils';
import { isNumber } from '/@/utils/toolsValidate';
import OprateSteps from './oprateSteps.vue';
const props = defineProps({
cardList: {
type: Array,
default: () => {
return [];
},
},
colNum: {
type: Number,
default: 1
},
rowNum: {
type: Number,
default: 1
},
colGap: {
type: String,
default: '6px'
},
rowGap: {
type: String,
default: '6px'
},
width: {
type: [Number, String],
default: 100,
},
height: {
type: [Number, String],
default: 'auto',
},
api: {
type: Function,
required: true,
},
method: {
type: String,
required: true,
},
operateHtml: String, // 操作手册html
fontSize: {
type: String,
default: '14px',
},
});
const wrapWidth = computed(() => {
let width = props.width;
if (isNumber(width)) {
width= `${props.width}px`;
}
return width;
});
const style = computed(() => {
// let width = props.width;
// if (isNumber(width)) {
// width= `${props.width}px`;
// }
let height = props.height;
if (isNumber(height)) {
height = `${props.height}px`;
}
let colNumStr = '';
for (let i = 0; i < props.colNum; i++) {
colNumStr = colNumStr + ' 1fr';
}
colNumStr += ';';
let rowNumStr = '';
for (let i = 0; i < props.rowNum; i++) {
rowNumStr = rowNumStr + ' 1fr';
}
rowNumStr += ';';
return `width: ${wrapWidth.value};height: ${height};grid-template-columns: ${colNumStr};grid-template-rows: ${rowNumStr};gap:${props.rowGap} ${props.colGap};`
});
const getSpanStyle = (item: any) => {
let style= '';
if (item.rowSpan) {
style = `${style} grid-row-start: span ${item.rowSpan};`
}
if (item.colSpan) {
style = `${style} grid-column-start: span ${item.colSpan};`
}
return style;
}
// 请求数据
const getData = async (param: any) => {
let res = await getAPI(props.api)[props.method](param);
updateNum(res.data.result);
};
// 更新数量
const updateNum = (data: any) => {
data = data || {};
props.cardList.forEach((item: any) => {
item.num = data[item.key] || 0;
});
};
defineExpose({ getData, updateNum });
</script>
<style scoped lang="scss">
.datacollect-num-card {
display: grid;
// grid-template-columns: 1fr 1fr;
// grid-template-rows: 1fr 1fr;
// gap: 10px 10px;
label {
display: block;
}
& > li {
padding: 10px 0;
border-radius: 6px;
}
&-primary {
background-color: var(--el-color-primary);
}
&-success {
background-color: var(--el-color-success);
}
&-warning {
background-color: var(--el-color-warning);
}
&-info {
background-color: var(--el-color-info-light-3);
}
}
</style>
引用模块
<!-- 数量卡片 -->
<NumCard class="mt5" :cardList="state.numList" :width="330" :height="170" :colNum="2" :rowNum="2" colGap="10px" rowGap="10px" :operateHtml="$t('message.collectfctOperatStep')" ref="numCardRef" />
自定义内容
numList: [
{ label: '良品数', num: 0, key: 'goodQty', type: 'success' },
{ label: '计划数量', num: 0, key: 'moplanqty', type: 'primary', rowSpan: 2 },
{ label: '不良数', num: 0, key: 'ngQty', type: 'warning' },
],