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

This commit is contained in:
jackhoo_98 2023-03-30 13:47:16 +08:00
commit fc3d0d2d12
28 changed files with 251 additions and 152 deletions

View File

@ -13,7 +13,7 @@ export const delApply_api = (id: string) => server.remove(`/application/${id}`)
// 获取组织列表 // 获取组织列表
export const getDepartmentList_api = (params: any) => server.get(`/organization/_all/tree`, params); export const getDepartmentList_api = (params: any) => server.get(`/organization/_all/tree`, params);
// 获取应用详情 // 获取应用详情
export const getAppInfo_api = (id: string) => server.get(`/application/${id}`); export const getAppInfo_api = (id: string) => server.get<any>(`/application/${id}`);
// 新增应用 // 新增应用
export const addApp_api = (data: object) => server.post(`/application`, data); export const addApp_api = (data: object) => server.post(`/application`, data);
// 更新应用 // 更新应用

View File

@ -176,8 +176,8 @@ const objectValue = ref<string>('');
const handleItemModalSubmit = () => { const handleItemModalSubmit = () => {
myValue.value = objectValue.value.replace(/[\r\n]\s*/g, ''); myValue.value = objectValue.value.replace(/[\r\n]\s*/g, '');
modalVis.value = false; modalVis.value = false;
emit('update:modelValue', objectValue.value);
emit('change', objectValue.value) emit('change', objectValue.value)
emit('update:modelValue', myValue.value);
}; };
// //
@ -192,23 +192,23 @@ const handleFileChange = (info: UploadChangeParam<UploadFile<any>>) => {
}; };
const selectChange = (e: string, option: any) => { const selectChange = (e: string, option: any) => {
emit('change', e, option)
emit('update:modelValue', myValue.value); emit('update:modelValue', myValue.value);
emit('change', e, option)
} }
const timeChange = (e: any) => { const timeChange = (e: any) => {
emit('change', e)
emit('update:modelValue', myValue.value); emit('update:modelValue', myValue.value);
emit('change', e)
} }
const inputChange = (e: any) => { const inputChange = (e: any) => {
emit('change', e && e.target ? e.target.value : e)
emit('update:modelValue', myValue.value); emit('update:modelValue', myValue.value);
emit('change', e && e.target ? e.target.value : e)
} }
const dateChange = (e: any) => { const dateChange = (e: any) => {
emit('change', e)
emit('update:modelValue', myValue.value); emit('update:modelValue', myValue.value);
emit('change', e)
} }
myValue.value = props.modelValue myValue.value = props.modelValue

View File

