Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
XieYongHong 2023-07-06 15:01:02 +08:00
commit 590a82b156
14 changed files with 235 additions and 180 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 B

After

Width:  |  Height:  |  Size: 898 B

View File

@ -23,12 +23,13 @@
@refresh="onRefresh(item.key)"
/>
</template>
<div v-if="list.length < 12" style="color: #666666; text-align: center; padding: 8px;">这是最后一条数据了</div>
</j-scrollbar>
<div class="no-data" v-else>
<j-empty />
</div>
<div class="btns">
<span @click="onMore(item.key)">查看更多</span>
<j-button type="link" @click="onMore(item.key)">查看更多</j-button>
</div>
</div>
</j-spin>
@ -192,17 +193,8 @@ const onMore = (key: string) => {
.btns {
display: flex;
height: 46px;
line-height: 46px;
span {
display: block;
width: 100%;
text-align: center;
cursor: pointer;
// &:first-child {
// border-right: 1px solid #f0f0f0;
// }
}
justify-content: center;
align-items: center;
}
}
}

View File

@ -21,12 +21,14 @@
}}
</div>
</div>
<div class="message">{{ props.data?.message }}</div>
<j-ellipsis :lineClamp="2">
{{ props.data?.message }}
</j-ellipsis>
</div>
<div class="list-item-right">
<j-button @click.stop="detail">查看详情</j-button>
<j-button v-if="state === 'unread'" @click.stop="read('_read')">标为已读</j-button>
<j-button v-else @click.stop="read('_unread')">标为未读</j-button>
<j-button style="margin-bottom: 5px;" class="btn" @click.stop="detail">查看详情</j-button>
<j-button class="btn" v-if="state === 'unread'" @click.stop="read('_read')">标为已读</j-button>
<j-button class="btn" v-else @click.stop="read('_unread')">标为未读</j-button>
</div>
</div>
</div>
@ -100,10 +102,13 @@ const read = (type: '_read' | '_unread') => {
.list-items {
width: 312px;
overflow: hidden;
height: 80px;
border-bottom: 1px solid #f0f0f0;
margin: 0 24px;
box-sizing: content-box;
// &:hover {
// background-color: #F9FAFF;
// }
}
.list-item {
list-style: none;
@ -116,12 +121,12 @@ const read = (type: '_read' | '_unread') => {
.list-item-left {
padding: 12px 0;
width: 312px;
height: 80px;
// height: 100px;
.header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
// margin-bottom: 10px;
.title {
display: flex;
@ -142,19 +147,20 @@ const read = (type: '_read' | '_unread') => {
color: rgba(0, 0, 0, 0.45);
}
}
.message {
font-size: 12px;
}
}
.list-item-right {
width: 100px;
padding: 6px 12px 6px 0;
padding: 5px 12px 5px 0;
display: flex;
flex-direction: column;
justify-content: space-between;
justify-content: center;
.btn {
border: none;
background-color: #F1F4FF;
color: @primary-color;
}
}
}
</style>

View File

@ -6,34 +6,24 @@
<!-- 已登录-绑定三方账号 -->
<template v-if='!!token'>
<div class='info'>
<j-card style='width: 280px'>
<template #title>
<div class='info-head'>
<img :src="getImage('/bind/Rectangle.png')" />
<span>个人信息</span>
</div>
</template>
<div class='info-body'>
<img
<div class='info-body'>
<j-avatar
:size="86"
style="margin-bottom: 16px;"
:src="
user?.avatar ||
getImage('/bind/jetlinksLogo.png')
"
user?.avatar ||
getImage('/bind/jetlinksLogo.png')
"
/>
<p>账号{{ user?.username }}</p>
<p>用户名{{ user?.name }}</p>
<div class="info-body-item"><span>账号</span><j-ellipsis :lineClamp="2">{{ user?.username || '-' }}</j-ellipsis></div>
<div class="info-body-item"><span>用户名</span><j-ellipsis :lineClamp="2">{{ user?.name || "-" }}</j-ellipsis></div>
</div>
</j-card>
<img :src="getImage('/bind/Vector.png')" />
<j-card style='width: 280px'>
<template #title>
<div class='info-head'>
<img :src="getImage('/bind/Rectangle.png')" />
<span>三方账户信息</span>
</div>
</template>
<div class='info-body'>
<img
<div class='info-body'>
<j-avatar
:size="86"
shape="square"
style="margin-bottom: 16px;"
:src="
bindUser?.avatar ||
iconMap.get(
@ -41,10 +31,9 @@
) || getImage('/apply/internal-standalone.png')
"
/>
<p>账号{{ bindUser?.result?.userId || '-' }}</p>
<p>用户名{{ bindUser?.result?.name || '-' }}</p>
<div class="info-body-item"><span>账号</span><j-ellipsis :lineClamp="2">{{ bindUser?.result?.userId || '' }}</j-ellipsis></div>
<div class="info-body-item"><span>用户名</span><j-ellipsis :lineClamp="2">{{ bindUser?.result?.name || '' }}</j-ellipsis></div>
</div>
</j-card>
</div>
<div class='btn'>
<j-button type='primary' @click='handleBind'
@ -331,17 +320,17 @@ getDetail()
.content {
box-sizing: border-box;
width: 850px;
width: 928px;
min-height: 510px;
background: #fff;
border: 1px solid #e0e4e8;
border-radius: 2px;
border-radius: 22px;
padding: 40px;
.title {
margin: 30px 0;
color: #0f1222;
margin-bottom: 30px;
color: #333333;
font-weight: 400;
font-size: 20px;
font-size: 22px;
font-family: 'PingFang SC';
font-style: normal;
line-height: 25px;
@ -352,24 +341,28 @@ getDetail()
.info {
display: flex;
align-items: center;
justify-content: center;
gap: 20px;
justify-content: space-between;
padding: 86px 0;
&-head {
display: flex;
align-items: baseline;
gap: 10px;
img {
width: 69px;
}
&-body {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
gap: 8px;
width: 317px;
img {
width: 70px;
height: 70px;
&-item {
display: flex;
color: #333333;
span {
color: #666666;
white-space: nowrap;
}
}
}
}

View File

@ -1,7 +1,7 @@
<template>
<j-modal visible @cancel="emit('close')" :closable="false">
<div style="padding: 30px;">
<div style="display: flex; margin-bottom: 32px">
<div style="display: flex; padding-bottom: 24px; margin-bottom: 24px; border-bottom: 1px solid #E4E7F6">
<j-avatar :size="100" :src="userInfos.avatar"></j-avatar>
<div style="margin-left: 24px;">
<div class="name">{{ userInfos.name }}</div>

View File

@ -17,7 +17,11 @@
progress-dot
@change="onChange"
>
<j-step :title="item" v-for="(item, index) in list" :key="item">
<j-step
:title="item"
v-for="(item, index) in list"
:key="item"
>
<template #description>
<span v-if="current === index">进行中</span>
<span v-if="current < index">未开始</span>
@ -96,6 +100,8 @@ import {
validateField_api,
} from '@/api/account/center';
import { onlyMessage } from '@/utils/comm';
import { Modal } from 'jetlinks-ui-components';
import { LoginPath } from '@/router/menu';
type formType = {
oldPassword: string;
@ -103,9 +109,10 @@ type formType = {
confirmPassword: string;
};
const emits = defineEmits(['save', 'close']);
const emits = defineEmits(['close']);
const router = useRouter();
const list = ['验证密码', '设置密码', '二次确认']
const list = ['验证密码', '设置密码', '二次确认'];
const loading = ref(false);
const formRef = ref<any>();
@ -191,7 +198,15 @@ const handleOk = () => {
.then((resp) => {
if (resp.status === 200) {
onlyMessage('保存成功', 'success');
emits('save');
emits('close')
Modal.warning({
content: '密码已重置,请重新登录',
okText: '确定',
onOk() {
localStorage.clear();
router.push(LoginPath);
},
});
}
})
.finally(() => (loading.value = false));

View File

@ -69,7 +69,6 @@
<EditPassword
v-if="editPasswordVisible"
@close="editPasswordVisible = false"
@save="onPasswordSave"
/>
</div>
</template>
@ -148,9 +147,9 @@ const onSave = () => {
editInfoVisible.value = false;
};
const onPasswordSave = () => {
editPasswordVisible.value = false;
};
// const onPasswordSave = () => {
// editPasswordVisible.value = false;
// };
const onAvatarChange = (url: string) => {
updateMeInfo_api({

View File

@ -1,12 +1,12 @@
<template>
<div class="metadata-map">
<div class="left">
<j-input-search
style="width: 350px; margin-bottom: 24px"
placeholder="搜索平台属性名称"
allowClear
@search="search"
/>
<j-space style="margin-bottom: 24px">
<j-select @change="onSearchChange" show-search allow-clear placeholder="请选择属性名称" style="width: 250px;">
<j-select-option :label="item.name" v-for="item in dataSourceCache" :value="item?.id" :key="item?.id">{{item?.name}}</j-select-option>
</j-select>
<j-button type="primary" @click="onSearch"><AIcon type="SearchOutlined" /></j-button>
</j-space>
<div class="box">
<j-scrollbar height="100%">
<j-table
@ -150,6 +150,7 @@ const filterValue = ref<boolean | undefined>(undefined);
const originalData = ref([]);
const _value = ref<any>(undefined);
const searchValue = ref<any>(undefined);
const columns = [
{
@ -212,17 +213,23 @@ const getMetadataMapData = () => {
const customRow = (record: any) => {
return {
id: record.id,
class: _value.value === record.name ? 'metadata-search-row' : '',
class: _value.value === record?.name ? 'metadata-search-row' : '',
};
};
const search = (value: string) => {
if (value) {
const onSearchChange = (_: any, options: any) => {
searchValue.value = options?.label
}
const onSearch = () => {
if (searchValue.value) {
const _item: any = dataSourceCache.value.find((item: any) => {
return value === item.name;
return searchValue.value === item?.name;
});
_value.value = _item.name;
document.getElementById(_item?.id)?.scrollIntoView(); //
if(_item) {
_value.value = _item?.name;
document.getElementById(_item?.id)?.scrollIntoView(); //
}
} else {
_value.value = undefined;
}
@ -239,7 +246,7 @@ const getDefaultMetadata = async () => {
targetOptions.value = _properties.map((item) => ({
...item,
label: item.name,
label: item?.name,
value: item.id,
}));
@ -260,7 +267,7 @@ const getDefaultMetadata = async () => {
return {
index: index + 1,
id: item.id, // id
name: item.name,
name: item?.name,
type: item.valueType?.type,
original: _m?.originalId, // id
};

View File

@ -1,14 +1,14 @@
<template>
<div class="file">
<j-form layout="vertical">
<j-form-item label="下载模板">
<div class="file-download">
<j-button @click="downFile('xlsx')">模板格式.xlsx</j-button>
<j-button @click="downFile('csv')">模板格式.csv</j-button>
</div>
</j-form-item>
<j-form-item label="文件上传">
<!-- 导入系统已存在的设备数据不会更改已存在设备的所属产品信息 -->
<j-form-item>
<template #label>
<div>
文件上传
<div class="alert"><AIcon style="margin-right: 5px;" type="InfoCircleOutlined" />导入系统已存在的设备数据不会更改已存在设备的所属产品信息</div>
</div>
</template>
<a-upload-dragger
v-model:fileList="modelRef.upload"
name="file"
@ -28,15 +28,10 @@
:disabled="disabled"
@drop="handleDrop"
>
<div
style="
height: 115px;
line-height: 115px;
color: #666666;
"
>
<!-- <AIcon style="font-size: 20px;" type="PlusCircleOutlined" /> -->
点击或拖拽上传文件
<div class="dragger-box">
<AIcon class="icon" type="PlusCircleFilled" />
<span style="margin: 16px 0 8px 0">点击或拖拽上传文件</span>
<span>格式.xlsx, .csv</span>
</div>
</a-upload-dragger>
</j-form-item>
@ -45,23 +40,38 @@
>导入并启用</j-checkbox
>
</div>
<div v-if="importLoading" class="result">
<div v-if="flag">
<j-spin size="small" style="margin-right: 10px" />正在导入
</div>
<div v-else>
<AIcon
style="
color: #08e21e;
margin-right: 10px;
font-size: 16px;
"
type="CheckCircleOutlined"
/>
</div>
<div>导入成功{{ count }} </div>
<div>
导入失败<span style="color: #ff595e">{{ errCount }}</span>
<a
v-if="errMessage && !flag && errCount > 0"
style="margin-left: 20px"
@click="downError"
>下载</a
>
</div>
</div>
<j-form-item label="下载模板">
<div class="file-download">
<j-button class="btn" @click="downFile('xlsx')">模板格式.xlsx</j-button>
<j-button class="btn" @click="downFile('csv')">模板格式.csv</j-button>
</div>
</j-form-item>
</j-form>
<div v-if="importLoading" class="result">
<div v-if="flag">
<j-spin size="small" style="margin-right: 10px" />正在导入
</div>
<div v-else>
<AIcon
style="color: #08e21e; margin-right: 10px; font-size: 16px"
type="CheckCircleOutlined"
/>
</div>
<div>导入成功{{ count }} </div>
<div>
导入失败<span style="color: #ff595e">{{ errCount }}</span>
<a v-if="errMessage && !flag && errCount > 0" style="margin-left: 20px" @click="downError">下载</a>
</div>
</div>
</div>
</template>
@ -125,8 +135,8 @@ const beforeUpload = (_file: any) => {
const handleDrop = () => {};
const downError = () => {
window.open(errMessage.value)
}
window.open(errMessage.value);
};
const submitData = async (fileUrl: string) => {
if (!!fileUrl) {
@ -147,7 +157,7 @@ const submitData = async (fileUrl: string) => {
count.value = dt;
} else {
if (res.detailFile) {
errMessage.value = res.detailFile
errMessage.value = res.detailFile;
} else {
et += 1;
errCount.value = et;
@ -196,9 +206,23 @@ const uploadChange = async (info: Record<string, any>) => {
.file-download {
display: flex;
gap: 16px;
> button {
flex: 1;
min-width: 0;
.btn {
border: none;
background-color: #ECECF0;
width: 152px;
color: #666666;
}
}
.dragger-box {
margin: 46px 0;
display: flex;
flex-direction: column;
color: #666666;
.icon {
font-size: 30px;
color: @primary-color;
}
}
@ -208,5 +232,21 @@ const uploadChange = async (info: Record<string, any>) => {
color: #605e5c;
}
}
.alert {
height: 40px;
width: 100%;
padding: 0 20px 0 10px;
color: rgba(0, 0, 0, 0.55);
line-height: 40px;
background-color: #f6f6f6;
}
:deep(.ant-form-item) {
.ant-upload.ant-upload-drag {
background: #F8F9FC;
border: 1px dashed rgba(212, 219, 243, 0.7);
}
}
}
</style>

View File

@ -1,12 +1,12 @@
<template>
<div class="metadata-map">
<div class="left">
<j-input-search
style="width: 350px; margin-bottom: 24px"
placeholder="搜索平台属性名称"
allowClear
@search="search"
/>
<j-space style="margin-bottom: 24px">
<j-select @change="onSearchChange" show-search allow-clear placeholder="请选择属性名称" style="width: 250px;">
<j-select-option :label="item.name" v-for="item in dataSourceCache" :value="item?.id" :key="item?.id">{{item?.name}}</j-select-option>
</j-select>
<j-button type="primary" @click="onSearch"><AIcon type="SearchOutlined" /></j-button>
</j-space>
<div class="box">
<j-scrollbar height="100%">
<j-table
@ -150,6 +150,7 @@ const pluginOptions = ref<any[]>([]);
const filterValue = ref<boolean | undefined>(undefined);
const originalData = ref([]);
const searchValue = ref<any>(undefined);
// const tableFilter = (value: string, record: any) => {
// return true
@ -210,30 +211,26 @@ const getMetadataMapData = () => {
});
};
// const search = (value: string) => {
// if (value) {
// dataSource.value = dataSourceCache.value.filter((item: any) => {
// return !!item.name?.includes(value)
// })
// } else {
// dataSource.value = dataSourceCache.value
// }
// }
const customRow = (record: any) => {
return {
id: record.id,
class: _value.value === record.name ? 'metadata-search-row' : '',
class: _value.value === record?.name ? 'metadata-search-row' : '',
};
};
const onSearchChange = (_: any, options: any) => {
searchValue.value = options?.label
}
const search = (value: string) => {
if (value) {
const onSearch = () => {
if (searchValue.value) {
const _item: any = dataSourceCache.value.find((item: any) => {
return value === item.name;
return searchValue.value === item?.name;
});
_value.value = _item.name;
document.getElementById(_item?.id)?.scrollIntoView(); //
if(_item) {
_value.value = _item?.name;
document.getElementById(_item?.id)?.scrollIntoView(); //
}
} else {
_value.value = undefined;
}
@ -247,7 +244,7 @@ const getDefaultMetadata = async () => {
const metadataMap: any = await getMetadataMapData();
pluginOptions.value = pluginProperties.map((item) => ({
...item,
label: item.name,
label: item?.name,
value: item.id,
}));
@ -269,7 +266,7 @@ const getDefaultMetadata = async () => {
return {
index: index + 1,
id: item.id, // id
name: item.name,
name: item?.name,
type: item.valueType?.type,
plugin: _m?.pluginId, // id
};

View File

@ -6,7 +6,7 @@
@cancel="emit('close')"
@ok="onSave"
>
<ApplyList v-model:photoUrl="photoUrl" :options="typeOptions" v-model:value="type" />
<ApplyList type="add" :options="typeOptions" v-model:value="type" />
</j-modal>
</template>
@ -21,12 +21,11 @@ const emit = defineEmits(['close']);
const menuStory = useMenuStore();
const type = ref('');
const photoUrl = ref('');
const typeOptions = ref<any[]>([]);
const onSave = () => {
if(type.value){
menuStory.jumpPage('system/Apply/Save', {}, { provider: type.value, photoUrl: photoUrl.value });
menuStory.jumpPage('system/Apply/Save', {}, { provider: type.value });
} else {
onlyMessage('请先选择应用类型', 'error')
}

View File

@ -8,7 +8,7 @@
@click="onChange(item.value)"
:class="{ active: item.value === _value }"
>
<div>
<div v-if="type === 'edit'">
<MUpload
:defaultValue="defaultImg[item.value]"
:borderStyle="{
@ -22,6 +22,9 @@
@change="(_url) => onImgChange(_url, item.value)"
/>
</div>
<div v-else>
<j-avatar :src="urlValue[item.value] || defaultImg[item.value]" shape="square" :size="64" />
</div>
<span>{{ item.label }}</span>
</div>
</div>
@ -49,6 +52,10 @@ const props = defineProps({
type: Array as PropType<any[]>,
default: () => [],
},
type: {
type: String,
default: 'edit'
}
});
const emit = defineEmits(['update:value', 'update:photoUrl']);

View File

@ -43,23 +43,26 @@
:disabled="!!routeQuery.id || !!routeQuery?.provider"
/>
</j-form-item>
<j-form-item
label="接入方式"
name="integrationModes"
:rules="[
{
required: true,
message: '请选择接入方式',
},
]"
>
<j-check-button
v-model:value="form.data.integrationModes"
:options="joinOptions"
:multiple="true"
/>
</j-form-item>
<j-row>
<j-col :span="joinOptions.length >= 3 ? 24 : 6 * joinOptions.length">
<j-form-item
label="接入方式"
name="integrationModes"
:rules="[
{
required: true,
message: '请选择接入方式',
},
]"
>
<j-check-button
v-model:value="form.data.integrationModes"
:options="joinOptions"
:multiple="true"
/>
</j-form-item>
</j-col>
</j-row>
<j-collapse style="margin-bottom: 20px;">
<j-collapse-panel
v-for="(item, index) in form.data.integrationModes"
@ -1581,9 +1584,6 @@ onMounted(async () => {
}
if(routeQuery.provider){
form.data.provider = routeQuery?.provider as applyType;
if(routeQuery.photoUrl) {
form.data.logoUrl = routeQuery?.photoUrl as string;
}
typeOptions.value = typeOptions.value.filter((i: any) => {
return i.value === routeQuery.provider;
});

View File

@ -231,7 +231,7 @@ watch(
);
</script>
<style lang="less">
<style lang="less" scoped>
.action-search {
padding: 0;
}