fix: 替换vue3-markdown-it为markdown-it

* fix: 替换vue3-markdown-it为markdown-it
This commit is contained in:
XieYongHong 2024-04-24 14:39:44 +08:00 committed by GitHub
parent f75d40f223
commit 926cc90cd3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 3353 additions and 4327 deletions

View File

@ -1,3 +1,3 @@
#!/usr/bin/env bash #!/usr/bin/env bash
docker build -t registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.2.0-SNAPSHOT . docker build -t registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.1.0-TEST .
docker push registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.2.0-SNAPSHOT docker push registry.cn-shenzhen.aliyuncs.com/jetlinks/jetlinks-ui-vue:2.1.0-TEST

View File

@ -1,7 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
API_BASE_PATH=$API_BASE_PATH; API_BASE_PATH=$API_BASE_PATH;
SERVER_NAME=$SERVER_NAME SERVER_NAME=$SERVER_NAME;
NAMESERVERS=$(cat /etc/resolv.conf | grep "nameserver" | awk '{print $2}' | tr '\n' ' ') NAMESERVERS=$(cat /etc/resolv.conf | grep "nameserver" | awk '{print $2}' | tr '\n' ' ')
if [ -z "$API_BASE_PATH" ]; then if [ -z "$API_BASE_PATH" ]; then
API_BASE_PATH="http://jetlinks:8844/"; API_BASE_PATH="http://jetlinks:8844/";
@ -17,6 +18,8 @@ serverName="server_name $SERVER_NAME;"
sed -i '4c '"$serverName"'' /etc/nginx/conf.d/default.conf sed -i '4c '"$serverName"'' /etc/nginx/conf.d/default.conf
sed -i '11c '"$resolver"'' /etc/nginx/conf.d/default.conf sed -i '11c '"$resolver"'' /etc/nginx/conf.d/default.conf
sed -i '20c '"$apiUrl"'' /etc/nginx/conf.d/default.conf sed -i '25c '"$apiUrl"'' /etc/nginx/conf.d/default.conf
sed -i 's/\${SERVER_NAME}/'$SERVER_NAME'/g' /etc/nginx/conf.d/default.conf
nginx -g "daemon off;" nginx -g "daemon off;"

View File

