push
This commit is contained in:
40
nervui-resource-repository/src/view/resource-type-add.vue
Normal file
40
nervui-resource-repository/src/view/resource-type-add.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<!-- @format -->
|
||||
|
||||
<template>
|
||||
<NsViewAddForm v-bind="getBindValue"/>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, provide } from 'vue';
|
||||
import {formProps} from "/nerv-lib/component/form/form/props";
|
||||
import {PropTypes} from "/nerv-lib/util";
|
||||
import NsMarkDown from '../component/markdown.vue';
|
||||
import NsUploadCustom from '../component/upload-custom.vue';
|
||||
export default defineComponent({
|
||||
name: 'ResourceTypeAdd',
|
||||
props: {
|
||||
...formProps,
|
||||
api: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
},
|
||||
components: { NsMarkDown, NsUploadCustom },
|
||||
setup(props, {attrs}) {
|
||||
provide('components', () => {
|
||||
return {
|
||||
NsMarkDown,
|
||||
NsUploadCustom
|
||||
};
|
||||
});
|
||||
const getBindValue = computed(() => ({
|
||||
...attrs,
|
||||
...props,
|
||||
}));
|
||||
return {
|
||||
getBindValue,
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
</style>
|
||||
129
nervui-resource-repository/src/view/resource-type-detail.vue
Normal file
129
nervui-resource-repository/src/view/resource-type-detail.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<Skeleton
|
||||
active
|
||||
:loading="loading">
|
||||
<page-title :title="data?.alias"/>
|
||||
<a-page-header class="ns-page-header">
|
||||
<template #extra>
|
||||
<ns-button @click="onBack">返回</ns-button>
|
||||
<ns-button @click="onEdit" type="primary" v-if="authMap['edit']">编辑</ns-button>
|
||||
<ns-button @click="onRelease" type="primary" v-if="!data?.shelfState && authMap['putAway']">上架</ns-button>
|
||||
<ns-button @click="onUnRelease" type="primary" v-if="data?.shelfState && authMap['putAway']">下架</ns-button>
|
||||
<ns-button @click="onRemove" type="primary" v-if="authMap['remove']">删除</ns-button>
|
||||
|
||||
</template>
|
||||
</a-page-header>
|
||||
<div class="content-wrapper">
|
||||
<NsMarkDown
|
||||
:value="data?.detail"
|
||||
:previewOnly="true"
|
||||
:htmlPreview="true"/>
|
||||
</div>
|
||||
</Skeleton>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref} from 'vue';
|
||||
import NsMarkDown from '../component/markdown.vue';
|
||||
import {http} from "/nerv-lib/util";
|
||||
import {useRoute} from "vue-router";
|
||||
import {useNavigate} from "/nerv-lib/use/use-navigate";
|
||||
import { NsModal} from "/nerv-lib/component";
|
||||
import {Skeleton} from "ant-design-vue";
|
||||
import {APP} from "/@/router/index.ts";
|
||||
import {authorizationService} from "/nerv-lib/paas";
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ResourceTypeDetail',
|
||||
props: {},
|
||||
components: {NsMarkDown, Skeleton},
|
||||
setup(props, {attrs}) {
|
||||
let loading = ref(true);
|
||||
let data = ref({});
|
||||
const route = useRoute();
|
||||
const params = route.params;
|
||||
const code = params?.id;
|
||||
const { navigateBack } = useNavigate();
|
||||
const unReleaseData = ref({
|
||||
code: code,
|
||||
shelfState: false
|
||||
})
|
||||
const removeData = ref({
|
||||
code: code,
|
||||
})
|
||||
http.get(`/api/${APP}/objs/ResourceTypes/` + params.id).then(res => {
|
||||
loading.value = false;
|
||||
data.value = res;
|
||||
})
|
||||
//权限部分
|
||||
let authMap = ref({});
|
||||
const resourceTypeClassOp= ['edit', 'putAway', 'remove'];
|
||||
resourceTypeClassOp.forEach( key => {
|
||||
authMap.value[key]= authorizationService().checkPermission('resourceRepo', 'resourceType', key);
|
||||
})
|
||||
return {
|
||||
data,
|
||||
navigateBack,
|
||||
code,
|
||||
removeData,
|
||||
unReleaseData,
|
||||
loading,
|
||||
authMap
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onEdit() {
|
||||
this.$router.push('edit');
|
||||
},
|
||||
onRelease() {
|
||||
this.$router.push('release');
|
||||
},
|
||||
onUnRelease() {
|
||||
const thisObj = this;
|
||||
NsModal.confirm({
|
||||
title: '警告',
|
||||
content: `确定要下架该资源类型吗?\n下架后不可恢复,请谨慎操作!`,
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk() {
|
||||
http.post(`/api/${APP}/objs/ResourceTypes/PutAway`, thisObj.unReleaseData).then(res=>{
|
||||
// navigateBack()
|
||||
thisObj.$router.push({name:'resourceType', path: '/rr/resourceRepository/list'});
|
||||
})
|
||||
},
|
||||
});
|
||||
},
|
||||
onRemove() {
|
||||
const thisObj = this;
|
||||
NsModal.confirm({
|
||||
title: '警告',
|
||||
content: `确定要删除该资源类型吗?\n删除后不可恢复,请谨慎操作!`,
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk() {
|
||||
http.delete(`/api/${APP}/objs/ResourceTypes`, thisObj.removeData).then(res=>{
|
||||
thisObj.$router.push({name:'resourceType', path: '/rr/resourceRepository/list'});
|
||||
})
|
||||
},
|
||||
});
|
||||
},
|
||||
onBack() {
|
||||
this.navigateBack();
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ant-page-header {
|
||||
padding: 0 24px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
:deep(.ant-page-header-heading-extra) {
|
||||
margin-right: auto !important;
|
||||
margin-left: 0;
|
||||
}
|
||||
.content-wrapper {
|
||||
margin: 0 24px
|
||||
}
|
||||
</style>
|
||||
121
nervui-resource-repository/src/view/resource-type-edit.vue
Normal file
121
nervui-resource-repository/src/view/resource-type-edit.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
|
||||
<template>
|
||||
<div class="editResourceType">
|
||||
<page-title title="编辑" />
|
||||
<a-page-header>
|
||||
<template #extra>
|
||||
<ns-button @click="navigateBack">返回</ns-button>
|
||||
<ns-button type="primary" :disabled="!mainRef?.validateResult" @click="submit">保存</ns-button>
|
||||
</template>
|
||||
</a-page-header>
|
||||
<Skeleton
|
||||
active
|
||||
:loading="loading">
|
||||
<ns-form
|
||||
style="margin-left: 24px"
|
||||
ref="mainRef"
|
||||
formLayout="修改"
|
||||
v-bind="getBindValue"
|
||||
:schemas="schemas"
|
||||
:model ="data"
|
||||
/>
|
||||
</Skeleton>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, computed, provide, ref } from 'vue';
|
||||
import {formProps} from "/nerv-lib/component/form/form/props";
|
||||
import {http, PropTypes} from "/nerv-lib/util";
|
||||
import NsMarkDown from '../component/markdown.vue';
|
||||
import NsUploadCustom from "/@/component/upload-custom.vue";
|
||||
import {useNavigate} from "/nerv-lib/use/use-navigate";
|
||||
import {NsMessage} from "/nerv-lib/component";
|
||||
import {useRouter} from "vue-router";
|
||||
import {Skeleton} from "ant-design-vue";
|
||||
import {APP} from "/@/router/index.ts";
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ResourceTypeEdit',
|
||||
props: {
|
||||
...formProps,
|
||||
title: PropTypes.string,
|
||||
getApi: Object | String
|
||||
},
|
||||
components: { NsMarkDown, Skeleton },
|
||||
setup(props, {attrs}) {
|
||||
provide('components', () => {
|
||||
return {
|
||||
NsMarkDown,
|
||||
NsUploadCustom
|
||||
};
|
||||
});
|
||||
const { navigateBack } = useNavigate();
|
||||
let loading = ref(false);
|
||||
const router = useRouter();
|
||||
const { params } = router.currentRoute.value;
|
||||
let data = ref({});
|
||||
const baseImageUrl = ref();
|
||||
let schemas = ref([])
|
||||
const initData = async () => {
|
||||
http.get(props.getApi + '/' + params.id).then(res=>{
|
||||
data.value = res;
|
||||
baseImageUrl.value = `/api/${APP}/objs/Images/${res?.iconID}`;
|
||||
schemas.value = props.schemas;
|
||||
schemas.value?.forEach(fc=>{
|
||||
if( fc['field']=='logo') {
|
||||
fc.componentProps.baseImageUrl = baseImageUrl.value;
|
||||
}
|
||||
})
|
||||
loading.value = false;
|
||||
})
|
||||
};
|
||||
initData();
|
||||
const mainRef = ref();
|
||||
function submit() {
|
||||
mainRef.value
|
||||
.triggerSubmit()
|
||||
.then((formData) => {
|
||||
http.put(`/api/${APP}/objs/ResourceTypes`, formData).then((res) => {
|
||||
NsMessage.success('操作成功', 1, () => {
|
||||
router.push({name:'resourceType', path: '/rr/resourceRepository/list'});
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(() => ({}));
|
||||
}
|
||||
|
||||
const getBindValue = computed(() => ({
|
||||
...attrs,
|
||||
...props,
|
||||
|
||||
}));
|
||||
return {
|
||||
getBindValue,
|
||||
navigateBack,
|
||||
schemas,
|
||||
data,
|
||||
mainRef,
|
||||
submit
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ant-col {
|
||||
flex: 0 0 120px !important;
|
||||
}
|
||||
.ant-page-header {
|
||||
padding: 0 24px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
:deep(.ant-page-header-heading-extra) {
|
||||
margin-right: auto !important;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.customConfig {
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
113
nervui-resource-repository/src/view/resource-type-release.vue
Normal file
113
nervui-resource-repository/src/view/resource-type-release.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<page-title :title="title"/>
|
||||
<a-page-header class="ns-page-header">
|
||||
<template #extra>
|
||||
<ns-button @click="navigateBack">返回</ns-button>
|
||||
<ns-button @click="submit" type="primary" :disabled="!testFlag">保存</ns-button>
|
||||
<ns-button @click="testConnect" type="primary" :disabled="mainRef?.validateResult ? !mainRef?.validateResult : true"
|
||||
>测试连接</ns-button>
|
||||
</template>
|
||||
</a-page-header>
|
||||
<ns-form
|
||||
style="margin-top: 30px; margin-left: 24px"
|
||||
ref="mainRef"
|
||||
formLayout="配置"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
<div class="ant-row ant-form-item" v-if="testFlag">
|
||||
<div class="ant-form-item-label item-label">
|
||||
<label title="可执行操作">可执行操作</label>
|
||||
</div>
|
||||
<div class="ant-col ant-col-20 ant-form-item-control">
|
||||
<div class="item-result">
|
||||
{{testResult}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {defineComponent, ref} from 'vue';
|
||||
import NsMarkDown from '../component/markdown.vue';
|
||||
import {http} from "/nerv-lib/util";
|
||||
import {useRoute} from "vue-router";
|
||||
import {useNavigate} from "/nerv-lib/use/use-navigate";
|
||||
import {APP} from "/@/router/index.ts";
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ResourceTypeRelease',
|
||||
props: {},
|
||||
components: {NsMarkDown},
|
||||
setup(props, {attrs}) {
|
||||
const mainRef = ref('');
|
||||
const title = ref('配置资源服务地址');
|
||||
const route = useRoute();
|
||||
const code = route.params.id
|
||||
const testFlag = ref(false);
|
||||
const testResult = ref();
|
||||
const { navigateBack } = useNavigate();
|
||||
let releaseData = ref({
|
||||
code: code,
|
||||
shelfState: true
|
||||
});
|
||||
return {
|
||||
title,
|
||||
navigateBack,
|
||||
testFlag,
|
||||
mainRef,
|
||||
testResult,
|
||||
releaseData,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
const thisObj = this;
|
||||
this.mainRef.triggerSubmit().then((data:any)=>{
|
||||
http.post(`/api/${APP}/objs/ResourceTypes/PutAway`, this.releaseData).then(res=>{
|
||||
thisObj.$router.push({name:'resourceType', path: '/rr/resourceRepository/list'})
|
||||
})
|
||||
})
|
||||
},
|
||||
testConnect() {
|
||||
this.testFlag = false;
|
||||
this.mainRef.triggerSubmit().then((data:any)=>{
|
||||
const resourceProviderAddr = data['resourceProviderAddr']
|
||||
http.get(`/api/${APP}/objs/ResourceTypes/TestConnect?resourceProviderAddr=` + resourceProviderAddr ).then(res=>{
|
||||
this.testResult = res;
|
||||
this.testFlag = true;
|
||||
this.releaseData['resourceProviderAddr']= resourceProviderAddr;
|
||||
this.releaseData['configs']= this.testResult;
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ant-page-header {
|
||||
padding: 0 24px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
:deep(.ant-page-header-heading-extra) {
|
||||
margin-right: auto !important;
|
||||
margin-left: 0;
|
||||
}
|
||||
.content-wrapper {
|
||||
margin: 0 24px
|
||||
}
|
||||
.ant-form-item {
|
||||
margin-left: 24px;
|
||||
.item-label {
|
||||
text-align: left;
|
||||
flex: 0 0 100px;
|
||||
}
|
||||
.item-result {
|
||||
white-space: break-spaces;
|
||||
height: 500px;
|
||||
overflow: auto;
|
||||
background-color: #fbfbfb;
|
||||
padding: 4px
|
||||
}
|
||||
}
|
||||
</style>
|
||||
942
nervui-resource-repository/src/view/tree-and-table-list.vue
Normal file
942
nervui-resource-repository/src/view/tree-and-table-list.vue
Normal file
@@ -0,0 +1,942 @@
|
||||
<template>
|
||||
<page-title :title="getTitle"/>
|
||||
|
||||
<div class="ns-table-wrapper">
|
||||
<div class="ns-table" :class="{ 'ns-table-no-search': !(formConfig?.schemas.length > 0) }">
|
||||
<a-spin :spinning="tableState.loading">
|
||||
<a-row type="flex" class="ns-table-main">
|
||||
<a-col flex="180px">
|
||||
<ns-table-header
|
||||
:headerActions="headerActions"
|
||||
:searchData="formModel"
|
||||
:tableTitle="tableTitle"
|
||||
:data="tableState.selectedRows">
|
||||
<template #header="data">
|
||||
<slot name="header" v-bind="data || {}"></slot>
|
||||
</template>
|
||||
</ns-table-header>
|
||||
<Skeleton :loading="loadingTree" active>
|
||||
<div class="type-tree-wrapper">
|
||||
<div class="tree-top-header">
|
||||
<div class="tree-node-content-wrapper" :class="{'selected': allSelected}" @click="onAllSelect">全部类别</div>
|
||||
<ns-button type="link" @click="onContextMenuClick(null, 'add')" v-if="authMap['add']">
|
||||
<PlusCircleOutlined/>
|
||||
添加类别
|
||||
</ns-button>
|
||||
</div>
|
||||
<a-tree v-model:expandedKeys="expandedKeys" :tree-data="treeData" v-model:selectedKeys="selectedKeys"
|
||||
@expand="onExpand" @select="onTreeSelect">
|
||||
<template #title="{ key: treeKey, title, dataRef }">
|
||||
<a-dropdown :trigger="['contextmenu']">
|
||||
<span style="min-width: 80px; display: block">{{ title }}</span>
|
||||
<template #overlay>
|
||||
<a-menu @click="({ key: menuKey }) => onContextMenuClick(treeKey, menuKey, dataRef)">
|
||||
<a-menu-item key="edit" v-if="authMap['edit']">
|
||||
<EditOutlined/>
|
||||
编辑
|
||||
</a-menu-item>
|
||||
<a-menu-item key="add" v-if="authMap['add']">
|
||||
<PlusCircleOutlined/>
|
||||
添加
|
||||
</a-menu-item>
|
||||
<a-menu-item key="remove" v-if="authMap['remove']">
|
||||
<DeleteOutlined/>
|
||||
删除
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
</a-tree>
|
||||
</div>
|
||||
</Skeleton>
|
||||
</a-col>
|
||||
<a-col flex="auto">
|
||||
<!-- {{ formConfig }} -->
|
||||
<div class="ns-table-search">
|
||||
<ns-form
|
||||
ref="formElRef"
|
||||
class="ns-table-form"
|
||||
:showAction="true"
|
||||
v-bind="formConfig"
|
||||
formLayout="flex"
|
||||
:expand="expand"
|
||||
:showExpand="showExpand"
|
||||
:model="formModel"
|
||||
@finish="formFinish"/>
|
||||
</div>
|
||||
<Skeleton :loading="loadingTable" active>
|
||||
<div class="section0">
|
||||
<div class="section-content" v-if="tableData && tableData.length>0">
|
||||
<template v-for="(item) in tableData">
|
||||
<div class="item card-item" @click="onCLickCard(item)">
|
||||
<header class="item-header">
|
||||
<div class="info-card-header">
|
||||
<div class="card-title">{{ item['alias'] }}</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="info-item-block">
|
||||
<div class="card-icon"><img :src="imgSrc + item['iconID']" alt=""></div>
|
||||
<div class="card-description-wrapper">
|
||||
<div class="card-description"><span>{{ item['desc'] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="item-footer">
|
||||
<div class="card-item-footer">
|
||||
<div class="card-footer-left">
|
||||
{{ item['typeClassAlias'] }}
|
||||
</div>
|
||||
<div class="card-footer-right">
|
||||
<div class="card-status">
|
||||
<span v-if="item['shelfState']"> <i class="iconfont iconGreen font-12"></i> 已上架
|
||||
</span>
|
||||
<span v-if="!item['shelfState']"><i class="iconfont iconRed font-12"></i> 待上架
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="section-content" v-if="tableData && tableData.length === 0 || !tableData">
|
||||
<div class="ns-table-content"> <a-empty /> </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination" v-if="tableData && tableData.length === 0 || tableData!=null">
|
||||
<a-pagination
|
||||
v-bind="getPagination"
|
||||
show-quick-jumper
|
||||
show-size-changer
|
||||
@change=" (current,pageSize) => onChange({current,pageSize})"
|
||||
size="small"
|
||||
:show-total="(total, range) => `显示 ${range[0]} 到 ${range[1]} 条数据,共计${total}条`"
|
||||
/>
|
||||
</div>
|
||||
</Skeleton>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-spin>
|
||||
</div>
|
||||
</div>
|
||||
<a-modal v-model:visible="modalVisible" :title="modalOperation.title" @ok="handleOk" @cancel="cancel" v-if="modalVisible">
|
||||
<div class="add-form" id="app" v-if="typeSchema.length">
|
||||
<ns-form
|
||||
ref="configRef"
|
||||
formLayout="ns-vertical-form"
|
||||
:schemas="typeSchema"
|
||||
:model="typeData"
|
||||
/>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {computed, defineComponent, reactive, ref, unref, watch} from "vue";
|
||||
import {Skeleton, Pagination} from "ant-design-vue";
|
||||
import {debounce, cloneDeep, isArray, get} from "lodash-es";
|
||||
import {tableProps} from "../../../lib/component/table/props";
|
||||
import {http, PropTypes, stringUtil} from "../../../lib/util";
|
||||
import {useRoute} from "vue-router";
|
||||
import {PlusCircleOutlined, EditOutlined, DeleteOutlined, ExclamationCircleOutlined} from "@ant-design/icons-vue";
|
||||
import {NsMessage, NsModal} from "../../../lib/component";
|
||||
import {RequestParams} from "/nerv-lib/component/table/table";
|
||||
import {AxiosRequestConfig} from "axios";
|
||||
import {useApi, useParams} from "/nerv-lib/use";
|
||||
import {useTableRefresh} from "/nerv-lib/component/table/use-table-refresh";
|
||||
import {useTableSession} from "/nerv-lib/component/table/use-table-session";
|
||||
import {APP} from "/@/router/index.ts";
|
||||
import {authorizationService} from "/nerv-lib/paas";
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TreeAndTableList',
|
||||
components: {
|
||||
Skeleton,
|
||||
PlusCircleOutlined,
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
'a-pagination': Pagination,
|
||||
},
|
||||
props: {
|
||||
...tableProps,
|
||||
title: PropTypes.string,
|
||||
tableTitle: PropTypes.func,
|
||||
showTitle: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
resultField: PropTypes.string
|
||||
},
|
||||
setup: (props, {attrs, emit}) => {
|
||||
const nsTableRef = ref();
|
||||
const route = useRoute();
|
||||
const formModel = ref({});
|
||||
// 搜索form参数
|
||||
const formParamsRef = ref({});
|
||||
// table参数
|
||||
const tableState = reactive({
|
||||
selectedRowKeys: [],
|
||||
selectedRows: [],
|
||||
loading: false,
|
||||
loadError: false,
|
||||
loadErrorMessage: '',
|
||||
});
|
||||
const expandedKeys = ref()
|
||||
const { delayFetch } = useTableRefresh({ props, reload });
|
||||
const defaultPageRef = ref(0);
|
||||
const { getParams } = useParams();
|
||||
const treeParamsRef = ref({});
|
||||
const dataRef = ref([]);
|
||||
const orderRef = ref({});
|
||||
const { setTableSession } = useTableSession(formModel.value, formParamsRef, defaultPageRef);
|
||||
const tableData = ref<Recordable[]>([]);
|
||||
let allSelected = ref(true);
|
||||
const selectedKeys = ref([]);
|
||||
let loadingTable = ref<boolean>(false);
|
||||
let loadingTree = ref<boolean>(false);
|
||||
const imgSrc = ref(`/api/${APP}/objs/Images/`)
|
||||
let typeFieldErrors = ref({});
|
||||
// 缓存
|
||||
function initTableSession() {
|
||||
const { fullPath } = route;
|
||||
const tableSession = JSON.parse(sessionStorage[fullPath] || '{}');
|
||||
if (!props.enableTableSession) return;
|
||||
if (tableSession['formModel']) {
|
||||
Object.assign(formModel.value, tableSession['formModel']);
|
||||
let code = formModel.value['typeClassCode'];
|
||||
if(code){
|
||||
treeParamsRef.value['typeClassCode'] = code;
|
||||
selectedKeys.value =[ code];
|
||||
allSelected.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
initTableSession();
|
||||
//权限部分
|
||||
let authMap = ref({});
|
||||
const resourceTypeClassOp= ['add', 'edit', 'remove'];
|
||||
resourceTypeClassOp.forEach( key => {
|
||||
authMap.value[key]= authorizationService().checkPermission('resourceRepo', 'resourceTypeClass', key);
|
||||
})
|
||||
// 页面标题
|
||||
const getTitle = computed(() => {
|
||||
const {title} = props;
|
||||
if (title) return title;
|
||||
const {
|
||||
params: {pageTitle},
|
||||
} = route;
|
||||
if (pageTitle) return pageTitle;
|
||||
});
|
||||
// 搜索参数
|
||||
const formFinish = debounce((data) => {
|
||||
formParamsRef.value = data;
|
||||
fetch({
|
||||
page: 1,
|
||||
});
|
||||
}, 300);
|
||||
const tableChangeEvent = (pagination: Props, filters: [], sorter?: any) => {
|
||||
// console.log('params', pagination, filters, sorter);
|
||||
if (sorter?.field) {
|
||||
if (sorter.order) {
|
||||
orderRef.value = {
|
||||
[props.paramsOrderField]: stringUtil.toLine(
|
||||
`${sorter.field} ${sorter.order.replace('end', '')}`,
|
||||
),
|
||||
};
|
||||
} else {
|
||||
orderRef.value = { [props.paramsOrderField]: '' }; //覆盖默认params
|
||||
}
|
||||
fetch({
|
||||
page: pagination?.current || getPagination.value?.current || 1,
|
||||
pageSize: pagination?.pageSize,
|
||||
});
|
||||
} else if (pagination?.current) {
|
||||
fetch({
|
||||
page: pagination?.current,
|
||||
pageSize: pagination.pageSize,
|
||||
});
|
||||
}
|
||||
};
|
||||
// pagination
|
||||
const getPagination: Recordable | Boolean = computed(() => {
|
||||
const { pagination } = props;
|
||||
if (pagination) {
|
||||
const current = get(dataRef.value, props.pageField);
|
||||
return {
|
||||
showQuickJumper: true,
|
||||
showLessItems: true,
|
||||
showSizeChanger: true,
|
||||
showTotal: (total: number, range: Array<number>) =>
|
||||
`显示第${range[0]}到${range[1]}条记录 ,共 ${total} 条记录`,
|
||||
...(pagination as Props),
|
||||
total: get(dataRef.value, props.totalField),
|
||||
current: (current >= 0 ? current : 0) + props.pageFieldOffset, // 后端0 开始
|
||||
pageSize: get(dataRef.value, props.sizeField),
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const getTableBindValues = computed(() => {
|
||||
const { params, dynamicParams } = props;
|
||||
return {
|
||||
...attrs,
|
||||
...props,
|
||||
params: dynamicParams
|
||||
? getParams({ ...route.params, ...route.query }, dynamicParams, params)
|
||||
: params || {},
|
||||
pagination: getPagination.value,
|
||||
onChange: tableChangeEvent,
|
||||
};
|
||||
});
|
||||
|
||||
watch(
|
||||
() => getTableBindValues.value.api,
|
||||
() => {
|
||||
fetch();
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
|
||||
function fetch(requestParams: RequestParams = {}, clearDelay = true) {
|
||||
clearDelay && delayFetch();
|
||||
const { api, pagination } = props;
|
||||
const { page, pageSize } = requestParams;
|
||||
if (api) {
|
||||
let pageParams: Recordable = {};
|
||||
|
||||
if (pagination !== false) {
|
||||
pageParams = {
|
||||
[props.paramsPageField]: page ? page - props.pageFieldOffset : defaultPageRef.value, // 后端0 开始
|
||||
[props.paramsPageSizeField]:
|
||||
pageSize || getPagination.value?.pageSize || props.defaultPageSize,
|
||||
};
|
||||
} else {
|
||||
pageParams = {
|
||||
[props.paramsPageField]: defaultPageRef.value, // 后端0 开始
|
||||
[props.paramsPageSizeField]:
|
||||
pageSize || getPagination.value?.pageSize || props.defaultPageSize,
|
||||
};
|
||||
}
|
||||
const httpParams = {
|
||||
...getTableBindValues.value.params,
|
||||
...pageParams,
|
||||
...formParamsRef.value,
|
||||
...treeParamsRef.value,
|
||||
...orderRef.value,
|
||||
|
||||
};
|
||||
|
||||
setTableSession(pageParams[props.paramsPageField]);
|
||||
|
||||
clearDelay && setLoading(true);
|
||||
|
||||
const requestConfig: AxiosRequestConfig = { method: 'get' };
|
||||
const { httpRequest } = useApi();
|
||||
httpRequest({
|
||||
api,
|
||||
params: httpParams,
|
||||
pathParams: { ...route.params, ...route.query },
|
||||
requestConfig,
|
||||
}).then((res: any) => {
|
||||
|
||||
tableState.loadError = false;
|
||||
tableState.loadErrorMessage = '';
|
||||
dataRef.value = res;
|
||||
tableData.value = get(unref(dataRef), props.listField);
|
||||
emit('update:dataSource', tableData.value);
|
||||
clearDelay && setLoading(false);
|
||||
loadingTable.value = false;
|
||||
})
|
||||
.catch((error: any) => {
|
||||
const { response, code, message } = error || {};
|
||||
let errMessage = response?.data?.msg;
|
||||
const err: string = error?.toString?.() ?? '';
|
||||
if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
|
||||
errMessage = '接口请求超时,请刷新页面重试!';
|
||||
}
|
||||
if (err?.includes('Network Error')) {
|
||||
errMessage = '网络异常,请检查您的网络连接是否正常!';
|
||||
}
|
||||
tableState.loadError = true;
|
||||
tableState.loadErrorMessage = errMessage;
|
||||
clearDelay && setLoading(false);
|
||||
loadingTable.value = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setLoading(loading: boolean) {
|
||||
tableState.loading = loading;
|
||||
}
|
||||
|
||||
|
||||
// 右侧树形结构
|
||||
const treeData = ref( []);
|
||||
// 树形结构添加
|
||||
let typeSchema = ref([]);
|
||||
const getTypeSchema = (mode) => {
|
||||
let schema = [
|
||||
{
|
||||
field: 'alias',
|
||||
component: 'NsInput',
|
||||
label: '类别名称',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'change',
|
||||
validator: async (rule, value) => {
|
||||
if (!value) {
|
||||
return Promise.reject('类别名称不能为空');
|
||||
}
|
||||
if (!/^[a-zA-Z0-9\u4e00-\u9fa5][a-zA-Z0-9-_\u4e00-\u9fa5]{0,50}$/.test(value)) {
|
||||
return Promise.reject(
|
||||
'只能包括大小写字母、中文、数字和短横线(-)、下划线(_)。必须以字母、中文、数字开头。长度必须在1–50字符之间。'
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
trigger: 'change',
|
||||
validator: async (rule, value) => {
|
||||
if (Object.keys(typeFieldErrors.value).indexOf('alias') !== -1) {
|
||||
const errorInfo = typeFieldErrors.value['alias'];
|
||||
delete typeFieldErrors.value['alias'];
|
||||
return Promise.reject(errorInfo);
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
if (mode === 'add') {
|
||||
schema.push(
|
||||
{
|
||||
field: 'code',
|
||||
component: 'NsInput',
|
||||
label: '类别代码',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'change',
|
||||
validator: async (rule, value) => {
|
||||
if (!value) {
|
||||
return Promise.reject('类别代码不能为空');
|
||||
}
|
||||
if (!/^[a-zA-Z0-9\u4e00-\u9fa5][a-zA-Z0-9-_\u4e00-\u9fa5]{0,50}$/.test(value)) {
|
||||
return Promise.reject(
|
||||
'只能包括大小写字母、中文、数字和短横线(-)、下划线(_)。必须以字母、中文、数字开头。长度必须在1–50字符之间。'
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
trigger: 'change',
|
||||
validator: async (rule, value) => {
|
||||
if (Object.keys(typeFieldErrors.value).indexOf('code') !== -1) {
|
||||
const errorInfo = typeFieldErrors.value['code'];
|
||||
delete typeFieldErrors.value['code'];
|
||||
return Promise.reject(errorInfo);
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
} else if (mode === 'edit') {
|
||||
schema.push(
|
||||
{
|
||||
field: 'code',
|
||||
component: 'NsInputText',
|
||||
label: '类别代码',
|
||||
})
|
||||
}
|
||||
return schema || [];
|
||||
}
|
||||
const typeData = ref({});
|
||||
let modalVisible = ref(false);
|
||||
let modalOperation = ref({
|
||||
title: '添加类别',
|
||||
key: 'add'
|
||||
});
|
||||
// 搜索
|
||||
const formElRef = ref(null);
|
||||
const getFormConfig = computed(() => {
|
||||
const formConfig = cloneDeep(props.formConfig);
|
||||
if (formConfig) {
|
||||
formConfig.showAction = false;
|
||||
if (!isArray(formConfig.schemas)) {
|
||||
formConfig.schemas = [];
|
||||
}
|
||||
if (formConfig.keySearch !== false) {
|
||||
formConfig.schemas.push({
|
||||
field: 'alias',
|
||||
label: '关键字',
|
||||
component: 'NsInputSearch',
|
||||
rules: [
|
||||
{
|
||||
message: '请输入关键字',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
componentProps: {
|
||||
maxlength: 50,
|
||||
onSearch: () => {
|
||||
unref(formElRef)?.triggerSubmit()
|
||||
// unref(nsTableRef)?.formElRef?.triggerSubmit();
|
||||
},
|
||||
onKeydown: (event) => {
|
||||
//fix 单个input回车会提交表单 造成重复提交
|
||||
if (event.key === 'Enter' || event.code === 'Enter') {
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
placeholder: '请输入关键字',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
return formConfig;
|
||||
});
|
||||
// 卡片列表分页信息
|
||||
function onTreeSelect(selectedKeys: never[],
|
||||
e: {
|
||||
selected: boolean;
|
||||
selectedNodes: { props: { dataRef: any } }[];
|
||||
node: any;
|
||||
event: any;
|
||||
})
|
||||
{
|
||||
allSelected.value = false;
|
||||
const dataRef = e.selectedNodes[0];
|
||||
treeParamsRef.value = getParams(dataRef, {typeClassCode: 'code'});
|
||||
unref(formElRef)?.triggerSubmit();
|
||||
let key = 'typeClassCode';
|
||||
if (e.selected) {
|
||||
formModel.value[key] = treeParamsRef.value[key];
|
||||
} else {
|
||||
updateFormModel();
|
||||
}
|
||||
}
|
||||
function reload(clearDelay = true) {
|
||||
const pagination = unref(getPagination);
|
||||
fetch(
|
||||
{
|
||||
page: pagination === false ? 1 : pagination.current,
|
||||
},
|
||||
clearDelay,
|
||||
);
|
||||
}
|
||||
const updateFormModel = function (value?:any) {
|
||||
const key = 'typeClassCode';
|
||||
const model: object = formModel.value;
|
||||
if (value) {
|
||||
if (Object.keys(model).includes(key) && model[key] === value) {
|
||||
delete model[key];
|
||||
}
|
||||
} else if (Object.keys(model).includes(key)){
|
||||
delete model[key];
|
||||
}
|
||||
}
|
||||
return {
|
||||
tableState,
|
||||
getTitle,
|
||||
treeData,
|
||||
expandedKeys,
|
||||
formModel,
|
||||
formFinish,
|
||||
tableData,
|
||||
typeSchema,
|
||||
typeData,
|
||||
modalVisible,
|
||||
modalOperation,
|
||||
typeFieldErrors,
|
||||
getTypeSchema,
|
||||
formConfig: getFormConfig.value,
|
||||
nsTableRef,
|
||||
formElRef,
|
||||
getParams,
|
||||
onTreeSelect,
|
||||
|
||||
onChange: tableChangeEvent,
|
||||
allSelected,
|
||||
selectedKeys,
|
||||
treeParamsRef,
|
||||
loadingTable,
|
||||
loadingTree,
|
||||
imgSrc,
|
||||
getTableBindValues,
|
||||
getPagination,
|
||||
authMap,
|
||||
updateFormModel,
|
||||
setTableSession
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getDataTree()
|
||||
},
|
||||
methods: {
|
||||
onCLickCard(item) {
|
||||
this.$router.push(item['code'] + '/detail' );
|
||||
},
|
||||
// 转换树结构数据
|
||||
transferTree(data) {
|
||||
if( isArray(data) && data.length > 0) {
|
||||
data.forEach(it=>{
|
||||
it['title'] = it['alias'];
|
||||
it['key']=it['code'];
|
||||
if(it['children'] ) {
|
||||
this.transferTree(it['children']);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
getDataTree() {
|
||||
http.get(`/api/${APP}/objs/ResourceTypeClasses`).then(res => {
|
||||
this.transferTree(res)
|
||||
this.treeData = res;
|
||||
|
||||
this.loadingTree = false;
|
||||
}).catch( err => {
|
||||
this.loadingTree = false;
|
||||
})
|
||||
},
|
||||
onAllSelect() {
|
||||
this.allSelected = !this.allSelected;
|
||||
this.selectedKeys = [];
|
||||
this.treeParamsRef = null;
|
||||
this.updateFormModel();
|
||||
this.formElRef.triggerSubmit();
|
||||
},
|
||||
// onExpand(keys) {
|
||||
// this.expandedKeys = keys;
|
||||
// },
|
||||
onContextMenuClick(treeKey, menuKey, data) {
|
||||
this.modalOperation.key = menuKey
|
||||
if (menuKey === 'add') {
|
||||
this.modalOperation.title = '添加类别';
|
||||
this.modalVisible = true;
|
||||
this.typeData['parentID'] = data?.id || null;
|
||||
this.typeSchema = this.getTypeSchema('add')
|
||||
}
|
||||
if (menuKey === 'edit') {
|
||||
this.modalOperation.title = '编辑类别';
|
||||
this.modalVisible = true;
|
||||
this.typeData = {
|
||||
alias: data['title'],
|
||||
code: data['code'],
|
||||
id: data['id'],
|
||||
parentID: data['parentID']
|
||||
}
|
||||
this.typeSchema = [
|
||||
{
|
||||
field: 'alias',
|
||||
component: 'NsInput',
|
||||
label: '类别名称',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
trigger: 'change',
|
||||
validator: async (rule, value) => {
|
||||
if (!value) {
|
||||
return Promise.reject('类别名称不能为空');
|
||||
}
|
||||
if (!/^[a-zA-Z0-9\u4e00-\u9fa5][a-zA-Z0-9-_\u4e00-\u9fa5]{0,50}$/.test(value)) {
|
||||
return Promise.reject(
|
||||
'只能包括大小写字母、中文、数字和短横线(-)、下划线(_)。必须以字母、中文、数字开头。长度必须在1–50字符之间。'
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
field: 'code',
|
||||
component: 'NsInputText',
|
||||
label: '类别代码'
|
||||
},
|
||||
{
|
||||
field: 'parentID',
|
||||
label: '类别',
|
||||
component: 'NsSelectTreeApi',
|
||||
componentProps: {
|
||||
showCheckedStrategy: 'TreeSelect.SHOW_ALL',
|
||||
selectType: 'tree',
|
||||
api: `/api/${APP}/objs/ResourceTypeClasses`,
|
||||
labelField: 'alias',
|
||||
valueField: 'id',
|
||||
resultField: '',
|
||||
immediate: true,
|
||||
placeholder: '请选择类型',
|
||||
allowClear: true,
|
||||
unSelectable: {
|
||||
level: -1,
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
if (menuKey === 'remove') {
|
||||
const thisObj = this;
|
||||
NsModal.confirm(
|
||||
{
|
||||
title: '警告',
|
||||
content: `确定要删除该项吗?\n删除后不可恢复,请谨慎操作!`,
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk() {
|
||||
http.delete(`/api/${APP}/objs/ResourceTypeClasses`, {id: data['id']}).then(() => {
|
||||
NsMessage.success('删除成功');
|
||||
if (data['code']) {
|
||||
thisObj.updateFormModel( data['code']);
|
||||
thisObj.setTableSession(thisObj.getPagination.current);
|
||||
}
|
||||
thisObj.getDataTree();
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
handleArgumentError(data) {
|
||||
const error = data?.response?.data;
|
||||
if(error && error['errType'] === 'ArgumentError') {
|
||||
this.typeFieldErrors = error['fieldErrors'];
|
||||
this.$refs.configRef.triggerSubmit();
|
||||
}
|
||||
},
|
||||
addType() {
|
||||
http.post(`/api/${APP}/objs/ResourceTypeClasses`, this.typeData).then((res) => {
|
||||
NsMessage.success('操作成功');
|
||||
this.getDataTree();
|
||||
this.typeData = {};
|
||||
this.modalVisible = false;
|
||||
}).catch((e)=>{
|
||||
this.handleArgumentError(e)
|
||||
})
|
||||
},
|
||||
editType() {
|
||||
if (Object.keys(this.typeData).includes('parentID')) {
|
||||
this.typeData['parentID'] = 0;
|
||||
}
|
||||
http.put(`/api/${APP}/objs/ResourceTypeClasses`, this.typeData).then((res) => {
|
||||
NsMessage.success('操作成功');
|
||||
this.getDataTree();
|
||||
this.typeData = {};
|
||||
this.modalVisible = false;
|
||||
}).catch((e)=>{
|
||||
this.handleArgumentError(e)
|
||||
})
|
||||
},
|
||||
removeType() {
|
||||
console.log(this.typeData)
|
||||
},
|
||||
handleOk() {
|
||||
if (['add'].includes(this.modalOperation.key)) {
|
||||
this.$refs.configRef.triggerSubmit().then(() => {
|
||||
this.addType();
|
||||
});
|
||||
}
|
||||
if (['edit'].includes(this.modalOperation.key)) {
|
||||
this.$refs.configRef.triggerSubmit().then(() => {
|
||||
this.editType();
|
||||
});
|
||||
}
|
||||
if (['remove'].includes(this.modalOperation.key)) {
|
||||
this.removeType();
|
||||
}
|
||||
},
|
||||
cancel() {
|
||||
this.typeData = {};
|
||||
this.modalVisible = false;
|
||||
this.typeFieldErrors = {};
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ns-table-main {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
:deep(.ns-table-header) {
|
||||
min-width: unset;
|
||||
.ant-btn {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ns-table-wrapper {
|
||||
margin: 0 24px;
|
||||
}
|
||||
|
||||
:deep(.ns-table-search .ns-form-item label) {
|
||||
display: none;
|
||||
}
|
||||
.type-tree-wrapper {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
border-right: 1px solid rgba(0, 0, 0, 0.08);
|
||||
height: 800px;
|
||||
overflow-y: auto;
|
||||
|
||||
.tree-top-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
margin-bottom: 4px;
|
||||
.tree-node-content-wrapper {
|
||||
padding: 0 4px;
|
||||
line-height: 30px;
|
||||
&.selected {
|
||||
background-color: rgba(0, 172, 255, 0.1);
|
||||
color: #00acff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-tree ) {
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
|
||||
.ant-tree-node-content-wrapper.ant-tree-node-selected {
|
||||
background-color: rgba(0, 172, 255, 0.1);
|
||||
color: #00acff
|
||||
}
|
||||
}
|
||||
|
||||
// 卡片列表
|
||||
.section0 {
|
||||
height: 100%;
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
.iconRed {
|
||||
color: #EB5757;
|
||||
}
|
||||
.iconGreen {
|
||||
color: #0DCB70;
|
||||
}
|
||||
.font-12 {
|
||||
font-size: 12px;
|
||||
}
|
||||
margin: 0 6px 0 24px;
|
||||
|
||||
.section-content {
|
||||
.item {
|
||||
width: 24%;
|
||||
//border: 1px solid #dedede;
|
||||
margin-right: 8px;
|
||||
display: inline-block;
|
||||
margin-bottom: 10px;
|
||||
cursor: pointer;
|
||||
//transition: box-shadow 400ms;
|
||||
//box-shadow: none;s
|
||||
|
||||
transition-property: box-shadow, border;
|
||||
transition-duration: 400ms, 400ms;
|
||||
|
||||
|
||||
border: 1px solid #F1F3F5;
|
||||
box-shadow: 0 0 16px rgba(0, 0, 0, 0.09);
|
||||
border-radius: 6px;
|
||||
|
||||
&:hover {
|
||||
//box-shadow: 0 2px 12px rgba(0, 172, 255, .7);
|
||||
border: 1px solid #6DCFFF;
|
||||
box-shadow: 0 0 16px rgba(0, 172, 255, 0.3);
|
||||
}
|
||||
|
||||
.item-header {
|
||||
background-color: inherit;
|
||||
display: flex;
|
||||
height: auto;
|
||||
padding: 10px 14px 0 14px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
//border-bottom: .05rem solid #dedede;
|
||||
.info-card-header {
|
||||
flex: 1;
|
||||
height: 32px;
|
||||
max-height: 32px;
|
||||
overflow: hidden;
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
overflow-x: hidden;
|
||||
overflow-y: hidden;
|
||||
text-overflow: ellipsis
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info-item-block {
|
||||
height: 90px;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
//border-bottom: .05rem solid #dedede;
|
||||
padding: 4px 14px;
|
||||
display: flex;
|
||||
|
||||
.card-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
//width: 54px;
|
||||
max-height: 88px;
|
||||
img {
|
||||
width: 64px;
|
||||
max-height: 88px;
|
||||
}
|
||||
}
|
||||
|
||||
.card-description-wrapper {
|
||||
display: grid;
|
||||
height: 88px;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
.card-description {
|
||||
max-height: 88px;
|
||||
padding-left: 6px;
|
||||
|
||||
span {
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-footer {
|
||||
padding: 10px 14px;
|
||||
background-color: #fafbfe;
|
||||
border-bottom-left-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
|
||||
.card-item-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
|
||||
.card-footer-left {
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 6px;
|
||||
}
|
||||
// 无数据
|
||||
.ant-empty-description {
|
||||
color: #bfbfbf;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user