Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev

This commit is contained in:
jackhoo_98 2023-04-01 18:42:04 +08:00
commit bdc4f065ef
19 changed files with 122 additions and 64 deletions

View File

@ -9,7 +9,7 @@ export const updateMeInfo_api = (data:object) => server.put(`/user/detail`,data)
// 修改登录用户密码 // 修改登录用户密码
export const updateMepsd_api = (data:object) => server.put(`/user/passwd`,data); export const updateMepsd_api = (data:object) => server.put(`/user/passwd`,data);
// 第三方账号解绑 // 第三方账号解绑
export const unBind_api = (appId: string) => server.post(`/application/sso/${appId}/unbind/me`, []); export const unBind_api = (appId: string) => server.request.post(`/application/sso/${appId}/unbind/me`);
/** /**
* *
* @param type * @param type

View File

@ -136,6 +136,7 @@ const breadcrumb = computed(() =>
watchEffect(() => { watchEffect(() => {
if (router.currentRoute) { if (router.currentRoute) {
const paths = router.currentRoute.value.name as string const paths = router.currentRoute.value.name as string
console.log(paths)
if (paths) { if (paths) {
const _metas = findRouteMeta(paths) const _metas = findRouteMeta(paths)
state.selectedKeys = _metas.map(item => item.path) state.selectedKeys = _metas.map(item => item.path)

View File

@ -25,7 +25,7 @@
import { getListByUnRead_api } from '@/api/account/notificationRecord'; import { getListByUnRead_api } from '@/api/account/notificationRecord';
import NoticeInfo from './NoticeInfo.vue'; import NoticeInfo from './NoticeInfo.vue';
import { getWebSocket } from '@/utils/websocket'; import { getWebSocket } from '@/utils/websocket';
import { notification, Button } from 'ant-design-vue'; import { notification, Button } from 'jetlinks-ui-components';
import { changeStatus_api } from '@/api/account/notificationRecord'; import { changeStatus_api } from '@/api/account/notificationRecord';
import { useUserInfo } from '@/store/userInfo'; import { useUserInfo } from '@/store/userInfo';

View File

@ -28,6 +28,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { loginout_api } from '@/api/login'; import { loginout_api } from '@/api/login';
import { useUserInfo } from '@/store/userInfo'; import { useUserInfo } from '@/store/userInfo';
import { LoginPath } from '@/router/menu'
const {push} = useRouter(); const {push} = useRouter();
@ -37,7 +38,7 @@ const userInfo = useUserInfo().$state.userInfos as any;
const logOut = () => { const logOut = () => {
loginout_api().then(() => { loginout_api().then(() => {
localStorage.clear(); localStorage.clear();
push('/user/login'); push(LoginPath);
}); });
}; };
</script> </script>

View File

@ -1,4 +1,4 @@
export const LoginPath = '/login' export const LoginPath = '/user/login'
export const InitHomePath = '/init-home' export const InitHomePath = '/init-home'
export const AccountCenterBindPath = '/account/center/bind' export const AccountCenterBindPath = '/account/center/bind'
export const InitLicense = '/init-license' export const InitLicense = '/init-license'

View File

@ -100,7 +100,6 @@ export const useMenuStore = defineStore({
// 是否存在通知订阅 // 是否存在通知订阅
const hasMessageSub = resp.result.some((item: { code: string }) => item.code === MESSAGE_SUBSCRIBE_MENU_CODE) const hasMessageSub = resp.result.some((item: { code: string }) => item.code === MESSAGE_SUBSCRIBE_MENU_CODE)
console.log('hasMessageSub', hasMessageSub)
if (!hasMessageSub) { if (!hasMessageSub) {
AccountMenu.children = AccountMenu.children.filter((item: { code: string }) => ![NotificationSubscriptionCode, NotificationRecordCode].includes(item.code) ) AccountMenu.children = AccountMenu.children.filter((item: { code: string }) => ![NotificationSubscriptionCode, NotificationRecordCode].includes(item.code) )
} }

View File

@ -25,7 +25,7 @@ export const useProductStore = defineStore({
} }
}, },
async refresh(id: string) { async refresh(id: string) {
this.getDetail(id) await this.getDetail(id)
const res = await getDeviceNumber(encodeQuery({ terms: { productId: id } })) const res = await getDeviceNumber(encodeQuery({ terms: { productId: id } }))
if (res.status === 200) { if (res.status === 200) {
this.current.count = res.result this.current.count = res.result

View File

@ -212,6 +212,7 @@ export const findCodeRoute = (asyncRouterMap: any[]) => {
function getDetail(code: string, url: string) { function getDetail(code: string, url: string) {
const detail = findDetailRouteItem(code, url) const detail = findDetailRouteItem(code, url)
if (!detail) return if (!detail) return
routeMeta[(detail as MenuItem).code] = { routeMeta[(detail as MenuItem).code] = {
path: detail.url, path: detail.url,
title: detail.name, title: detail.name,
@ -243,11 +244,19 @@ export const findCodeRoute = (asyncRouterMap: any[]) => {
getDetail(_code, url) getDetail(_code, url)
}) })
} }
const _code = route.appId ? `/${route.appId}${route.url}` : route.code
getDetail(route.code, route.url) if (!route.appId) {
getDetail(_code, route.url)
} else {
routeMeta[_code] = {
path: `/${route.appId}${route.url}`,
title: route.name,
parentName: code,
buttons: []
}
}
if (route.children) { if (route.children) {
findChildren(route.children, route.code) findChildren(route.children, _code)
} }
}) })
} }
@ -262,9 +271,11 @@ export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level =
const menusData: any[] = [] const menusData: any[] = []
const silderMenus: any[] = [] const silderMenus: any[] = []
_asyncRouterMap.forEach((route: any) => { _asyncRouterMap.forEach((route: any) => {
const hasAppId = route.appId
const _route: any = { const _route: any = {
path: `${route.url}`, path: hasAppId ? `/${route.appId}${route.url}` : `${route.url}`,
name: route.code, name: hasAppId ? `/${route.appId}${route.url}` : route.code,
url: hasAppId ? `/${route.appId}${route.url}` : route.url,
meta: { meta: {
icon: route.icon, icon: route.icon,
title: route.name, title: route.name,
@ -274,7 +285,6 @@ export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level =
} }
const silder = { ..._route } const silder = { ..._route }
// 查看是否有隐藏子路由 // 查看是否有隐藏子路由
route.children = findChildrenRoute(route.code, route.url, route.children) route.children = findChildrenRoute(route.code, route.url, route.children)
route.children = findDetailRoutes(route.children) route.children = findDetailRoutes(route.children)
@ -287,7 +297,7 @@ export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level =
if (showChildren && _route.children.length) { if (showChildren && _route.children.length) {
_route.component = level === 1 ? BasicLayoutPage : BlankLayoutPage _route.component = level === 1 ? BasicLayoutPage : BlankLayoutPage
_route.redirect = route.children[0].url _route.redirect = _route.children[0].url
} else { } else {
const myComponent = resolveComponent(route.code) const myComponent = resolveComponent(route.code)
// _route.component = myComponent ? myComponent : BlankLayoutPage; // _route.component = myComponent ? myComponent : BlankLayoutPage;
@ -300,7 +310,11 @@ export function filterAsyncRouter(asyncRouterMap: any, parentCode = '', level =
} }
} }
} else { } else {
_route.component = route.component || resolveComponent(route.code) || BlankLayoutPage if (hasAppId) {
_route.component = route.component || resolveComponent('iframe')
} else {
_route.component = route.component || resolveComponent(route.code) || BlankLayoutPage
}
} }
menusData.push(_route) menusData.push(_route)
silderMenus.push(silder) silderMenus.push(silder)

View File

@ -288,10 +288,10 @@
model="CARD" model="CARD"
:defaultParams="{ :defaultParams="{
...temp, ...temp,
sorts: [ sorts: productStore.current?.accessId ? [
{ name: 'id', value: productStore.current?.accessId }, { name: 'id', value: productStore.current?.accessId },
{ name: 'createTime', order: 'desc' }, { name: 'createTime', order: 'desc' },
], ] : [{ name: 'createTime', order: 'desc' }],
}" }"
:params="queryParams" :params="queryParams"
@cancelSelect="cancelSelect" @cancelSelect="cancelSelect"
@ -412,7 +412,6 @@ import {
modify, modify,
} from '@/api/device/product'; } from '@/api/device/product';
import { isNoCommunity } from '@/utils/utils'; import { isNoCommunity } from '@/utils/utils';
const productStore = useProductStore();
import Driver from 'driver.js'; import Driver from 'driver.js';
import 'driver.js/dist/driver.min.css'; import 'driver.js/dist/driver.min.css';
import { marked } from 'marked'; import { marked } from 'marked';
@ -420,7 +419,9 @@ import type { TableColumnType } from 'ant-design-vue';
import { useMenuStore } from '@/store/menu'; import { useMenuStore } from '@/store/menu';
import _ from 'lodash'; import _ from 'lodash';
import { accessConfigTypeFilter } from '@/utils/setting'; import { accessConfigTypeFilter } from '@/utils/setting';
import DeviceApi from '@/api/media/device';
const productStore = useProductStore();
const tableRef = ref(); const tableRef = ref();
const formRef = ref(); const formRef = ref();
const menuStore = useMenuStore(); const menuStore = useMenuStore();
@ -844,7 +845,9 @@ const submitData = async () => {
obj.metadata = JSON.stringify(mdata); obj.metadata = JSON.stringify(mdata);
} }
} }
// // DeviceApi.getConfiguration(current.value?.protocol, current.value?.transport)
// visible.value = false;
//
const resp: any = obj.id const resp: any = obj.id
? await updateDevice(obj) ? await updateDevice(obj)
: await saveDevice(obj); : await saveDevice(obj);

View File

@ -227,7 +227,7 @@ const handleImport = async () => {
if (props?.type === 'device') { if (props?.type === 'device') {
await instanceStore.refresh(id as string) await instanceStore.refresh(id as string)
} else { } else {
await productStore.refresh(id as string) await productStore.getDetail(id as string)
} }
metadataStore.set('importMetadata', true) metadataStore.set('importMetadata', true)
// Store.set(SystemConst.GET_METADATA, true) // Store.set(SystemConst.GET_METADATA, true)
@ -257,22 +257,12 @@ const handleImport = async () => {
} }
loading.value = false loading.value = false
if (resp.success) { if (resp.success) {
if (props?.type === 'device') { message.success('导入成功')
// const detail = instanceStore.current
// detail.metadata = JSON.stringify(paramsDevice)
// instanceStore.setCurrent(detail)
message.success('导入成功')
} else {
// const detail = productStore.current
// detail.metadata = params.metadata
// productStore.setCurrent(detail)
message.success('导入成功')
}
} }
if (props?.type === 'device') { if (props?.type === 'device') {
await instanceStore.refresh(id as string) await instanceStore.refresh(id as string)
} else { } else {
await productStore.refresh(id as string) await productStore.getDetail(id as string)
} }
metadataStore.set('importMetadata', true) metadataStore.set('importMetadata', true)
// Store.set(SystemConst.GET_METADATA, true) // Store.set(SystemConst.GET_METADATA, true)

View File

@ -14,6 +14,7 @@ import { LocalStore } from '@/utils/comm';
import { getAppInfo_api } from '@/api/system/apply'; import { getAppInfo_api } from '@/api/system/apply';
const iframeUrl = ref<string>(''); const iframeUrl = ref<string>('');
const route = useRoute()
const handle = async (appId: string, url: string) => { const handle = async (appId: string, url: string) => {
const res = await getAppInfo_api(appId); const res = await getAppInfo_api(appId);
@ -25,7 +26,7 @@ const handle = async (appId: string, url: string) => {
} }
if (res.result.provider === 'internal-standalone') { if (res.result.provider === 'internal-standalone') {
//{baseUrl}/api/application/sso/{appId}/login?redirect={menuUrl} //{baseUrl}/api/application/sso/{appId}/login?redirect={menuUrl}
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`;
iframeUrl.value = urlStandalone; iframeUrl.value = urlStandalone;
// console.log(urlStandalone); // console.log(urlStandalone);
} else if (res.result.provider === 'internal-integrated') { } else if (res.result.provider === 'internal-integrated') {
@ -41,9 +42,9 @@ const handle = async (appId: string, url: string) => {
}; };
watchEffect(() => { watchEffect(() => {
const params = location.pathname.split('/')?.[1]; const params = route.path.split('/')?.[1];
const url = location.pathname.split('/').slice(2).join('/'); const url = route.path.split('/').slice(2).join('/');
// console.log(params, url); console.log(params, url);
handle(params, url); handle(params, url);
}); });
</script> </script>

View File

@ -22,7 +22,11 @@ export const USER_CENTER_MENU_DATA = {
{ {
permission: 'user', permission: 'user',
action: ['update-self-pwd'] action: ['update-self-pwd']
} },
{
permission: 'system_config',
actions: ['query'],
},
] ]
} }
] ]

View File

@ -65,12 +65,12 @@ const handleOptions = computed(() => {
{ {
label: _item.trueText || true, label: _item.trueText || true,
value: _item.trueValue || true, value: _item.trueValue || true,
id: _item.trueValue || true, id: String(_item.trueValue || true),
}, },
{ {
label: _item.falseText || false, label: _item.falseText || false,
value: _item.falseValue || false, value: _item.falseValue || false,
id: _item.falseValue || false, id: String(_item.falseValue || false),
}, },
]; ];
} }

View File

@ -135,13 +135,15 @@ const handleOptions = computed(() => {
return [ return [
{ {
label: _item.trueText || true, label: _item.trueText || true,
name: _item.trueText || true,
value: _item.trueValue || true, value: _item.trueValue || true,
id: _item.trueValue || true, id: String(_item.trueValue || true),
}, },
{ {
label: _item.falseText || false, label: _item.falseText || false,
name: _item.falseText || false,
value: _item.falseValue || false, value: _item.falseValue || false,
id: _item.falseValue || false, id: String(_item.falseValue || false),
}, },
]; ];
} }
@ -149,6 +151,7 @@ const handleOptions = computed(() => {
return _item?.elements.map((i: any) => { return _item?.elements.map((i: any) => {
return { return {
label: i.text, label: i.text,
name: i.text,
value: i.value, value: i.value,
id: i.value, id: i.value,
}; };
@ -168,7 +171,7 @@ const onChange = () => {
}); });
}; };
const onValueChange = (val: any) => { const onValueChange = (val: any, label: string) => {
const obj = { const obj = {
[`${propertyModelRef.properties}`]: { [`${propertyModelRef.properties}`]: {
value: propertyModelRef?.propertiesValue, value: propertyModelRef?.propertiesValue,
@ -176,7 +179,7 @@ const onValueChange = (val: any) => {
}, },
}; };
emit('update:value', obj); emit('update:value', obj);
emit('change', val?.name || val) emit('change', label || val)
}; };
watch( watch(

View File

@ -83,7 +83,7 @@ import ParamsDropdown, { DoubleParamsDropdown } from '../../components/ParamsDro
import { inject } from 'vue' import { inject } from 'vue'
import { useSceneStore } from 'store/scene' import { useSceneStore } from 'store/scene'
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import {cloneDeep, flattenDeep, isArray, set} from 'lodash-es' import { cloneDeep, flattenDeep, isArray, isObject, set } from 'lodash-es'
import { Form } from 'jetlinks-ui-components' import { Form } from 'jetlinks-ui-components'
import {treeFilter} from "@/utils/comm"; import {treeFilter} from "@/utils/comm";
import { timeTypeKeys } from '@/views/rule-engine/Scene/Save/components/Terms/util' import { timeTypeKeys } from '@/views/rule-engine/Scene/Save/components/Terms/util'
@ -177,12 +177,21 @@ const handOptionByColumn = (option: any) => {
termTypeOptions.value = option.termTypes || [] termTypeOptions.value = option.termTypes || []
tabsOptions.value[0].component = option.type tabsOptions.value[0].component = option.type
columnType.value = option.type columnType.value = option.type
const _options = isArray(option.options) ? option.options : [] const _options = option.options
if (option.type === 'boolean') { if (option.type === 'boolean') {
valueOptions.value = _options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || [ // _optionsObject
{ label: '是', value: true }, if (isObject(_options)) {
{ label: '否', value: false }, const bool = (_options as any)?.bool
] valueOptions.value = [
{ label: bool.falseText, name: bool.falseText, value: bool.falseValue, id: bool.falseValue },
{ label: bool.trueText, name: bool.trueText, value: bool.trueValue, id: bool.trueValue },
]
} else {
valueOptions.value = _options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || [
{ label: '是', name: '是', value: 'true', id: 'true' },
{ label: '否', name: '否', value: 'false', id: 'false' },
]
}
} else if(option.type === 'enum') { } else if(option.type === 'enum') {
valueOptions.value = _options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || [] valueOptions.value = _options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || []
} else{ } else{

View File

@ -11,7 +11,7 @@
</template> </template>
<script lang='ts' setup name='DropdownMenus'> <script lang='ts' setup name='DropdownMenus'>
import { isBoolean, isUndefined } from 'lodash-es' import { isArray, isBoolean, isString, isUndefined } from 'lodash-es'
import { getOption } from '../DropdownButton/util' import { getOption } from '../DropdownButton/util'
type ValueType = string| number | boolean type ValueType = string| number | boolean
@ -45,6 +45,9 @@ const myOptions = computed(() => {
_label = _value === true ? '是' : '否' _label = _value === true ? '是' : '否'
_value = String(_value) _value = String(_value)
} }
if (isArray(_value)) {
_value = JSON.stringify(_value)
}
return { return {
...item, ...item,
label: _label, label: _label,
@ -60,7 +63,10 @@ const handleBoolean = (key: string) => {
} }
const click = (e: any) => { const click = (e: any) => {
const _key = ['true', 'false'].includes(e.key) ? handleBoolean(e.key) : e.key let _key = ['true', 'false'].includes(e.key) ? handleBoolean(e.key) : e.key
if (isString(_key) && _key.startsWith('[') && _key.endsWith(']')) {
_key = JSON.parse(_key)
}
const option = getOption(myOptions.value, _key, props.valueName) const option = getOption(myOptions.value, _key, props.valueName)
myValue.value = e.key myValue.value = e.key
emit('update:value', _key) emit('update:value', _key)
@ -71,7 +77,13 @@ const click = (e: any) => {
} }
watch(() => props.value, () => { watch(() => props.value, () => {
myValue.value = isBoolean(props.value) ? String(props.value) : props.value if (isBoolean(props.value)) {
myValue.value = isBoolean(props.value)
} else if (isArray(props.value)) {
myValue.value = JSON.stringify(props.value)
} else {
myValue.value = props.value
}
}, { immediate: true}) }, { immediate: true})
</script> </script>

View File

@ -38,6 +38,7 @@
<DropdownMenus <DropdownMenus
v-if='(["metric", "upper"].includes(item.key) ? metricOptions : options).length' v-if='(["metric", "upper"].includes(item.key) ? metricOptions : options).length'
:options='["metric", "upper"].includes(item.key) ? metricOptions : options' :options='["metric", "upper"].includes(item.key) ? metricOptions : options'
:value='myValue'
:valueName='valueName' :valueName='valueName'
@click='onSelect' @click='onSelect'
/> />
@ -162,6 +163,7 @@ watchEffect(() => {
const option = getOption(_options, props.value as string, props.valueName) // label const option = getOption(_options, props.value as string, props.valueName) // label
myValue.value = props.value myValue.value = props.value
mySource.value = props.source mySource.value = props.source
console.log(_options, props.value, props.valueName, option)
if (option) { if (option) {
label.value = option[props.labelName] || option.name label.value = option[props.labelName] || option.name
treeOpenKeys.value = openKeysByTree(_options, props.value, props.valueName) treeOpenKeys.value = openKeysByTree(_options, props.value, props.valueName)

View File

@ -81,7 +81,7 @@ import { ContextKey, arrayParamsKey, timeTypeKeys } from './util'
import { useSceneStore } from 'store/scene' import { useSceneStore } from 'store/scene'
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { Form } from 'jetlinks-ui-components' import { Form } from 'jetlinks-ui-components'
import {isArray, pick} from 'lodash-es' import { isArray, isObject, pick } from 'lodash-es'
const sceneStore = useSceneStore() const sceneStore = useSceneStore()
const { data: formModel } = storeToRefs(sceneStore) const { data: formModel } = storeToRefs(sceneStore)
@ -178,10 +178,20 @@ const handOptionByColumn = (option: any) => {
} }
if (option.dataType === 'boolean') { if (option.dataType === 'boolean') {
valueOptions.value = option.options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || [ // _optionsObject
{ label: '是', value: true, id: true }, const _options = option.options || option.others
{ label: '否', value: false, id: false }, if (isObject(_options)) {
] const bool = (_options as any)?.bool
valueOptions.value = [
{ label: bool.falseText, value: String(bool.falseValue)},
{ label: bool.trueText, value: String(bool.trueValue)},
]
} else {
valueOptions.value = option.options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || [
{ label: '是', value: 'true' },
{ label: '否', value: 'false' },
]
}
} else if(option.dataType === 'enum') { } else if(option.dataType === 'enum') {
valueOptions.value = option.options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || [] valueOptions.value = option.options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || []
} else{ } else{

View File

@ -1439,7 +1439,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable'; import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
import { LocalStore, filterSelectNode } from '@/utils/comm'; import { LocalStore, filterSelectNode, onlyMessage } from '@/utils/comm'
import { testIP } from '@/utils/validate'; import { testIP } from '@/utils/validate';
import { import {
@ -1799,12 +1799,21 @@ function clickSave() {
delete params.page.parameters; delete params.page.parameters;
} }
if ( if (params.provider === 'internal-standalone') {
params.provider === 'internal-standalone' && // API
params.integrationModes.includes('ssoClient') && if (
params.integrationModes.length === 1 (params.integrationModes.includes('ssoClient') &&
) params.integrationModes.length === 1) ||
return message.warning('配置单点登录需同时配置api配置'); (
params.integrationModes.includes('ssoClient') &&
params.integrationModes.includes('apiServer') &&
params.integrationModes.length === 2
)
) {
return message.warning('配置单点登录需同时配置API客服端');
}
}
//-api id?clientId:appId //-api id?clientId:appId
if (params.provider === 'internal-standalone') { if (params.provider === 'internal-standalone') {