feat:添加设备分类页面/代码格式化

main
黄伟杰 2 months ago
parent a22d95d134
commit b16865d0bf

@ -2,7 +2,7 @@ export interface RecipeConfigVO {
id: number
recipeCode: string
recipeName: string
recipeType?: string
recipeType?: string | number
productId?: number
productName?: string
deviceId?: number

@ -0,0 +1,58 @@
import request from '@/config/axios'
// 设备类型 VO
export interface DeviceTypeVO {
id: number // id
code: string // 编码
name: string // 名称
remark: string // 备注
sort: number // 排序
parentId?: number
parentChain?: string
createTime?: string
}
export interface DeviceTypeTreeVO extends DeviceTypeVO {
parentId?: number
parentChain?: string
createTime?: string
children?: DeviceTypeTreeVO[]
leaf?: boolean
}
// 设备类型 API
export const DeviceTypeApi = {
// 查询设备类型分页
getDeviceTypePage: async (params: any) => {
return await request.get({ url: `/mes/device-type/page`, params })
},
getDeviceTypeTree: async (params: any) => {
return await request.get({ url: `/mes/device-type/tree`, params })
},
// 查询设备类型详情
getDeviceType: async (id: number) => {
return await request.get({ url: `/mes/device-type/get?id=` + id })
},
// 新增设备类型
createDeviceType: async (data: DeviceTypeVO) => {
return await request.post({ url: `/mes/device-type/create`, data })
},
// 修改设备类型
updateDeviceType: async (data: DeviceTypeVO) => {
return await request.put({ url: `/mes/device-type/update`, data })
},
// 删除设备类型
deleteDeviceType: async (id: number) => {
return await request.delete({ url: `/mes/device-type/delete?id=` + id })
},
// 导出设备类型 Excel
exportDeviceType: async (params) => {
return await request.download({ url: `/mes/device-type/export-excel`, params })
}
}

@ -165,8 +165,8 @@ $toolbar-position: -55px;
width: 80px;
height: 25px;
font-size: 12px;
color: #6a6a6a;
line-height: 25px;
color: #6a6a6a;
text-align: center;
background: #fff;
box-shadow:

@ -94,9 +94,9 @@ const handleCloneComponent = (component: DiyComponent<any>) => {
<style scoped lang="scss">
.editor-left {
z-index: 1;
flex-shrink: 0;
user-select: none;
box-shadow: 8px 0 8px -8px rgb(0 0 0 / 12%);
user-select: none;
flex-shrink: 0;
:deep(.el-collapse) {
border-top: none;

@ -55,12 +55,12 @@ const handleToggleFab = () => {
/* 模态背景 */
.modal-bg {
position: absolute;
left: calc(50% - 375px / 2);
top: 0;
left: calc(50% - 375px / 2);
z-index: 11;
width: 375px;
height: 100%;
background-color: rgba(#000000, 0.4);
background-color: rgba(#000, 0.4);
}
.fab-icon {

@ -192,39 +192,39 @@ const handleAppLinkChange = (appLink: AppLink) => {
<style scoped lang="scss">
.hot-zone {
position: absolute;
z-index: 10;
display: flex;
font-size: 16px;
color: var(--el-color-primary);
cursor: move;
background: var(--el-color-primary-light-7);
opacity: 0.8;
border: 1px solid var(--el-color-primary);
color: var(--el-color-primary);
font-size: 16px;
display: flex;
opacity: 0.8;
align-items: center;
justify-content: center;
cursor: move;
z-index: 10;
/* 控制点 */
.ctrl-dot {
position: absolute;
z-index: 11;
width: 8px;
height: 8px;
border-radius: 50%;
border: inherit;
background-color: #fff;
z-index: 11;
border: inherit;
border-radius: 50%;
}
.delete {
display: none;
position: absolute;
top: 0;
right: 0;
display: none;
padding: 2px 2px 6px 6px;
background-color: var(--el-color-primary);
border-radius: 0 0 0 80%;
cursor: pointer;
color: #fff;
text-align: right;
cursor: pointer;
background-color: var(--el-color-primary);
border-radius: 0 0 0 80%;
}
&:hover {

@ -28,15 +28,15 @@ const props = defineProps<{ property: HotZoneProperty }>()
<style scoped lang="scss">
.hot-zone {
position: absolute;
z-index: 10;
display: flex;
font-size: 14px;
color: var(--el-color-primary);
cursor: move;
background: var(--el-color-primary-light-7);
opacity: 0.8;
border: 1px solid var(--el-color-primary);
color: var(--el-color-primary);
font-size: 14px;
display: flex;
opacity: 0.8;
align-items: center;
justify-content: center;
cursor: move;
z-index: 10;
}
</style>

@ -42,22 +42,22 @@ const handleOpenEditDialog = () => {
<style scoped lang="scss">
.hot-zone {
position: absolute;
display: flex;
font-size: 12px;
color: #fff;
cursor: move;
background: #409effbf;
border: 1px solid var(--el-color-primary);
color: #fff;
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
cursor: move;
/* 控制点 */
.ctrl-dot {
position: absolute;
width: 4px;
height: 4px;
border-radius: 50%;
background-color: #fff;
border-radius: 50%;
}
}
</style>

@ -103,13 +103,16 @@ watch(
.el-carousel__indicator {
padding-top: 0;
padding-bottom: 0;
.el-carousel__button {
--el-carousel-indicator-height: 6px;
--el-carousel-indicator-width: 6px;
--el-carousel-indicator-out-color: #ff6000;
border-radius: 6px;
}
}
.el-carousel__indicator.is-active {
.el-carousel__button {
--el-carousel-indicator-width: 12px;

@ -64,10 +64,10 @@ const getSearchProp = (cell: NavigationBarCellProperty) => {
.navigation-bar {
display: flex;
height: 50px;
padding: 0 6px;
background: #fff;
justify-content: space-between;
align-items: center;
padding: 0 6px;
/* 左边 */
.left {

@ -545,11 +545,12 @@ $toolbar-height: 42px;
gap: 8px;
:deep(.el-tag) {
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
border: none;
box-shadow: 0 2px 8px 0 rgb(0 0 0 / 10%);
.el-tag__content {
width: 100%;
display: flex;
width: 100%;
align-items: center;
justify-content: flex-start;

@ -50,6 +50,7 @@ watch(
<style scoped lang="scss">
:deep(.el-input-group__append) {
padding: 0;
.el-color-picker__trigger {
padding: 0;
border-left: none;

@ -225,15 +225,16 @@ const eachCube = (callback: (x: number, y: number, cube: Cube) => void) => {
<style lang="scss" scoped>
.cube-table {
position: relative;
border-spacing: 0;
border-collapse: collapse;
border-spacing: 0;
.cube {
border: 1px solid var(--el-border-color);
text-align: center;
color: var(--el-text-color-secondary);
text-align: center;
cursor: pointer;
border: 1px solid var(--el-border-color);
box-sizing: border-box;
&.active {
background: var(--el-color-primary-light-9);
}
@ -242,28 +243,28 @@ const eachCube = (callback: (x: number, y: number, cube: Cube) => void) => {
.hot-area {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid var(--el-color-primary);
background: var(--el-color-primary-light-8);
color: var(--el-color-primary);
box-sizing: border-box;
border-spacing: 0;
border-collapse: collapse;
cursor: pointer;
background: var(--el-color-primary-light-8);
border: 1px solid var(--el-color-primary);
border-collapse: collapse;
border-spacing: 0;
box-sizing: border-box;
align-items: center;
justify-content: center;
.btn-delete {
z-index: 1;
position: absolute;
top: -8px;
right: -8px;
height: 16px;
width: 16px;
z-index: 1;
display: flex;
width: 16px;
height: 16px;
background-color: #fff;
border-radius: 50%;
align-items: center;
justify-content: center;
border-radius: 50%;
background-color: #fff;
}
}
}

@ -51,14 +51,14 @@ onMounted(async () => {
<style lang="scss">
.markdown-view {
font-family: PingFang SC;
max-width: 100%;
font-family: "PingFang SC";
font-size: 0.95rem;
font-weight: 400;
line-height: 1.6rem;
letter-spacing: 0em;
text-align: left;
letter-spacing: 0;
color: #3b3e55;
max-width: 100%;
text-align: left;
pre {
position: relative;
@ -69,22 +69,23 @@ onMounted(async () => {
}
code.hljs {
border-radius: 6px;
padding-top: 20px;
width: auto;
@media screen and (min-width: 1536px) {
padding-top: 20px;
border-radius: 6px;
@media screen and (width >= 1536px) {
width: 960px;
}
@media screen and (max-width: 1536px) and (min-width: 1024px) {
@media screen and (width <= 1536px) and (width >= 1024px) {
width: calc(100vw - 400px - 64px - 32px * 2);
}
@media screen and (max-width: 1024px) and (min-width: 768px) {
@media screen and (width <= 1024px) and (width >= 768px) {
width: calc(100vw - 32px * 2);
}
@media screen and (max-width: 768px) {
@media screen and (width <= 768px) {
width: calc(100vw - 16px * 2);
}
}
@ -107,9 +108,9 @@ onMounted(async () => {
h4,
h5,
h6 {
color: var(--color-G900);
margin: 24px 0 8px;
font-weight: 600;
color: var(--el-text-color-primary);
}
h1 {
@ -145,11 +146,11 @@ onMounted(async () => {
/* 列表(有序,无序) */
ul,
ol {
margin: 0 0 8px 0;
padding: 0;
margin: 0 0 8px;
font-size: 16px;
line-height: 24px;
color: #3b3e55; // var(--color-CG600);
color: #3b3e55; // var(--el-text-color-primary);
}
li {
@ -158,8 +159,8 @@ onMounted(async () => {
}
ol > li {
list-style-type: decimal;
margin-bottom: 1rem;
list-style-type: decimal;
// ,
// &:nth-child(n + 10) {
// margin-left: 30px;
@ -171,23 +172,23 @@ onMounted(async () => {
}
ul > li {
list-style-type: disc;
font-size: 16px;
line-height: 24px;
margin-right: 11px;
margin-bottom: 1rem;
font-size: 16px;
line-height: 24px;
color: #3b3e55; // var(--color-G900);
list-style-type: disc;
}
ol ul,
ol ul > li,
ul ul,
ul ul li {
margin-bottom: 1rem;
margin-left: 6px;
// list-style: circle;
font-size: 16px;
list-style: none;
margin-left: 6px;
margin-bottom: 1rem;
}
ul ul ul,

@ -139,11 +139,13 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
.el-transfer {
display: flex;
}
.el-transfer__buttons {
display: flex !important;
flex-direction: column-reverse;
justify-content: center;
gap: 20px;
.el-transfer__button:nth-child(2) {
margin: 0;
}

@ -466,9 +466,9 @@ onMounted(async () => {
<style lang="scss" scoped>
.button-setting-pane {
display: flex;
flex-direction: column;
font-size: 14px;
margin-top: 8px;
font-size: 14px;
flex-direction: column;
.button-setting-desc {
padding-right: 8px;

@ -296,7 +296,9 @@ const clear = () => {
$prefix-cls: #{$namespace}-setting;
.#{$prefix-cls} {
z-index: 1200;
border-radius: 6px 0 0 6px;
z-index: 1200;/*修正没有z-index会被表格层覆盖,值不要超过4000*/
/* 修正没有z-index会被表格层覆盖,值不要超过4000 */
}
</style>

@ -91,7 +91,7 @@ const handleLock = async () => {
<style lang="scss" scoped>
:global(.v-lock-dialog) {
@media (max-width: 767px) {
@media (width <= 767px) {
max-width: calc(100vw - 16px);
}
}

@ -205,6 +205,7 @@ $error-color: #ed6f6f;
font-size: 90px;
}
}
@media screen and (min-width: $screen-lg) {
span:not(.meridiem) {
font-size: 220px;
@ -216,6 +217,7 @@ $error-color: #ed6f6f;
font-size: 260px;
}
}
@media screen and (min-width: $screen-2xl) {
span:not(.meridiem) {
font-size: 320px;
@ -230,7 +232,7 @@ $error-color: #ed6f6f;
display: flex;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
background-color: rgb(0 0 0 / 50%);
backdrop-filter: blur(8px);
justify-content: center;
align-items: center;

@ -461,8 +461,8 @@ getAllApi()
</script>
<style scoped>
.demo-progress .el-progress--line {
margin-bottom: 15px;
max-width: 600px;
margin-bottom: 15px;
}
img{

@ -205,15 +205,18 @@ onMounted(() => {
<style lang="scss" scoped>
:deep() {
.el-table--fit .el-table__inner-wrapper:before {
.el-table--fit .el-table__inner-wrapper::before {
height: 0;
}
.el-card {
border-radius: 8px;
}
.el-form--inline .el-form-item {
margin-right: 10px;
}
.el-divider--horizontal {
margin-top: 6px;
}

@ -283,12 +283,13 @@ onMounted(() => {
<style lang="scss" scoped>
.process-definition-container::before {
content: '';
border-left: 1px solid #e6e6e6;
position: absolute;
left: 20.8%;
height: 100%;
border-left: 1px solid #e6e6e6;
content: '';
}
:deep() {
.definition-item-card {
.el-card__body {

@ -42,8 +42,8 @@ watch(
</script>
<style lang="scss" scoped>
.box-card {
height: 100%;
width: 100%;
height: 100%;
margin-bottom: 0;
:deep(.el-card__body) {
@ -52,9 +52,9 @@ watch(
}
:deep(.process-viewer) {
width: 100%;
height: 100% !important;
min-height: 100%;
width: 100%;
overflow: auto;
}
}

@ -155,13 +155,13 @@ const setSimpleModelNodeTaskStatus = (
<style lang="scss" scoped>
.process-viewer-container {
height: 100%;
width: 100%;
height: 100%;
:deep(.process-viewer) {
width: 100%;
height: 100% !important;
min-height: 100%;
width: 100%;
overflow: auto;
}
}

@ -1,42 +1,26 @@
<template>
<ContentWrap>
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="配方编码" prop="recipeCode">
<el-input
v-model="queryParams.recipeCode"
placeholder="请输入配方编码"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
v-model="queryParams.recipeCode" placeholder="请输入配方编码" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="配方名称" prop="recipeName">
<el-input
v-model="queryParams.recipeName"
placeholder="请输入配方名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
v-model="queryParams.recipeName" placeholder="请输入配方名称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item label="产品名称" prop="productName">
<el-input
v-model="queryParams.productName"
placeholder="请输入产品名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
v-model="queryParams.productName" placeholder="请输入产品名称" clearable @keyup.enter="handleQuery"
class="!w-240px" />
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 查询</el-button>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> 查询
</el-button>
<el-button type="primary" plain @click="openDialog('create')">
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
@ -49,78 +33,60 @@
<ContentWrap>
<el-table
ref="tableRef"
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
@selection-change="handleSelectionChange"
>
ref="tableRef" v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id"
highlight-current-row @selection-change="handleSelectionChange" @row-click="handleRowClick">
<el-table-column type="selection" width="55" reserve-selection />
<el-table-column label="配方编码" align="center" prop="recipeCode" />
<el-table-column label="配方名称" align="center" prop="recipeName" />
<el-table-column label="配方类型" align="center" prop="recipeType" />
<el-table-column label="配方类型" align="center" prop="recipeType">
<template #default="scope">
{{ getRecipeTypeLabel(scope.row.recipeType) }}
</template>
</el-table-column>
<el-table-column label="关联产品" align="center" prop="productName" />
<el-table-column label="关联设备" align="center" prop="deviceName" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" width="240px" fixed="right">
<template #default="scope">
<el-button link type="primary" @click="openConfigDialog(scope.row)"></el-button>
<el-button link type="info" @click="openDetail(scope.row)"></el-button>
<el-button link type="warning" @click="openDialog('update', scope.row)">编辑</el-button>
<el-button link type="danger" @click="handleDelete(scope.row)"></el-button>
<el-button link type="primary" @click.stop="openConfigDialog(scope.row)">配置</el-button>
<el-button link type="warning" @click.stop="openDialog('update', scope.row)">编辑</el-button>
<el-button link type="danger" @click.stop="handleDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="handlePagination"
/>
:total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
@pagination="handlePagination" />
</ContentWrap>
<ContentWrap v-if="detailVisible">
<div class="flex items-center justify-between mb-12px">
<div class="text-14px">
详情{{ detailMeta.recipeCode }} - {{ detailMeta.recipeName }}
</div>
<el-button link type="info" @click="closeDetail"></el-button>
</div>
<el-table
v-loading="detailLoading"
:data="detailList"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
>
<el-table-column label="序号" align="center" width="80">
<template #default="scope">
{{ (detailQueryParams.pageNo - 1) * detailQueryParams.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="点位名称" align="center" prop="pointName" />
<el-table-column label="点位类型" align="center" prop="pointType" />
<el-table-column label="数据类型" align="center" prop="dataType" />
<el-table-column label="单位" align="center" prop="dataUnit" />
</el-table>
<Pagination
:total="detailTotal"
v-model:page="detailQueryParams.pageNo"
v-model:limit="detailQueryParams.pageSize"
@pagination="handleDetailPagination"
/>
<el-tabs v-model="detailActiveTab" class="mb-12px">
<template #extra>
<el-button link type="info" @click="closeDetail"></el-button>
</template>
<el-tab-pane :label="`详情:${detailMeta.recipeCode} - ${detailMeta.recipeName}`" name="detail">
<el-table
v-loading="detailLoading" :data="detailList" :stripe="true" :show-overflow-tooltip="true"
row-key="id">
<el-table-column label="序号" align="center" width="80">
<template #default="scope">
{{ (detailQueryParams.pageNo - 1) * detailQueryParams.pageSize + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="点位名称" align="center" prop="pointName" />
<el-table-column label="点位类型" align="center" prop="pointType" />
<el-table-column label="数据类型" align="center" prop="dataType" />
<el-table-column label="单位" align="center" prop="dataUnit" />
</el-table>
<Pagination
:total="detailTotal" v-model:page="detailQueryParams.pageNo"
v-model:limit="detailQueryParams.pageSize" @pagination="handleDetailPagination" />
</el-tab-pane>
</el-tabs>
</ContentWrap>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="720px">
<el-form
ref="dialogFormRef"
:model="dialogForm"
:rules="dialogRules"
label-width="100px"
v-loading="dialogLoading"
>
<el-form ref="dialogFormRef" :model="dialogForm" :rules="dialogRules" label-width="100px" v-loading="dialogLoading">
<el-form-item label="配方编码" prop="recipeCode">
<el-input v-model="dialogForm.recipeCode" placeholder="请输入配方编码" clearable />
</el-form-item>
@ -128,40 +94,24 @@
<el-input v-model="dialogForm.recipeName" placeholder="请输入配方名称" clearable />
</el-form-item>
<el-form-item label="配方类型" prop="recipeType">
<el-input v-model="dialogForm.recipeType" placeholder="请输入配方类型" clearable />
<el-select
v-model="dialogForm.recipeType" placeholder="请选择配方类型" clearable filterable class="!w-full"
:loading="recipeTypeLoading">
<el-option v-for="item in recipeTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="关联产品" prop="productId">
<el-select
v-model="dialogForm.productId"
placeholder="请选择关联产品"
clearable
filterable
class="!w-full"
:loading="productLoading"
>
<el-option
v-for="item in productOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
v-model="dialogForm.productId" placeholder="请选择关联产品" clearable filterable class="!w-full"
:loading="productLoading">
<el-option v-for="item in productOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="关联设备" prop="deviceId">
<el-select
v-model="dialogForm.deviceId"
placeholder="请选择关联设备"
clearable
filterable
class="!w-full"
:loading="deviceLoading"
>
<el-option
v-for="item in deviceOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
v-model="dialogForm.deviceId" placeholder="请选择关联设备" clearable filterable class="!w-full"
:loading="deviceLoading">
<el-option v-for="item in deviceOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
@ -177,11 +127,8 @@
<Dialog title="配置" v-model="configVisible" width="920px">
<div v-loading="configLoading">
<el-transfer
v-model="configSelectedKeys"
:data="configCandidates"
filterable
:titles="['候选点位', '已选点位']"
/>
class="formula-config-transfer" v-model="configSelectedKeys" :data="configCandidates" filterable
:titles="['来源', '目标']" />
</div>
<template #footer>
<el-button @click="configVisible = false"> </el-button>
@ -194,6 +141,7 @@
import download from '@/utils/download'
import { ProductApi } from '@/api/erp/product/product'
import { DeviceApi } from '@/api/iot/device'
import { RecipeApi } from '@/api/iot/recipe'
import { RecipeConfigApi, RecipeConfigVO, RecipePointDetailVO } from '@/api/iot/recipeConfig'
type SelectOption = { label: string; value: number }
@ -204,8 +152,6 @@ const message = useMessage()
const { t } = useI18n()
const loading = ref(false)
const tableRef = ref()
const queryFormRef = ref()
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
@ -278,13 +224,15 @@ const handleDelete = async (row: RecipeConfigVO) => {
await RecipeConfigApi.deleteRecipeConfig(row.id)
message.success(t('common.delSuccess'))
await getList()
} catch {}
} catch { }
}
const productLoading = ref(false)
const productOptions = ref<SelectOption[]>([])
const deviceLoading = ref(false)
const deviceOptions = ref<SelectOption[]>([])
const recipeTypeLoading = ref(false)
const recipeTypeOptions = ref<SelectOption[]>([])
const productLabelMap = computed<Record<number, string>>(() => {
return productOptions.value.reduce((acc, cur) => {
@ -300,6 +248,19 @@ const deviceLabelMap = computed<Record<number, string>>(() => {
}, {} as Record<number, string>)
})
const recipeTypeLabelMap = computed<Record<number, string>>(() => {
return recipeTypeOptions.value.reduce((acc, cur) => {
acc[cur.value] = cur.label
return acc
}, {} as Record<number, string>)
})
const getRecipeTypeLabel = (value: unknown) => {
const num = Number(value)
if (!Number.isNaN(num) && recipeTypeLabelMap.value[num]) return recipeTypeLabelMap.value[num]
return (value as any) ?? ''
}
const getProductOptions = async () => {
productLoading.value = true
try {
@ -320,9 +281,23 @@ const getDeviceOptions = async () => {
}
}
const getRecipeTypeOptions = async () => {
recipeTypeLoading.value = true
try {
const data = await RecipeApi.getRecipePage(undefined)
recipeTypeOptions.value = (data?.list ?? []).map((item: any) => ({
label: item.name,
value: item.id
}))
} finally {
recipeTypeLoading.value = false
}
}
const ensureOptionsLoaded = async () => {
if (!productOptions.value.length) await getProductOptions()
if (!deviceOptions.value.length) await getDeviceOptions()
if (!recipeTypeOptions.value.length) await getRecipeTypeOptions()
}
type DialogMode = 'create' | 'update'
@ -335,7 +310,7 @@ const dialogForm = reactive({
id: undefined as number | undefined,
recipeCode: '',
recipeName: '',
recipeType: '',
recipeType: undefined as number | undefined,
productId: undefined as number | undefined,
deviceId: undefined as number | undefined,
remark: ''
@ -358,7 +333,7 @@ const openDialog = async (mode: DialogMode, row?: RecipeConfigVO) => {
dialogForm.id = undefined
dialogForm.recipeCode = ''
dialogForm.recipeName = ''
dialogForm.recipeType = ''
dialogForm.recipeType = undefined
dialogForm.productId = undefined
dialogForm.deviceId = undefined
dialogForm.remark = ''
@ -368,7 +343,7 @@ const openDialog = async (mode: DialogMode, row?: RecipeConfigVO) => {
dialogForm.id = row?.id
dialogForm.recipeCode = row?.recipeCode ?? ''
dialogForm.recipeName = row?.recipeName ?? ''
dialogForm.recipeType = row?.recipeType ?? ''
dialogForm.recipeType = typeof row?.recipeType === 'number' ? row.recipeType : Number(row?.recipeType) || undefined
dialogForm.productId = row?.productId
dialogForm.deviceId = row?.deviceId
dialogForm.remark = row?.remark ?? ''
@ -405,6 +380,7 @@ const submitDialog = async () => {
}
const detailVisible = ref(false)
const detailActiveTab = ref('detail')
const detailLoading = ref(false)
const detailList = ref<RecipePointDetailVO[]>([])
const detailTotal = ref(0)
@ -442,11 +418,19 @@ const openDetail = async (row: RecipeConfigVO) => {
detailQueryParams.recipeId = row.id
detailQueryParams.pageNo = 1
detailVisible.value = true
detailActiveTab.value = 'detail'
await getDetailList()
}
const handleRowClick = async (row: RecipeConfigVO, column: any) => {
if (column?.type === 'selection') return
if (column?.label === '操作') return
await openDetail(row)
}
const closeDetail = () => {
detailVisible.value = false
detailActiveTab.value = 'detail'
detailMeta.recipeId = undefined
detailMeta.recipeCode = ''
detailMeta.recipeName = ''
@ -518,4 +502,21 @@ onMounted(() => {
})
</script>
<style scoped></style>
<style scoped>
:deep(.formula-config-transfer.el-transfer) {
--el-transfer-panel-body-height: 440px;
display: flex;
width: 100%;
}
:deep(.formula-config-transfer .el-transfer-panel) {
width: calc((100% - 96px) / 2);
}
:deep(.el-transfer__buttons) {
display: flex;
text-align: center;
align-items: center;
}
</style>

@ -3,7 +3,8 @@
<div class="single-device-dialog">
<el-form class="-mb-15px" :inline="true" label-width="80px">
<el-form-item label="采集时间">
<el-date-picker v-model="collectionTimeRange" value-format="YYYY-MM-DD HH:mm:ss" type="datetimerange"
<el-date-picker
v-model="collectionTimeRange" value-format="YYYY-MM-DD HH:mm:ss" type="datetimerange"
start-placeholder="开始时间" end-placeholder="结束时间"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-360px" />
</el-form-item>
@ -19,15 +20,18 @@
采集时间{{ group.collectTime || '-' }}
</div>
<div v-if="group.sections.length" class="single-device-dialog__table-grid">
<div v-for="section in group.sections" :key="`${group.key}-${section.key}`"
<div
v-for="section in group.sections" :key="`${group.key}-${section.key}`"
class="single-device-dialog__section">
<div class="single-device-dialog__section-title">
{{ section.title }}
</div>
<el-empty v-if="!section.columns.length" description="暂无数据" />
<el-table v-else :data="section.rows" :border="true" :header-cell-style="headerCellStyle"
<el-table
v-else :data="section.rows" :border="true" :header-cell-style="headerCellStyle"
:cell-style="bodyCellStyle" size="small">
<el-table-column v-for="col in section.columns" :key="col.prop" :prop="col.prop" :label="col.label"
<el-table-column
v-for="col in section.columns" :key="col.prop" :prop="col.prop" :label="col.label"
align="center">
<template #default="scope">
<span>{{ formatCell(scope.row[col.prop]) }}</span>
@ -228,16 +232,16 @@ watch(
.single-device-dialog__record {
padding: 12px;
background: var(--el-bg-color-overlay);
border: 1px solid var(--el-border-color);
border-radius: 6px;
background: var(--el-bg-color-overlay);
}
.single-device-dialog__section {
padding: 10px;
background: var(--el-fill-color-lighter);
border: 1px solid var(--el-border-color);
border-radius: 6px;
background: var(--el-fill-color-lighter);
}
.single-device-dialog__section :deep(.el-table) {
@ -245,14 +249,14 @@ watch(
}
.single-device-dialog__record-title {
font-size: 13px;
margin-bottom: 6px;
font-size: 13px;
color: var(--el-text-color-secondary);
}
.single-device-dialog__section-title {
font-size: 13px;
margin-bottom: 4px;
font-size: 13px;
color: var(--el-text-color-primary);
}

@ -204,8 +204,8 @@ watch(
}
.single-device-dialog__section-title {
font-size: 13px;
margin-bottom: 4px;
font-size: 13px;
color: var(--el-text-color-primary);
}

@ -136,11 +136,11 @@ const emitActivityChange = () => {
display: flex;
width: 60px;
height: 60px;
cursor: pointer;
border: 1px dashed var(--el-border-color-darker);
border-radius: 8px;
align-items: center;
justify-content: center;
cursor: pointer;
}
.spu-pic {

@ -208,8 +208,8 @@ onBeforeUnmount(() => {
//transition: border-left 0.05s ease-in-out; /* */
.username {
min-width: 0;
max-width: 60%;
min-width: 0;
}
.last-message {
@ -218,27 +218,27 @@ onBeforeUnmount(() => {
.last-message,
.username {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
}
.active {
background-color: rgba(128, 128, 128, 0.5); //
background-color: rgb(128 128 128 / 50%); //
}
.right-menu-ul {
position: absolute;
background-color: var(--app-content-bg-color);
width: 130px;
padding: 5px;
margin: 0;
list-style-type: none; /* 移除默认的项目符号 */
background-color: var(--app-content-bg-color);
border-radius: 12px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 阴影效果 */
width: 130px;
box-shadow: 0 2px 4px rgb(0 0 0 / 10%); /* 阴影效果 */
li {
padding: 8px 16px;

@ -372,36 +372,36 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
<style lang="scss" scoped>
.kefu {
background-color: #f5f5f5;
position: relative;
width: calc(100% - 300px - 260px);
background-color: #f5f5f5;
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 1px; /* 实际宽度 */
height: 100%;
background-color: var(--el-border-color);
content: '';
transform: scaleX(0.3); /* 缩小宽度 */
}
.kefu-header {
background-color: #f5f5f5;
position: relative;
display: flex;
background-color: #f5f5f5;
align-items: center;
justify-content: space-between;
&::before {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 1px; /* 初始宽度 */
background-color: var(--el-border-color);
content: '';
transform: scaleY(0.3); /* 缩小视觉高度 */
}
@ -412,30 +412,30 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
}
&-content {
margin: 0;
padding: 10px;
position: relative;
height: 100%;
width: 100%;
height: 100%;
padding: 10px;
margin: 0;
.newMessageTip {
position: absolute;
bottom: 35px;
right: 35px;
background-color: var(--app-content-bg-color);
bottom: 35px;
padding: 10px;
border-radius: 30px;
font-size: 12px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 阴影效果 */
background-color: var(--app-content-bg-color);
border-radius: 30px;
box-shadow: 0 2px 4px rgb(0 0 0 / 10%); /* 阴影效果 */
}
.ss-row-left {
justify-content: flex-start;
.kefu-message {
background-color: #fff;
margin-left: 10px;
margin-top: 3px;
margin-left: 10px;
background-color: #fff;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
border-bottom-left-radius: 10px;
@ -446,22 +446,22 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
justify-content: flex-end;
.kefu-message {
background-color: rgb(206, 223, 255);
margin-right: 10px;
margin-top: 3px;
border-top-left-radius: 10px;
margin-right: 10px;
background-color: rgb(206 223 255);
border-bottom-right-radius: 10px;
border-bottom-left-radius: 10px;
border-top-left-radius: 10px;
}
}
//
.kefu-message {
color: #414141;
font-weight: 500;
padding: 5px 10px;
width: auto;
max-width: 50%;
padding: 5px 10px;
font-weight: 500;
color: #414141;
//text-align: left;
//display: inline-block !important;
//word-break: break-all;
@ -475,30 +475,30 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
.date-message,
.system-message {
width: fit-content;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 8px;
padding: 0 5px;
color: #fff;
font-size: 10px;
color: #fff;
background-color: rgb(0 0 0 / 10%);
border-radius: 8px;
}
}
.kefu-footer {
position: relative;
display: flex;
flex-direction: column;
height: auto;
margin: 0;
padding: 0;
margin: 0;
flex-direction: column;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 1px; /* 初始宽度 */
background-color: var(--el-border-color);
content: '';
transform: scaleY(0.3); /* 缩小视觉高度 */
}
@ -509,13 +509,13 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
}
::v-deep(textarea) {
resize: none;
background-color: #f5f5f5;
resize: none;
}
:deep(.el-input__wrapper) {
box-shadow: none !important;
border-radius: 0;
box-shadow: none !important;
}
::v-deep(.el-textarea__inner) {

@ -170,31 +170,31 @@ const getUserData = async () => {
background-color: #f5f5f5;
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 1px; /* 实际宽度 */
height: 100%;
background-color: var(--el-border-color);
content: '';
transform: scaleX(0.3); /* 缩小宽度 */
}
&-header {
background-color: #f5f5f5;
position: relative;
display: flex;
background-color: #f5f5f5;
align-items: center;
justify-content: space-around;
&::before {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 1px; /* 初始宽度 */
background-color: var(--el-border-color);
content: '';
transform: scaleY(0.3); /* 缩小视觉高度 */
}
@ -204,45 +204,39 @@ const getUserData = async () => {
}
&-item {
height: 100%;
width: 100%;
position: relative;
width: 100%;
height: 100%;
&-activation::before {
content: '';
position: absolute; /* 绝对定位 */
top: 0;
left: 0;
right: 0;
bottom: 0; /* 覆盖整个元素 */
border-bottom: 2px solid rgba(128, 128, 128, 0.5); /* 边框样式 */
inset: 0; /* 覆盖整个元素 */
pointer-events: none; /* 确保点击事件不会被伪元素拦截 */
border-bottom: 2px solid rgb(128 128 128 / 50%); /* 边框样式 */
content: '';
}
&:hover::before {
content: '';
position: absolute; /* 绝对定位 */
top: 0;
left: 0;
right: 0;
bottom: 0; /* 覆盖整个元素 */
border-bottom: 2px solid rgba(128, 128, 128, 0.5); /* 边框样式 */
inset: 0; /* 覆盖整个元素 */
pointer-events: none; /* 确保点击事件不会被伪元素拦截 */
border-bottom: 2px solid rgb(128 128 128 / 50%); /* 边框样式 */
content: '';
}
}
}
&-content {
margin: 0;
padding: 0;
position: relative;
height: 100%;
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
&-tabs {
height: 100%;
width: 100%;
height: 100%;
}
}

@ -109,10 +109,10 @@ function formatOrderStatus(order: any) {
<style lang="scss" scoped>
.order-list-card-box {
border-radius: 10px;
padding: 10px;
border: 1px var(--el-border-color) solid;
background-color: #fff; //
border: 1px var(--el-border-color) solid;
border-radius: 10px;
.order-card-header {
height: 28px;
@ -123,8 +123,8 @@ function formatOrderStatus(order: any) {
span {
&:hover {
text-decoration: underline;
color: var(--left-menu-bg-active-color);
text-decoration: underline;
}
}
}
@ -144,9 +144,9 @@ function formatOrderStatus(order: any) {
}
.discounts-money {
font-family: OPPOSANS;
font-size: 16px;
line-height: normal;
font-family: OPPOSANS;
}
.pay-color {
@ -156,26 +156,26 @@ function formatOrderStatus(order: any) {
}
.warning-color {
color: #faad14;
font-size: 11px;
font-weight: bold;
color: #faad14;
}
.danger-color {
color: #ff3000;
font-size: 11px;
font-weight: bold;
color: #ff3000;
}
.success-color {
color: #52c41a;
font-size: 11px;
font-weight: bold;
color: #52c41a;
}
.info-color {
color: #999999;
font-size: 11px;
font-weight: bold;
color: #999;
}
</style>

@ -68,20 +68,20 @@ const openDetail = (spuId: number) => {
<style lang="scss" scoped>
.button {
background-color: #007bff;
color: white;
border: none;
padding: 5px 10px;
color: white;
cursor: pointer;
background-color: #007bff;
border: none;
}
.product-warp {
display: flex;
width: 100%;
padding: 10px;
background-color: #fff;
border-radius: 8px;
display: flex;
align-items: center;
padding: 10px;
&-left {
width: 70px;
@ -97,14 +97,14 @@ const openDetail = (spuId: number) => {
flex: 1;
.description {
display: -webkit-box;
width: 100%;
overflow: hidden;
font-size: 16px;
font-weight: bold;
display: -webkit-box;
-webkit-line-clamp: 1; /* 显示一行 */
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1; /* 显示一行 */
}
.price {

@ -102,11 +102,11 @@ onBeforeUnmount(() => {
<style lang="scss">
.kefu-layout {
position: absolute;
flex: 1;
top: 0;
left: 0;
height: 100%;
width: 100%;
height: 100%;
flex: 1;
}
/* 定义滚动条样式 */
@ -117,15 +117,15 @@ onBeforeUnmount(() => {
/* 定义滚动条轨道 内阴影+圆角 */
::-webkit-scrollbar-track {
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
border-radius: 10px;
background-color: #fff;
border-radius: 10px;
box-shadow: inset 0 0 0 rgb(240 240 240 / 50%);
}
/* 定义滑块 内阴影+圆角 */
::-webkit-scrollbar-thumb {
background-color: rgb(240 240 240 / 50%);
border-radius: 10px;
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
background-color: rgba(240, 240, 240, 0.5);
box-shadow: inset 0 0 0 rgb(240 240 240 / 50%);
}
</style>

@ -132,11 +132,11 @@ const emitActivityChange = () => {
display: flex;
width: 60px;
height: 60px;
cursor: pointer;
border: 1px dashed var(--el-border-color-darker);
border-radius: 8px;
align-items: center;
justify-content: center;
cursor: pointer;
}
.spu-pic {

@ -134,11 +134,11 @@ const emitActivityChange = () => {
display: flex;
width: 60px;
height: 60px;
cursor: pointer;
border: 1px dashed var(--el-border-color-darker);
border-radius: 8px;
align-items: center;
justify-content: center;
cursor: pointer;
}
.spu-pic {

@ -394,11 +394,11 @@ onMounted(async () => {
.el-timeline-right-content {
display: flex;
align-items: center;
min-height: 30px;
padding: 10px;
border-radius: var(--el-card-border-radius);
background-color: var(--app-content-bg-color);
border-radius: var(--el-card-border-radius);
align-items: center;
&::before {
position: absolute;

@ -70,8 +70,8 @@ withDefaults(defineProps<{ user: UserApi.UserVO; wallet: WalletApi.WalletVO; col
justify-content: space-between;
.el-descriptions__label {
width: 120px;
display: block;
width: 120px;
text-align: left;
}

@ -151,8 +151,8 @@ withDefaults(defineProps<{ user: UserApi.UserVO; mode?: string }>(), {
justify-content: space-between;
.el-descriptions__label {
width: 120px;
display: block;
width: 120px;
text-align: left;
}

@ -0,0 +1,117 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入编码" />
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入排序" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DeviceTypeApi, DeviceTypeTreeVO, DeviceTypeVO } from '@/api/mes/devicetype'
/** 设备类型 表单 */
defineOptions({ name: 'DeviceTypeForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
code: undefined,
name: undefined,
remark: undefined,
sort: undefined,
parentId: undefined
})
const formRules = reactive({
code: [{ required: true, message: '编码不能为空', trigger: 'blur' }],
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, parentRow?: DeviceTypeTreeVO) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
if (type === 'create') {
formData.value.parentId = parentRow?.id ?? 0
}
//
if (id) {
formLoading.value = true
try {
formData.value = await DeviceTypeApi.getDeviceType(id)
if (formData.value.parentId === undefined) {
formData.value.parentId = parentRow?.parentId ?? 0
}
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as DeviceTypeVO
if (formType.value === 'create') {
await DeviceTypeApi.createDeviceType(data)
message.success(t('common.createSuccess'))
} else {
await DeviceTypeApi.updateDeviceType(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
code: undefined,
name: undefined,
remark: undefined,
sort: undefined,
parentId: undefined
}
formRef.value?.resetFields()
}
</script>

@ -0,0 +1,233 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="编码" prop="code">
<el-input
v-model="queryParams.code"
placeholder="请输入编码"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['mes:device-type:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
row-key="id"
default-expand-all
:tree-props="{ children: 'children' }"
>
<el-table-column label="id" align="center" prop="id" />
<el-table-column label="编码" align="center" prop="code" />
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('create', undefined, scope.row)"
>
添加
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id, scope.row)"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
v-if="showPagination"
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<DeviceTypeForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { DeviceTypeApi, DeviceTypeTreeVO } from '@/api/mes/devicetype'
import DeviceTypeForm from './DeviceTypeForm.vue'
/** 设备类型 列表 */
defineOptions({ name: 'DeviceType' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<DeviceTypeTreeVO[]>([]) //
const total = ref(0) //
const showPagination = ref(true)
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
code: undefined,
name: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const [createStartTime, createEndTime] = Array.isArray(queryParams.createTime)
? queryParams.createTime
: []
const data = await DeviceTypeApi.getDeviceTypeTree({
pageNo: queryParams.pageNo,
pageSize: queryParams.pageSize,
code: queryParams.code,
name: queryParams.name,
createStartTime: createStartTime || undefined,
createEndTime: createEndTime || undefined
})
if (Array.isArray(data)) {
list.value = data
total.value = data.length
showPagination.value = false
return
}
list.value = data.list
total.value = data.total
showPagination.value = true
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number, parentRow?: DeviceTypeTreeVO) => {
formRef.value.open(type, id, parentRow)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await DeviceTypeApi.deleteDeviceType(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await DeviceTypeApi.exportDeviceType(queryParams)
download.excel(data, '设备类型.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

@ -62,7 +62,7 @@
<el-divider />
<el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
<el-descriptions-item label="支付通道异步回调内容">
<el-text style="white-space: pre-wrap; word-break: break-word">
<el-text style=" word-break: break-word;white-space: pre-wrap">
{{ detailData.extension.channelNotifyData }}
</el-text>
</el-descriptions-item>

@ -62,7 +62,7 @@
</el-descriptions>
<el-descriptions :column="1" label-class-name="desc-label" direction="vertical" border>
<el-descriptions-item label="支付通道异步回调内容">
<el-text style="white-space: pre-wrap; word-break: break-word">
<el-text style=" word-break: break-word;white-space: pre-wrap">
{{ refundDetail.channelNotifyData }}
</el-text>
</el-descriptions-item>

Loading…
Cancel
Save