@ -11,6 +11,11 @@ server {
resolver $NAMESERVERS ipv6=off; resolver $NAMESERVERS ipv6=off;
root /usr/share/nginx/html; root /usr/share/nginx/html;
include /etc/nginx/mime.types; include /etc/nginx/mime.types;
if ($http_Host !~* ^${SERVER_NAME}) {
return 403;
}
location / { location / {
index index.html; index index.html;
} }

View File

@ -27,11 +27,23 @@
"global": "^4.4.0", "global": "^4.4.0",
"jetlinks-store": "^0.0.3", "jetlinks-store": "^0.0.3",
"jetlinks-ui-components": "^1.0.38", "jetlinks-ui-components": "^1.0.38",
"js-cookie": "^3.0.1",
"jsencrypt": "^3.3.2", "jsencrypt": "^3.3.2",
"less": "^4.1.3", "less": "^4.1.3",
"less-loader": "^11.1.0", "less-loader": "^11.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"markdown-it": "^14.1.0",
"markdown-it-abbr": "^2.0.0",
"markdown-it-anchor": "^8.6.7",
"markdown-it-deflist": "^3.0.0",
"markdown-it-emoji": "^3.0.0",
"markdown-it-footnote": "^4.0.0",
"markdown-it-highlightjs": "^4.0.1",
"markdown-it-ins": "^4.0.0",
"markdown-it-mark": "^4.0.0",
"markdown-it-sub": "^2.0.0",
"markdown-it-sup": "^2.0.0",
"markdown-it-task-lists": "^2.1.1",
"markdown-it-toc-done-right": "^4.2.0",
"marked": "^4.2.12", "marked": "^4.2.12",
"moment": "^2.29.4", "moment": "^2.29.4",
"monaco-editor": "^0.36.0", "monaco-editor": "^0.36.0",
@ -43,12 +55,11 @@
"unplugin-vue-components": "^0.22.12", "unplugin-vue-components": "^0.22.12",
"v-clipboard3": "^0.1.4", "v-clipboard3": "^0.1.4",
"vite-plugin-monaco-editor": "^1.1.0", "vite-plugin-monaco-editor": "^1.1.0",
"vue": "^3.2.45", "vue": "3.3.4",
"vue-cropper": "^1.0.9", "vue-cropper": "^1.0.9",
"vue-json-viewer": "^3.0.4", "vue-json-viewer": "^3.0.4",
"vue-router": "^4.1.6", "vue-router": "^4.1.6",
"vue3-json-viewer": "^2.2.2", "vue3-json-viewer": "^2.2.2",
"vue3-markdown-it": "^1.0.10",
"vue3-ts-jsoneditor": "^2.7.1" "vue3-ts-jsoneditor": "^2.7.1"
}, },
"devDependencies": { "devDependencies": {

File diff suppressed because one or more lines are too long

View File

@ -47,7 +47,7 @@ import type { OperatorItem } from './typings';
import { treeFilter } from '@/utils/tree' import { treeFilter } from '@/utils/tree'
import { PropertyMetadata } from '@/views/device/Product/typings'; import { PropertyMetadata } from '@/views/device/Product/typings';
import { getOperator } from '@/api/device/product' import { getOperator } from '@/api/device/product'
import Markdown from 'vue3-markdown-it' import Markdown from '@/components/Markdown'
const props = defineProps({ const props = defineProps({
id: String id: String

View File

@ -2,16 +2,69 @@
<div class="debug-container"> <div class="debug-container">
<div class="top"> <div class="top">
<div class="header"> <div class="header">
<div> <j-tabs v-model:activeKey="headerType">
<div class="title"> <j-tab-pane key="property">
<template #tab>
<span class="title">
属性赋值 属性赋值
</span>
</template>
</j-tab-pane>
<j-tab-pane key="tag">
<template #tab>
<span class="title">
标签赋值
</span>
</template>
</j-tab-pane>
</j-tabs>
<!-- <div>
<j-dropdown>
<div class="title" @click.prevent>
{{
headerType === 'property'
? '属性赋值'
: '标签赋值'
}}
<div class="description"> <div class="description">
请对上方规则使用的属性进行赋值 {{
`请对上方规则使用的${
headerType === 'property'
? '属性'
: '标签'
}进行赋值`
}}
</div> </div>
</div> </div>
<template #overlay>
<j-menu>
<j-menu-item>
<a
href="javascript:;"
@click="headerType = 'property'"
>属性赋值</a
>
</j-menu-item>
<j-menu-item>
<a
href="javascript:;"
@click="headerType = 'tag'"
>标签赋值</a
>
</j-menu-item>
</j-menu>
</template>
</j-dropdown>
</div> -->
</div> </div>
<div class="description">
{{
`请对上方规则使用的${
headerType === 'property' ? '属性' : '标签'
}进行赋值`
}}
</div> </div>
<div class="top-bottom"> <div class="top-bottom" v-if="headerType === 'property'">
<j-table <j-table
:columns="columns" :columns="columns"
:data-source="property" :data-source="property"
@ -62,6 +115,51 @@
添加条目 添加条目
</j-button> </j-button>
</div> </div>
<div class="top-bottom" v-if="headerType === 'tag'">
<j-table
:columns="tagColumns"
:data-source="tag"
:pagination="false"
bordered
size="small"
:scroll="{ y: 200 }"
>
<template #bodyCell="{ column, record, index }">
<template v-if="column.key === 'id'">
<j-select
showSearch
:options="tagOptions"
v-model:value="record.id"
size="small"
style="width: 100%; z-index: 1400 !important"
/>
</template>
<template v-if="column.key === 'current'">
<j-input
v-model:value="record.current"
size="small"
></j-input>
</template>
<template v-if="column.key === 'action'">
<AIcon
type="DeleteOutlined"
@click="deleteTagItem(index)"
/>
</template>
</template>
</j-table>
<j-button
type="dashed"
block
style="margin-top: 5px"
@click="addTagItem"
>
<template #icon>
<AIcon type="PlusOutlined" />
</template>
添加条目
</j-button>
</div>
</div> </div>
<div class="bottom"> <div class="bottom">
<div class="header"> <div class="header">
@ -98,7 +196,9 @@
:span="3" :span="3"
> >
<template #label> <template #label>
<template v-if="!!runningState(index + 1, item._time)"> <template
v-if="!!runningState(index + 1, item._time)"
>
{{ runningState(index + 1, item._time) }} {{ runningState(index + 1, item._time) }}
</template> </template>
<template v-else>{{ <template v-else>{{
@ -140,7 +240,19 @@ type propertyType = {
last?: string; last?: string;
}; };
const property = ref<propertyType[]>([]); const property = ref<propertyType[]>([]);
const tag = ref<Array<any>>([]);
const headerOptions = [
{
key: 'property',
label: '属性赋值',
title: '属性赋值',
},
{
key: 'tag',
label: '标签赋值',
title: '标签赋值',
},
];
const columns = [ const columns = [
{ {
title: '属性名称', title: '属性名称',
@ -164,17 +276,42 @@ const columns = [
}, },
]; ];
const tagColumns = [
{
title: '属性名称',
dataIndex: 'id',
key: 'id',
},
{
title: '当前值',
dataIndex: 'current',
key: 'current',
},
{
title: '操作',
key: 'action',
width: 50,
},
];
const headerType = ref('property');
const addItem = () => { const addItem = () => {
property.value.push({}); property.value.push({});
}; };
const addTagItem = () => {
tag.value.push({});
};
const deleteItem = (index: number) => { const deleteItem = (index: number) => {
property.value.splice(index, 1); property.value.splice(index, 1);
}; };
const deleteTagItem = (index: number) => {
tag.value.splice(index, 1);
};
const ws = ref(); const ws = ref();
const virtualIdRef = ref(new Date().getTime()); const virtualIdRef = ref(new Date().getTime());
const medataSource = inject<Ref<any[]>>('_dataSource'); const medataSource = inject<Ref<any[]>>('_dataSource');
const tagsSource = inject<Ref<any[]>>('_tagsDataSource');
const productStore = useProductStore(); const productStore = useProductStore();
const ruleEditorStore = useRuleEditorStore(); const ruleEditorStore = useRuleEditorStore();
@ -188,7 +325,10 @@ const runScript = () => {
const _item = propertiesList.find((i: any) => i.id === item.id); const _item = propertiesList.find((i: any) => i.id === item.id);
return { ...item, type: _item?.valueType?.type }; return { ...item, type: _item?.valueType?.type };
}); });
let _tags = {};
tag.value.forEach((item) => {
_tags[item.id] = item.current;
});
if (ws.value) { if (ws.value) {
ws.value.unsubscribe?.(); ws.value.unsubscribe?.();
} }
@ -208,12 +348,13 @@ const runScript = () => {
...props.virtualRule, ...props.virtualRule,
}, },
properties: _properties || [], properties: _properties || [],
tags: _tags,
}, },
).subscribe((data: any) => { ).subscribe((data: any) => {
ruleEditorStore.state.log.push({ ruleEditorStore.state.log.push({
time: new Date().getTime(), time: new Date().getTime(),
content: JSON.stringify(data.payload), content: JSON.stringify(data.payload),
_time: unref(time.value) _time: unref(time.value),
}); });
emits('success', false); emits('success', false);
if (props.virtualRule?.type !== 'window') { if (props.virtualRule?.type !== 'window') {
@ -275,8 +416,8 @@ const stopAction = () => {
if (ws.value) { if (ws.value) {
ws.value.unsubscribe?.(); ws.value.unsubscribe?.();
} }
window.clearInterval(timer.value) window.clearInterval(timer.value);
timer.value = null timer.value = null;
}; };
const clearAction = () => { const clearAction = () => {
ruleEditorStore.set('log', []); ruleEditorStore.set('log', []);
@ -287,8 +428,8 @@ onUnmounted(() => {
ws.value.unsubscribe?.(); ws.value.unsubscribe?.();
} }
clearAction(); clearAction();
window.clearInterval(timer.value) window.clearInterval(timer.value);
timer.value = null timer.value = null;
}); });
const options = computed(() => { const options = computed(() => {
@ -300,6 +441,13 @@ const options = computed(() => {
})); }));
}); });
const tagOptions = computed(() => {
return (tagsSource.value || []).map((item) => ({
label: item.name,
value: item.id,
}));
});
// const getProperty = () => { // const getProperty = () => {
// // const metadata = productStore.current.metadata || '{}'; // // const metadata = productStore.current.metadata || '{}';
// // const _p: PropertyMetadata[] = JSON.parse(metadata).properties || []; // // const _p: PropertyMetadata[] = JSON.parse(metadata).properties || [];

View File

@ -8,8 +8,6 @@
/> />
<div class="tree"> <div class="tree">
<j-scrollbar> <j-scrollbar>
<j-tree <j-tree
@select="selectTree" @select="selectTree"
:field-names="{ title: 'name', key: 'id' }" :field-names="{ title: 'name', key: 'id' }"
@ -25,13 +23,15 @@
</div> </div>
<div <div
:class=" :class="
node.children?.length > 0 ? 'parent' : 'add' node.children?.length > 0
? 'parent'
: 'add'
" "
> >
<j-popover <j-popover
v-if="node.type === 'property'" v-if="node.type === 'property'"
:overlayStyle="{ :overlayStyle="{
zIndex: 1200 zIndex: 1200,
}" }"
placement="right" placement="right"
title="请选择使用值" title="请选择使用值"
@ -44,7 +44,9 @@
> >
<j-button <j-button
type="text" type="text"
@click="recentClick(node)" @click="
recentClick(node)
"
> >
$recent实时值 $recent实时值
</j-button> </j-button>
@ -64,8 +66,40 @@
</template> </template>
<a class="has-property">添加</a> <a class="has-property">添加</a>
</j-popover> </j-popover>
<j-popover
<a class="no-property" v-else @click.stop="addClick(node)"> 添加 </a> v-else-if="node.type === 'tags'"
:overlayStyle="{
zIndex: 1200,
}"
placement="right"
title="请选择使用值"
>
<template #content>
<j-space direction="vertical">
<j-tooltip
placement="right"
title="实时值为空时获取上一有效值补齐,实时值不为空则使用实时值"
>
<j-button
type="text"
@click="
recentTagsClick(node)
"
>
tag实时值
</j-button>
</j-tooltip>
</j-space>
</template>
<a class="has-property">添加</a>
</j-popover>
<a
class="no-property"
v-else
@click.stop="addClick(node)"
>
添加
</a>
</div> </div>
</div> </div>
</template> </template>
@ -84,11 +118,13 @@ import type { OperatorItem } from './typings';
import { treeFilter } from '@/utils/tree'; import { treeFilter } from '@/utils/tree';
import { PropertyMetadata } from '@/views/device/Product/typings'; import { PropertyMetadata } from '@/views/device/Product/typings';
import { getOperator } from '@/api/device/product'; import { getOperator } from '@/api/device/product';
import Markdown from 'vue3-markdown-it'; import { inject } from 'vue';
import { Descriptions } from 'ant-design-vue';
import Markdown from '@/components/Markdown'
const props = defineProps({ const props = defineProps({
id: String, id: String,
propertiesOptions: Array propertiesOptions: Array,
}); });
interface Emits { interface Emits {
@ -99,7 +135,7 @@ const emit = defineEmits<Emits>();
const item = ref<Partial<OperatorItem>>(); const item = ref<Partial<OperatorItem>>();
const data = ref<OperatorItem[]>([]); const data = ref<OperatorItem[]>([]);
const dataRef = ref<OperatorItem[]>([]); const dataRef = ref<OperatorItem[]>([]);
const tagsMetadata: any = inject('_tagsDataSource');
const search = (value: string) => { const search = (value: string) => {
if (value) { if (value) {
const nodes = treeFilter( const nodes = treeFilter(
@ -117,6 +153,9 @@ const selectTree = (k: any, info: any) => {
item.value = info.node as unknown as OperatorItem; item.value = info.node as unknown as OperatorItem;
}; };
const recentTagsClick = (node:OperatorItem) =>{
emit('addOperatorValue',`tag("${node.id}")`)
}
const recentClick = (node: OperatorItem) => { const recentClick = (node: OperatorItem) => {
emit('addOperatorValue', `$recent("${node.id}")`); emit('addOperatorValue', `$recent("${node.id}")`);
}; };
@ -131,7 +170,7 @@ const productStore = useProductStore();
const getData = async (id?: string) => { const getData = async (id?: string) => {
// const metadata = productStore.current.metadata || '{}'; // const metadata = productStore.current.metadata || '{}';
const _properties = props.propertiesOptions as PropertyMetadata[] const _properties = props.propertiesOptions as PropertyMetadata[];
const properties = { const properties = {
id: 'property', id: 'property',
name: '属性', name: '属性',
@ -149,10 +188,33 @@ const getData = async (id?: string) => {
type: 'property', type: 'property',
})), })),
}; };
const tags = {
id: 'tags',
name: '标签',
Description: '',
code: '',
children: tagsMetadata.value.map((i: any) => ({
id: i.id,
name: i.name,
description: `### ${i.name}
\n 数据类型: ${i.valueType?.type}
\n 是否只读: ${i.expands?.readOnly || 'false'}
\n 可写数值范围: `,
type: 'tags',
})),
};
const response = await getOperator(); const response = await getOperator();
if (response.status === 200) { if (response.status === 200) {
data.value = [properties as OperatorItem, ...response.result]; data.value = [
dataRef.value = [properties as OperatorItem, ...response.result]; properties as OperatorItem,
tags as any,
...response.result,
];
dataRef.value = [
properties as OperatorItem,
tags as any,
...response.result,
];
} }
}; };
@ -186,7 +248,6 @@ watch(
padding: 10px; padding: 10px;
margin-right: 10px; margin-right: 10px;
.tree { .tree {
height: 300px; height: 300px;
//overflow-y: auto; //overflow-y: auto;

View File

@ -0,0 +1,117 @@
import { h, onMounted, onUpdated, ref } from 'vue';
import MarkdownIt from 'markdown-it';
import MarkdownItAbbr from 'markdown-it-abbr';
import MarkdownItAnchor from 'markdown-it-anchor';
import MarkdownItDeflist from 'markdown-it-deflist';
import { full as emoji } from 'markdown-it-emoji'
import MarkdownItFootnote from 'markdown-it-footnote';
import MarkdownItHighlightjs from 'markdown-it-highlightjs';
import MarkdownItIns from 'markdown-it-ins';
import MarkdownItMark from 'markdown-it-mark';
import MarkdownItSub from 'markdown-it-sub';
import MarkdownItSup from 'markdown-it-sup';
import MarkdownItTasklists from 'markdown-it-task-lists';
import MarkdownItTOC from 'markdown-it-toc-done-right';
const props = {
anchor: {
type: Object,
default: () => ({})
},
breaks: {
type: Boolean,
default: false
},
emoji: {
type: Object,
default: () => ({})
},
highlight: {
type: Object,
default: () => ({})
},
html: {
type: Boolean,
default: false
},
langPrefix: {
type: String,
default: 'language-'
},
linkify: {
type: Boolean,
default: false
},
plugins: {
type: Array,
default: () => []
},
quotes: {
type: String,
default: '“”‘’'
},
source: {
type: String,
default: ''
},
tasklists: {
type: Object,
default: () => ({})
},
toc: {
type: Object,
default: () => ({})
},
typographer: {
type: Boolean,
default: false
},
xhtmlOut: {
type: Boolean,
default: false
}
};
export default {
name: 'Markdown',
props,
setup(props) {
const md = ref();
const renderMarkdown = () => {
let markdown = new MarkdownIt()
.use(MarkdownItAbbr)
.use(MarkdownItAnchor, props.anchor)
.use(MarkdownItDeflist)
.use(emoji, props.emoji)
.use(MarkdownItFootnote)
.use(MarkdownItHighlightjs, props.highlight)
.use(MarkdownItIns)
.use(MarkdownItMark)
.use(MarkdownItSub)
.use(MarkdownItSup)
.use(MarkdownItTasklists, props.tasklists)
.use(MarkdownItTOC, props.toc)
.set({
breaks: props.breaks,
html: props.html,
langPrefix: props.langPrefix,
linkify: props.linkify,
quotes: props.quotes,
typographer: props.typographer,
xhtmlOut: props.xhtmlOut
});
props.plugins.forEach(({ plugin, options = {} }) => {
markdown.use(plugin, options);
});
md.value = markdown.render(props.source);
};
onMounted(() => renderMarkdown());
onUpdated(() => renderMarkdown());
return () => h('div', { innerHTML: md.value, style: { height: '100%'} });
}
};

View File

@ -11,6 +11,7 @@ import JProUpload from './Upload/index.vue'
import { BasicLayoutPage, BlankLayoutPage, FullPage } from './Layout' import { BasicLayoutPage, BlankLayoutPage, FullPage } from './Layout'
import RadioCard from './RadioCard/index.vue' import RadioCard from './RadioCard/index.vue'
import { PageContainer, AIcon, Ellipsis } from 'jetlinks-ui-components' import { PageContainer, AIcon, Ellipsis } from 'jetlinks-ui-components'
import MarkDown from './Markdown'
// import Ellipsis from './Ellipsis/index.vue' // import Ellipsis from './Ellipsis/index.vue'
import JEmpty from './Empty/index.vue' import JEmpty from './Empty/index.vue'
import AMapComponent from './AMapComponent/index.vue' import AMapComponent from './AMapComponent/index.vue'
@ -41,5 +42,6 @@ export default {
.component('RowPagination', RowPagination) .component('RowPagination', RowPagination)
.component('FullPage', FullPage) .component('FullPage', FullPage)
.component('RadioCard', RadioCard) .component('RadioCard', RadioCard)
.component('MarkDown', MarkDown)
} }
} }

1
src/global.d.ts vendored
View File

@ -10,7 +10,6 @@ declare module '*.gif';
declare module '*.bmp'; declare module '*.bmp';
declare module '*.js'; declare module '*.js';
declare module '*.ts'; declare module '*.ts';
declare module 'js-cookie';
declare module 'jetlinks-ui-components'; declare module 'jetlinks-ui-components';
declare module 'vue3-json-viewer'; declare module 'vue3-json-viewer';
declare module 'event-source-polyfill'; declare module 'event-source-polyfill';

View File

@ -1,4 +1,4 @@
import JSEncrypt from "jsencrypt"; import JSEncrypt from "jsencrypt/bin/jsencrypt.min.js";
export const encrypt =(txt:string,publicKey:string)=>{ export const encrypt =(txt:string,publicKey:string)=>{
const encryptor = new JSEncrypt() const encryptor = new JSEncrypt()

View File

@ -32,7 +32,7 @@
v-if=" v-if="
showLoad || showLoad ||
(!getType(record?.value) && (!getType(record?.value) &&
data?.valueType?.fileType === 'base64') data?.valueType?.bodyType === 'base64')
" "
type="link" type="link"
@click="_download(record)" @click="_download(record)"
@ -128,7 +128,7 @@ const columns = computed(() => {
const showLoad = computed(() => { const showLoad = computed(() => {
return ( return (
_props.data.valueType?.type === 'file' && _props.data.valueType?.type === 'file' &&
_props.data?.valueType?.fileType === 'Binary(二进制)' _props.data?.valueType?.bodyType === 'Binary(二进制)'
); );
}); });

View File

@ -7,7 +7,7 @@
-- --
</div> </div>
<div v-else-if="_data.data?.valueType?.type === 'file'"> <div v-else-if="_data.data?.valueType?.type === 'file'">
<template v-if="data?.valueType?.fileType === 'base64'"> <template v-if="data?.valueType?.bodyType === 'base64'">
<div :class="valueClass" v-if="!!getType(value?.formatValue)"> <div :class="valueClass" v-if="!!getType(value?.formatValue)">
<img :src="imgMap.get(_type)" @error="onError" /> <img :src="imgMap.get(_type)" @error="onError" />
</div> </div>
@ -16,7 +16,7 @@
</div> </div>
</template> </template>
<div <div
v-else-if="data?.valueType?.fileType === 'Binary(二进制)'" v-else-if="data?.valueType?.bodyType === 'Binary(二进制)'"
:class="valueClass" :class="valueClass"
> >
<img :src="imgMap.get('other')" /> <img :src="imgMap.get('other')" />

View File

@ -89,26 +89,22 @@ const productName = computed(() => {
}) })
const handleOk = async () => { const handleOk = async () => {
const params = paramsEncodeQuery(props.data); const params = paramsEncodeQuery(props.data);
// downloadFile( // downloadFile(
// deviceExport(modelRef.product || '', modelRef.fileType), // deviceExport(modelRef.product || '', modelRef.fileType),
// params, // params,
// ); // );
// const res: any = await deviceExport( const res: any = await deviceExport(
// modelRef.product || '', modelRef.product || '',
// modelRef.fileType, modelRef.fileType,
// params params
// ); );
console.log(props.data,params) if (res) {
window.open(`${deviceExportPath( modelRef.product || '',modelRef.fileType)}?X-Access-Token=${getToken() const blob = new Blob([res], { type: modelRef.fileType });
}`) const url = URL.createObjectURL(blob);
// if (res) { downloadFileByUrl(url, `${productName.value ? (productName.value + '下设备') : '设备实例'}`, modelRef.fileType);
// const blob = new Blob([res], { type: modelRef.fileType }); emit('close');
// const url = URL.createObjectURL(blob); }
// downloadFileByUrl(url, `${productName.value ? (productName.value + '') : ''}`, modelRef.fileType);
// emit('close');
// }
}; };
const handleCancel = () => { const handleCancel = () => {

View File

@ -334,7 +334,7 @@ import BatchDropdown from '@/components/BatchDropdown/index.vue';
import { BatchActionsType } from '@/components/BatchDropdown/types'; import { BatchActionsType } from '@/components/BatchDropdown/types';
import { useRouterParams } from '@/utils/hooks/useParams'; import { useRouterParams } from '@/utils/hooks/useParams';
import { accessConfigTypeFilter } from '@/utils/setting'; import { accessConfigTypeFilter } from '@/utils/setting';
import TagSearch from './components/TagSearch.vue' import TagSearch from './components/TagSearch.vue';
const instanceRef = ref<Record<string, any>>({}); const instanceRef = ref<Record<string, any>>({});
const params = ref<Record<string, any>>({}); const params = ref<Record<string, any>>({});
@ -478,7 +478,15 @@ const columns = [
type: 'select', type: 'select',
options: () => options: () =>
new Promise((resolve) => { new Promise((resolve) => {
queryGatewayList({}).then((resp: any) => { queryGatewayList({
paging: false,
sorts: [
{
name: 'createTime',
order: 'desc',
},
],
}).then((resp: any) => {
resolve( resolve(
resp.result.map((item: any) => ({ resp.result.map((item: any) => ({
label: item.name, label: item.name,
@ -509,6 +517,7 @@ const columns = [
hideInTable: true, hideInTable: true,
search: { search: {
type: 'treeSelect', type: 'treeSelect',
termOptions: ['eq'],
// handleValue(v) { // handleValue(v) {
// return { // return {
// assetType: 'device', // assetType: 'device',
@ -554,7 +563,11 @@ const columns = [
dataIndex: 'id$dev-tag', dataIndex: 'id$dev-tag',
title: '设备标签', title: '设备标签',
hideInTable: true, hideInTable: true,
search : { type: 'component' , components: TagSearch , termOptions:['eq'] } search: {
type: 'component',
components: TagSearch,
termOptions: ['eq'],
},
}, },
{ {
title: '说明', title: '说明',
@ -720,7 +733,9 @@ const getActions = (
const resp = await _delete(data.id); const resp = await _delete(data.id);
if (resp.status === 200) { if (resp.status === 200) {
onlyMessage('操作成功!'); onlyMessage('操作成功!');
const index = _selectedRowKeys.value.findIndex((id: any) => id === data.id); const index = _selectedRowKeys.value.findIndex(
(id: any) => id === data.id,
);
if (index !== -1) { if (index !== -1) {
_selectedRowKeys.value.splice(index, 1); _selectedRowKeys.value.splice(index, 1);
} }

View File

@ -303,6 +303,7 @@ const {basicLayout} = storeToRefs(system);
const router = useRouter() const router = useRouter()
const { data: metadata, noEdit, productNoEdit } = useMetadata(_target, props.type); const { data: metadata, noEdit, productNoEdit } = useMetadata(_target, props.type);
const { data: tagsMetadata } = useMetadata(_target,'tags')
const { hasOperate } = useOperateLimits(_target); const { hasOperate } = useOperateLimits(_target);
const permissionStore = usePermissionStore() const permissionStore = usePermissionStore()
@ -339,7 +340,8 @@ const showLastDelete = computed(() => {
return dataSourceCache.value.length === 1 return dataSourceCache.value.length === 1
}) })
provide('_dataSource', dataSourceCache) provide('_dataSource', dataSourceCache);
provide('_tagsDataSource',tagsMetadata)
const showDetail = (data: any) => { const showDetail = (data: any) => {
detailData.data = data detailData.data = data
detailData.visible = true detailData.visible = true
@ -558,6 +560,7 @@ onUnmounted(() => {
watch(() => metadata.value, () => { watch(() => metadata.value, () => {
dataSource.value = metadata.value dataSource.value = metadata.value
}, { immediate: true }) }, { immediate: true })
onBeforeRouteUpdate((to, from, next) => { // onBeforeRouteUpdate((to, from, next) => { //

View File

@ -21,7 +21,7 @@
<a-descriptions-item v-if="['int', 'long', 'float', 'double'].includes(data.valueType.type)" label="单位">{{ unitLabel }}</a-descriptions-item> <a-descriptions-item v-if="['int', 'long', 'float', 'double'].includes(data.valueType.type)" label="单位">{{ unitLabel }}</a-descriptions-item>
<a-descriptions-item v-if="['float', 'double'].includes(data.valueType.type)" label="精度">{{ data.valueType?.scale }}</a-descriptions-item> <a-descriptions-item v-if="['float', 'double'].includes(data.valueType.type)" label="精度">{{ data.valueType?.scale }}</a-descriptions-item>
<a-descriptions-item v-if="['string', 'password'].includes(data.valueType.type)" label="最大长度">{{ data.valueType?.maxLength }}</a-descriptions-item> <a-descriptions-item v-if="['string', 'password'].includes(data.valueType.type)" label="最大长度">{{ data.valueType?.maxLength }}</a-descriptions-item>
<a-descriptions-item v-if="data.valueType.type === 'file'" label="文件类型">{{ data.valueType?.fileType }}</a-descriptions-item> <a-descriptions-item v-if="data.valueType.type === 'file'" label="文件类型">{{ data.valueType?.bodyType }}</a-descriptions-item>
<a-descriptions-item v-if="data.valueType.type === 'date'" label="格式">{{ data.valueType?.format }}</a-descriptions-item> <a-descriptions-item v-if="data.valueType.type === 'date'" label="格式">{{ data.valueType?.format }}</a-descriptions-item>
<a-descriptions-item <a-descriptions-item
v-if=" v-if="

View File

@ -21,7 +21,7 @@
<a-descriptions-item v-if="['int', 'long', 'float', 'double'].includes(data.valueType.type)" label="单位">{{ unitLabel }}</a-descriptions-item> <a-descriptions-item v-if="['int', 'long', 'float', 'double'].includes(data.valueType.type)" label="单位">{{ unitLabel }}</a-descriptions-item>
<a-descriptions-item v-if="['float', 'double'].includes(data.valueType.type)" label="精度">{{ data.valueType?.scale }}</a-descriptions-item> <a-descriptions-item v-if="['float', 'double'].includes(data.valueType.type)" label="精度">{{ data.valueType?.scale }}</a-descriptions-item>
<a-descriptions-item v-if="['string', 'password'].includes(data.valueType.type)" label="最大长度">{{ data.valueType?.maxLength }}</a-descriptions-item> <a-descriptions-item v-if="['string', 'password'].includes(data.valueType.type)" label="最大长度">{{ data.valueType?.maxLength }}</a-descriptions-item>
<a-descriptions-item v-if="data.valueType.type === 'file'" label="文件类型">{{ data.valueType?.fileType }}</a-descriptions-item> <a-descriptions-item v-if="data.valueType.type === 'file'" label="文件类型">{{ data.valueType?.bodyType }}</a-descriptions-item>
<a-descriptions-item v-if="data.valueType.type === 'date'" label="格式">{{ data.valueType?.format }}</a-descriptions-item> <a-descriptions-item v-if="data.valueType.type === 'date'" label="格式">{{ data.valueType?.format }}</a-descriptions-item>
<a-descriptions-item <a-descriptions-item
v-if=" v-if="

View File

@ -47,11 +47,11 @@
]"> ]">
<JsonParam v-model:value="_value.properties" :name="name.concat(['properties'])"></JsonParam> <JsonParam v-model:value="_value.properties" :name="name.concat(['properties'])"></JsonParam>
</j-form-item> </j-form-item>
<j-form-item label="文件类型" :name="name.concat(['fileType'])" v-if="['file'].includes(_value.type)" initialValue="url" <j-form-item label="文件类型" :name="name.concat(['bodyType'])" v-if="['file'].includes(_value.type)" initialValue="url"
:rules="[ :rules="[
{ required: true, message: '请选择文件类型' }, { required: true, message: '请选择文件类型' },
]"> ]">
<j-select v-model:value="_value.fileType" :options="FileTypeList" size="small" placeholder="请选择文件类型"></j-select> <j-select v-model:value="_value.bodyType" :options="FileTypeList" size="small" placeholder="请选择文件类型"></j-select>
</j-form-item> </j-form-item>
</template> </template>
<script lang="ts" setup mame="BaseForm"> <script lang="ts" setup mame="BaseForm">
@ -158,7 +158,7 @@ const changeType = (val: SelectValue) => {
_value.value.scale = 2 _value.value.scale = 2
} }
if (['file'].includes(val as string)) { if (['file'].includes(val as string)) {
_value.value.fileType = _value.value.fileType || 'url' _value.value.bodyType = _value.value.bodyType || 'url'
} }
if (['date'].includes(val as string)) { if (['date'].includes(val as string)) {
_value.value.format = _value.value.format || 'yyyy-MM-dd HH:mm:ss' _value.value.format = _value.value.format || 'yyyy-MM-dd HH:mm:ss'

View File

@ -52,7 +52,7 @@ export const validateValueType = async (_rule: Rule, val: Record<any, any>, titl
if (['object'].includes(val.type)) { if (['object'].includes(val.type)) {
await validateJson(_rule, val.properties) await validateJson(_rule, val.properties)
} }
if (['file'].includes(val.type) && !val.fileType) { if (['file'].includes(val.type) && !val.bodyType) {
return Promise.reject(new Error('请选择文件类型')) return Promise.reject(new Error('请选择文件类型'))
} }
return Promise.resolve(); return Promise.resolve();

View File

@ -53,7 +53,7 @@ export const validatorConfig = (value: any, _isObject: boolean = false) => {
return Promise.reject('请添加参数') return Promise.reject('请添加参数')
} }
if (value.type === 'file' && (!value.fileType || (isObject(value.fileType) && !Object.keys(value.fileType).length))) { if (value.type === 'file' && (!value.bodyType || (isObject(value.bodyType) && !Object.keys(value.bodyType).length))) {
return Promise.reject('请选择文件类型') return Promise.reject('请选择文件类型')
} }
@ -65,9 +65,16 @@ export const handleTypeValue = (type:string, value: any = {}) => {
switch (type) { switch (type) {
//bug#22609 //bug#22609
case 'array': case 'array':
if(value.type === 'array'){
obj.elementType = { obj.elementType = {
...value,
elementType:{
type: 'object', type: 'object',
properties: [] properties: []
}
}
}else{
obj.elementType = value
} }
break; break;
case 'object': case 'object':
@ -80,7 +87,7 @@ export const handleTypeValue = (type:string, value: any = {}) => {
obj.unit = value obj.unit = value
break; break;
case 'file': case 'file':
obj.fileType = value obj.bodyType = value
break; break;
case 'date': case 'date':
obj.format = value obj.format = value
@ -119,7 +126,7 @@ export const typeSelectChange = (type: string) => {
obj.unit = undefined obj.unit = undefined
break; break;
case 'file': case 'file':
obj.fileType = undefined obj.bodyType = undefined
break; break;
case 'date': case 'date':
obj.format = undefined obj.format = undefined

View File

@ -61,7 +61,7 @@
</DataTableInteger> </DataTableInteger>
<DataTableFile <DataTableFile
v-else-if="type === 'file'" v-else-if="type === 'file'"
v-model:value="myValue.fileType" v-model:value="myValue.bodyType"
placement="topRight" placement="topRight"
@confirm="valueChange" @confirm="valueChange"
> >

View File

@ -40,7 +40,7 @@
placement="bottomRight" placement="bottomRight"
@confirm="(data) => {valueChange(data, 'int')}" @confirm="(data) => {valueChange(data, 'int')}"
/> />
<DataTableFile v-else-if="type === 'file'" v-model:value="_valueType.fileType" placement="bottomRight" @confirm="(data) => {valueChange(data, 'file')}"/> <DataTableFile v-else-if="type === 'file'" v-model:value="_valueType.bodyType" placement="bottomRight" @confirm="(data) => {valueChange(data, 'file')}"/>
<DataTableDate v-else-if="type === 'date'" v-model:value="_valueType.format" placement="bottomRight" @confirm="(data) => {valueChange(data, 'date')}"/> <DataTableDate v-else-if="type === 'date'" v-model:value="_valueType.format" placement="bottomRight" @confirm="(data) => {valueChange(data, 'date')}"/>
<DataTableString <DataTableString
v-else-if="['string', 'password'].includes(type)" v-else-if="['string', 'password'].includes(type)"

View File

@ -17,7 +17,7 @@
placement="topRight" placement="topRight"
v-model:value="formData.unit" v-model:value="formData.unit"
/> />
<DataTableFile v-else-if="formData.type === 'file'" v-model:value="formData.fileType" placement="topRight"/> <DataTableFile v-else-if="formData.type === 'file'" v-model:value="formData.bodyType" placement="topRight"/>
<DataTableDate v-else-if="formData.type === 'date'" v-model:value="formData.date" placement="topRight"/> <DataTableDate v-else-if="formData.type === 'date'" v-model:value="formData.date" placement="topRight"/>
<DataTableString <DataTableString
v-else-if="['string', 'password'].includes(formData.type)" v-else-if="['string', 'password'].includes(formData.type)"

View File

@ -40,7 +40,7 @@
v-model:value="data.unit" v-model:value="data.unit"
@confirm="valueChange" @confirm="valueChange"
/> />
<DataTableFile v-else-if="type === 'file'" placement="bottomRight" v-model:value="data.fileType" @confirm="valueChange"/> <DataTableFile v-else-if="type === 'file'" placement="bottomRight" v-model:value="data.bodyType" @confirm="valueChange"/>
<DataTableDate v-else-if="type === 'date'" placement="bottomRight" v-model:value="data.date" @confirm="valueChange"/> <DataTableDate v-else-if="type === 'date'" placement="bottomRight" v-model:value="data.date" @confirm="valueChange"/>
<DataTableString <DataTableString
v-else-if="['string', 'password'].includes(type)" v-else-if="['string', 'password'].includes(type)"

View File

@ -20,7 +20,9 @@ const useMetadata = (type: 'device' | 'product', key?: MetadataType, ): {
const { current: productCurrent } = storeToRefs(productStore) const { current: productCurrent } = storeToRefs(productStore)
const handleMetadata = (_metadataStr: string) => { const handleMetadata = (_metadataStr: string) => {
const _metadata = JSON.parse(_metadataStr || '{}') const fileTypeReg = new RegExp('"fileType":',"g")
const _dealMetadata = _metadataStr.replaceAll(fileTypeReg,'"bodyType":')
const _metadata = JSON.parse(_dealMetadata || '{}')
const newMetadata = (key ? _metadata?.[key] || [] : []) as any[] const newMetadata = (key ? _metadata?.[key] || [] : []) as any[]

View File

@ -33,7 +33,7 @@ export const testType = (data:any,index:number,isArray?:boolean,isObject?:boolea
} }
} }
if(data.type === 'file' && !isArray && !isObject){ if(data.type === 'file' && !isArray && !isObject){
if(!data?.fileType){ if(!data?.bodyType){
onlyMessage(`方法定义inputs第${index+1}个数组ValueType中缺失fileType属性`,'error') onlyMessage(`方法定义inputs第${index+1}个数组ValueType中缺失fileType属性`,'error')
return true return true
} }
@ -102,7 +102,7 @@ export const testAliType = (data:any,index:number,isArray?:boolean,isObject?:boo
} }
} }
if(data.dataType.type === 'file' && !isArray && !isObject){ if(data.dataType.type === 'file' && !isArray && !isObject){
if(!data.dataType?.fileType){ if(!data.dataType?.bodyType){
onlyMessage(`方法定义inputs第${index+1}个数组dataType中缺失fileType属性`,'error') onlyMessage(`方法定义inputs第${index+1}个数组dataType中缺失fileType属性`,'error')
return true return true
} }

View File

@ -12,7 +12,9 @@
ref="cardManageRef" ref="cardManageRef"
:columns="columns" :columns="columns"
:request="query" :request="query"
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:rowSelection=" :rowSelection="
isCheck isCheck
? { ? {
@ -152,7 +154,9 @@
> >
<template #img> <template #img>
<slot name="img"> <slot name="img">
<img :src="getImage('/iot-card/iot-card-bg.png')" /> <img
:src="getImage('/iot-card/iot-card-bg.png')"
/>
</slot> </slot>
</template> </template>
<template #content> <template #content>
@ -167,18 +171,24 @@
平台对接 平台对接
</div> </div>
<Ellipsis style="width: calc(100% - 20px)"> <Ellipsis style="width: calc(100% - 20px)">
<div>{{ slotProps.platformConfigName }}</div> <div>
{{ slotProps.platformConfigName }}
</div>
</Ellipsis> </Ellipsis>
</j-col> </j-col>
<j-col :span="6"> <j-col :span="6">
<div class="card-item-content-text">类型</div> <div class="card-item-content-text">
类型
</div>
<div>{{ slotProps.cardType.text }}</div> <div>{{ slotProps.cardType.text }}</div>
</j-col> </j-col>
<j-col :span="6"> <j-col :span="6">
<div class="card-item-content-text"> <div class="card-item-content-text">
绑定设备 绑定设备
</div> </div>
<Ellipsis>{{ slotProps.deviceName }}</Ellipsis> <Ellipsis>{{
slotProps.deviceName
}}</Ellipsis>
</j-col> </j-col>
</j-row> </j-row>
<j-divider style="margin: 12px 0" /> <j-divider style="margin: 12px 0" />
@ -187,11 +197,13 @@
<div class="progress-text"> <div class="progress-text">
<div> <div>
{{ {{
slotProps.totalFlow ? ( slotProps.totalFlow
? (
(slotProps.usedFlow / (slotProps.usedFlow /
slotProps.totalFlow) * slotProps.totalFlow) *
100 100
).toFixed(2) : '0.00' ).toFixed(2)
: '0.00'
}} }}
% %
</div> </div>
@ -203,9 +215,11 @@
:strokeColor="'#ADC6FF'" :strokeColor="'#ADC6FF'"
:showInfo="false" :showInfo="false"
:percent=" :percent="
slotProps.totalFlow ? (slotProps.usedFlow / slotProps.totalFlow
? (slotProps.usedFlow /
slotProps.totalFlow) * slotProps.totalFlow) *
100 : 0 100
: 0
" "
/> />
</div> </div>
@ -265,7 +279,7 @@
}} }}
</div> </div>
</template> </template>
<template #operatorName='slotProps'> <template #operatorName="slotProps">
{{ OperatorMap[slotProps.operatorName] }} {{ OperatorMap[slotProps.operatorName] }}
</template> </template>
<template #cardType="slotProps"> <template #cardType="slotProps">
@ -332,7 +346,11 @@
</j-pro-table> </j-pro-table>
</FullPage> </FullPage>
<!-- 批量导入 --> <!-- 批量导入 -->
<Import v-if="importVisible" @close="importVisible = false" @save="importSave"/> <Import
v-if="importVisible"
@close="importVisible = false"
@save="importSave"
/>
<!-- 批量导出 --> <!-- 批量导出 -->
<Export <Export
v-if="exportVisible" v-if="exportVisible"
@ -382,9 +400,9 @@ import { useMenuStore } from 'store/menu';
import BadgeStatus from '@/components/BadgeStatus/index.vue'; import BadgeStatus from '@/components/BadgeStatus/index.vue';
import BatchDropdown from '@/components/BatchDropdown/index.vue'; import BatchDropdown from '@/components/BatchDropdown/index.vue';
import { BatchActionsType } from '@/components/BatchDropdown/types'; import { BatchActionsType } from '@/components/BatchDropdown/types';
import {usePermissionStore} from "store/permission"; import { usePermissionStore } from 'store/permission';
import {useRouterParams} from "@/utils/hooks/useParams"; import { useRouterParams } from '@/utils/hooks/useParams';
import { OperatorList, OperatorMap } from '@/views/iot-card/data' import { OperatorMap } from '@/views/iot-card/data';
const router = useRouter(); const router = useRouter();
const menuStory = useMenuStore(); const menuStory = useMenuStore();
@ -433,8 +451,8 @@ const columns = [
width: 200, width: 200,
search: { search: {
type: 'string', type: 'string',
rename: 'deviceName' rename: 'deviceName',
} },
}, },
{ {
title: '平台对接', title: '平台对接',
@ -467,7 +485,22 @@ const columns = [
width: 120, width: 120,
search: { search: {
type: 'select', type: 'select',
options: OperatorList, options: async () => {
return [
{
label: '移动',
value: '移动',
},
{
label: '电信',
value: '电信',
},
{
label: '联通',
value: '联通',
},
];
},
}, },
}, },
{ {
@ -538,7 +571,7 @@ const columns = [
{ label: '未激活', value: 'toBeActivated' }, { label: '未激活', value: 'toBeActivated' },
{ label: '停机', value: 'deactivate' }, { label: '停机', value: 'deactivate' },
{ label: '其它', value: 'using,toBeActivated,deactivate' }, { label: '其它', value: 'using,toBeActivated,deactivate' },
] ],
}, },
}, },
{ {
@ -552,11 +585,11 @@ const columns = [
const btnHasPermission = usePermissionStore().hasPermission; const btnHasPermission = usePermissionStore().hasPermission;
const paltformPermission = btnHasPermission(`iot-card/Platform:add`); const paltformPermission = btnHasPermission(`iot-card/Platform:add`);
const importSave = () => { const importSave = () => {
cardManageRef.value?.reload() cardManageRef.value?.reload();
importVisible.value = false importVisible.value = false;
} };
const routerParams = useRouterParams() const routerParams = useRouterParams();
const getActions = ( const getActions = (
data: Partial<Record<string, any>>, data: Partial<Record<string, any>>,
@ -680,7 +713,9 @@ const getActions = (
const resp: any = await del(data.id); const resp: any = await del(data.id);
if (resp.status === 200) { if (resp.status === 200) {
onlyMessage('操作成功'); onlyMessage('操作成功');
const index = _selectedRowKeys.value.findIndex((id: any) => id === data.id); const index = _selectedRowKeys.value.findIndex(
(id: any) => id === data.id,
);
if (index !== -1) { if (index !== -1) {
_selectedRowKeys.value.splice(index, 1); _selectedRowKeys.value.splice(index, 1);
} }
@ -716,15 +751,19 @@ const getActions = (
}; };
const handleSearch = (e: any) => { const handleSearch = (e: any) => {
const newParams = (e?.terms as any[])?.map(item1 => { const newParams = (e?.terms as any[])?.map((item1) => {
item1.terms = item1.terms.map((item2: any) => { item1.terms = item1.terms.map((item2: any) => {
if (['cardStateType'].includes(item2.column) && !(['using', 'toBeActivated', 'deactivate'].includes(item2.value))) { // if (
item2.termType = item2.termType === 'not' ? 'in' : 'nin' ['cardStateType'].includes(item2.column) &&
!['using', 'toBeActivated', 'deactivate'].includes(item2.value)
) {
//
item2.termType = item2.termType === 'not' ? 'in' : 'nin';
} }
return item2 return item2;
}) });
return item1 return item1;
}) });
params.value = { terms: newParams || [] }; params.value = { terms: newParams || [] };
}; };
@ -739,7 +778,7 @@ const cancelSelect = () => {
const handleClick = (dt: any) => { const handleClick = (dt: any) => {
if (!dt?.cardStateType) { if (!dt?.cardStateType) {
return return;
} }
if (isCheck.value) { if (isCheck.value) {
if (_selectedRowKeys.value.includes(dt.id)) { if (_selectedRowKeys.value.includes(dt.id)) {
@ -809,7 +848,10 @@ const handleActive = () => {
} }
}); });
} else { } else {
onlyMessage('仅支持同一个运营商下且最少10条数据,最多100条数据', 'warning'); onlyMessage(
'仅支持同一个运营商下且最少10条数据,最多100条数据',
'warning',
);
} }
}; };
@ -827,7 +869,10 @@ const handleStop = () => {
} }
}); });
} else { } else {
onlyMessage('仅支持同一个运营商下且最少10条数据,最多100条数据', 'warning'); onlyMessage(
'仅支持同一个运营商下且最少10条数据,最多100条数据',
'warning',
);
} }
}; };
@ -845,7 +890,10 @@ const handleResumption = () => {
} }
}); });
} else { } else {
onlyMessage('仅支持同一个运营商下且最少10条数据,最多100条数据', 'warning'); onlyMessage(
'仅支持同一个运营商下且最少10条数据,最多100条数据',
'warning',
);
} }
}; };
@ -869,7 +917,9 @@ const handelRemove = async () => {
onlyMessage('请选择数据', 'error'); onlyMessage('请选择数据', 'error');
return; return;
} }
const resp = await removeCards(_selectedRowKeys.value.map( v => ({ id:v }))); const resp = await removeCards(
_selectedRowKeys.value.map((v) => ({ id: v })),
);
if (resp.status === 200) { if (resp.status === 200) {
onlyMessage('操作成功'); onlyMessage('操作成功');
_selectedRowKeys.value = []; _selectedRowKeys.value = [];
@ -963,9 +1013,9 @@ const batchActions: BatchActionsType[] = [
onMounted(() => { onMounted(() => {
if (routerParams.params.value.type === 'add' && paltformPermission) { if (routerParams.params.value.type === 'add' && paltformPermission) {
handleAdd() handleAdd();
} }
}) });
</script> </script>
<style scoped lang="less"> <style scoped lang="less">

View File

@ -50,15 +50,15 @@
<div class="item-english">物联卡</div> <div class="item-english">物联卡</div>
<div class="item-content"> <div class="item-content">
<div <div
v-for="iten in pieChartData" v-for="item in pieChartData"
:key="iten.key" :key="item.key"
class="item-node" class="item-node"
> >
<div class="item-node-text"> <div class="item-node-text">
{{ iten.value }} {{ item.value }}
</div> </div>
<div :class="`state ${iten.className}`"> <div :class="`state ${item.className}`">
{{ iten.name }} {{ item.name }}
</div> </div>
</div> </div>
</div> </div>
@ -159,7 +159,7 @@ const barChartData = ref<any[]>([]);
const pieChartData = ref<any[]>([ const pieChartData = ref<any[]>([
{ {
key: 'using', key: 'using',
name: '正常', name: '激活',
value: 0, value: 0,
className: 'normal', className: 'normal',
}, },

View File

@ -122,7 +122,7 @@ const columns = [
}, },
{ {
title: '接入方式', title: '接入方式',
dataIndex: 'accessName', dataIndex: 'accessId',
width: 150, width: 150,
ellipsis: true, ellipsis: true,
search: { search: {
@ -192,12 +192,14 @@ const columns = [
hideInTable: true, hideInTable: true,
search: { search: {
type: 'treeSelect', type: 'treeSelect',
termOptions: ['eq'],
componentProps: { componentProps: {
fieldNames: { fieldNames: {
label: 'name', label: 'name',
value: 'value', value: 'value',
}, },
}, },
options: () => new Promise((resolve) => { options: () => new Promise((resolve) => {
getTreeData_api({ paging: false }).then((resp: any) => { getTreeData_api({ paging: false }).then((resp: any) => {
const formatValue = (list: any[]) => { const formatValue = (list: any[]) => {

View File

@ -30,7 +30,7 @@
@mouseout='mouseout' @mouseout='mouseout'
> >
<j-popconfirm <j-popconfirm
title='该操作将清空其它所有否则条件,确认删除?' title='该操作将清空过滤条件,确认删除?'
placement="topRight" placement="topRight"
@confirm='onDeleteAll' @confirm='onDeleteAll'
> >
@ -156,7 +156,7 @@ const WarpClass = computed(() => {
const onDelete = () => { const onDelete = () => {
if (FormModel.value.branches?.length == 2) { if (FormModel.value.branches?.length == 2) {
FormModel.value.branches?.splice(props.name, 1, null) FormModel.value.branches?.splice(props.name, 1)
} else { } else {
FormModel.value.branches?.splice(props.name, 1) FormModel.value.branches?.splice(props.name, 1)
} }
@ -164,8 +164,8 @@ const onDelete = () => {
const onDeleteAll = () => { const onDeleteAll = () => {
if (FormModel.value.branches) { if (FormModel.value.branches) {
FormModel.value.branches.length = props.name FormModel.value.branches[props.name].when = []
FormModel.value.branches.push(null as any) FormModel.value.options.when[props.branches_Index].terms = []
} }
} }

View File

@ -287,7 +287,6 @@ watchEffect(() => {
activeKey.value = _group[0].id activeKey.value = _group[0].id
} }
} }
console.log(group.value,'group')
}) })
</script> </script>

View File

@ -461,7 +461,7 @@ const uploader: uploaderType = {
if (!typeBool) { if (!typeBool) {
onlyMessage(`请上传.jpg.png.jfif.pjp.pjpeg.jpeg格式的图片`, 'error'); onlyMessage(`请上传.jpg.png.jfif.pjp.pjpeg.jpeg格式的图片`, 'error');
} else if (!sizeBool) { } else if (!sizeBool) {
onlyMessage(`图片大小必须小于2M`, 'error'); onlyMessage(`图片大小必须小于4M`, 'error');
} }
return typeBool && sizeBool; return typeBool && sizeBool;
}, },

6432
yarn.lock

File diff suppressed because it is too large Load Diff