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

This commit is contained in:
jackhoo_98 2023-03-29 22:08:54 +08:00
commit d0c53252ec
23 changed files with 245 additions and 95 deletions

View File

@ -12,6 +12,19 @@
<script setup lang="ts">
import { ConfigProvider } from 'jetlinks-ui-components'
import zhCN from 'jetlinks-ui-components/es/locale/zh_CN';
import { storeToRefs } from 'pinia';
import { useSystem } from './store/system';
import DefaultSetting from '../config/config'
const system = useSystem();
const {configInfo} = storeToRefs(system);
watchEffect(() => {
const ico: any = document.querySelector('link[rel="icon"]');
if(ico !== null){
ico.href = configInfo.value?.front?.ico || DefaultSetting?.logo
}
})
</script>

View File

@ -38,6 +38,7 @@ import { useMenuStore } from '@/store/menu';
import { clearMenuItem } from 'jetlinks-ui-components/es/ProLayout/util';
import { AccountMenu } from '@/router/menu'
import { useSystem } from '@/store/system';
import { storeToRefs } from 'pinia';
type StateType = {
collapsed: boolean;
@ -52,13 +53,13 @@ const route = useRoute();
const menu = useMenuStore();
const system = useSystem();
const configInfo = system.configInfo;
const {configInfo} = storeToRefs(system);
const layoutConf = reactive({
theme: configInfo.front?.headerTheme || DefaultSetting.layout.theme,
theme: configInfo.value.front?.headerTheme || DefaultSetting.layout.theme,
siderWidth: DefaultSetting.layout.siderWidth,
logo: configInfo.front?.logo || DefaultSetting.layout.logo,
title: configInfo.front?.title || DefaultSetting.layout.title,
logo: configInfo.value.front?.logo || DefaultSetting.layout.logo,
title: configInfo.value.front?.title || DefaultSetting.layout.title,
menuData: [...clearMenuItem(menu.siderMenus), AccountMenu],
// menuData: menu.siderMenus,
splitMenus: true,

View File

@ -107,8 +107,10 @@ const read = (type: string, data: any) => {
const getList = () => {
loading.value = true;
const params = {
'sorts[0].name': 'notifyTime',
'sorts[0].order': 'desc',
sorts: [{
name: 'notifyTime',
order: 'desc'
}],
terms: [
{
terms: [

View File

@ -85,6 +85,7 @@
width="700px"
@cancel="modalVis = false"
@ok="handleItemModalSubmit"
:zIndex='1100'
>
<div style="width: 100%; height: 300px">
<JMonacoEditor v-model:modelValue="objectValue" />
@ -157,15 +158,17 @@ const componentsType = ref<ITypes>({
});
const typeMap = new Map(Object.entries(componentsType.value));
const myValue = computed({
get: () => {
return props.modelValue;
},
set: (val: any) => {
objectValue.value = val;
emit('update:modelValue', val);
},
});
// const myValue = computed({
// get: () => {
// return props.modelValue;
// },
// set: (val: any) => {
// objectValue.value = val;
// emit('update:modelValue', val);
// },
// });
const myValue = ref(props.modelValue)
//
const modalVis = ref<boolean>(false);
@ -174,6 +177,7 @@ const handleItemModalSubmit = () => {
myValue.value = objectValue.value.replace(/[\r\n]\s*/g, '');
modalVis.value = false;
emit('change', objectValue.value)
emit('update:modelValue', myValue.value);
};
//
@ -189,18 +193,28 @@ const handleFileChange = (info: UploadChangeParam<UploadFile<any>>) => {
const selectChange = (e: string, option: any) => {
emit('change', e, option)
emit('update:modelValue', myValue.value);
}
const timeChange = (e: any) => {
emit('change', e)
emit('update:modelValue', myValue.value);
}
const inputChange = (e: any) => {
emit('change', e && e.target ? e.target.value : e)
emit('update:modelValue', myValue.value);
}
const dateChange = (e: any) => {
emit('change', e)
emit('update:modelValue', myValue.value);
}
myValue.value = props.modelValue
if (props.itemType === 'object') {
objectValue.value = props.modelValue as string
}
</script>

View File

@ -26,8 +26,7 @@ export const useDepartmentStore = defineStore({
},
setSelectedKeys(value: string[], type?: string) {
// 分页保留选中项
// this.crossPageKeys = type === 'pagination' ? [...new Set([...this.crossPageKeys, ...value])] : value;
this.crossPageKeys = [...new Set([...this.crossPageKeys, ...value])];
this.crossPageKeys = type === 'concat' ? [...new Set([...this.crossPageKeys, ...value])] : value;
}
}
})

View File

@ -114,7 +114,10 @@
<h3>修改密码</h3>
<div class="content">
<div class="content" style="align-items: flex-end">
<AIcon type="LockOutlined" style="color: #1d39c4; font-size: 70px" />
<AIcon
type="LockOutlined"
style="color: #1d39c4; font-size: 70px"
/>
<span
style="margin-left: 5px; color: rgba(0, 0, 0, 0.55)"
>安全性高的密码可以使帐号更安全建议您定期更换密码,设置一个包含字母,符号或数字中至少两项且长度超过8位的密码</span
@ -261,7 +264,9 @@ const unBind = (id: string) => {
});
};
const clickBind = (id: string) => {
window.open(`/${origin}/application/sso/${id}/login?autoCreateUser=false`);
window.open(
`${location.host}${BASE_API_PATH}/application/sso/${id}/login?autoCreateUser=false`,
);
localStorage.setItem('onBind', 'false');
localStorage.setItem('onLogin', 'yes');
window.onstorage = (e) => {

View File

@ -154,6 +154,7 @@ const columns = [
scopedSlots: true,
search: {
type: 'date',
rename: 'registryTime'
},
},
{

View File

@ -478,12 +478,6 @@ export default {
buttons: [
{ id: 'view', name: '查看', enabled: true, granted: true },
{ id: 'update', name: '编辑', enabled: true, granted: true },
{
id: 'action',
name: '启/禁用',
enabled: true,
granted: true,
},
{ id: 'delete', name: '删除', enabled: true, granted: true },
{
id: 'add',
@ -949,12 +943,6 @@ export default {
buttons: [
{ id: 'view', name: '查看', enabled: true, granted: true },
{ id: 'update', name: '编辑', enabled: true, granted: true },
{
id: 'action',
name: '启/禁用',
enabled: true,
granted: true,
},
{ id: 'delete', name: '删除', enabled: true, granted: true },
{
id: 'add',

View File

@ -2083,8 +2083,9 @@ export default [
],
},
],
accessSupport: { text: "不支持", value: "unsupported" },
supportDataAccess: false
accessSupport: { text: "支持", value: "support" },
supportDataAccess: true,
assetType: 'aliyunNorthOutput'
},
],
},

View File

@ -26,7 +26,7 @@
</slot>
</template>
<template #content>
<h3 class="card-item-content-title">
<h3 style='font-size: 16px;width: calc(100% - 90px)'>
<Ellipsis>
{{ slotProps.name }}
</Ellipsis>

View File

@ -71,7 +71,7 @@ import { queryPlatformNoPage, recharge } from '@/api/iot-card/cardManagement';
import { message } from 'jetlinks-ui-components';
import { PaymentMethod } from '@/views/iot-card/data';
const emit = defineEmits(['change']);
const emit = defineEmits(['change', 'save']);
const btnLoading = ref<boolean>(false);
const configList = ref<Record<string, any>[]>([]);
@ -171,7 +171,7 @@ const handleOk = () => {
} else {
window.open(resp.result);
}
emit('change');
emit('change', true);
formRef.value.resetFields();
}
})

View File

@ -150,7 +150,7 @@ const handleSearch = (p: any) => {
const deviceQuery = (p: any) => {
const sorts: any = [];
if (props.value) {
if (props.value[0]?.value) {
sorts.push({
name: 'id',
value: props.value[0]?.value,

View File

@ -47,7 +47,7 @@ const change = (number: number) => {
_keys.add(number)
}
}
rowKeys.value = [..._keys.values()]
rowKeys.value = [..._keys.values()].sort((a, b) => a - b )
emit('update:value', rowKeys.value)
emit('change', rowKeys.value)
}

View File

@ -15,7 +15,7 @@
]'
option-type='button'
button-style='solid'
@change='updateValue'
@change='triggerChange'
/>
</j-form-item>
<j-form-item v-if='showCron' name='cron' :rules="cronRules">
@ -75,7 +75,7 @@
style='max-width: 170px'
:precision='0'
:min='1'
:max='59'
:max='unitMax'
v-model:value='formModel.period.every'
@change='updateValue'
>
@ -87,7 +87,7 @@
{ label: "分", value: "minutes" },
{ label: "小时", value: "hours" },
]'
@select='updateValue'
@select='periodUnitChange'
/>
</template>
</j-input-number>
@ -124,6 +124,7 @@ const props = defineProps({
})
const emit = defineEmits<Emit>()
const unitMax = ref<number>(99)
const cronRules = [
{ max: 64, message: '最多可输入64个字符' },
@ -170,7 +171,9 @@ const showPeriod = computed(() => {
return formModel.trigger !== 'cron' && formModel.mod === 'period'
})
const updateValue = () => {
const cloneValue = cloneDeep(formModel)
if (cloneValue.trigger === 'cron') {
delete cloneValue.when
@ -186,6 +189,26 @@ const updateValue = () => {
emit('update:value', cloneValue)
}
const triggerChange = () => {
formModel.when = []
formModel.cron = undefined
updateValue()
}
/**
* 频率单位切换
* @param v
*/
const periodUnitChange = (v: any) => {
if(v === 'hours') {
unitMax.value = 99999
} else {
unitMax.value = 99
}
formModel.period!.every = 1
updateValue()
}
defineExpose({
validateFields: () => new Promise(async (resolve) => {
const data = await timerForm.value?.validateFields()

View File

@ -427,7 +427,7 @@ const uploader: uploaderType = {
},
//
beforeIconUpload: (file) => {
const typeBool = uploader.iconTypes.includes(file.type);
const typeBool = file.type.includes('.icon');
const sizeBool = file.size / 1024 / 1024 < 1;
if (!typeBool) {
message.error(`请上传ico格式的图片`);

View File

@ -147,7 +147,7 @@
:danger="true"
:popConfirm="{
title: `确认删除`,
onConfirm: () => clickDel(record),
onConfirm: () => clickDel(record, index),
}"
:disabled="record.status"
>
@ -358,14 +358,18 @@ const addRow = () => {
table.data.push(initData);
};
const clickDel = (row: any) => {
const clickDel = (row: any, index: number) => {
if (row.scale !== undefined) {
delSaveRow_api(id, leftData.selectedKeys[0], [row.name]).then(
(resp: any) => {
if (resp.status === 200) table.data.splice(row.index, 1);
if (resp.status === 200) {
table.data.splice(index, 1)
}
},
);
} else table.data.splice(row.index, 1);
} else {
table.data.splice(index, 1)
};
};
const clickSave = () => {

View File

@ -66,7 +66,10 @@
<j-form-item
:name="['shareConfig', 'adminUrl']"
label="管理地址"
:rules="[{ required: true, message: '请输入管理地址' }]"
:rules="[
{ required: true, message: '请输入管理地址' },
{ validator: validateAdminUrl },
]"
>
<j-input
v-model:value="form.data.shareConfig.adminUrl"
@ -80,7 +83,10 @@
<j-form-item
:name="['shareConfig', 'addresses']"
label="链接地址"
:rules="[{ required: true, message: '请输入链接地址' }]"
:rules="[
{ required: true, message: '请输入链接地址' },
{ validator: validateAddress },
]"
>
<j-input
v-model:value="form.data.shareConfig.addresses"
@ -213,6 +219,44 @@ const checkUrl = (_rule: Rule, value: string): Promise<any> => {
}
};
/**
* 管理地址校验
*/
const validateAdminUrl = (_rule: Rule, value: string): Promise<any> => {
return new Promise((resolve, reject) => {
if (!value) {
resolve('');
} else {
const arr = value.split('://');
if (arr[0] === 'http' || arr[0] === 'https') {
resolve('');
} else {
reject('请输入正确的管理地址');
}
}
});
};
/**
* 链接地址校验
* @param _rule
* @param value
*/
const validateAddress = (_rule: Rule, value: string): Promise<any> => {
return new Promise((resolve, reject) => {
if (!value) {
resolve('');
} else {
const reg =
/(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/;
if (reg.test(value)) {
resolve('');
} else {
reject('请输入正确的链接地址');
}
}
});
};
const getTypeOption = () => {
getDataTypeDict_api().then((resp: any) => {
const result = resp.result as dictItemType[];
@ -234,17 +278,17 @@ const form = reactive({
watch(
() => props.data,
(newValue) => {
form.data = {...newValue, shareConfig: { ...newValue?.shareConfig }}
form.data = { ...newValue, shareConfig: { ...newValue?.shareConfig } };
},
{
immediate: true,
deep: true
deep: true,
},
);
onMounted(() => {
getTypeOption();
})
});
const confirm = () => {
loading.value = true;
@ -255,7 +299,7 @@ const confirm = () => {
if (resp.status === 200) {
message.success('操作成功');
emits('confirm');
formRef.value?.resetFields()
formRef.value?.resetFields();
}
})
.finally(() => {

View File

@ -317,6 +317,13 @@ const table: any = {
const { pageIndex, pageSize, total, data } =
resp.result as resultType;
const ids = data.map((item) => item.id);
// : ///
const idxMap = {
read: 0,
save: 1,
delete: 2,
share: 3,
};
// fix: bug#10706
getBindingsPermission(props.assetType, ids).then(
(perResp: any) => {
@ -329,7 +336,15 @@ const table: any = {
disabled: true,
}));
item.selectPermissions = ['read'];
//
item.permissionList = item.permissionList
.map((m: any) => {
return {
...m,
idx: idxMap[m.value],
};
})
.sort((a: any, b: any) => a.idx - b.idx);
//
if (props.assetType === 'product') {
item.state = {

View File

@ -7,9 +7,10 @@
centered
:confirmLoading="loading"
@ok="confirm"
@cancel="emits('update:visible', false)"
@cancel="cancel"
>
<pro-search
type="simple"
:columns="columns"
target="category"
@search="(params:any)=>queryParams = {...params}"
@ -33,7 +34,6 @@
:pagination="{
showSizeChanger: true,
pageSizeOptions: ['10', '20', '50', '100'],
change: handlePageChange,
}"
/>
</div>
@ -63,7 +63,8 @@ const confirm = () => {
message.success('操作成功');
emits('confirm');
emits('update:visible', false);
table._selectedRowKeys = [];
// table._selectedRowKeys = [];
department.setSelectedKeys([]);
})
.finally(() => (loading.value = false));
} else {
@ -72,6 +73,11 @@ const confirm = () => {
}
};
const cancel = () => {
emits('update:visible', false);
department.setSelectedKeys([]);
};
const columns = [
{
title: '姓名',
@ -134,42 +140,24 @@ const table = reactive({
}
},
onSelectChange: (keys: string[]) => {
table._selectedRowKeys = keys;
// console.log(': ', keys);
// table._selectedRowKeys = keys;
department.setSelectedKeys(keys, keys.length ? 'concat' : '');
},
cancelSelect: () => {
table._selectedRowKeys = [];
// console.log(' ', 1111111111);
// table._selectedRowKeys = [];
department.setSelectedKeys([], 'concat');
},
});
watch(
() => table._selectedRowKeys,
() => department.crossPageKeys,
(val: string[]) => {
// console.log('_selectedRowKeys: ', val);
department.setSelectedKeys(val);
// const newKeys = [];
// val.forEach((key: string) => {
// if (!department.crossPageKeys.includes(key)) {
// newKeys.push(key);
// }
// });
// if (newKeys.length) {
// department.setSelectedKeys(val);
// console.log('_selectedRowKeys: ', val);
// }
// console.log('crossPageKeys: ', val);
table._selectedRowKeys = val;
},
);
// watch(
// () => department.crossPageKeys,
// (val: string[]) => {
// // console.log('crossPageKeys: ', val);
// table._selectedRowKeys = val;
// },
// );
const handlePageChange = () => {
console.log('PageChange');
// department.setSelectedKeys([], 'pagination');
};
</script>
<style lang="less" scoped>

View File

@ -362,6 +362,7 @@ const form = reactive({
? '支持'
: '间接控制',
},
owner: 'iot',
};
api(params)
.then((resp: any) => {

View File

@ -25,7 +25,7 @@
:params="queryParams"
:rowSelection="{
selectedRowKeys: selectedRowKeys,
onChange: (keys:string[])=>selectedRowKeys = keys,
onSelect: changeSelect,
}"
@cancelSelect="selectedRowKeys = []"
>
@ -99,4 +99,14 @@ const confirm = () => {
});
}
};
const changeSelect = (item: any, state: boolean) => {
const arr = new Set(selectedRowKeys.value);
console.log(item,state);
if(state){
arr.add(item.id)
}else{
arr.delete(item.id)
}
selectedRowKeys.value = [...arr.values()];
};
</script>

View File

@ -282,6 +282,7 @@ function menuChange(
row: tableItemType,
setButtonBool: boolean = true,
): undefined {
console.log(row, 'test');
//
if (setButtonBool) {
if (row.buttons && row.buttons.length > 0)
@ -293,16 +294,16 @@ function menuChange(
//
if (row.buttons && row.buttons.length > 0) setStatus(row, 'buttons');
else setStatus(row, 'children');
//
if (row.accessSupport && row.accessSupport.value === 'support') {
//
if (row.selectAccesses && !row.granted && !row.indeterminate)
row.selectAccesses = '';
// 'creator'
else if (!row.selectAccesses && (row.granted || row.indeterminate))
row.selectAccesses = 'creator';
}
updataAuthority(row);
// if (row.accessSupport && row.accessSupport.value === 'support') {
// //
// if (row.selectAccesses && !row.granted && !row.indeterminate)
// row.selectAccesses = '';
// // 'creator'
// else if (!row.selectAccesses && (row.granted || row.indeterminate))
// row.selectAccesses = 'creator';
// }
//
if (row.parentId) {
@ -334,6 +335,38 @@ function menuChange(
}
emits('update:selectItems', selectList); //
}
/**
* 更新权限
*/
const updataAuthority = (row: any) => {
if (row.accessSupport && row.accessSupport.value === 'support') {
//
if (row.selectAccesses && !row.granted && !row.indeterminate)
row.selectAccesses = '';
// 'creator'
else if (!row.selectAccesses && (row.granted || row.indeterminate))
row.selectAccesses = 'creator';
}
if (row.children?.length > 0) {
row.children?.forEach((item) => {
if (item.accessSupport && item.accessSupport.value === 'support') {
//
if (item.selectAccesses && !item.granted && !item.indeterminate)
item.selectAccesses = '';
// 'creator'
else if (
!item.selectAccesses &&
(item.granted || item.indeterminate)
)
item.selectAccesses = 'creator';
}
if (item.children) {
updataAuthority(item.children);
}
});
}
};
/**
* 操作权限改变事件
* @param row 触发的项
@ -376,6 +409,14 @@ function setChildrenChecked(childrens: tableItemType[], value: boolean) {
item.buttons.forEach((button) => {
button.granted = value;
});
if (item.assetAccesses?.length > 0) {
item.assetAccesses?.forEach((i) => {
if (i.supportId === 'creator') {
i.granted = true;
}
});
// console.log( item.assetAccesses);
}
item.children && setChildrenChecked(item.children, value);
});
}

View File

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