@ -122,7 +122,7 @@ const showNotification = (message: string, description: string, key?: string, sh
if (show) { if (show) {
Notification.error({ Notification.error({
key, key,
message, message: '',
description description
}) })
} }

View File

@ -265,7 +265,7 @@ const unBind = (id: string) => {
}; };
const clickBind = (id: string) => { const clickBind = (id: string) => {
window.open( window.open(
`${location.host}${BASE_API_PATH}/application/sso/${id}/login?autoCreateUser=false`, `${BASE_API_PATH}/application/sso/${id}/login?autoCreateUser=false`,
); );
localStorage.setItem('onBind', 'false'); localStorage.setItem('onBind', 'false');
localStorage.setItem('onLogin', 'yes'); localStorage.setItem('onLogin', 'yes');

View File

@ -6,7 +6,7 @@
<span>精简模式下参数只支持输入框的方式录入</span> <span>精简模式下参数只支持输入框的方式录入</span>
</j-space> </j-space>
</div> </div>
<j-tabs v-model="activeKey" tab-position="left"> <j-tabs v-model="activeKey" tab-position="left" @change="onTabChange" :destroyInactiveTabPane="true">
<j-tab-pane v-for="func in newFunctions" :key="func.id"> <j-tab-pane v-for="func in newFunctions" :key="func.id">
<template #tab> <template #tab>
<Ellipsis style="width: 100px; text-align: left"> <Ellipsis style="width: 100px; text-align: left">
@ -95,7 +95,7 @@
:ref="`result${func.id}Ref`" :ref="`result${func.id}Ref`"
class="execute-result" class="execute-result"
> >
{{ func.executeResult }} {{ executeResult || '' }}
</span> </span>
</j-col> </j-col>
</j-row> </j-row>
@ -135,6 +135,8 @@ const columns = ref([
}, },
]); ]);
const executeResult = ref('')
// //
const newFunctions = computed(() => { const newFunctions = computed(() => {
const result: any = []; const result: any = [];
@ -205,7 +207,7 @@ const handleExecute = async (func: any) => {
); );
if (!success) return; if (!success) return;
message.success('操作成功'); message.success('操作成功');
func.executeResult = result instanceof Array ? result[0] : result; executeResult.value = result instanceof Array ? result[0] : result;
proxy?.$forceUpdate(); proxy?.$forceUpdate();
}) })
.catch((err: any) => { .catch((err: any) => {
@ -216,8 +218,13 @@ const handleExecute = async (func: any) => {
* 清空 * 清空
*/ */
const handleClear = (func: any) => { const handleClear = (func: any) => {
executeResult.value = ''
proxy?.$refs[`${func.id}Ref`][0].resetFields(); proxy?.$refs[`${func.id}Ref`][0].resetFields();
}; };
const onTabChange = (_key: string) => {
executeResult.value = ''
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -220,7 +220,7 @@
</template> </template>
<template #createTime="slotProps"> <template #createTime="slotProps">
<span>{{ <span>{{
dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss') slotProps?.createTime ? dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss') : ''
}}</span> }}</span>
</template> </template>
<template #action="slotProps"> <template #action="slotProps">

View File

@ -47,7 +47,7 @@
</template> </template>
<template #registerTime="slotProps"> <template #registerTime="slotProps">
<span>{{ <span>{{
dayjs(slotProps.registerTime).format('YYYY-MM-DD HH:mm:ss') slotProps?.registerTime ? dayjs(slotProps.registerTime).format('YYYY-MM-DD HH:mm:ss') : ''
}}</span> }}</span>
</template> </template>
</JProTable> </JProTable>

View File

@ -0,0 +1,49 @@
<template>
<page-container>
<iframe
:src="iframeUrl"
frameBorder="0"
style="width: 100%; height: calc(100vh - 140px)"
></iframe>
</page-container>
</template>
<script setup lang="ts">
import { TOKEN_KEY } from '@/utils/variable';
import { LocalStore } from '@/utils/comm';
import { getAppInfo_api } from '@/api/system/apply';
const iframeUrl = ref<string>('');
const handle = async (appId: string, url: string) => {
const res = await getAppInfo_api(appId);
let menuUrl: any = url;
if (res.status === 200) {
// console.log(res.result);
if (res.result.page.routeType === 'hash') {
menuUrl = `${url}`;
}
if (res.result.provider === 'internal-standalone') {
//{baseUrl}/api/application/sso/{appId}/login?redirect={menuUrl}
const urlStandalone = `${res.result.page.baseUrl}/api/application/sso/${appId}/login?redirect=${menuUrl}?layout=false`;
iframeUrl.value = urlStandalone;
// console.log(urlStandalone);
} else if (res.result.provider === 'internal-integrated') {
const tokenUrl = `${
res.result.page.baseUrl
}?X-Access-Token=${LocalStore.get(TOKEN_KEY)}`;
iframeUrl.value = tokenUrl;
} else {
const urlOther = `${res.result.page.baseUrl}/${menuUrl}`;
iframeUrl.value = urlOther;
}
}
};
watchEffect(() => {
const params = location.pathname.split('/')?.[1];
const url = location.pathname.split('/').slice(2).join('/');
// console.log(params, url);
handle(params, url);
});
</script>

View File

@ -1366,16 +1366,7 @@ export default [
}, },
], ],
}, },
{
id: 'action',
name: '启/禁用',
permissions: [
{
permission: 'firmware-upgrade-task-manager',
actions: ['save'],
}
],
},
], ],
accessSupport: { text: "间接支持", value: "indirect" }, accessSupport: { text: "间接支持", value: "indirect" },
supportDataAccess: false, supportDataAccess: false,
@ -1688,7 +1679,7 @@ export default [
], ],
accessSupport: { text: "支持", value: "support" }, accessSupport: { text: "支持", value: "support" },
supportDataAccess: true, supportDataAccess: true,
assetType: 'ataCollectCollector' assetType: 'dataCollectCollector'
}, },
], ],
}, },

