feat: 新增平台对接
This commit is contained in:
parent
67d637cca9
commit
001bb6bce0
|
@ -0,0 +1,31 @@
|
|||
import server from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 分页查询平台接入列表
|
||||
* @param data
|
||||
*/
|
||||
export const queryList = (data: any) => server.post(`/network/card/platform/_query`, data)
|
||||
|
||||
/**
|
||||
* 根据id查询详情
|
||||
* @param id
|
||||
*/
|
||||
export const queryById = (id: any) => server.get(`/network/card/platform/${id}`)
|
||||
|
||||
/**
|
||||
* 新增
|
||||
* @param data
|
||||
*/
|
||||
export const save = (data: any) => server.post(`/network/card/platform`, data)
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param data
|
||||
*/
|
||||
export const update = (data: any) => server.patch(`/network/card/platform`, data)
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param id
|
||||
*/
|
||||
export const del = (id: string) => server.remove(`/network/card/platform/${id}`)
|
|
@ -0,0 +1,249 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<a-card>
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="14">
|
||||
<TitleComponent data="详情" />
|
||||
<a-form
|
||||
:layout="'vertical'"
|
||||
ref="formRef"
|
||||
:rules="rules"
|
||||
:model="form"
|
||||
>
|
||||
<a-form-item
|
||||
label="平台类型"
|
||||
name="operatorName"
|
||||
required
|
||||
>
|
||||
<PlatformType
|
||||
:disabled="false"
|
||||
:model="'singular'"
|
||||
:itemStyle="{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-around',
|
||||
minWidth: '130px',
|
||||
}"
|
||||
:options="platformTypeList"
|
||||
v-model:value="form.operatorName"
|
||||
@change="typeChange"
|
||||
></PlatformType
|
||||
></a-form-item>
|
||||
<a-form-item label="名称" name="name">
|
||||
<a-input
|
||||
v-model:value="form.name"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<!-- onelink -->
|
||||
<div v-if="form.operatorName === 'onelink'">
|
||||
<a-form-item label="App ID" name="appId">
|
||||
<a-input
|
||||
v-model:value="form.appId"
|
||||
placeholder="请输入App ID"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="Password" name="passWord">
|
||||
<a-input-password
|
||||
v-model:value="form.passWord"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="接口地址" name="apiAddr">
|
||||
<a-input
|
||||
v-model:value="form.apiAddr"
|
||||
placeholder="请输入接口地址"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<!-- ctwing -->
|
||||
<div v-if="form.operatorName === 'ctwing'">
|
||||
<a-form-item label="用户id" name="userId">
|
||||
<a-input
|
||||
v-model:value="form.userId"
|
||||
placeholder="请输入用户id"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="密码" name="passWord">
|
||||
<a-input-password
|
||||
v-model:value="form.passWord"
|
||||
placeholder="请输入密码"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="secretKey" name="secretKey">
|
||||
<a-input
|
||||
v-model:value="form.secretKey"
|
||||
placeholder="请输入secretKey"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
<!-- unicom -->
|
||||
<div v-if="form.operatorName === 'unicom'">
|
||||
<a-form-item label="App ID" name="appId">
|
||||
<a-input
|
||||
v-model:value="form.appId"
|
||||
placeholder="请输入App ID"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="App Secret" name="appSecret">
|
||||
<a-input
|
||||
v-model:value="form.appSecret"
|
||||
placeholder="请输入App Secret"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="创建者ID" name="openId">
|
||||
<a-input
|
||||
v-model:value="form.openId"
|
||||
placeholder="请输入创建者ID"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<a-form-item label="说明" name="explain">
|
||||
<a-textarea
|
||||
v-model:value="form.explain"
|
||||
placeholder="请输入说明"
|
||||
showCount
|
||||
:rows="3"
|
||||
:maxlength="200"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-divider />
|
||||
<a-button
|
||||
:loading="saveBtnLoading"
|
||||
type="primary"
|
||||
@click="handleSave"
|
||||
>
|
||||
保存
|
||||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-col :span="10">
|
||||
<Doc :type="form.operatorName" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getImage } from '@/utils/comm';
|
||||
import PlatformType from '@/views/iot-card/components/PlatformType.vue';
|
||||
import { queryById, save, update } from '@/api/iot-card/platform';
|
||||
import { message } from 'ant-design-vue';
|
||||
import Doc from '../doc/index.vue';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
const formRef = ref();
|
||||
const saveBtnLoading = ref<boolean>(false);
|
||||
|
||||
const form = reactive({
|
||||
operatorName: 'onelink',
|
||||
name: undefined,
|
||||
// onelink
|
||||
appId: undefined,
|
||||
passWord: undefined,
|
||||
apiAddr: undefined,
|
||||
// ctwing
|
||||
userId: undefined,
|
||||
secretKey: undefined,
|
||||
// unicom
|
||||
appSecret: undefined,
|
||||
openId: undefined,
|
||||
explain: undefined,
|
||||
});
|
||||
|
||||
const platformTypeList = [
|
||||
{
|
||||
label: '移动OneLink',
|
||||
value: 'onelink',
|
||||
imgUrl: getImage('/iot-card/onelink.png'),
|
||||
imgSize: ['78px', '20px'],
|
||||
},
|
||||
{
|
||||
label: '电信Ctwing',
|
||||
value: 'ctwing',
|
||||
imgUrl: getImage('/iot-card/ctwingcmp.png'),
|
||||
imgSize: ['52px', '25px'],
|
||||
},
|
||||
{
|
||||
label: '联通Unicom',
|
||||
value: 'unicom',
|
||||
imgUrl: getImage('/iot-card/unicom.png'),
|
||||
imgSize: ['56px', '41px'],
|
||||
},
|
||||
];
|
||||
|
||||
const rules = {
|
||||
name: [
|
||||
{ required: true, message: '请输入名称' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
],
|
||||
appId: [
|
||||
{ required: true, message: '请输入App ID' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
],
|
||||
passWord: [
|
||||
{ required: true, message: '请输入密码' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
],
|
||||
apiAddr: [{ required: true, message: '请输入接口地址' }],
|
||||
userId: [
|
||||
{ required: true, message: '请输入用户 ID' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
],
|
||||
secretKey: [{ required: true, message: '请输入secretKey' }],
|
||||
appSecret: [{ required: true, message: '请输入App Secret' }],
|
||||
openId: [{ required: true, message: '请输入创建者ID' }],
|
||||
explain: [{ required: false, max: 200, message: '最多可输入200个字符' }],
|
||||
};
|
||||
|
||||
const getDetail = async () => {
|
||||
if (route.params.id === ':id') return;
|
||||
const resp: any = await queryById(route.params.id);
|
||||
if (resp.status === 200) {
|
||||
Object.assign(form, resp.result, { ...resp.result.config });
|
||||
}
|
||||
};
|
||||
|
||||
const typeChange = (val: any) => {
|
||||
formRef.value.resetFields();
|
||||
form.operatorName = val;
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
const data: any = await formRef.value.validate();
|
||||
const formData = {
|
||||
operatorName: data.operatorName,
|
||||
name: data.name,
|
||||
config: {
|
||||
appId: data.appId,
|
||||
passWord: data.passWord,
|
||||
apiAddr: data.apiAddr,
|
||||
userId: data.userId,
|
||||
secretKey: data.secretKey,
|
||||
appSecret: data.appSecret,
|
||||
openId: data.openId,
|
||||
},
|
||||
explain: data.explain,
|
||||
};
|
||||
saveBtnLoading.value = true;
|
||||
|
||||
const res: any =
|
||||
route.params.id === ':id'
|
||||
? await save(formData)
|
||||
: await update({ id: route.params.id, ...formData });
|
||||
if (res.status === 200) {
|
||||
message.success('保存成功!');
|
||||
router.back();
|
||||
}
|
||||
saveBtnLoading.value = false;
|
||||
};
|
||||
|
||||
getDetail();
|
||||
</script>
|
|
@ -0,0 +1,220 @@
|
|||
<template>
|
||||
<div v-if="type === 'onelink'" class="doc">
|
||||
<div class="url">
|
||||
中国移动物联卡能力开放平台:
|
||||
<a
|
||||
style="word-break: break-all"
|
||||
href="https://api.iot.10086.cn/api/index.html#/login"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
https://api.iot.10086.cn/api/index.html#/login
|
||||
</a>
|
||||
</div>
|
||||
<h1>1.概述</h1>
|
||||
<p>
|
||||
平台对接通过API的方式与三方系统进行数据对接,为物联卡的管理提供数据交互支持。
|
||||
</p>
|
||||
<h1>2.配置说明</h1>
|
||||
<h2>1、APP ID</h2>
|
||||
<p>
|
||||
第三方应用唯一标识,中国移动物联网全网管理员在 OneLink
|
||||
能力开放平台上分配并展示给集团客户。
|
||||
<br />
|
||||
获取路径:“中移物联卡能力开放平台”--“个人中心”--“客户信息”--“接入信息”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/onelink-appid.png')"
|
||||
/>
|
||||
</div>
|
||||
<h2>2、Password</h2>
|
||||
<p>
|
||||
API 接入秘钥,由中国移动物联网提供,集团客户从“OneLink
|
||||
能力开放平台”获取。
|
||||
<br />
|
||||
获取路径:“中移物联卡能力开放平台”--“个人中心”--“客户信息”--“接入信息”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/onelink-pass.png')"
|
||||
/>
|
||||
</div>
|
||||
<h2>3、接口地址</h2>
|
||||
<p>
|
||||
https://api.iot.10086.cn/v5/ec/get/token
|
||||
<br />
|
||||
token后缀请根据实际情况填写
|
||||
<br />
|
||||
示例:https://api.iot.10086.cn/v5/authService?appid=xxx&password=xxx&transid=xxx
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-if="type === 'ctwing'" class="doc">
|
||||
<div class="url">
|
||||
5G连接管理平台:
|
||||
<a
|
||||
style="word-break: break-all"
|
||||
href="https://cmp.ctwing.cn:4821/login"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
https://cmp.ctwing.cn:4821/login
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<h1>1.概述</h1>
|
||||
<p>
|
||||
平台对接通过API的方式与三方系统进行数据对接,为物联卡的管理提供数据交互支持。
|
||||
</p>
|
||||
<h1>2.配置说明</h1>
|
||||
<h2>1、用户 id</h2>
|
||||
<p>
|
||||
5G连接管理平台用户的唯一标识,用于身份识别。
|
||||
<br />
|
||||
获取路径:“5G连接管理平台”--“能力开放”--“API网关账号管理”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/ctwing-id.png')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2>2、密码</h2>
|
||||
<p>
|
||||
用户id经加密之后的密码。
|
||||
<br />
|
||||
获取路径:“5G连接管理平台”--“能力开放”--“API网关账号管理”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/ctwing-pass.png')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2>3、secretKey</h2>
|
||||
<p>
|
||||
APP secret唯一秘钥。
|
||||
<br />
|
||||
获取路径:“5G连接管理平台”--“能力开放”--“API网关账号管理”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/ctwing-secret.png')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="type === 'unicom'" class="doc">
|
||||
<div class="url">
|
||||
雁飞智连CMP平台:
|
||||
<a
|
||||
style="word-break: break-all"
|
||||
href=" https://cmp.10646.cn/webframe/login"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
https://cmp.10646.cn/webframe/login
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h1>1.概述</h1>
|
||||
<p>
|
||||
平台对接通过API的方式与三方系统进行数据对接,为物联卡的管理提供数据交互支持。
|
||||
</p>
|
||||
<h1>2.配置说明</h1>
|
||||
<h2>1、APP ID</h2>
|
||||
<p>
|
||||
第三方应用唯一标识。
|
||||
<br />
|
||||
获取路径:“雁飞智连CMP平台”--“我的应用”--“应用列表”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/unicom-id.png')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2>2、App Secret</h2>
|
||||
<p>
|
||||
API 接入秘钥。
|
||||
<br />
|
||||
获取路径:“雁飞智连CMP平台”--“我的应用”--“应用列表”
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/unicom-secret.png')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2>3、创建者ID</h2>
|
||||
<p>
|
||||
接口参数中的 OpenId。
|
||||
<br />
|
||||
获取路径:“雁飞智连CMP平台”--“我的应用”--“应用列表”
|
||||
<br />
|
||||
</p>
|
||||
<div class="image">
|
||||
<a-image
|
||||
width="100%"
|
||||
:src="getImage('/iot-card/unicom-openid.png')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getImage } from '@/utils/comm';
|
||||
|
||||
const props = defineProps({
|
||||
type: { type: String, default: 'onelink' },
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.doc {
|
||||
height: 800px;
|
||||
padding: 24px;
|
||||
overflow-y: auto;
|
||||
color: rgba(#000, 0.8);
|
||||
font-size: 14px;
|
||||
background-color: #fafafa;
|
||||
|
||||
.url {
|
||||
padding: 8px 16px;
|
||||
color: #2f54eb;
|
||||
background-color: rgba(#a7bdf7, 0.2);
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 16px 0;
|
||||
color: rgba(#000, 0.85);
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
|
||||
// &:first-child {
|
||||
// margin-top: 0;
|
||||
// }
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 6px 0;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.image {
|
||||
margin: 16px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,305 @@
|
|||
<!-- 平台对接 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<Search
|
||||
:columns="columns"
|
||||
target="platform-search"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<JTable
|
||||
ref="platformRef"
|
||||
:columns="columns"
|
||||
:request="queryList"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
||||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleAdd">
|
||||
<AIcon type="PlusOutlined" />新增
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
:value="slotProps"
|
||||
:actions="getActions(slotProps, 'card')"
|
||||
v-bind="slotProps"
|
||||
:status="slotProps.state.value"
|
||||
:statusText="slotProps.state.text"
|
||||
:statusNames="{
|
||||
enabled: 'success',
|
||||
disabled: 'error',
|
||||
}"
|
||||
>
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
<img :src="getImage('/iot-card/iot-card-bg.png')" />
|
||||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<h3 class="card-item-content-title">
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
<a-row>
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
平台类型
|
||||
</div>
|
||||
<div>{{ slotProps.operatorName }}</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">说明</div>
|
||||
<div>{{ slotProps.explain }}</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<a-tooltip
|
||||
v-bind="item.tooltip"
|
||||
:title="item.disabled && item.tooltip.title"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="item.popConfirm"
|
||||
v-bind="item.popConfirm"
|
||||
:disabled="item.disabled"
|
||||
>
|
||||
<a-button :disabled="item.disabled">
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item.text }}</span>
|
||||
</template>
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<template v-else>
|
||||
<a-button
|
||||
:disabled="item.disabled"
|
||||
@click="item.onClick"
|
||||
>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item.text }}</span>
|
||||
</template>
|
||||
</a-button>
|
||||
</template>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</CardBox>
|
||||
</template>
|
||||
<template #state="slotProps">
|
||||
<a-badge
|
||||
:text="slotProps.state.text"
|
||||
:status="
|
||||
slotProps.state.value === 'disabled'
|
||||
? 'error'
|
||||
: 'success'
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm v-if="i.popConfirm" v-bind="i.popConfirm">
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getImage } from '@/utils/comm';
|
||||
import type { ActionsType } from '@/components/Table';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { queryList, update, del } from '@/api/iot-card/platform';
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const platformRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
ellipsis: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '平台类型',
|
||||
dataIndex: 'operatorName',
|
||||
key: 'operatorName',
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '移动OneLink', value: 'onelink' },
|
||||
{ label: '电信Ctwing', value: 'ctwing' },
|
||||
{ label: '联通Unicom', value: 'unicom' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'state',
|
||||
key: 'state',
|
||||
scopedSlots: true,
|
||||
width: 120,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '启用', value: 'enabled' },
|
||||
{ label: '禁用', value: 'disabled' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
dataIndex: 'explain',
|
||||
key: 'explain',
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
width: 250,
|
||||
scopedSlots: true,
|
||||
},
|
||||
];
|
||||
|
||||
const statusUpdate = async (data: any) => {
|
||||
const res = await update(data);
|
||||
if (res.status === 200) {
|
||||
message.success('操作成功');
|
||||
platformRef.value?.reload();
|
||||
}
|
||||
};
|
||||
|
||||
const getActions = (
|
||||
data: Partial<Record<string, any>>,
|
||||
type: 'card' | 'table',
|
||||
): ActionsType[] => {
|
||||
if (!data) return [];
|
||||
return [
|
||||
{
|
||||
key: 'edit',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
},
|
||||
icon: 'EditOutlined',
|
||||
onClick: () => {
|
||||
router.push(`/iot-card/Platform/detail/${data.id}`);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'action',
|
||||
text: data.state.value === 'enabled' ? '禁用' : '启用',
|
||||
tooltip: {
|
||||
title: data.state.value === 'enabled' ? '禁用' : '启用',
|
||||
},
|
||||
icon:
|
||||
data.state.value === 'enabled'
|
||||
? 'StopOutlined'
|
||||
: 'PlayCircleOutlined',
|
||||
popConfirm: {
|
||||
title: `确认${
|
||||
data.state.value === 'enabled' ? '禁用' : '启用'
|
||||
}?`,
|
||||
okText: ' 确定',
|
||||
cancelText: '取消',
|
||||
onConfirm: () => {
|
||||
if (data.state.value === 'enabled') {
|
||||
statusUpdate({
|
||||
id: data.id,
|
||||
config: { ...data.config },
|
||||
state: 'disabled',
|
||||
operatorName: data.operatorName,
|
||||
});
|
||||
} else {
|
||||
statusUpdate({
|
||||
id: data.id,
|
||||
config: { ...data.config },
|
||||
state: 'enabled',
|
||||
operatorName: data.operatorName,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
text: '删除',
|
||||
tooltip: {
|
||||
title:
|
||||
data.state.value !== 'enabled' ? '删除' : '请先禁用再删除',
|
||||
},
|
||||
disabled: data.state.value === 'enabled',
|
||||
popConfirm: {
|
||||
title: '确认删除?',
|
||||
okText: ' 确定',
|
||||
cancelText: '取消',
|
||||
onConfirm: async () => {
|
||||
const resp: any = await del(data.id);
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
platformRef.value?.reload();
|
||||
} else {
|
||||
message.error('操作失败!');
|
||||
}
|
||||
},
|
||||
},
|
||||
icon: 'DeleteOutlined',
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
const handleSearch = (params: any) => {
|
||||
console.log(params);
|
||||
params.value = params;
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
const handleAdd = () => {
|
||||
router.push(`/iot-card/Platform/detail/:id`)
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
|
@ -0,0 +1,205 @@
|
|||
<!-- 平台类型 -->
|
||||
<template>
|
||||
<div :class="['radio-card-items', className, disabled ? 'disabled' : '']">
|
||||
<div
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:style="itemStyle"
|
||||
:class="[
|
||||
'radio-card-item',
|
||||
keys.includes(item.value) ? 'checked' : '',
|
||||
]"
|
||||
@click="toggleOption(item.value)"
|
||||
>
|
||||
<div class="card-list">
|
||||
<div>
|
||||
<img
|
||||
:style="`width: ${item.imgSize?.[0]}; height: ${item.imgSize?.[1]}`"
|
||||
v-if="item.imgUrl"
|
||||
:src="item.imgUrl"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div>{{ item.label }}</div>
|
||||
</div>
|
||||
<div class="checked-icon">
|
||||
<div><AIcon type="CheckOutlined" /></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const emit = defineEmits(['update:value', 'change'], );
|
||||
|
||||
const props = defineProps({
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
required: true,
|
||||
},
|
||||
model: {
|
||||
validator: function (value) {
|
||||
return ['multiple', 'singular'].includes(value);
|
||||
},
|
||||
default: () => 'singular',
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: () => '',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: () => true,
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
},
|
||||
itemStyle: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const keys = ref(
|
||||
!(props.model && props.model === 'singular') ? props.value : [props.value],
|
||||
);
|
||||
|
||||
const toggleOption = (key) => {
|
||||
if (props.disabled) {
|
||||
return;
|
||||
} else {
|
||||
const optionIndex = keys.value.includes(key);
|
||||
const newKeys = [...keys.value];
|
||||
const singular = props.model && props.model === 'singular';
|
||||
if (!optionIndex) {
|
||||
if (!(props.model && props.model === 'singular')) {
|
||||
newKeys.push(key);
|
||||
} else {
|
||||
newKeys[0] = key;
|
||||
}
|
||||
} else {
|
||||
newKeys.splice(optionIndex, 1);
|
||||
}
|
||||
emit('update:value', singular ? newKeys[0] : newKeys);
|
||||
emit('change', singular ? newKeys[0] : newKeys);
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.value,
|
||||
(newVal) => {
|
||||
keys.value = !(props.model && props.model === 'singular')
|
||||
? newVal
|
||||
: [newVal];
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@border: 1px solid @border-color-base;
|
||||
|
||||
.radio-card-items {
|
||||
display: flex;
|
||||
|
||||
.radio-card-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 180px;
|
||||
padding: 22px 28px;
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
border: @border;
|
||||
border-radius: @border-radius-base;
|
||||
|
||||
.card-list {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
div {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
> img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
> span {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: @primary-color-hover;
|
||||
border-color: @primary-color-hover;
|
||||
}
|
||||
|
||||
.checked-icon {
|
||||
position: absolute;
|
||||
right: -22px;
|
||||
bottom: -22px;
|
||||
z-index: 2;
|
||||
display: none;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
color: #fff;
|
||||
background-color: @primary-color-active;
|
||||
transform: rotate(-45deg);
|
||||
|
||||
> div {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
transform: rotate(45deg);
|
||||
|
||||
> span {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: 6px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.checked {
|
||||
position: relative;
|
||||
color: @primary-color-active;
|
||||
border-color: @primary-color-active;
|
||||
|
||||
> .checked-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
.radio-card-item {
|
||||
color: @disabled-color;
|
||||
border-color: @disabled-bg;
|
||||
cursor: not-allowed;
|
||||
|
||||
.checked-icon {
|
||||
background-color: @disabled-active-bg;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: @disabled-color;
|
||||
border-color: @disabled-active-bg;
|
||||
}
|
||||
|
||||
&.checked {
|
||||
color: @disabled-color;
|
||||
border-color: @disabled-active-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue