Merge branch 'dev' into dev-dictionary

# Conflicts:
#	src/views/device/Instance/Detail/ChildDevice/index.vue
This commit is contained in:
XieYongHong 2023-10-24 15:53:05 +08:00
commit 6a2250cbf3
33 changed files with 250 additions and 204 deletions

2
.npmrc
View File

@ -1,2 +1,2 @@
always-auth=true always-auth=true
registry=http://registry.jetlinks.cn/ registry=https://registry.npmjs.org/

View File

@ -48,6 +48,18 @@ yarn dev:force
此处可以更改系统名称、主题色、系统logo、浏览器页签等 此处可以更改系统名称、主题色、系统logo、浏览器页签等
#### 主题色
```javascript
// src/App.vue
ConfigProvider.config({
theme: {
primaryColor: "#315efb"
}
})
```
#### 2.默认配置 #### 2.默认配置
在代码根目录找到`config\config.ts`文件 在代码根目录找到`config\config.ts`文件

View File

@ -25,7 +25,7 @@
"event-source-polyfill": "^1.0.31", "event-source-polyfill": "^1.0.31",
"global": "^4.4.0", "global": "^4.4.0",
"jetlinks-store": "^0.0.3", "jetlinks-store": "^0.0.3",
"jetlinks-ui-components": "^1.0.33", "jetlinks-ui-components": "^1.0.34-2",
"js-cookie": "^3.0.1", "js-cookie": "^3.0.1",
"jsencrypt": "^3.3.2", "jsencrypt": "^3.3.2",
"less": "^4.1.3", "less": "^4.1.3",

View File

@ -15,7 +15,11 @@ const system = useSystem();
const {configInfo} = storeToRefs(system); const {configInfo} = storeToRefs(system);
system.setDocumentTitle() system.setDocumentTitle()
ConfigProvider.config({
theme: {
primaryColor: "#315efb"
}
})
</script> </script>
<style scoped> <style scoped>

View File

@ -29,7 +29,7 @@
</div> </div>
</div> </div>
<div class="editor"> <div class="editor">
<j-monaco-editor v-if="loading" v-model:model-value="_value" theme="vs" ref="editor" language="javascript" :registrationTypescript="typescriptTip" <j-monaco-editor v-if="loading" v-model:model-value="_value" theme="vs" ref="editor" language="javascript" :registrationTypescript="typescriptTip" :registrationTips="registrationTips"
:init="editorInit"/> :init="editorInit"/>
</div> </div>
</div> </div>
@ -41,11 +41,13 @@ import {
} from '@/api/device/instance'; } from '@/api/device/instance';
import { useInstanceStore } from '@/store/instance'; import { useInstanceStore } from '@/store/instance';
import { useProductStore } from '@/store/product'; import { useProductStore } from '@/store/product';
import { cloneDeep } from 'lodash-es';
import { inject } from 'vue' import { inject } from 'vue'
interface Props { interface Props {
mode?: 'advance' | 'simple'; mode?: 'advance' | 'simple';
id?: string; id?: string;
value?: string; value?: string;
tips?: Array<any>
} }
const props = defineProps<Props>() const props = defineProps<Props>()
const target = inject('target') const target = inject('target')
@ -71,28 +73,9 @@ type SymbolType = {
const typescriptTip = reactive({ const typescriptTip = reactive({
typescript: '' typescript: ''
}) })
const registrationTips = ref<any>({
const queryCode = () => { name: 'javascript'
let id = '' })
if(target==='device'){
id = instanceStore.current.id
queryTypescript(id).then(res => {
if (res.status===200) {
typescriptTip.typescript = res.result
}
})
}else if(target ==='product'){
id = productStore.current.id
queryProductTs(id).then(res => {
if (res.status===200) {
typescriptTip.typescript = res.result
}
})
}
}
queryCode()
const editorInit = (editor: any, monaco: any) => { const editorInit = (editor: any, monaco: any) => {
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({ monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: true, noSemanticValidation: true,
@ -200,11 +183,27 @@ const _value = computed({
}) })
const loading = ref(false) const loading = ref(false)
onMounted(() => { const queryCode = () => {
setTimeout(() => { registrationTips.value.suggestions = cloneDeep(props.tips)
loading.value = true; let id = ''
}, 100); if(target==='device'){
}) id = instanceStore.current.id
queryTypescript(id).then(res => {
if (res.status===200) {
typescriptTip.typescript = res.result
}
})
}else if(target ==='product'){
id = productStore.current.id
queryProductTs(id).then(res => {
if (res.status===200) {
typescriptTip.typescript = res.result
}
})
}
}
const addOperatorValue = (val: string) => { const addOperatorValue = (val: string) => {
editor.value?.insert(val) editor.value?.insert(val)
@ -220,6 +219,13 @@ defineExpose({
addOperatorValue addOperatorValue
}) })
onMounted(() => {
setTimeout(() => {
loading.value = true;
}, 100);
})
queryCode()
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.editor-box { .editor-box {

View File

@ -32,6 +32,7 @@
mode="advance" mode="advance"
key="advance" key="advance"
v-model:value="_value" v-model:value="_value"
:tips="tips"
/> />
</div> </div>
</div> </div>
@ -59,7 +60,8 @@ import Editor from './Editor/index.vue';
import Debug from './Debug/index.vue'; import Debug from './Debug/index.vue';
import Operator from './Operator/index.vue'; import Operator from './Operator/index.vue';
import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable' import { FULL_CODE } from 'jetlinks-ui-components/es/DataTable'
import { cloneDeep } from 'lodash-es';
import { PropertyMetadata } from '@/views/device/Product/typings';
interface Emits { interface Emits {
(e: 'save', data: string | undefined): void; (e: 'save', data: string | undefined): void;
(e: 'close'): void; (e: 'close'): void;
@ -77,7 +79,7 @@ const props = defineProps({
const _value = ref<string | undefined>(props.value); const _value = ref<string | undefined>(props.value);
const _disabled = ref<boolean>(true); const _disabled = ref<boolean>(true);
const fullRef = inject(FULL_CODE); const fullRef = inject(FULL_CODE);
const tips = ref<any[]>([])
const handleCancel = () => { const handleCancel = () => {
emit('close'); emit('close');
}; };
@ -98,6 +100,29 @@ const addOperatorValue = (val: string) => {
editor.value.addOperatorValue(val); editor.value.addOperatorValue(val);
}; };
const getAllCrud = () => {
const list = cloneDeep(props.propertiesOptions)?.filter((i:any)=>
props?.id !== i.id
)
console.log(list,'list')
//
list.forEach(item => {
console.log(item)
const config = item
tips.value.push({
label: `${config.name}$recent实时值`,
insertText:`$recent ("${config.id}")`,
kind: 18,
})
tips.value.push({
label: `${config.name}上一值`,
insertText: `$lastState("${config.id}"))`,
kind: 18
})
})
}
watch(() => _value.value, () => { watch(() => _value.value, () => {
_disabled.value = true _disabled.value = true
}) })
@ -105,6 +130,7 @@ watch(() => _value.value, () => {
const onSuccess = (bool: boolean) => { const onSuccess = (bool: boolean) => {
_disabled.value = bool; _disabled.value = bool;
} }
getAllCrud()
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.header { .header {

View File

@ -107,8 +107,6 @@ const jump = (item: any) => {
router.push(item.path) router.push(item.path)
} }
watchEffect(() => { watchEffect(() => {
if (router.currentRoute) { if (router.currentRoute) {
const paths = router.currentRoute.value.matched const paths = router.currentRoute.value.matched
@ -116,6 +114,10 @@ watchEffect(() => {
basicLayout.value.openKeys = paths.map(item => item.path) basicLayout.value.openKeys = paths.map(item => item.path)
console.log(paths) // console.log(paths) //
} }
if (route.query?.layout === 'false') {
basicLayout.value.pure = true
}
}) })
const toDoc = () => window.open('http://doc.v2.jetlinks.cn/'); const toDoc = () => window.open('http://doc.v2.jetlinks.cn/');

View File

@ -1,7 +1,7 @@
<template> <template>
<template v-if="isPermission"> <template v-if="isPermission">
<template v-if="popConfirm"> <template v-if="popConfirm">
<j-popconfirm :overlayStyle='{width: "220px"}' v-bind="popConfirm" :disabled="!isPermission || props.disabled"> <j-popconfirm :disabled="!isPermission || props.disabled" :overlayStyle='{width: "220px", zIndex: 1075 }' v-bind="popConfirm">
<j-tooltip v-if="tooltip" v-bind="tooltip"> <j-tooltip v-if="tooltip" v-bind="tooltip">
<slot v-if="noButton"></slot> <slot v-if="noButton"></slot>
<j-button v-else v-bind="props" :disabled="_isPermission" :style="props.style"> <j-button v-else v-bind="props" :disabled="_isPermission" :style="props.style">
@ -120,4 +120,4 @@ const _isPermission = computed(() =>
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
</style> </style>

View File

@ -4,7 +4,7 @@ import store from './store'
import components from './components' import components from './components'
import router from './router' import router from './router'
import './style.less' import './style.less'
import 'ant-design-vue/dist/antd.variable.min.css'
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn'; import 'dayjs/locale/zh-cn';
dayjs.locale('zh-cn'); dayjs.locale('zh-cn');

View File

@ -89,4 +89,4 @@ export const useSystem = defineStore('system', {
} }
} }
} }
}) })

View File

@ -30,9 +30,9 @@ body {
.ant-pro-top-nav-header { .ant-pro-top-nav-header {
.ant-menu-item { .ant-menu-item {
padding: 0 10px !important; padding: 0 14px !important;
&:not(:first-child) { &:first-child {
margin-left: 8px !important; padding: 0 10px !important;
} }
} }
} }

View File

@ -71,8 +71,8 @@ export const isNoCommunity = !(localStorage.getItem(SystemConst.VERSION_CODE) ==
/** /**
* *
* @param length * @param length
* @returns * @returns
*/ */
export const randomString = (length?: number) => { export const randomString = (length?: number) => {
const tempLength = length || 32; const tempLength = length || 32;
@ -87,8 +87,8 @@ export const randomString = (length?: number) => {
/** /**
* *
* @param time * @param time
* @returns * @returns
*/ */
export const timestampFormat = (time: number) => { export const timestampFormat = (time: number) => {
let hour = 0; let hour = 0;
@ -182,4 +182,4 @@ export const EventEmitter = {
}) })
return this return this
} }
} }

View File

@ -90,6 +90,7 @@ import {
} from '@/utils/consts'; } from '@/utils/consts';
import { usePermissionStore } from '@/store/permission'; import { usePermissionStore } from '@/store/permission';
import RoleShow from './components/RoleShow/index.vue'; import RoleShow from './components/RoleShow/index.vue';
import {isNoCommunity} from "@/utils/utils";
const imageTypes = reactive([ const imageTypes = reactive([
'image/jpeg', 'image/jpeg',
@ -103,7 +104,8 @@ const imageTypes = reactive([
const user = useUserInfo(); const user = useUserInfo();
type KeyType = 'HomeView' | 'BindThirdAccount' | 'Subscribe' | 'StationMessage'; type KeyType = 'HomeView' | 'BindThirdAccount' | 'Subscribe' | 'StationMessage';
const list: { key: KeyType; title: string }[] = [ console.log(isNoCommunity)
const list: { key: KeyType; title: string }[] = isNoCommunity ? [
{ {
key: 'HomeView', key: 'HomeView',
title: '首页视图', title: '首页视图',
@ -120,6 +122,19 @@ const list: { key: KeyType; title: string }[] = [
key: 'StationMessage', key: 'StationMessage',
title: '站内信', title: '站内信',
}, },
] : [
{
key: 'HomeView',
title: '首页视图',
},
{
key: 'Subscribe',
title: '我的订阅',
},
{
key: 'StationMessage',
title: '站内信',
},
]; ];
const tabs = { const tabs = {

View File

@ -28,7 +28,7 @@
></j-col> ></j-col>
<j-col :span="6" <j-col :span="6"
><TopCard ><TopCard
title="今日设备息量" title="今日设备息量"
:footer="messageFooter" :footer="messageFooter"
:value="dayMessage" :value="dayMessage"
> >

View File

@ -1,106 +1,60 @@
<template> <template>
<SaveChild <SaveChild v-if="childVisible" @close-child-save="closeChildSave" :childData="_current" />
v-if="childVisible"
@close-child-save="closeChildSave"
:childData="_current"
/>
<div v-else> <div v-else>
<pro-search <pro-search :columns="columns" target="child-device" @search="handleSearch" class="device-child-device-search" />
:columns="columns"
target="child-device"
@search="handleSearch"
class="device-child-device-search"
/>
<!-- <j-divider /> --> <!-- <j-divider /> -->
<JProTable <JProTable ref="childDeviceRef" :columns="columns" :request="query" :bodyStyle="{
ref="childDeviceRef" padding: 0
:columns="columns" }" :defaultParams="{
:request="query" terms: [
:bodyStyle="{ {
padding: 0 column: 'parentId',
}" value: detail?.id || '',
:defaultParams="{ termType: 'eq',
terms: [ },
{ ],
column: 'parentId', }" :rowSelection="{
value: detail?.id || '', selectedRowKeys: _selectedRowKeys,
termType: 'eq', onChange: onSelectChange,
}, }" :params="params" :model="'TABLE'">
],
}"
:rowSelection="{
selectedRowKeys: _selectedRowKeys,
onChange: onSelectChange,
}"
:params="params"
:model="'TABLE'"
>
<template #rightExtraRender> <template #rightExtraRender>
<j-space> <j-space>
<PermissionButton <PermissionButton type="primary" v-if="detail?.accessProvider === 'official-edge-gateway'
type="primary" " hasPermission="device/Instance:update" @click="
v-if=" _current = {};
detail?.accessProvider === 'official-edge-gateway' childVisible = true;
" ">新增并绑定</PermissionButton>
hasPermission="device/Instance:update" <PermissionButton type="primary" @click="visible = true" hasPermission="device/Instance:update">
@click=" 绑定</PermissionButton>
_current = {}; <PermissionButton type="primary" hasPermission="device/Instance:update" :popConfirm="{
childVisible = true; title: '确定解绑吗?',
" onConfirm: handleUnBind,
>新增并绑定</PermissionButton }">批量解除</PermissionButton>
>
<PermissionButton
type="primary"
@click="visible = true"
hasPermission="device/Instance:update"
>
绑定</PermissionButton
>
<PermissionButton
type="primary"
hasPermission="device/Instance:update"
:popConfirm="{
title: '确定解绑吗?',
onConfirm: handleUnBind,
}"
>批量解除</PermissionButton
>
</j-space> </j-space>
</template> </template>
<template #registryTime="slotProps"> <template #registryTime="slotProps">
{{ {{
slotProps.registryTime slotProps.registryTime
? moment(slotProps.registryTime).format( ? moment(slotProps.registryTime).format(
'YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm:ss',
) )
: '' : ''
}} }}
</template> </template>
<template #state="slotProps"> <template #state="slotProps">
<j-badge <j-badge :text="slotProps.state.text" :status="statusMap.get(slotProps.state.value)" />
:text="slotProps.state.text"
:status="statusMap.get(slotProps.state.value)"
/>
</template> </template>
<template #action="slotProps"> <template #action="slotProps">
<j-space :size="16"> <j-space :size="16">
<template <template v-for="i in getActions(slotProps, 'table')" :key="i.key">
v-for="i in getActions(slotProps, 'table')" <PermissionButton v-if="i.key !== 'update' || detail.accessProvider === 'official-edge-gateway'"
:key="i.key" :disabled="i.disabled" :popConfirm="i.popConfirm" :tooltip="{
>
<PermissionButton
v-if="i.key !== 'update' || detail.accessProvider === 'official-edge-gateway'"
:disabled="i.disabled"
:popConfirm="i.popConfirm"
:tooltip="{
...i.tooltip, ...i.tooltip,
}" }" @click="i.onClick" type="link" style="padding: 0px"
@click="i.onClick" :hasPermission="'device/Instance:' + i.key">
type="link" <template #icon>
style="padding: 0px" <AIcon :type="i.icon" />
:hasPermission="'device/Instance:' + i.key" </template>
>
<template #icon><AIcon :type="i.icon" /></template>
</PermissionButton> </PermissionButton>
</template> </template>
</j-space> </j-space>
@ -113,7 +67,7 @@
<script setup lang="ts"> <script setup lang="ts">
import moment from 'moment'; import moment from 'moment';
import type { ActionsType } from '@/components/Table'; import type { ActionsType } from '@/components/Table';
import {query, unbindDevice, unbindBatchDevice, queryByParent , deleteDeviceMapping} from '@/api/device/instance'; import { query, unbindDevice, unbindBatchDevice, queryByParent, deleteDeviceMapping } from '@/api/device/instance';
import { useInstanceStore } from '@/store/instance'; import { useInstanceStore } from '@/store/instance';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import BindChildDevice from './BindChildDevice/index.vue'; import BindChildDevice from './BindChildDevice/index.vue';
@ -241,10 +195,12 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
data.id, data.id,
{}, {},
); );
const res = await deleteDeviceMapping( if (instanceStore.current.accessProvider === 'official-edge-gateway') {
detail.value.id, const res = await deleteDeviceMapping(
{deviceIds:[data.id]} detail.value.id,
) { ids: [data.id] }
)
}
if (resp.status === 200) { if (resp.status === 200) {
childDeviceRef.value?.reload(); childDeviceRef.value?.reload();
onlyMessage('操作成功!'); onlyMessage('操作成功!');
@ -285,11 +241,13 @@ const handleUnBind = async () => {
detail.value.id, detail.value.id,
_selectedRowKeys.value, _selectedRowKeys.value,
); );
if (resp.status === 200) { if (instanceStore.current.accessProvider === 'official-edge-gateway') {
const res = await deleteDeviceMapping( const res = await deleteDeviceMapping(
detail.value.id, detail.value.id,
{ids:[_selectedRowKeys.value]} { ids: [_selectedRowKeys.value] }
) )
}
if (resp.status === 200) {
onlyMessage('操作成功!'); onlyMessage('操作成功!');
cancelSelect(); cancelSelect();
childDeviceRef.value?.reload(); childDeviceRef.value?.reload();
@ -316,7 +274,7 @@ const closeBindDevice = (val: boolean) => {
const closeChildSave = () => { const closeChildSave = () => {
childVisible.value = false; childVisible.value = false;
}; };
onMounted(()=>{ onMounted(() => {
console.log(detail.value.accessProvider) console.log(detail.value.accessProvider)
}) })
</script> </script>

View File

@ -1806,4 +1806,4 @@ const Status = defineComponent({
}, },
}) })
export default Status export default Status

View File

@ -177,7 +177,7 @@ const newFunctions = computed(() => {
required: tableItem.expands?.required required: tableItem.expands?.required
}); });
} }
result.push({ result.push({
...func, ...func,
table: array, table: array,
@ -197,7 +197,7 @@ const handleExecute = async (func: any) => {
.then(async () => { .then(async () => {
const obj = {}; const obj = {};
func.table.forEach((item: any) => { func.table.forEach((item: any) => {
if (item.type === 'object') { if (item.type === 'object' && item.value) {
obj[item.id] = JSON.parse(item.value); obj[item.id] = JSON.parse(item.value);
} else { } else {
obj[item.id] = item.value; obj[item.id] = item.value;

View File

@ -313,8 +313,9 @@ const submitData = () => {
if (form.id === '') { if (form.id === '') {
form.id = undefined; form.id = undefined;
} }
const res = await addProduct(form); const res = await addProduct(form).finally(()=>{
loading.value = false loading.value = false
});
if (res.status === 200) { if (res.status === 200) {
onlyMessage('保存成功!'); onlyMessage('保存成功!');
visible.value = false; visible.value = false;

View File

@ -65,16 +65,13 @@
<AIcon type="SettingOutlined" /> <AIcon type="SettingOutlined" />
配置 配置
</j-button> </j-button>
</j-tooltip> </j-tooltip>
<PermissionButton <InputParams
v-else v-else
:has-permission="`${permission}:update`" v-model:value="data.record.inputs"
type="link" :has-permission="`${permission}:update`"
key="inputs" />
>
<InputParams v-model:value="data.record.inputs" />
</PermissionButton>
</template> </template>
<template #output="{ data }"> <template #output="{ data }">
{{ data.record.output?.type }} {{ data.record.output?.type }}
@ -99,14 +96,11 @@
配置 配置
</j-button> </j-button>
</j-tooltip> </j-tooltip>
<PermissionButton <ConfigParams
v-else v-else
:has-permission="`${permission}:update`" v-model:value="data.record.valueType"
type="link" :has-permission="`${permission}:update`"
key="properties" />
>
<ConfigParams v-model:value="data.record.valueType" />
</PermissionButton>
</template> </template>
<template #outInput> <template #outInput>
object object
@ -127,22 +121,17 @@
配置 配置
</j-button> --> </j-button> -->
<!-- </j-tooltip> --> <!-- </j-tooltip> -->
<PermissionButton <OtherSetting
:has-permission="`${permission}:update`"
type="link"
key="setting"
:tooltip="target === 'device' && productNoEdit.id?.includes?.(data.record.id) ? {
title: '继承自产品物模型的数据不支持删除',
} : undefined"
>
<OtherSetting
v-model:value="data.record.expands" v-model:value="data.record.expands"
:id="data.record.id" :id="data.record.id"
:disabled="target === 'device' && productNoEdit.id?.includes?.(data.record.id)" :disabled="target === 'device' && productNoEdit.id?.includes?.(data.record.id)"
:record="data.record" :record="data.record"
:type="data.record.valueType.type" :type="data.record.valueType.type"
:has-permission="`${permission}:update`"
:tooltip="target === 'device' && productNoEdit.id?.includes?.(data.record.id) ? {
title: '继承自产品物模型的数据不支持删除',
} : undefined"
/> />
</PermissionButton>
</template> </template>
<template #action="{data}"> <template #action="{data}">
@ -563,4 +552,4 @@ onBeforeRouteLeave((to, from, next) => { // 设备管理外路由跳转
justify-content: space-between; justify-content: space-between;
padding-bottom: 16px; padding-bottom: 16px;
} }
</style> </style>

View File

@ -6,7 +6,15 @@
<template #config="{ data }"> <template #config="{ data }">
<ConfigModal v-model:value="data.record.valueType" :showOther="false" /> <ConfigModal v-model:value="data.record.valueType" :showOther="false" />
</template> </template>
<ModelButton /> <PermissionButton
key="properties"
:has-permission="hasPermission"
style="padding-left: 0;"
type="link"
>
<AIcon type="SettingOutlined" />
配置
</PermissionButton>
</DataTableObject> </DataTableObject>
</template> </template>
@ -23,7 +31,7 @@ import {omit} from "lodash-es";
import {TypeStringMap, validatorConfig} from "../../columns"; import {TypeStringMap, validatorConfig} from "../../columns";
const columns = [ const columns = [
{ {
title: '参数标识', title: '参数标识',
dataIndex: 'id', dataIndex: 'id',
type: 'text', type: 'text',
@ -52,7 +60,7 @@ const columns = [
] ]
} }
}, },
{ {
title: '参数名称', title: '参数名称',
dataIndex: 'name', dataIndex: 'name',
type: 'text', type: 'text',
@ -139,6 +147,7 @@ const props = defineProps({
type: Array as PropType<{ label: string; value: string }[]>, type: Array as PropType<{ label: string; value: string }[]>,
default: () => [], default: () => [],
}, },
hasPermission: String,
}); });
const value = ref(props.value.properties); const value = ref(props.value.properties);
@ -151,7 +160,7 @@ const confirm = (data: any) => {
}) })
console.log('ConfigParams',newObject) console.log('ConfigParams',newObject)
emit('update:value', { emit('update:value', {
properties: newObject, properties: newObject,
type: 'object', type: 'object',

View File

@ -9,7 +9,14 @@
<template #config="{ data }"> <template #config="{ data }">
<ConfigModal v-model:value="data.record.valueType" :showOther="false" /> <ConfigModal v-model:value="data.record.valueType" :showOther="false" />
</template> </template>
<ModelButton /> <PermissionButton
key="properties"
:has-permission="hasPermission"
type="link"
>
<AIcon type="SettingOutlined" />
配置
</PermissionButton>
</DataTableObject> </DataTableObject>
</template> </template>
@ -43,6 +50,7 @@ const props = defineProps({
type: Array as PropType<{ label: string; value: string }[]>, type: Array as PropType<{ label: string; value: string }[]>,
default: () => [], default: () => [],
}, },
hasPermission: String,
}); });
const formItemContext = Form.useInjectFormItemContext(); const formItemContext = Form.useInjectFormItemContext();

View File

@ -17,4 +17,4 @@ const props = defineProps({
<style scoped> <style scoped>
</style> </style>

View File

@ -120,7 +120,7 @@ const validator = (_: any, value: any) => {
} }
const typeValidator = (_: any, value: any) => { const typeValidator = (_: any, value: any) => {
if (value === undefined) { if (value === undefined || value === null) {
return Promise.reject(validatorTip()) return Promise.reject(validatorTip())
} }
if (type === 'string' && value?.length > 64) { if (type === 'string' && value?.length > 64) {
@ -146,7 +146,7 @@ const handleValueByType = (value: any, isRange: boolean = false) => {
const confirm = () => { const confirm = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
formRef.value.validate().then(() => { formRef.value.validate().then((res) => {
let value = props.value.range === true ? formData.rangeValue : formData.value let value = props.value.range === true ? formData.rangeValue : formData.value
if (['int', 'long'].includes(type)) { if (['int', 'long'].includes(type)) {

View File

@ -51,8 +51,17 @@
/> />
</div> </div>
</template> </template>
<PermissionButton
<ModelButton :disabled="disabled"/> key="setting"
:disabled="disabled"
:has-permission="hasPermission"
:tooltip="tooltip"
style="padding-left: 0;"
type="link"
>
<AIcon type="SettingOutlined" />
配置
</PermissionButton>
</j-popconfirm-modal> </j-popconfirm-modal>
</template> </template>
@ -88,6 +97,8 @@ const props = defineProps({
type: Object, type: Object,
default: () => ({}) default: () => ({})
}, },
hasPermission: String,
tooltip: Object
}) })
const fullRef = inject(FULL_CODE); const fullRef = inject(FULL_CODE);
@ -225,4 +236,4 @@ watch(() => props.value, () => {
<style scoped> <style scoped>
</style> </style>

View File

@ -31,7 +31,7 @@ const handle = async (appId: string, url: string) => {
let menuUrl: any = url; let menuUrl: any = url;
if (res.status === 200) { if (res.status === 200) {
if (res.result.page.routeType === 'hash') { if (res.result.page.routeType === 'hash') {
menuUrl = `/#${url}`; menuUrl = `#${url}`;
} }
if (res.result.provider === 'internal-standalone') { if (res.result.provider === 'internal-standalone') {
const urlStandalone = `${res.result.page.baseUrl}/api/application/sso/${appId}/login?redirect=${menuUrl}?layout=false`; const urlStandalone = `${res.result.page.baseUrl}/api/application/sso/${appId}/login?redirect=${menuUrl}?layout=false`;

View File

@ -5,12 +5,12 @@ const Webhook = () => {
<div class={'doc'}> <div class={'doc'}>
<h1>1. </h1> <h1>1. </h1>
<div> <div>
webhook是一个接收HTTP请求的URLHTTP WebHook是一个接收HTTP请求的URLHTTP
POST请求Webhook的第三方系统可以基于该URL订阅本平台系统信息便 POST请求WebHook的第三方系统可以基于该URL订阅本平台系统信息便
</div> </div>
<h1>2.</h1> <h1>2.</h1>
<h2>1Webhook</h2> <h2>1WebHook</h2>
<div>Webhook地址</div> <div>WebHook地址</div>
<h2>2</h2> <h2>2</h2>
<div> <div>

View File

@ -278,12 +278,12 @@
<!-- webhook --> <!-- webhook -->
<template v-if="formData.type === 'webhook'"> <template v-if="formData.type === 'webhook'">
<j-form-item <j-form-item
label="Webhook" label="WebHook"
v-bind="validateInfos['configuration.url']" v-bind="validateInfos['configuration.url']"
> >
<j-input <j-input
v-model:value="formData.configuration.url" v-model:value="formData.configuration.url"
placeholder="请输入Webhook" placeholder="请输入WebHook"
/> />
</j-form-item> </j-form-item>
<j-form-item label="请求头"> <j-form-item label="请求头">

View File

@ -28,7 +28,7 @@ export const NOTICE_METHOD: INoticeMethod[] = [
value: 'sms', value: 'sms',
}, },
{ {
label: 'webhook', label: 'WebHook',
value: 'webhook', value: 'webhook',
}, },
]; ];
@ -75,7 +75,7 @@ export const MSG_TYPE = {
], ],
webhook: [ webhook: [
{ {
label: 'webhook', label: 'WebHook',
value: 'http', value: 'http',
logo: getImage('/notice/webhook.png'), logo: getImage('/notice/webhook.png'),
}, },

View File

@ -192,6 +192,12 @@ const columns = [
hideInTable: true, hideInTable: true,
search: { search: {
type: 'treeSelect', type: 'treeSelect',
componentProps: {
fieldNames: {
label: 'name',
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[]) => {
@ -260,4 +266,4 @@ const handleClick = (detail: any) => {
padding-right: 0px; padding-right: 0px;
padding-left: 0px; padding-left: 0px;
} }
</style> </style>

View File

@ -263,7 +263,6 @@ const productQuery = (p: any) => {
} }
sorts.push({ name: 'createTime', order: 'desc' }); sorts.push({ name: 'createTime', order: 'desc' });
p.sorts = sorts; p.sorts = sorts;
console.log('productQuery',p)
return queryProductList(p); return queryProductList(p);
}; };

View File

@ -162,4 +162,4 @@ watchEffect(() => {
<style scoped lang='less'> <style scoped lang='less'>
@import './index.less'; @import './index.less';
</style> </style>

View File

@ -196,4 +196,4 @@ watchEffect(() => {
display: none; display: none;
} }
} }
</style> </style>

View File

@ -3738,10 +3738,10 @@ jetlinks-store@^0.0.3:
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz" resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q== integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
jetlinks-ui-components@^1.0.33: jetlinks-ui-components@^1.0.34-2:
version "1.0.33" version "1.0.34-2"
resolved "http://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.33.tgz#49ce2b8c1e7be66272864728d5df82f834ec4490" resolved "https://registry.npmjs.org/jetlinks-ui-components/-/jetlinks-ui-components-1.0.34-2.tgz#8acd9f5dd4e5baa89703391620c80545c60ea98d"
integrity sha512-vYUP4MhzO6r0golmKqO8lHk8w5ldhAkgXWZfFII1Zoa7JtUwveqpSywTU23iSmCN+4muPaSLvHw713k6OdzLmg== integrity sha512-Z8/TRoJut1CuGsXXkzUYwvmKdQ1FhvXc46uK308M76Ezv4iJIGphwt1ancqVst0+WRBWoG6ps2ZsBbqCSQB7Rg==
dependencies: dependencies:
"@vueuse/core" "^9.12.0" "@vueuse/core" "^9.12.0"
"@vueuse/router" "^9.13.0" "@vueuse/router" "^9.13.0"