Junjie
4 天以前 8bfe1168a42d4e3750a15b0c0fb0a7629d6cf91c
src/main/webapp/static/js/config/config.js
@@ -850,6 +850,186 @@
        return result;
    }
    fieldMeta = [
        {
            field: 'id',
            columnName: 'id',
            label: 'ID',
            tableProp: 'id',
            exportField: 'id',
            kind: 'text',
            valueType: 'number',
            required: true,
            primaryKey: true,
            searchable: false,
            sortable: true,
            textarea: false,
            minWidth: 90,
            enumOptions: [],
            foreignQuery: '',
            checkboxActiveRaw: '1',
            checkboxInactiveRaw: '0'
        },
        {
            field: 'name',
            columnName: 'name',
            label: '名称',
            tableProp: 'name',
            exportField: 'name',
            kind: 'text',
            valueType: 'string',
            required: true,
            primaryKey: false,
            searchable: false,
            sortable: false,
            textarea: false,
            minWidth: 180,
            dialogSpan: 12,
            enumOptions: [],
            foreignQuery: '',
            checkboxActiveRaw: 'Y',
            checkboxInactiveRaw: 'N'
        },
        {
            field: 'code',
            columnName: 'code',
            label: '编码',
            tableProp: 'code',
            exportField: 'code',
            kind: 'text',
            valueType: 'string',
            required: true,
            primaryKey: false,
            searchable: true,
            sortable: false,
            textarea: false,
            minWidth: 180,
            dialogSpan: 12,
            enumOptions: [],
            foreignQuery: '',
            checkboxActiveRaw: 'Y',
            checkboxInactiveRaw: 'N'
        },
        {
            field: 'value',
            columnName: 'value',
            label: '对应值',
            tableProp: 'value',
            exportField: 'value',
            kind: 'text',
            valueType: 'string',
            required: true,
            primaryKey: false,
            searchable: false,
            sortable: false,
            textarea: false,
            minWidth: 220,
            dialogSpan: 24,
            enumOptions: [],
            foreignQuery: '',
            checkboxActiveRaw: 'Y',
            checkboxInactiveRaw: 'N'
        },
        {
            field: 'type',
            columnName: 'type',
            label: '类型',
            tableProp: 'type$',
            exportField: 'type$',
            kind: 'enum',
            valueType: 'number',
            required: true,
            primaryKey: false,
            searchable: false,
            sortable: false,
            textarea: false,
            minWidth: 120,
            dialogSpan: 12,
            enumOptions: [
                { rawValue: '1', label: 'String' },
                { rawValue: '2', label: 'JSON' }
            ],
            foreignQuery: '',
            checkboxActiveRaw: '1',
            checkboxInactiveRaw: '0'
        },
        {
            field: 'status',
            columnName: 'status',
            label: '状态',
            tableProp: 'status$',
            exportField: 'status$',
            kind: 'enum',
            valueType: 'number',
            required: true,
            primaryKey: false,
            searchable: false,
            sortable: false,
            textarea: false,
            minWidth: 120,
            dialogSpan: 12,
            enumOptions: [
                { rawValue: '1', label: '正常' },
                { rawValue: '0', label: '禁用' }
            ],
            foreignQuery: '',
            checkboxActiveRaw: '1',
            checkboxInactiveRaw: '0'
        },
        {
            field: 'selectType',
            columnName: 'select_type',
            label: '筛选类型',
            tableProp: 'selectType',
            exportField: 'selectType',
            kind: 'text',
            valueType: 'string',
            required: false,
            primaryKey: false,
            searchable: true,
            sortable: false,
            textarea: false,
            minWidth: 140,
            dialogSpan: 24,
            suggestInput: true,
            enumOptions: [],
            foreignQuery: '',
            checkboxActiveRaw: 'Y',
            checkboxInactiveRaw: 'N'
        }
    ];
    function applySelectTypeOptions(options) {
        var normalizedOptions = [];
        (options || []).forEach(function (item) {
            var rawValue = '';
            var label = '';
            if (item && typeof item === 'object') {
                rawValue = item.value !== undefined ? item.value : (item.rawValue !== undefined ? item.rawValue : (item.label !== undefined ? item.label : ''));
                label = item.label !== undefined ? item.label : rawValue;
            } else {
                rawValue = item;
                label = item;
            }
            rawValue = isEmptyValue(rawValue) ? '' : String(rawValue);
            label = isEmptyValue(label) ? rawValue : String(label);
            if (!rawValue) {
                return;
            }
            normalizedOptions.push({
                rawValue: rawValue,
                label: label
            });
        });
        fieldMeta.forEach(function (field) {
            if (field.field !== 'selectType') {
                return;
            }
            field.kind = 'enum';
            field.enumOptions = normalizedOptions;
        });
    }
    function isEmptyValue(value) {
        return value === null || value === undefined || value === '';
    }
