943 lines
29 KiB
Vue
943 lines
29 KiB
Vue
<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>
|