Table.js 8.32 KB
import template from "./Table.html";
import style from "antd/lib/table/style/index.css";
angular.module("esNgAntd").directive("antdTable", function (esNgAntd) {
    return {
        controllerAs: "antdTable",
        restrict: "E",
        transclude: true,
        replace: true,
        scope: {
            columns: "=",
            dSource: "=",
            rowSelection: "=",
            rowKey: "@",
            loading: "@",
            onChange: "&",
            size: "@",
        },
        template: template,
        controller: function ($scope, $element, $attrs) {
            this.getContext = function () {
                return $scope;
            };

            $scope.state = {
                size: $scope.size || "default",
                dataSource: [],
                selectedrecordKeys: [],
                selectedrecords: [],
                isSelectAll: false,
                rowKey: $scope.rowKey || "id",
                sortDirections: ["ascend", "descend"],
                sorter: {
                    field: null,
                    order: null,
                },
            };
            $scope.watch = {
                dSource: (newValue) => {
                    if (newValue !== undefined) {
                        let dataSource = [];
                        newValue.forEach((record, index) => {
                            let row = {};

                            if ($scope.rowSelection) {
                                row.checked = false;
                                row.disabled = false;
                            }

                            if (
                                $scope.rowSelection &&
                                typeof $scope.rowSelection.getCheckboxProps ===
                                    "function"
                            ) {
                                let extraAttr =
                                    $scope.rowSelection.getCheckboxProps(
                                        record
                                    );
                                row = Object.assign(row, extraAttr);
                            }

                            $scope.columns.forEach((column) => {
                                // 排序
                                if (column.sortOrder) {
                                    $scope.state.sorter.field = column.key;
                                    $scope.state.sorter.order =
                                        column.sortOrder;
                                }

                                row[column.key] = column.render
                                    ? $scope.getRender(column, record, index)
                                    : record[column.key];
                            }); // 主键

                            if ($scope.rowKey !== undefined) {
                                row[$scope.state.rowKey] =
                                    record[$scope.state.rowKey];
                            } else {
                                row[$scope.state.rowKey] = index + 1;
                            }

                            dataSource[index] = row;
                        });
                        $scope.state.dataSource = dataSource;
                    }
                },
                "rowSelection.selectedRowKeys": (newVal) => {
                    if (Array.isArray(newVal)) {
                        if (newVal.length > 0) {
                            $scope.state.dataSource.map(function (row, key) {
                                if (newVal.includes(key)) {
                                    row.checked = true;
                                }
                            });
                        } else {
                            $scope.state.dataSource.map(function (row) {
                                row.checked = false;
                            });
                        }
                    }
                },
            };

            for (const key in $scope.watch) {
                $scope.$watch(key, $scope.watch[key], true);
            }

            $scope.getParameterName = function (fn) {
                if (typeof fn !== "object" && typeof fn !== "function") return;
                const COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
                const DEFAULT_PARAMS = /=[^,)]+/gm;
                const FAT_ARROWS = /=>.*$/gm;
                let code = fn.prototype
                    ? fn.prototype.constructor.toString()
                    : fn.toString();
                code = code
                    .replace(COMMENTS, "")
                    .replace(FAT_ARROWS, "")
                    .replace(DEFAULT_PARAMS, "");
                let result = code
                    .slice(code.indexOf("(") + 1, code.indexOf(")"))
                    .match(/([^\s,]+)/g);
                return result === null ? [] : result;
            };

            $scope.getRender = function (column, record, index) {
                let params = $scope.getParameterName(column.render);
                return column
                    .render(record[column.key], record, index)
                    .replace(
                        new RegExp(`(\{\{.*?)${params[0]}(.*?\}\})`, "g"),
                        `$1dataSource[${index}].${column.key}$2`
                    )
                    .replace(
                        new RegExp(`(\{\{.*?)${params[1]}(.*?\}\})`, "g"),
                        `$1dataSource[${index}]$2`
                    )
                    .replace(
                        new RegExp(`(\{\{.*?)${params[2]}(.*?\}\})`, "g"),
                        `$1${index}$2`
                    );
            };

            $scope.handleSelectAll = function (event) {
                $scope.state.isSelectAll = event.target.checked;
                $scope.state.selectedrecordKeys = [];
                $scope.state.selectedrecords = [];
                $scope.state.dataSource.map((record, key) => {
                    if (record.disabled === false) {
                        record.checked = event.target.checked;
                    }

                    if (record.checked) {
                        $scope.state.selectedrecordKeys.push(key);
                        $scope.state.selectedrecords.push($scope.dSource[key]);
                    }

                    return record;
                });

                if (typeof $scope.rowSelection.onChange === "function") {
                    $scope.rowSelection.onChange(
                        $scope.state.selectedrecordKeys,
                        $scope.state.selectedrecords
                    );
                }
            };

            $scope.handleSelect = function (event, index) {
                let pos = $scope.state.selectedrecordKeys.findIndex(
                    (value) => value === index
                );

                if (event.target.checked && pos === -1) {
                    $scope.state.selectedrecordKeys.push(index);
                    $scope.state.selectedrecords.push($scope.dSource[index]);
                } else {
                    $scope.state.selectedrecordKeys.splice(pos, 1);
                    $scope.state.selectedrecords.splice(pos, 1);
                }

                if ($scope.state.selectedrecordKeys.length === 0) {
                    $scope.state.isSelectAll = false;
                }

                if (typeof $scope.rowSelection.onChange === "function") {
                    $scope.rowSelection.onChange(
                        $scope.state.selectedrecordKeys,
                        $scope.state.selectedrecords
                    );
                }
            };

            $scope.handleSorter = function (key) {
                $scope.state.sorter.field = key;

                if ($scope.state.sorter.order === null) {
                    $scope.state.sorter.order = "ascend";
                } else if ($scope.state.sorter.order === "ascend") {
                    $scope.state.sorter.order = "descend";
                } else if ($scope.state.sorter.order === "descend") {
                    $scope.state.sorter.order = null;
                    $scope.state.sorter.field = null;
                }

                $scope.onChange({
                    sorter: $scope.state.sorter,
                });
            };
        },
        link: function ($scope, $element, $attrs, $controllers, $transclude) {
            esNgAntd.createStyle("ant-table", style);
        },
    };
});