32 changed files with 570 additions and 223 deletions
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 551 B |
@ -0,0 +1,201 @@ |
|||||||
|
<template> |
||||||
|
<div class="storage-data-filter"> |
||||||
|
<div class="time-item"> |
||||||
|
<el-config-provider :locale="locale"> |
||||||
|
<span>开始时间:</span> |
||||||
|
<div class="item item-time"> |
||||||
|
<el-date-picker |
||||||
|
class="data-picker" |
||||||
|
v-model="filterData.startDay" |
||||||
|
type="date" |
||||||
|
placeholder="请选择时间" |
||||||
|
value-format="YYYY-MM-DD HH:mm:ss" |
||||||
|
:clearable="false" |
||||||
|
:editable="false" |
||||||
|
/> |
||||||
|
<el-checkbox v-model="checkbox.startDay" size="large" /> |
||||||
|
</div> |
||||||
|
<span>终止时间:</span> |
||||||
|
<div class="item item-time"> |
||||||
|
<el-date-picker |
||||||
|
class="data-picker" |
||||||
|
v-model="filterData.endDay" |
||||||
|
type="date" |
||||||
|
placeholder="请选择时间" |
||||||
|
value-format="YYYY-MM-DD HH:mm:ss" |
||||||
|
:clearable="false" |
||||||
|
:editable="false" |
||||||
|
:disabled-date="endDisabledDate" |
||||||
|
/> |
||||||
|
<el-checkbox v-model="checkbox.endDay" size="large" /> |
||||||
|
</div> |
||||||
|
</el-config-provider> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="item"> |
||||||
|
<el-input placeholder="请输入设备序列号" v-model="filterData.serialNo" /> |
||||||
|
<el-checkbox v-model="checkbox.serialNo" size="large" /> |
||||||
|
</div> |
||||||
|
<div class="item"> |
||||||
|
<el-input placeholder="请输入设备名称" v-model="filterData.name" /> |
||||||
|
<el-checkbox v-model="checkbox.name" size="large" /> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="item"> |
||||||
|
<el-cascader |
||||||
|
v-model="filterData.categoryId" |
||||||
|
:options="categoryTreeData" |
||||||
|
placeholder="请选择设备分类" |
||||||
|
:props="{ |
||||||
|
checkStrictly: true, |
||||||
|
value: 'id', |
||||||
|
label: 'name', |
||||||
|
}" |
||||||
|
/> |
||||||
|
<el-checkbox v-model="checkbox.categoryId" size="large" /> |
||||||
|
</div> |
||||||
|
<div class="item item-btn"> |
||||||
|
<EdfsButton |
||||||
|
inner-text="搜索" |
||||||
|
type="primary" |
||||||
|
style="width: 100%" |
||||||
|
@click="onSearch" |
||||||
|
/> |
||||||
|
<EdfsButton inner-text="重置" style="width: 100%" @click="onReset" /> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import dayjs from 'dayjs' |
||||||
|
import zhCn from 'element-plus/dist/locale/zh-cn.mjs' |
||||||
|
import EdfsButton from '@/components/dashboard/Edfs-button/index.vue' |
||||||
|
|
||||||
|
import type { CustomerVO } from '@/api/module/eam/customer' |
||||||
|
|
||||||
|
const locale = zhCn |
||||||
|
|
||||||
|
const prop = defineProps<{ |
||||||
|
categoryTreeData: Array<Pick<CustomerVO, 'id' | 'name'>> |
||||||
|
}>() |
||||||
|
const endDisabledDate = (time: Date) => { |
||||||
|
return ( |
||||||
|
time.getTime() < |
||||||
|
dayjs(filterData.value.startDay).add(1, 'days').startOf('day').valueOf() |
||||||
|
) |
||||||
|
} |
||||||
|
const emit = defineEmits(['search']) |
||||||
|
|
||||||
|
type FilterKeys = keyof typeof filterData.value |
||||||
|
|
||||||
|
const filterData = ref({ |
||||||
|
startDay: '', |
||||||
|
endDay: '', |
||||||
|
name: '', |
||||||
|
serialNo: '', |
||||||
|
categoryId: [], |
||||||
|
}) |
||||||
|
|
||||||
|
const checkbox = ref<Record<FilterKeys, boolean>>({ |
||||||
|
startDay: false, |
||||||
|
endDay: false, |
||||||
|
name: false, |
||||||
|
serialNo: false, |
||||||
|
categoryId: false, |
||||||
|
}) |
||||||
|
|
||||||
|
function onSearch() { |
||||||
|
emit('search', formatParams()) |
||||||
|
} |
||||||
|
|
||||||
|
function formatParams() { |
||||||
|
const params: Partial<Record<FilterKeys, string>> = {} |
||||||
|
const keys = Object.keys(checkbox.value) as FilterKeys[] |
||||||
|
for (const key of keys) { |
||||||
|
if (checkbox.value[key]) { |
||||||
|
if (key === 'startDay' || key === 'endDay') { |
||||||
|
params['createTime'] = [filterData.value.startDay, filterData.value.endDay] |
||||||
|
} else { |
||||||
|
params[key] = filterData.value[key] |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return params |
||||||
|
} |
||||||
|
|
||||||
|
function onReset() { |
||||||
|
filterData.value = { |
||||||
|
startDay: '', |
||||||
|
endDay: '', |
||||||
|
name: '', |
||||||
|
serialNo: '', |
||||||
|
categoryId: [], |
||||||
|
} |
||||||
|
checkbox.value = { |
||||||
|
startDay: false, |
||||||
|
endDay: false, |
||||||
|
name: false, |
||||||
|
serialNo: false, |
||||||
|
categoryId: false, |
||||||
|
} |
||||||
|
onSearch() |
||||||
|
} |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
onSearch() |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.storage-data-filter { |
||||||
|
padding: 16px; |
||||||
|
box-sizing: border-box; |
||||||
|
span { |
||||||
|
font-size: 14px; |
||||||
|
color: var(--label-color); |
||||||
|
} |
||||||
|
.time-item { |
||||||
|
margin-bottom: 32px; |
||||||
|
.item { |
||||||
|
margin-top: 0; |
||||||
|
|
||||||
|
margin-bottom: 16px; |
||||||
|
} |
||||||
|
} |
||||||
|
.item { |
||||||
|
margin-top: 16px; |
||||||
|
height: 32px; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
|
||||||
|
:deep(.el-checkbox:last-of-type) { |
||||||
|
margin-left: 8px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.item-btn { |
||||||
|
margin-top: 36px; |
||||||
|
} |
||||||
|
|
||||||
|
:deep(.data-picker) { |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
:deep(.el-input__icon) { |
||||||
|
// margin: 0; |
||||||
|
} |
||||||
|
:deep(.el-date-editor .el-input__wrapper) { |
||||||
|
height: 100%; |
||||||
|
line-height: 100%; |
||||||
|
flex-direction: row-reverse; |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 1px 0 1px 11px; |
||||||
|
} |
||||||
|
|
||||||
|
:deep(.el-input__icon), |
||||||
|
:deep(.el-input__prefix-inner), |
||||||
|
:deep(.el-input__prefix), |
||||||
|
:deep(.perfix-icon) { |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,125 @@ |
|||||||
|
<template> |
||||||
|
<v-chart class="chart" :option="option" :autoresize="autoresize" /> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import VChart from 'vue-echarts' |
||||||
|
import { use } from 'echarts/core' |
||||||
|
import { CanvasRenderer } from 'echarts/renderers' |
||||||
|
import { PieChart } from 'echarts/charts' |
||||||
|
import { |
||||||
|
TitleComponent, |
||||||
|
TooltipComponent, |
||||||
|
LegendComponent, |
||||||
|
GraphicComponent, |
||||||
|
} from 'echarts/components' |
||||||
|
import type { EChartsOption } from 'echarts' |
||||||
|
import { useTheme } from '@/utils/useTheme' |
||||||
|
use([ |
||||||
|
CanvasRenderer, |
||||||
|
PieChart, |
||||||
|
TitleComponent, |
||||||
|
TooltipComponent, |
||||||
|
GraphicComponent, |
||||||
|
LegendComponent, |
||||||
|
]) |
||||||
|
|
||||||
|
interface Props { |
||||||
|
data: any[] |
||||||
|
} |
||||||
|
const { chartGraphicTextColor } = useTheme() |
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), { |
||||||
|
data: () => [], |
||||||
|
}) |
||||||
|
|
||||||
|
const updateTrigger = ref(0) |
||||||
|
const autoresize = { |
||||||
|
throttle: 2500, |
||||||
|
onResize: () => { |
||||||
|
updateTrigger.value++ |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
// 数据总数 |
||||||
|
const total = computed(() => props.data.reduce((acc, cur) => acc + cur.value, 0)) |
||||||
|
|
||||||
|
const option = computed(() => { |
||||||
|
const trigger = updateTrigger.value |
||||||
|
const res: EChartsOption = { |
||||||
|
tooltip: { |
||||||
|
show: false, |
||||||
|
}, |
||||||
|
graphic: { |
||||||
|
elements: [ |
||||||
|
{ |
||||||
|
type: 'text', |
||||||
|
left: 'center', |
||||||
|
top: '30%', |
||||||
|
style: { |
||||||
|
text: total.value.toString(), |
||||||
|
fill: chartGraphicTextColor.value, |
||||||
|
fontSize: 20, |
||||||
|
fontWeight: 700, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
type: 'text', |
||||||
|
left: 'center', |
||||||
|
top: '42%', |
||||||
|
style: { |
||||||
|
text: '设备总数', |
||||||
|
fill: chartGraphicTextColor.value, |
||||||
|
fontSize: 16, |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
legend: { |
||||||
|
show: true, |
||||||
|
bottom: '3%', |
||||||
|
itemWidth: 20, |
||||||
|
itemHeight: 15, |
||||||
|
itemGap: 10, |
||||||
|
textStyle: { |
||||||
|
fontSize: 16, |
||||||
|
}, |
||||||
|
selectedMode: false, |
||||||
|
}, |
||||||
|
color: ['#4CAF50', '#2196F3', '#FBB852', '#FF9800', '#F44336', '#ccc'], |
||||||
|
series: [ |
||||||
|
{ |
||||||
|
type: 'pie', |
||||||
|
radius: ['40%', '55%'], |
||||||
|
center: ['50%', '40%'], |
||||||
|
data: props.data, |
||||||
|
avoidLabelOverlap: false, |
||||||
|
emphasis: { |
||||||
|
itemStyle: { |
||||||
|
shadowBlur: 10, |
||||||
|
shadowOffsetX: 1, |
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)', |
||||||
|
}, |
||||||
|
}, |
||||||
|
label: { |
||||||
|
show: true, |
||||||
|
position: 'outside', |
||||||
|
// formatter: '{b}: {c} ({d}%)', |
||||||
|
formatter: ' {c}', |
||||||
|
}, |
||||||
|
labelLine: { |
||||||
|
show: true, |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
} |
||||||
|
return res |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped lang="scss"> |
||||||
|
.chart { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
</style> |
Loading…
Reference in new issue