View File

@ -114,7 +114,6 @@ const functionData = computed(() => {
const rules = [{ const rules = [{
validator(_: string, value: any) { validator(_: string, value: any) {
console.log(value) console.log(value)
debugger
if (!value?.length && functionData.value.length) { if (!value?.length && functionData.value.length) {
return Promise.reject('请输入功能值') return Promise.reject('请输入功能值')
} else { } else {
@ -137,6 +136,7 @@ const onSelect = (v: string, item: any) => {
} }
const callDataChange = (v: any[]) => { const callDataChange = (v: any[]) => {
console.log('callDataChange',v)
emit('update:functionParameters', v) emit('update:functionParameters', v)
} }

View File

@ -65,10 +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,
}, },
{ {
label: _item.falseText || false, label: _item.falseText || false,
value: _item.falseValue || false, value: _item.falseValue || false,
id: _item.falseValue || false,
}, },
]; ];
} }
@ -77,6 +79,7 @@ const handleOptions = computed(() => {
return { return {
label: i.text, label: i.text,
value: i.value, value: i.value,
id: i.value,
}; };
}); });
} }

View File

@ -136,10 +136,12 @@ const handleOptions = computed(() => {
{ {
label: _item.trueText || true, label: _item.trueText || true,
value: _item.trueValue || true, value: _item.trueValue || true,
id: _item.trueValue || true,
}, },
{ {
label: _item.falseText || false, label: _item.falseText || false,
value: _item.falseValue || false, value: _item.falseValue || false,
id: _item.falseValue || false,
}, },
]; ];
} }
@ -148,6 +150,7 @@ const handleOptions = computed(() => {
return { return {
label: i.text, label: i.text,
value: i.value, value: i.value,
id: i.value,
}; };
}); });
} }

View File