@@ -877,11 +1057,17 @@
    }
    function isSearchableField(field) {
        return !!field && field.kind !== 'image' && !field.textarea;
        return !!field && field.searchable !== false && field.kind !== 'image' && !field.textarea;
    }
    function isSortableField(field) {
        if (!field) {
            return false;
        }
        if (field.sortable === true) {
            return true;
        }
        if (field.sortable === false) {
            return false;
        }
        if (field.primaryKey) {
@@ -903,6 +1089,9 @@
    function defaultSearchFieldValue(field) {
        if (field.kind === 'date') {
            return [];
        }
        if (field.kind === 'enum' && field.suggestInput) {
            return '';
        }
        if (field.kind === 'enum' || field.kind === 'checkbox') {
            return null;
@@ -960,13 +1149,14 @@
    function createFormRules() {
        var rules = {};
        fieldMeta.forEach(function (field) {
            var useInputRule = field.kind === 'enum' && field.suggestInput;
            if (field.primaryKey || !field.required) {
                return;
            }
            rules[field.field] = [{
                required: true,
                message: (field.kind === 'date' || field.kind === 'enum' ? '请选择' : '请输入') + field.label,
                trigger: (field.kind === 'date' || field.kind === 'enum') ? 'change' : 'blur'
                message: (field.kind === 'date' || (field.kind === 'enum' && !useInputRule) ? '请选择' : '请输入') + field.label,
                trigger: (field.kind === 'date' || (field.kind === 'enum' && !useInputRule)) ? 'change' : 'blur'
            }];
        });
        return rules;
@@ -1141,6 +1331,12 @@
                self.fetchForeignSuggestions(field, queryString, callback);
            };
        },
        getEnumSuggestionFetcher: function (field) {
            var self = this;
            return function (queryString, callback) {
                self.fetchEnumSuggestions(field, queryString, callback);
            };
        },
        fetchForeignSuggestions: function (field, queryString, callback) {
            if (!field.foreignQuery || !queryString) {
                callback([]);
@@ -1171,6 +1367,27 @@
                    callback([]);
                }
            });
        },
        fetchEnumSuggestions: function (field, queryString, callback) {
            var keyword = String(queryString || '').toLowerCase();
            var result = [];
            var seen = {};
            (field && field.enumOptions ? field.enumOptions : []).forEach(function (option) {
                var rawValue = option && option.rawValue !== undefined ? String(option.rawValue) : '';
                var label = option && option.label !== undefined ? String(option.label) : rawValue;
                var haystack = (label + ' ' + rawValue).toLowerCase();
                if (keyword && haystack.indexOf(keyword) === -1) {
                    return;
                }
                if (!rawValue || seen[rawValue]) {
                    return;
                }
                seen[rawValue] = true;
                result.push({
                    value: rawValue
                });
            });
            callback(result);
        },
        handleForeignSelect: function (field, item) {
            this.$set(this.displayTarget, field.field, item && item.value ? item.value : '');
@@ -1217,11 +1434,34 @@
                        mode: 'create',
                        submitting: false
                    },
                    tableHeight: 420,
                    layoutTimer: null,
                    tableResizeHandler: null,
                    grantTimer: null,
                    dialogForm: createFormDefaults(),
                    dialogDisplay: createDisplayDefaults(),
                    dialogRules: createFormRules()
                    dialogRules: createFormRules(),
                    grantStatus: {
                        granted: false,
                        remainingSeconds: 0,
                        expireAt: null
                    },
                    grantDialog: {
                        visible: false,
                        submitting: false,
                        form: {
                            account: '',
                            password: ''
                        },
                        rules: {
                            account: [
                                { required: true, message: '请输入管理员账号', trigger: 'blur' }
                            ],
                            password: [
                                { required: true, message: '请输入密码', trigger: 'blur' }
                            ]
                        }
                    }
                };
            },
            computed: {
@@ -1270,20 +1510,26 @@
                        };
                    });
                },
                tableHeight: function () {
                    return this.advancedFiltersVisible && this.hasAdvancedFilters
                        ? 'calc(100vh - 390px)'
                        : 'calc(100vh - 300px)';
                },
                formTarget: function () {
                    return this.dialogForm;
                },
                displayTarget: function () {
                    return this.dialogDisplay;
                },
                isDialogReadonly: function () {
                    return this.dialog.mode === 'detail';
                },
                grantStatusText: function () {
                    if (!this.grantStatus.granted) {
                        return '当前无最高权限授权';
                    }
                    return '剩余 ' + this.formatRemainingSeconds(this.grantStatus.remainingSeconds);
                }
            },
            created: function () {
                this.fetchSelectTypeOptions();
                this.loadTable();
                this.loadGrantStatus();
            },
            mounted: function () {
                var self = this;
@@ -1302,14 +1548,155 @@
                    window.removeEventListener('resize', this.tableResizeHandler);
                    this.tableResizeHandler = null;
                }
                this.stopGrantCountdown();
            },
            methods: $.extend({}, sharedMethods, {
                formatRemainingSeconds: function (seconds) {
                    var total = Number(seconds || 0);
                    var minutes;
                    var remainSeconds;
                    if (total <= 0) {
                        return '0秒';
                    }
                    minutes = Math.floor(total / 60);
                    remainSeconds = total % 60;
                    if (minutes <= 0) {
                        return remainSeconds + '秒';
                    }
                    if (remainSeconds === 0) {
                        return minutes + '分钟';
                    }
                    return minutes + '分' + remainSeconds + '秒';
                },
                stopGrantCountdown: function () {
                    if (this.grantTimer) {
                        clearInterval(this.grantTimer);
                        this.grantTimer = null;
                    }
                },
                startGrantCountdown: function () {
                    var self = this;
                    self.stopGrantCountdown();
                    if (!self.grantStatus.granted || Number(self.grantStatus.remainingSeconds) <= 0) {
                        return;
                    }
                    self.grantTimer = setInterval(function () {
                        if (!self.grantStatus.granted) {
                            self.stopGrantCountdown();
                            return;
                        }
                        if (self.grantStatus.remainingSeconds <= 1) {
                            self.grantStatus = {
                                granted: false,
                                remainingSeconds: 0,
                                expireAt: null
                            };
                            self.stopGrantCountdown();
                            return;
                        }
                        self.grantStatus.remainingSeconds -= 1;
                    }, 1000);
                },
                applyGrantStatus: function (payload) {
                    var status = payload || {};
                    this.grantStatus = {
                        granted: !!status.granted,
                        remainingSeconds: Number(status.remainingSeconds || 0),
                        expireAt: status.expireAt || null
                    };
                    this.startGrantCountdown();
                },
                loadGrantStatus: function () {
                    var self = this;
                    $.ajax({
                        url: baseUrl + '/highPrivilege/status/auth',
                        method: 'GET',
                        headers: self.authHeaders(),
                        success: function (res) {
                            if (self.handleForbidden(res)) {
                                return;
                            }
                            if (!res || res.code !== 200) {
                                return;
                            }
                            self.applyGrantStatus(res.data || {});
                        }
                    });
                },
                resetGrantDialog: function () {
                    this.grantDialog.submitting = false;
                    this.grantDialog.form = {
                        account: '',
                        password: ''
                    };
                    if (this.$refs.grantForm) {
                        this.$refs.grantForm.clearValidate();
                    }
                },
                openGrantDialog: function () {
                    this.grantDialog.visible = true;
                    this.$nextTick(this.resetGrantDialog);
                },
                submitGrant: function () {
                    var self = this;
                    if (!self.$refs.grantForm) {
                        return;
                    }
                    self.$refs.grantForm.validate(function (valid) {
                        if (!valid) {
                            return false;
                        }
                        self.grantDialog.submitting = true;
                        $.ajax({
                            url: baseUrl + '/highPrivilege/grant/auth',
                            method: 'POST',
                            contentType: 'application/json;charset=UTF-8',
                            headers: self.authHeaders(),
                            data: JSON.stringify({
                                account: self.grantDialog.form.account,
                                password: hex_md5(self.grantDialog.form.password || '')
                            }),
                            success: function (res) {
                                self.grantDialog.submitting = false;
                                if (self.handleForbidden(res)) {
                                    return;
                                }
                                if (!res || res.code !== 200) {
                                    self.$message.error((res && res.msg) ? res.msg : '授权失败');
                                    return;
                                }
                                self.$message.success('授权成功');
                                self.grantDialog.visible = false;
                                self.applyGrantStatus(res.data || {});
                            },
                            error: function () {
                                self.grantDialog.submitting = false;
                                self.$message.error('授权失败');
                            }
                        });
                        return true;
                    });
                },
                calculateTableHeight: function () {
                    var viewportHeight = window.innerHeight || document.documentElement.clientHeight || 860;
                    var tableWrap = this.$refs.tableWrap;
                    var pagerBar = this.$refs.pagerBar;
                    if (!tableWrap) {
                        this.tableHeight = Math.max(360, viewportHeight - (this.advancedFiltersVisible ? 360 : 300));
                        return;
                    }
                    var tableTop = tableWrap.getBoundingClientRect().top;
                    var pagerHeight = pagerBar ? pagerBar.offsetHeight : 56;
                    var bottomGap = 56;
                    this.tableHeight = Math.max(320, Math.floor(viewportHeight - tableTop - pagerHeight - bottomGap));
                },
                requestTableLayout: function (delay) {
                    var self = this;
                    if (self.layoutTimer) {
                        clearTimeout(self.layoutTimer);
                    }
                    self.$nextTick(function () {
                        self.calculateTableHeight();
                        self.layoutTimer = setTimeout(function () {
                            var table = self.$refs.dataTable;
                            if (table && typeof table.doLayout === 'function') {
@@ -1416,6 +1803,27 @@
                        }
                    });
                },
                fetchSelectTypeOptions: function () {
                    var self = this;
                    $.ajax({
                        url: baseUrl + '/config/getSelectTypes',
                        method: 'POST',
                        headers: self.authHeaders(),
                        success: function (res) {
                            if (self.handleForbidden(res)) {
                                return;
                            }
                            if (!res || res.code !== 200) {
                                return;
                            }
                            applySelectTypeOptions(Array.isArray(res.data) ? res.data : []);
                            self.fieldMeta = fieldMeta.slice();
                            self.allColumns = fieldMeta.slice();
                            self.dialogRules = createFormRules();
                            self.requestTableLayout(80);
                        }
                    });
                },
                handleSearch: function () {
                    this.page.curr = 1;
                    this.loadTable();
@@ -1475,8 +1883,23 @@
                        }
                    });
                },
                openDetailDialog: function (row) {
                    var self = this;
                    self.dialog.mode = 'detail';
                    self.dialog.visible = true;
                    self.$nextTick(function () {
                        self.resetDialogState();
                        fillFormFromRow(row, self.dialogForm, self.dialogDisplay);
                        if (self.$refs.dialogForm) {
                            self.$refs.dialogForm.clearValidate();
                        }
                    });
                },
                submitDialog: function () {
                    var self = this;
                    if (self.dialog.mode === 'detail') {
                        return;
                    }
                    if (!self.$refs.dialogForm) {
                        return;
                    }
@@ -1589,6 +2012,30 @@
                            self.$message.error('导出失败');
                        }
                    });
                },
                refreshCache: function () {
                    var self = this;
                    self.$confirm('确定刷新Redis缓存吗?', '提示', { type: 'warning' }).then(function () {
                        $.ajax({
                            url: baseUrl + '/config/refreshCache',
                            method: 'POST',
                            headers: self.authHeaders(),
                            success: function (res) {
                                if (self.handleForbidden(res)) {
                                    return;
                                }
                                if (!res || res.code !== 200) {
                                    self.$message.error((res && res.msg) ? res.msg : '刷新缓存失败');
                                    return;
                                }
                                self.$message.success('刷新缓存成功');
                                self.loadTable();
                            },
                            error: function () {
                                self.$message.error('刷新缓存失败');
                            }
                        });
                    }).catch(function () {});
                }
            })
        });