@ -35,7 +35,10 @@ const rules = [{
validator(_: any, v?: ActionsType) { validator(_: any, v?: ActionsType) {
console.log('validator',v) console.log('validator',v)
if (v?.executor === 'device') { if (v?.executor === 'device') {
if(!v.device?.productId || !v.device?.selectorValues) { if(
!v.device?.productId || //
!v.device?.selectorValues //
) {
return Promise.reject(new Error('该数据已发生变更,请重新配置')) return Promise.reject(new Error('该数据已发生变更,请重新配置'))
} }
} }
@ -53,12 +56,13 @@ const formTouchOff = () => {
const checkDeviceDelete = async () => { const checkDeviceDelete = async () => {
const item = _data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device const item = _data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device
const proResp = await queryProductList({ terms: [{ terms: [{ column: 'id', termType: 'eq', value: item!.productId }]}]}) const proResp = await queryProductList({ terms: [{ terms: [{ column: 'id', termType: 'eq', value: item!.productId }]}]})
if (proResp.success && (proResp.result as any)?.total === 0) { // if (proResp.success && (proResp.result as any)?.total === 0 && item && item.productId) { //
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.productId = undefined _data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.productId = undefined
formTouchOff() formTouchOff()
return return
} }
if (item?.selector === 'fixed') { if (item?.selector === 'fixed') {
console.log(item)
const deviceList = item!.selectorValues?.map(item => item.value) || [] const deviceList = item!.selectorValues?.map(item => item.value) || []
const deviceResp = await deviceQuery({ terms: [{ terms: [{ column: 'id', termType: 'in', value: deviceList.toString() }]}]}) const deviceResp = await deviceQuery({ terms: [{ terms: [{ column: 'id', termType: 'in', value: deviceList.toString() }]}]})
if (deviceResp.success && (deviceResp.result as any)?.total < (item!.selectorValues?.length || 0)) { // if (deviceResp.success && (deviceResp.result as any)?.total < (item!.selectorValues?.length || 0)) { //

View File

@ -1,9 +1,11 @@
<template> <template>
<j-menu class='scene-dropdown-menus' @click='click' :selectedKeys='[myValue]'> <j-menu class='scene-dropdown-menus' @click='click' :selectedKeys='[myValue]'>
<j-menu-item v-for='item in myOptions' :key='item.value' :title='item.label'> <j-menu-item v-for='item in myOptions' :key='item.value' :title='item.label'>
<Ellipsis > <div>
{{ item.label }} <Ellipsis >
</Ellipsis> {{ item.label }}
</Ellipsis>
</div>
</j-menu-item> </j-menu-item>
</j-menu> </j-menu>
</template> </template>
@ -60,7 +62,7 @@ const handleBoolean = (key: string) => {
const click = (e: any) => { const click = (e: any) => {
const _key = ['true', 'false'].includes(e.key) ? handleBoolean(e.key) : e.key const _key = ['true', 'false'].includes(e.key) ? handleBoolean(e.key) : e.key
const option = getOption(myOptions.value, _key, props.valueName) const option = getOption(myOptions.value, _key, props.valueName)
myValue.value = _key myValue.value = e.key
emit('update:value', _key) emit('update:value', _key)
emit('click', _key, { emit('click', _key, {
key: _key, key: _key,
@ -69,7 +71,7 @@ const click = (e: any) => {
} }
watch(() => props.value, () => { watch(() => props.value, () => {
myValue.value = props.value myValue.value = isBoolean(props.value) ? String(props.value) : props.value
}, { immediate: true}) }, { immediate: true})
</script> </script>

View File

@ -8,7 +8,9 @@
> >
<template #bodyCell="{ column, record, index }"> <template #bodyCell="{ column, record, index }">
<template v-if='column.dataIndex === "name"'> <template v-if='column.dataIndex === "name"'>
{{ record.name }} <Ellipsis>
{{ record.name }}
</Ellipsis>
</template> </template>
<template v-if='column.dataIndex === "type"'> <template v-if='column.dataIndex === "type"'>
{{ record.type }} {{ record.type }}
@ -29,12 +31,14 @@
</j-tooltip> </j-tooltip>
</template> </template>
<template v-if='column.dataIndex === "value"'> <template v-if='column.dataIndex === "value"'>
<ValueItem <div style='max-width: 260px'>
v-model:modelValue='record.value' <ValueItem
:itemType="record.type" v-model:modelValue='record.value'
:options="handleOptions(record)" :itemType="record.type"
@change='valueChange' :options="handleOptions(record)"
/> @change='valueChange'
/>
</div>
</template> </template>
</template> </template>
</j-table> </j-table>
@ -42,7 +46,6 @@
<script setup lang='ts' name='FunctionCall'> <script setup lang='ts' name='FunctionCall'>
import type { PropType } from 'vue' import type { PropType } from 'vue'
import { debounce } from 'lodash-es'
type Emit = { type Emit = {
(e: 'change', data: Array<{ name: string, value: any}>): void (e: 'change', data: Array<{ name: string, value: any}>): void
@ -69,7 +72,8 @@ const dataSource = reactive<{value: any[]}>({
const columns = [ const columns = [
{ {
title: '参数名称', title: '参数名称',
dataIndex: 'name' dataIndex: 'name',
width: 300
}, },
{ {
title: '类型', title: '类型',
@ -95,11 +99,13 @@ const handleOptions = (record: any) => {
} }
const valueChange = () => { const valueChange = () => {
const _value = dataSource.value.map(item => ({ const _value = dataSource.value.map(item => {
name: item.id, value: item.value return {
})) name: item.id, value: item.value
emit('change', _value) }
})
emit('update:value', _value) emit('update:value', _value)
emit('change', _value)
} }
watch(() => props.data, () => { watch(() => props.data, () => {

View File

@ -162,6 +162,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(option, _options, props.valueName)
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

@ -177,8 +177,8 @@ 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})) || [ valueOptions.value = option.options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || [
{ label: '是', value: true }, { label: '是', value: true, id: true },
{ label: '否', value: false }, { label: '否', value: false, id: 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})) || []

View File

@ -215,9 +215,20 @@ defineExpose({
resolve(data) resolve(data)
}) })
}) })
Object.assign(formModel, props.value) Object.assign(formModel, props.value)
formModel.when = props.value.when || [] formModel.when = props.value.when || []
watchEffect(() => {
if(props.value?.period.unit === 'hours') {
unitMax.
value = 99999
} else {
unitMax.value = 99
}
})
</script> </script>
<style scoped lang='less'> <style scoped lang='less'>

View File

@ -73,7 +73,7 @@ export const handleTimerOptions = (timer: OperationTimer):TimerOption => {
const whenStrArr = continuousValue(timer.when! || [], timer!.trigger); const whenStrArr = continuousValue(timer.when! || [], timer!.trigger);
const whenStrArr3 = whenStrArr.splice(0, 3); const whenStrArr3 = whenStrArr.splice(0, 3);
when += whenStrArr3.join('、'); when += whenStrArr3.join('、');
when += `${timer.when!.length}`; when += `...${timer.when!.length}`;
} }
if (timer.once) { if (timer.once) {

View File

@ -1718,20 +1718,20 @@ function getInfo(id: string) {
getAppInfo_api(id).then((resp: any) => { getAppInfo_api(id).then((resp: any) => {
// headersparameters, keylabel // headersparameters, keylabel
if (resp.result.apiClient) { if (resp.result.apiClient) {
resp.result.apiClient.headers = resp.result.apiClient.headers.map( resp.result.apiClient.headers = resp.result.apiClient.headers?.map(
(m: any) => ({ (m: any) => ({
...m, ...m,
label: m.key, label: m.key,
}), }),
); );
resp.result.apiClient.parameters = resp.result.apiClient.parameters =
resp.result.apiClient.parameters.map((m: any) => ({ resp.result.apiClient.parameters?.map((m: any) => ({
...m, ...m,
label: m.key, label: m.key,
})); }));
} }
if (resp.result.page) { if (resp.result.page) {
resp.result.page.parameters = resp.result.page.parameters.map( resp.result.page.parameters = resp.result.page.parameters?.map(
(m: any) => ({ (m: any) => ({
...m, ...m,
label: m.key, label: m.key,
@ -1741,7 +1741,7 @@ function getInfo(id: string) {
form.data = { form.data = {
...initForm, // , . : bug#10892 ...initForm, // , . : bug#10892
...resp.result, ...resp.result,
integrationModes: resp.result.integrationModes.map( integrationModes: resp.result.integrationModes?.map(
(item: any) => item.value, (item: any) => item.value,
), ),
} as formType; } as formType;
@ -1753,7 +1753,7 @@ function getRoleIdList() {
getRoleList_api().then((resp) => { getRoleList_api().then((resp) => {
if (resp.status === 200) { if (resp.status === 200) {
const result = resp.result as dictType; const result = resp.result as dictType;
form.roleIdList = result.map((item) => ({ form.roleIdList = result?.map((item) => ({
label: item.name, label: item.name,
value: item.id, value: item.id,
})); }));
@ -1821,13 +1821,13 @@ function clickSave() {
// headersparamslabelkey // headersparamslabelkey
if (params.integrationModes.includes('apiClient')) { if (params.integrationModes.includes('apiClient')) {
params.apiClient.headers = params.apiClient.headers.map( params.apiClient.headers = params.apiClient.headers?.map(
(m: any) => ({ (m: any) => ({
...m, ...m,
key: m.label, key: m.label,
}), }),
); );
params.apiClient.parameters = params.apiClient.parameters.map( params.apiClient.parameters = params.apiClient.parameters?.map(
(m: any) => ({ (m: any) => ({
...m, ...m,
key: m.label, key: m.label,
@ -1835,7 +1835,7 @@ function clickSave() {
); );
} }
if (params.integrationModes.includes('page')) { if (params.integrationModes.includes('page')) {
params.page.parameters = params.page.parameters.map((m: any) => ({ params.page.parameters = params.page.parameters?.map((m: any) => ({
...m, ...m,
key: m.label, key: m.label,
})); }));

View File

@ -23,58 +23,59 @@
</div> </div>
<div class="tree"> <div class="tree">
<jTree <j-spin :spinning='loading'>
v-if="treeData.length > 0" <jTree
:tree-data="treeData" v-if="treeData.length > 0"
v-model:selected-keys="selectedKeys" :tree-data="treeData"
v-model:expandedKeys="expandedKeys" v-model:selected-keys="selectedKeys"
:fieldNames="{ key: 'id' }" v-model:expandedKeys="expandedKeys"
> :fieldNames="{ key: 'id' }"
<template #title="{ name, data }"> >
<span>{{ name }}</span> <template #title="{ name, data }">
<span class="func-btns" @click="(e) => e.stopPropagation()"> <span>{{ name }}</span>
<PermissionButton <span class="func-btns" @click="(e) => e.stopPropagation()">
:hasPermission="`${permission}:update`" <PermissionButton
type="link" :hasPermission="`${permission}:update`"
:tooltip="{ type="link"
title: '编辑', :tooltip="{
}" title: '编辑',
@click="openDialog(data)" }"
> @click="openDialog(data)"
<AIcon type="EditOutlined" /> >
</PermissionButton> <AIcon type="EditOutlined" />
<PermissionButton </PermissionButton>
:hasPermission="`${permission}:add`" <PermissionButton
type="link" :hasPermission="`${permission}:add`"
:tooltip="{ type="link"
title: '新增子组织', :tooltip="{
}" title: '新增子组织',
@click=" }"
openDialog({ @click="
...data, openDialog({
id: '', ...data,
parentId: data.id, id: '',
}) parentId: data.id,
" })
> "
<AIcon type="PlusCircleOutlined" /> >
</PermissionButton> <AIcon type="PlusCircleOutlined" />
<PermissionButton </PermissionButton>
type="link" <PermissionButton
:hasPermission="`${permission}:delete`" type="link"
:tooltip="{ title: '删除' }" :hasPermission="`${permission}:delete`"
:popConfirm="{ :tooltip="{ title: '删除' }"
title: `确定要删除吗`, :popConfirm="{
onConfirm: () => delDepartment(data.id), title: `确定要删除吗`,
}" onConfirm: () => delDepartment(data.id),
> }"
<AIcon type="DeleteOutlined" /> >
</PermissionButton> <AIcon type="DeleteOutlined" />
</span> </PermissionButton>
</template> </span>
</jTree> </template>
<div class="loading" v-else-if="loading"><j-spin /></div> </jTree>
<j-empty v-else description="暂无数据" /> <j-empty v-else description="暂无数据" />
</j-spin>
</div> </div>
<!-- 编辑弹窗 --> <!-- 编辑弹窗 -->
<EditDepartmentDialog <EditDepartmentDialog
@ -227,6 +228,9 @@ function init() {
.left-tree-container { .left-tree-container {
padding-right: 24px; padding-right: 24px;
border-right: 1px solid #f0f0f0; border-right: 1px solid #f0f0f0;
display: flex;
height: 100%;
flex-direction: column;
.add-btn { .add-btn {
margin: 24px 0; margin: 24px 0;
@ -262,10 +266,17 @@ function init() {
} }
} }
.loading {
.tree {
overflow-y: auto;
overflow-x: hidden;
.loading {
display: flex; display: flex;
width: 100%;
justify-content: center; justify-content: center;
margin-top: 20px; margin-top: 20px;
}
} }
} }
</style> </style>

View File

@ -1,28 +1,30 @@
<template> <template>
<page-container> <page-container>
<div class="department-container"> <div class="department-warp">
<div class='department-container'>
<div class="left"> <div class="left">
<LeftTree @change="(id) => (departmentId = id)" /> <LeftTree @change="(id) => (departmentId = id)" />
</div> </div>
<div class="right"> <div class="right">
<j-tabs v-model:activeKey="activeKey" destroyInactiveTabPane> <j-tabs v-model:activeKey="activeKey" destroyInactiveTabPane>
<j-tab-pane key="product" tab="产品"> <j-tab-pane key="product" tab="产品">
<Product <Product
:parentId="departmentId" :parentId="departmentId"
@open-device-bind="openDeviceBind" @open-device-bind="openDeviceBind"
/> />
</j-tab-pane> </j-tab-pane>
<j-tab-pane key="device" tab="设备"> <j-tab-pane key="device" tab="设备">
<Device <Device
:parentId="departmentId" :parentId="departmentId"
v-model:bindBool="bindBool" v-model:bindBool="bindBool"
/> />
</j-tab-pane> </j-tab-pane>
<j-tab-pane key="user" tab="用户"> <j-tab-pane key="user" tab="用户">
<User :parentId="departmentId" /> <User :parentId="departmentId" />
</j-tab-pane> </j-tab-pane>
</j-tabs> </j-tabs>
</div> </div>
</div>
</div> </div>
</page-container> </page-container>
</template> </template>
@ -45,19 +47,25 @@ const openDeviceBind = () => {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.department-container { .department-warp {
display: flex; background-color: #fff;
background-color: #fff; padding: 24px;
padding: 24px; .department-container {
position: relative;
.left { .left {
flex-basis: 300px; position: absolute;
} height: 100%;
.right { width: 300px;
width: calc(100% - 300px); }
:deep(.ant-tabs-nav-wrap) {
padding-left: 24px; .right {
} width: calc(100% - 316px);
} margin-left: 316px;
:deep(.ant-tabs-nav-wrap) {
padding-left: 24px;
}
}
}
} }
</style> </style>

View File

@ -553,7 +553,7 @@ watch(
); );
watch( watch(
() => dialogs.editShow, () => dialogs.addShow,
(val: boolean) => { (val: boolean) => {
if (!val) tableData.selectedRows = []; if (!val) tableData.selectedRows = [];
}, },

View File

@ -155,6 +155,7 @@ const handleParams = (params: any) => {
// //
const tableRef = ref<Record<string, any>>({}); // const tableRef = ref<Record<string, any>>({}); //
const table = reactive({ const table = reactive({
_selectedRowKeys: [] as string[], _selectedRowKeys: [] as string[],

View File

@ -189,12 +189,13 @@
style="width: 500px" style="width: 500px"
placeholder="请选择资产类型" placeholder="请选择资产类型"
show-search show-search
:options="form.assetsType"
> >
<j-select-option <!-- <j-select-option
v-for="item in form.assetsType" v-for="item in form.assetsType"
:value="item.value" :value="item.value"
>{{ item.label }}</j-select-option >{{ item.label }}</j-select-option
> > -->
</j-select> </j-select>
</j-form-item> </j-form-item>

View File

@ -6,6 +6,7 @@
:pagination="false" :pagination="false"
:rowKey="'id'" :rowKey="'id'"
:scroll="{ y: '500px' }" :scroll="{ y: '500px' }"
ref="treeRef"
> >
<!-- 表头 --> <!-- 表头 -->
<template #headerCell="{ column }"> <template #headerCell="{ column }">
@ -99,13 +100,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { cloneDeep } from 'lodash-es'; import { cloneDeep } from 'lodash-es';
import { getPrimissTree_api } from '@/api/system/role'; import { getPrimissTree_api } from '@/api/system/role';
import { getCurrentInstance } from 'vue';
const emits = defineEmits(['update:selectItems']); const emits = defineEmits(['update:selectItems']);
const route = useRoute(); const route = useRoute();
const props = defineProps({ const props = defineProps({
selectItems: Array, selectItems: Array,
}); });
const treeRef = ref();
let { ctx: that, proxy } = getCurrentInstance();
const columns = [ const columns = [
{ {
title: '菜单权限', title: '菜单权限',
@ -282,7 +284,6 @@ function menuChange(
row: tableItemType, row: tableItemType,
setButtonBool: boolean = true, setButtonBool: boolean = true,
): undefined { ): undefined {
console.log(row, 'test');
// //
if (setButtonBool) { if (setButtonBool) {
if (row.buttons && row.buttons.length > 0) if (row.buttons && row.buttons.length > 0)
@ -334,6 +335,7 @@ function menuChange(
indeterminate.value = false; indeterminate.value = false;
} }
emits('update:selectItems', selectList); // emits('update:selectItems', selectList); //
treeRef.value.$forceUpdate();
} }
/** /**
@ -430,7 +432,6 @@ function setStatus(
prop: 'children' | 'buttons' = 'children', prop: 'children' | 'buttons' = 'children',
) { ) {
const childrens = target[prop] as any[]; const childrens = target[prop] as any[];
if (childrens && childrens instanceof Array) { if (childrens && childrens instanceof Array) {
// //
const indeterminateLen = childrens.filter( const indeterminateLen = childrens.filter(

View File

@ -92,8 +92,8 @@ export default defineConfig(({ mode}) => {
[env.VITE_APP_BASE_API]: { [env.VITE_APP_BASE_API]: {
// target: 'http://192.168.33.22:8800', // target: 'http://192.168.33.22:8800',
// target: 'http://192.168.32.244:8881', // target: 'http://192.168.32.244:8881',
target: 'http://120.77.179.54:8844', // 120测试 // target: 'http://120.77.179.54:8844', // 120测试
// target: 'http://192.168.33.46:8844', // 本地开发环境 target: 'http://192.168.33.46:8844', // 本地开发环境
ws: 'ws://192.168.33.46:8844', ws: 'ws://192.168.33.46:8844',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '') rewrite: (path) => path.replace(/^\/api/, '')

View File

@ -3700,8 +3700,8 @@ jetlinks-store@^0.0.3:
jetlinks-ui-components@^1.0.5: jetlinks-ui-components@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#a8c912f424b8e6c3e0aa8e2aa9ddcc59fe13cd3a" resolved "http://47.108.170.157:9013/jetlinks-ui-components/-/jetlinks-ui-components-1.0.5.tgz#d5d2b919f89cede8e7236149afdb9ab1e5684e9b"
integrity sha512-zZsVbqG7sLfKsizK+8sT0bCmAz7rEu/qoS5yYSEUzGMvTGQU3Q5W6qdT/5o5v92BYFP+1Kud1l5CNhA3e3NtWQ== integrity sha512-vWNz2YT1bsfh0xAAnJLEfFcukeX4QE3HyloaJJp3xU9wVbwtS38sdKEQepHZdsDKwzgKWdL03/o/qE3hgBKpwQ==
dependencies: dependencies:
"@vueuse/core" "^9.12.0" "@vueuse/core" "^9.12.0"
ant-design-vue "^3.2.15" ant-design-vue "^3.2.15"