diff --git a/.github/ISSUE_TEMPLATE/feaure_request.yml b/.github/ISSUE_TEMPLATE/feaure_request.yml index 34d0f3eb4..479a5c2b1 100644 --- a/.github/ISSUE_TEMPLATE/feaure_request.yml +++ b/.github/ISSUE_TEMPLATE/feaure_request.yml @@ -1,7 +1,7 @@ name: Feature Request description: Request a new feature from @VisActor/vtable title: '[Feature] ' -labels: [feature] +labels: [new-feature] body: - type: markdown attributes: diff --git a/.github/labeler.yml b/.github/labeler.yml index 35d17c2fd..c9436b693 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,15 +1,7 @@ -# Add 'vtable' label to any change within the 'vtable' package -vtable: +# Add 'core' label to any change within the 'core' package +core: - packages/vtable/** -# Add 'react-vtable' label to any change within the 'react-vtable' package -react-vtable: - - packages/react-vtable/** - -# Add 'openinula-vtable' label to any change within the 'openinula-vtable' package -openinula-vtable: - - packages/openinula-vtable/** - # Add 'test' label to any change to packages/*/__tests__/* files within the source dir test: - packages/*/__tests__/* @@ -42,5 +34,3 @@ bundler: # Add 'chore' label to any change to common/** files within the source dir chore: - common/** - - .github/** - - .vscode/** diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml index a3ab94f2b..888105186 100644 --- a/.github/workflows/label.yml +++ b/.github/workflows/label.yml @@ -16,6 +16,6 @@ jobs: pull-requests: write steps: - - uses: actions/labeler@v4 + - uses: actions/labeler@master with: repo-token: '${{ secrets.GITHUB_TOKEN }}' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index befd5255b..d44e24042 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,228 +1,72 @@ -# Contribution Guide +# Contributing -Firstly, I applaud your decision to join the ranks of open source contributors👍🏻. Moreover, we're very thankful you chose to participate in the VisActor community and contribute to this open-source project. +## Code of Conduct -## VTable Contribution Guide +We has adopted [the Contributor Covenant](CODE_OF_CONDUCT.md) as our Code of Conduct, and we expect project participants to adhere to it. Please read the full text so that you can understand what actions will and will not be tolerated. -VisActor team usually develops and maintains issues on github. Please open [Github website](https://github.com/), click the `Sign up` button in the upper right corner, and register an account to start your first step in the open source journey. +## Open Development -If you can't open the Github site for some reason, you can also develop the project through [Gitee](https://gitee.com/VisActor/VTable). +All work on VTable happens directly on GitHub. Both core team members and external contributors send pull requests which go through the same review process. -In the [VTable repository](https://github.com/VisActor/VTable), we have a [guide](https://github.com/VisActor/VTable/blob/develop/CONTRIBUTING.zh-CN.md) for all open source contributors, which introduces version management, branch management, and other content. **Please take a few minutes to read and understand it**. +## Semantic Versioning -## Your First PullRequest +VTable follows [semantic versioning](https://semver.org/). We release patch versions for critical bugfixes, minor versions for new features or non-essential changes, and major versions for any breaking changes. When we make breaking changes, we also introduce deprecation warnings in a minor version so that our users learn about the upcoming changes and migrate their code in advance. -### Step1: Install Git +Every significant change is documented in the changelog file. -Git is a version control system used to track and manage code changes in software development projects. It helps developers record and manage code history, facilitate team collaboration, code version control, merge code, and more. With Git, you can track every version of every file and easily switch and compare between different versions. Git also provides branch management capabilities, allowing for multiple parallel development tasks to be performed simultaneously. +## Release Schedule -- Visit the Git official website: -- Download the latest version of Git installer. -- Run the downloaded installer and follow the prompts in the installation wizard. -- After installation, you can use the `git version` command through the command line to confirm successful installation. +todo -
- -
+## Branch Organization -### Step2: Fork the project +Submit all changes directly to the main branch. We don’t use separate branches for development or for upcoming releases. We do our best to keep main in good shape, with all tests passing. -- You need to fork this project first, go to the [VTable project page](https://github.com/VisActor/VTable), and click the Fork button in the upper right corner +Code that lands in main must be compatible with the latest stable release. It may contain additional features, but no breaking changes. We should be able to release a new minor version from the tip of main at any time. -
- -
+## Bugs -- You will find the project "xxxx(your github username)/VTable" in your github account. -- On your local computer, use the following command to get a "VTable" folder. +We are using [GitHub Issues](todo) for our public bugs. We keep a close eye on this and try to make it clear when we have an internal fix in progress. Before filing a new task, try to make sure your problem doesn’t already exist. -``` -// ssh -git clone git@github.com:xxxx(your github user name)/VTable.git -// https -git clone https://github.com/xxxx(your github user name)/VTable.git -``` +We have already prepared issue templates for bug reports and feature requests. If you want to fire an issue, just enter the [New issue](todo) page and select either of them to get started. The best way to get your bug fixed is by using our issue template and provide reproduction steps with this [template](todo). -### Step3: Get the Project Code +## Proposing a Change -- Enter the VTable folder and add the remote address of VTable +If you intend to change the public API, or make any non-trivial changes to the implementation, we recommend filing an issue, or just enter the [New issue](todo) page and select either of them to get started. -``` -git remote add upstram https://github.com/VisActor/VTable.git -``` +If you’re only fixing a bug, it’s fine to submit a pull request right away but we still recommend to file an issue detailing what you’re fixing. This is helpful in case we don’t accept that specific fix but want to keep track of the issue. -- Get the latest source code of VTable +## Your First Pull Request -``` -git pull upstram develop -``` +Working on your first Pull Request? You can learn how from this free video series:[How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github) -### Step4: Create a Branch +To help you get your feet wet and get you familiar with our contribution process, we have a list of [good first issues](todo) that contain bugs that have a relatively limited scope. This is a great place to get started. -- Okay, now we can start contributing our code. The default branch of VTable is the develop branch. Whether it is for feature development, bug fixes, or documentation writing, please create a new branch and merge it into the develop branch. Use the following code to create a branch: +If you decide to fix an issue, please be sure to check the comment thread in case somebody is already working on a fix. If nobody is working on it at the moment, please leave a comment stating that you intend to work on it so other people don’t accidentally duplicate your effort. -``` -// Create a feature development branch -git checkout -b feat/xxxx +If somebody claims an issue but doesn’t follow up for more than two weeks, it’s fine to take it over but you should still leave a comment. -// Create a development branch for issue fixing -git checkout -b fix/xxxx +### Sending a Pull Request -// Create document, demo branch -git checkout -b docs/add-funnel-demo -``` +The core team is monitoring for pull requests. We will review your pull request and either merge it, request changes to it, or close it with an explanation. We’ll do our best to provide updates and feedback throughout the process. -- Now we can make changes to the code on the branch. -- Let's say we've added some code and committed it to the repository. -- `git commit -a -m "docs: add custom funnel demo and related docs"`. The commit message for VisActor follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification: +**Before submitting a pull request**, please make sure the following is done: - - `[optional scope]: `. - - Common `type` include docs (documentation, log changes), feat (new features), fix (bug fixes), refactor (code refactoring), etc. Please choose according to the actual situation. - - Please write the description in English with short and accurate descriptions. - - Before committing, we will perform commit lint checks. For details, see [inspection rules](https://github.com/VisActor/VTable/blob/develop/common/autoinstallers/lint/commitlint.config.js). +1. Fork the [repository](todo) and create your branch from `main`. +2. (If rush has been install, just go to step 3) global install [@microsoft/rush](https://rushjs.io/pages/intro/get_started/):`npm i --global @microsoft/rush`. +3. Run `rush update --full` in the repository root. +4. If you’ve fixed a bug or added code that should be tested, add tests! +5. Ensure the test suite passes (`rush test`). Tip: `rush test -- --watch TestName` is helpful in development. +6. Make sure your code lints (`rush lint`). Tip: Lint runs automatically when you git commit (Use Git Hooks). +7. Run `rush compile` for typecheck. -### Step5: Merge and Modify +## Development Workflow -- A common problem is that the remote upstram (@visactor/VTable) has been updated with new commits, which can cause conflicts when we submit a Pull Request. Therefore, we can merge the commits from other developers on the remote repository with our commits before submitting. To switch to the develop branch, use the following code: +After cloning VTable, run `rush update --full` to fetch its dependencies. Then, you can run several commands: -``` -git checkout develop -``` +1. `rush start` runs VTable test page locally. +2. `rush eslint` checks the code style. +3. `rush test` runs the complete test suite. +4. `rush run -p -s - ``` ## Introducing VTable @@ -38,9 +35,9 @@ Use at the top of a JavaScript file `import` Introducing VTable: ```js import * as VTable from '@visactor/vtable'; -or; +or -import { ListTable, PivotTable, TYPES, themes } from '@visactor/vtable'; +import {ListTable, PivotTable, TYPES, themes} from '@visactor/vtable'; ``` ### Import using script tags @@ -50,7 +47,7 @@ By adding directly in the HTML file ` ``` @@ -67,319 +64,320 @@ Before drawing we need to prepare a DOM container with height and width for VCha Next, we create a `Vtable.ListTable` Example, pass in the table configuration item: ```javascript livedemo template=vtable + const records = [ - { - 230517143221027: 'CA-2018-156720', - 230517143221030: 'JM-15580', - 230517143221032: 'Bagged Rubber Bands', - 230517143221023: 'Office Supplies', - 230517143221034: 'Fasteners', - 230517143221037: 'West', - 230517143221024: 'Loveland', - 230517143221029: '2018-12-30', - 230517143221042: '3', - 230517143221040: '3.024', - 230517143221041: '-0.605' +{ + "230517143221027": "CA-2018-156720", + "230517143221030": "JM-15580", + "230517143221032": "Bagged Rubber Bands", + "230517143221023": "Office Supplies", + "230517143221034": "Fasteners", + "230517143221037": "West", + "230517143221024": "Loveland", + "230517143221029": "2018-12-30", + "230517143221042": "3", + "230517143221040": "3.024", + "230517143221041": "-0.605" }, { - 230517143221027: 'CA-2018-115427', - 230517143221030: 'EB-13975', - 230517143221032: 'GBC Binding covers', - 230517143221023: 'Office Supplies', - 230517143221034: 'Binders', - 230517143221037: 'West', - 230517143221024: 'Fairfield', - 230517143221029: '2018-12-30', - 230517143221042: '2', - 230517143221040: '20.72', - 230517143221041: '6.475' + "230517143221027": "CA-2018-115427", + "230517143221030": "EB-13975", + "230517143221032": "GBC Binding covers", + "230517143221023": "Office Supplies", + "230517143221034": "Binders", + "230517143221037": "West", + "230517143221024": "Fairfield", + "230517143221029": "2018-12-30", + "230517143221042": "2", + "230517143221040": "20.72", + "230517143221041": "6.475" }, { - 230517143221027: 'CA-2018-115427', - 230517143221030: 'EB-13975', - 230517143221032: 'Cardinal Slant-D Ring Binder, Heavy Gauge Vinyl', - 230517143221023: 'Office Supplies', - 230517143221034: 'Binders', - 230517143221037: 'West', - 230517143221024: 'Fairfield', - 230517143221029: '2018-12-30', - 230517143221042: '2', - 230517143221040: '13.904', - 230517143221041: '4.519' + "230517143221027": "CA-2018-115427", + "230517143221030": "EB-13975", + "230517143221032": "Cardinal Slant-D Ring Binder, Heavy Gauge Vinyl", + "230517143221023": "Office Supplies", + "230517143221034": "Binders", + "230517143221037": "West", + "230517143221024": "Fairfield", + "230517143221029": "2018-12-30", + "230517143221042": "2", + "230517143221040": "13.904", + "230517143221041": "4.519" }, { - 230517143221027: 'CA-2018-143259', - 230517143221030: 'PO-18865', - 230517143221032: 'Wilson Jones Legal Size Ring Binders', - 230517143221023: 'Office Supplies', - 230517143221034: 'Binders', - 230517143221037: 'East', - 230517143221024: 'New York City', - 230517143221029: '2018-12-30', - 230517143221042: '3', - 230517143221040: '52.776', - 230517143221041: '19.791' + "230517143221027": "CA-2018-143259", + "230517143221030": "PO-18865", + "230517143221032": "Wilson Jones Legal Size Ring Binders", + "230517143221023": "Office Supplies", + "230517143221034": "Binders", + "230517143221037": "East", + "230517143221024": "New York City", + "230517143221029": "2018-12-30", + "230517143221042": "3", + "230517143221040": "52.776", + "230517143221041": "19.791" }, { - 230517143221027: 'CA-2018-143259', - 230517143221030: 'PO-18865', - 230517143221032: 'Gear Head AU3700S Headset', - 230517143221023: 'Technology', - 230517143221034: 'Phones', - 230517143221037: 'East', - 230517143221024: 'New York City', - 230517143221029: '2018-12-30', - 230517143221042: '7', - 230517143221040: '90.93', - 230517143221041: '2.728' + "230517143221027": "CA-2018-143259", + "230517143221030": "PO-18865", + "230517143221032": "Gear Head AU3700S Headset", + "230517143221023": "Technology", + "230517143221034": "Phones", + "230517143221037": "East", + "230517143221024": "New York City", + "230517143221029": "2018-12-30", + "230517143221042": "7", + "230517143221040": "90.93", + "230517143221041": "2.728" }, { - 230517143221027: 'CA-2018-143259', - 230517143221030: 'PO-18865', - 230517143221032: 'Bush Westfield Collection Bookcases, Fully Assembled', - 230517143221023: 'Furniture', - 230517143221034: 'Bookcases', - 230517143221037: 'East', - 230517143221024: 'New York City', - 230517143221029: '2018-12-30', - 230517143221042: '4', - 230517143221040: '323.136', - 230517143221041: '12.118' + "230517143221027": "CA-2018-143259", + "230517143221030": "PO-18865", + "230517143221032": "Bush Westfield Collection Bookcases, Fully Assembled", + "230517143221023": "Furniture", + "230517143221034": "Bookcases", + "230517143221037": "East", + "230517143221024": "New York City", + "230517143221029": "2018-12-30", + "230517143221042": "4", + "230517143221040": "323.136", + "230517143221041": "12.118" }, { - 230517143221027: 'CA-2018-126221', - 230517143221030: 'CC-12430', - 230517143221032: 'Eureka The Boss Plus 12-Amp Hard Box Upright Vacuum, Red', - 230517143221023: 'Office Supplies', - 230517143221034: 'Appliances', - 230517143221037: 'Central', - 230517143221024: 'Columbus', - 230517143221029: '2018-12-30', - 230517143221042: '2', - 230517143221040: '209.3', - 230517143221041: '56.511' + "230517143221027": "CA-2018-126221", + "230517143221030": "CC-12430", + "230517143221032": "Eureka The Boss Plus 12-Amp Hard Box Upright Vacuum, Red", + "230517143221023": "Office Supplies", + "230517143221034": "Appliances", + "230517143221037": "Central", + "230517143221024": "Columbus", + "230517143221029": "2018-12-30", + "230517143221042": "2", + "230517143221040": "209.3", + "230517143221041": "56.511" }, { - 230517143221027: 'US-2018-158526', - 230517143221030: 'KH-16360', - 230517143221032: 'Harbour Creations Steel Folding Chair', - 230517143221023: 'Furniture', - 230517143221034: 'Chairs', - 230517143221037: 'South', - 230517143221024: 'Louisville', - 230517143221029: '2018-12-29', - 230517143221042: '3', - 230517143221040: '258.75', - 230517143221041: '77.625' + "230517143221027": "US-2018-158526", + "230517143221030": "KH-16360", + "230517143221032": "Harbour Creations Steel Folding Chair", + "230517143221023": "Furniture", + "230517143221034": "Chairs", + "230517143221037": "South", + "230517143221024": "Louisville", + "230517143221029": "2018-12-29", + "230517143221042": "3", + "230517143221040": "258.75", + "230517143221041": "77.625" }, { - 230517143221027: 'US-2018-158526', - 230517143221030: 'KH-16360', - 230517143221032: 'Global Leather and Oak Executive Chair, Black', - 230517143221023: 'Furniture', - 230517143221034: 'Chairs', - 230517143221037: 'South', - 230517143221024: 'Louisville', - 230517143221029: '2018-12-29', - 230517143221042: '1', - 230517143221040: '300.98', - 230517143221041: '87.284' + "230517143221027": "US-2018-158526", + "230517143221030": "KH-16360", + "230517143221032": "Global Leather and Oak Executive Chair, Black", + "230517143221023": "Furniture", + "230517143221034": "Chairs", + "230517143221037": "South", + "230517143221024": "Louisville", + "230517143221029": "2018-12-29", + "230517143221042": "1", + "230517143221040": "300.98", + "230517143221041": "87.284" }, { - 230517143221027: 'US-2018-158526', - 230517143221030: 'KH-16360', - 230517143221032: 'Panasonic KP-350BK Electric Pencil Sharpener with Auto Stop', - 230517143221023: 'Office Supplies', - 230517143221034: 'Art', - 230517143221037: 'South', - 230517143221024: 'Louisville', - 230517143221029: '2018-12-29', - 230517143221042: '1', - 230517143221040: '34.58', - 230517143221041: '10.028' + "230517143221027": "US-2018-158526", + "230517143221030": "KH-16360", + "230517143221032": "Panasonic KP-350BK Electric Pencil Sharpener with Auto Stop", + "230517143221023": "Office Supplies", + "230517143221034": "Art", + "230517143221037": "South", + "230517143221024": "Louisville", + "230517143221029": "2018-12-29", + "230517143221042": "1", + "230517143221040": "34.58", + "230517143221041": "10.028" }, { - 230517143221027: 'US-2018-158526', - 230517143221030: 'KH-16360', - 230517143221032: 'GBC ProClick Spines for 32-Hole Punch', - 230517143221023: 'Office Supplies', - 230517143221034: 'Binders', - 230517143221037: 'South', - 230517143221024: 'Louisville', - 230517143221029: '2018-12-29', - 230517143221042: '1', - 230517143221040: '12.53', - 230517143221041: '5.889' + "230517143221027": "US-2018-158526", + "230517143221030": "KH-16360", + "230517143221032": "GBC ProClick Spines for 32-Hole Punch", + "230517143221023": "Office Supplies", + "230517143221034": "Binders", + "230517143221037": "South", + "230517143221024": "Louisville", + "230517143221029": "2018-12-29", + "230517143221042": "1", + "230517143221040": "12.53", + "230517143221041": "5.889" }, { - 230517143221027: 'US-2018-158526', - 230517143221030: 'KH-16360', - 230517143221032: 'DMI Arturo Collection Mission-style Design Wood Chair', - 230517143221023: 'Furniture', - 230517143221034: 'Chairs', - 230517143221037: 'South', - 230517143221024: 'Louisville', - 230517143221029: '2018-12-29', - 230517143221042: '8', - 230517143221040: '1207.84', - 230517143221041: '314.038' + "230517143221027": "US-2018-158526", + "230517143221030": "KH-16360", + "230517143221032": "DMI Arturo Collection Mission-style Design Wood Chair", + "230517143221023": "Furniture", + "230517143221034": "Chairs", + "230517143221037": "South", + "230517143221024": "Louisville", + "230517143221029": "2018-12-29", + "230517143221042": "8", + "230517143221040": "1207.84", + "230517143221041": "314.038" }, { - 230517143221027: 'CA-2018-130631', - 230517143221030: 'BS-11755', - 230517143221032: 'Hand-Finished Solid Wood Document Frame', - 230517143221023: 'Furniture', - 230517143221034: 'Furnishings', - 230517143221037: 'West', - 230517143221024: 'Edmonds', - 230517143221029: '2018-12-29', - 230517143221042: '2', - 230517143221040: '68.46', - 230517143221041: '20.538' + "230517143221027": "CA-2018-130631", + "230517143221030": "BS-11755", + "230517143221032": "Hand-Finished Solid Wood Document Frame", + "230517143221023": "Furniture", + "230517143221034": "Furnishings", + "230517143221037": "West", + "230517143221024": "Edmonds", + "230517143221029": "2018-12-29", + "230517143221042": "2", + "230517143221040": "68.46", + "230517143221041": "20.538" }, { - 230517143221027: 'CA-2018-130631', - 230517143221030: 'BS-11755', - 230517143221032: 'Acco Glide Clips', - 230517143221023: 'Office Supplies', - 230517143221034: 'Fasteners', - 230517143221037: 'West', - 230517143221024: 'Edmonds', - 230517143221029: '2018-12-29', - 230517143221042: '5', - 230517143221040: '19.6', - 230517143221041: '9.604' + "230517143221027": "CA-2018-130631", + "230517143221030": "BS-11755", + "230517143221032": "Acco Glide Clips", + "230517143221023": "Office Supplies", + "230517143221034": "Fasteners", + "230517143221037": "West", + "230517143221024": "Edmonds", + "230517143221029": "2018-12-29", + "230517143221042": "5", + "230517143221040": "19.6", + "230517143221041": "9.604" }, { - 230517143221027: 'CA-2018-146626', - 230517143221030: 'BP-11185', - 230517143221032: 'Nu-Dell Executive Frame', - 230517143221023: 'Furniture', - 230517143221034: 'Furnishings', - 230517143221037: 'West', - 230517143221024: 'Anaheim', - 230517143221029: '2018-12-29', - 230517143221042: '8', - 230517143221040: '101.12', - 230517143221041: '37.414' + "230517143221027": "CA-2018-146626", + "230517143221030": "BP-11185", + "230517143221032": "Nu-Dell Executive Frame", + "230517143221023": "Furniture", + "230517143221034": "Furnishings", + "230517143221037": "West", + "230517143221024": "Anaheim", + "230517143221029": "2018-12-29", + "230517143221042": "8", + "230517143221040": "101.12", + "230517143221041": "37.414" }, { - 230517143221027: 'CA-2018-158673', - 230517143221030: 'KB-16600', - 230517143221032: 'Xerox 1915', - 230517143221023: 'Office Supplies', - 230517143221034: 'Paper', - 230517143221037: 'Central', - 230517143221024: 'Grand Rapids', - 230517143221029: '2018-12-29', - 230517143221042: '2', - 230517143221040: '209.7', - 230517143221041: '100.656' + "230517143221027": "CA-2018-158673", + "230517143221030": "KB-16600", + "230517143221032": "Xerox 1915", + "230517143221023": "Office Supplies", + "230517143221034": "Paper", + "230517143221037": "Central", + "230517143221024": "Grand Rapids", + "230517143221029": "2018-12-29", + "230517143221042": "2", + "230517143221040": "209.7", + "230517143221041": "100.656" }, { - 230517143221027: 'US-2018-102638', - 230517143221030: 'MC-17845', - 230517143221032: 'Ideal Clamps', - 230517143221023: 'Office Supplies', - 230517143221034: 'Fasteners', - 230517143221037: 'East', - 230517143221024: 'New York City', - 230517143221029: '2018-12-29', - 230517143221042: '3', - 230517143221040: '6.03', - 230517143221041: '2.955' + "230517143221027": "US-2018-102638", + "230517143221030": "MC-17845", + "230517143221032": "Ideal Clamps", + "230517143221023": "Office Supplies", + "230517143221034": "Fasteners", + "230517143221037": "East", + "230517143221024": "New York City", + "230517143221029": "2018-12-29", + "230517143221042": "3", + "230517143221040": "6.03", + "230517143221041": "2.955" }, { - 230517143221027: 'CA-2018-118885', - 230517143221030: 'JG-15160', - 230517143221032: 'Adtran 1202752G1', - 230517143221023: 'Technology', - 230517143221034: 'Phones', - 230517143221037: 'West', - 230517143221024: 'Los Angeles', - 230517143221029: '2018-12-29', - 230517143221042: '3', - 230517143221040: '302.376', - 230517143221041: '22.678' + "230517143221027": "CA-2018-118885", + "230517143221030": "JG-15160", + "230517143221032": "Adtran 1202752G1", + "230517143221023": "Technology", + "230517143221034": "Phones", + "230517143221037": "West", + "230517143221024": "Los Angeles", + "230517143221029": "2018-12-29", + "230517143221042": "3", + "230517143221040": "302.376", + "230517143221041": "22.678" }, { - 230517143221027: 'CA-2018-118885', - 230517143221030: 'JG-15160', - 230517143221032: 'Global High-Back Leather Tilter, Burgundy', - 230517143221023: 'Furniture', - 230517143221034: 'Chairs', - 230517143221037: 'West', - 230517143221024: 'Los Angeles', - 230517143221029: '2018-12-29', - 230517143221042: '4', - 230517143221040: '393.568', - 230517143221041: '-44.276' + "230517143221027": "CA-2018-118885", + "230517143221030": "JG-15160", + "230517143221032": "Global High-Back Leather Tilter, Burgundy", + "230517143221023": "Furniture", + "230517143221034": "Chairs", + "230517143221037": "West", + "230517143221024": "Los Angeles", + "230517143221029": "2018-12-29", + "230517143221042": "4", + "230517143221040": "393.568", + "230517143221041": "-44.276" } ]; -const columns = [ - { - field: '230517143221027', - title: 'Order ID', - width: 'auto' - }, - { - field: '230517143221030', - title: 'Customer ID', - width: 'auto' - }, - { - field: '230517143221032', - title: 'Product Name', - width: 'auto' - }, - { - field: '230517143221023', - title: 'Category', - width: 'auto' - }, - { - field: '230517143221034', - title: 'Sub-Category', - width: 'auto' - }, - { - field: '230517143221037', - title: 'Region', - width: 'auto' - }, - { - field: '230517143221024', - title: 'City', - width: 'auto' - }, - { - field: '230517143221029', - title: 'Order Date', - width: 'auto' - }, - { - field: '230517143221042', - title: 'Quantity', - width: 'auto' - }, - { - field: '230517143221040', - title: 'Sales', - width: 'auto' - }, - { - field: '230517143221041', - title: 'Profit', - width: 'auto' - } +const columns =[ + { + "field": "230517143221027", + "title": "Order ID", + "width": "auto" + }, + { + "field": "230517143221030", + "title": "Customer ID", + "width": "auto" + }, + { + "field": "230517143221032", + "title": "Product Name", + "width": "auto" + }, + { + "field": "230517143221023", + "title": "Category", + "width": "auto" + }, + { + "field": "230517143221034", + "title": "Sub-Category", + "width": "auto" + }, + { + "field": "230517143221037", + "title": "Region", + "width": "auto" + }, + { + "field": "230517143221024", + "title": "City", + "width": "auto" + }, + { + "field": "230517143221029", + "title": "Order Date", + "width": "auto" + }, + { + "field": "230517143221042", + "title": "Quantity", + "width": "auto" + }, + { + "field": "230517143221040", + "title": "Sales", + "width": "auto" + }, + { + "field": "230517143221041", + "title": "Profit", + "width": "auto" + } ]; const option = { container: document.getElementById(CONTAINER_ID), records, columns, - widthMode: 'standard' + widthMode:'standard' }; // 创建 vchart 实例 diff --git a/docs/assets/guide/en/Load_on_Demand.md b/docs/assets/guide/en/Load_on_Demand.md deleted file mode 100644 index c004ec40e..000000000 --- a/docs/assets/guide/en/Load_on_Demand.md +++ /dev/null @@ -1,38 +0,0 @@ -# VTable on-demand loading - -By default, `ListTable`, `PivotTable` and `PivotChart` introduced from `@visactor/vtable` package contain all table-related components, which is a complete table component library. - -In order to meet the needs of package size optimization, VTable provides two types, `ListTableSimple` and `PivotTableSimple`, which are the most simplified lists and pivot tables, respectively. They only support text display and do not contain external components such as menus and titles. If you need some functions, you can load them on demand. The usage is as follows: - -```js -// ListTableSimple, PivotTableSimple are the simplest list and pivot table components, which do not include cell types and any components other than text -import {ListTableSimple, PivotTableSimple, registerTitle, registerTooltip} from '@visactor/vtable'; - -// Register title component -registerTitle(); - -// Register tooltip component -registerTooltip(); -``` - -## Load functions on demand - -### Functional components - -* registerAxis: axis component -* registerEmptyTip: empty prompt component -* registerLegend: legend component -* registerMenu: menu component -* registerTitle: title component -* registerTooltip: tooltip component - -### Cell type - -* registerChartCell: chart cell -* registerCheckboxCell: checkbox cell -* registerImageCell: Image cell -* registerProgressBarCell: Progress bar cell -* registerRadioCell: Radio button cell -* registerSparkLineCell: Sparkline cell -* registerTextCell: Text cell -* registerVideoCell: Video cell \ No newline at end of file diff --git a/docs/assets/guide/en/animation/appear_animation.md b/docs/assets/guide/en/animation/appear_animation.md deleted file mode 100644 index 68fd526b0..000000000 --- a/docs/assets/guide/en/animation/appear_animation.md +++ /dev/null @@ -1,19 +0,0 @@ -# Table entry animation - -VTable provides entry animation function, supports displaying the gradual entry effect when the table is initialized, and supports configuring the animation direction, duration, delay, etc. - -
- -
- -## Entry animation configuration items - -In option, `animationAppear` is the configuration item for the entry animation, and currently supports the following configurations: - -You can configure true to enable the default animation, or you can configure the animation parameters: -- `type` The type of the entry animation, currently supports `all` and `one-by-one`, and the default is `one-by-one` -- `direction` The direction of the entry animation, currently supports `row` and `column`, and the default is `row` -- `duration` The duration of a single animation, in milliseconds, for `one-by-one`, it is the duration of one animation, and the default is 500 -- `delay` The delay of the animation, in milliseconds; for `one-by-one`, it is the time difference between the two animations, for `all`, it is the delay of all animations, and the default is 0 - -For specific usage, please refer to [demo](../demo/animation/appear-animation) \ No newline at end of file diff --git a/docs/assets/guide/en/basic_function/frozen_column_row.md b/docs/assets/guide/en/basic_function/frozen_column.md similarity index 100% rename from docs/assets/guide/en/basic_function/frozen_column_row.md rename to docs/assets/guide/en/basic_function/frozen_column.md diff --git a/docs/assets/guide/en/basic_function/row_series_number.md b/docs/assets/guide/en/basic_function/row_series_number.md index 6d97c9ca0..4d237071b 100644 --- a/docs/assets/guide/en/basic_function/row_series_number.md +++ b/docs/assets/guide/en/basic_function/row_series_number.md @@ -29,8 +29,6 @@ export interface IRowSeriesNumber { // selectRangeInclude?: boolean; /** Whether the order can be dragged */ dragOrder?: boolean; - /** Whether to disable row serial number width adjustment. */ - disableColumnResize?: boolean; } ``` @@ -45,7 +43,6 @@ The specific configuration items are described as follows: - headerIcon: row number header cell icon - icon: row number body cell icon - dragOrder: Whether the row serial number order can be dragged, the default is false. If set to true, the icon at the dragging position will be displayed, and you can drag and drop on the icon to change its position. If you need to replace the icon, you can configure it yourself. Please refer to the tutorial: https://visactor.io/vtable/guide/custom_define/custom_icon for the chapter on resetting function icons. -- disableColumnResize: Whether to disable row serial number width adjustment, the default is false Other annotated configuration items will be gradually improved in the future, and anxious comrades can participate in joint construction and development. diff --git a/docs/assets/guide/en/basic_function/sort/list_sort.md b/docs/assets/guide/en/basic_function/sort.md similarity index 98% rename from docs/assets/guide/en/basic_function/sort/list_sort.md rename to docs/assets/guide/en/basic_function/sort.md index 45e7a0195..af31c5f5b 100644 --- a/docs/assets/guide/en/basic_function/sort/list_sort.md +++ b/docs/assets/guide/en/basic_function/sort.md @@ -1,9 +1,11 @@ -# ListTable sorting function +# Table sorting function In the process of data analytics, the sorting (sorting) function is very important for the organization and analysis of data. By sorting, users can quickly arrange the data they care about in front, improve the efficiency of data search and analysis, and quickly find outliers and patterns in the data. VTable provides rich sorting functions, users can easily open on demand, customize sorting rules, set initial sorting status, etc. +**Note**: This tutorial is only for the basic table ListTable. The pivot table sorting tutorial can be asynchronously accessed: https://visactor.io/vtable/guide/table_type/Pivot_table/pivot_table_dataAnalysis + ## Enable sorting To use the sorting function of VTable, you need to configure the table columns first. exist `columns` The configuration items for each column need to be set according to cellType (column type). In this tutorial, we mainly focus on sorting-related configurations. @@ -383,9 +385,8 @@ const option = { // 创建 VTable 实例 const tableInstance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); window.tableInstance = tableInstance; -let clickCount = 0; +const clickCount = 0; tableInstance.on('sort_click', args => { - clickCount++; const sortState = clickCount % 3 === 0 ? 'desc' : clickCount % 3 === 1 ? 'asc' : 'normal'; sortRecords(args.field, sortState) .then(records => { diff --git a/docs/assets/guide/en/basic_function/sort/pivot_sort.md b/docs/assets/guide/en/basic_function/sort/pivot_sort.md deleted file mode 100644 index 076285318..000000000 --- a/docs/assets/guide/en/basic_function/sort/pivot_sort.md +++ /dev/null @@ -1,323 +0,0 @@ -# Pivot table sorting function - -The sorting capability of a pivot table can be implemented in the following ways: - -1. To customize the tree structure of the pivot table header, you can pass rowTree and columnTree in to display the table according to this structure. In this case, even if sortRule is configured, it will not work. -2. Add `sort:true` in the dimension or indicator configuration to enable sorting. The sort button will be displayed and clicking the button will trigger sorting. -3. Sort by interface: Call the interface `updateSortRules` to sort. -4. Other special requirements: only display the sorting status, do not use the VTable sorting logic - -The first way to organize the table header tree structure by yourself has been mentioned when introducing the pivot table. You can refer to the tutorial: https://visactor.io/vtable/guide/table_type/Pivot_table/pivot_table_tree. - -**Note that several sorting methods should not be mixed** - -Next, we will mainly introduce the following implementation methods and precautions. - -## Configure sort to enable sorting - -### Sort by dimension value - -The sort configuration can be configured in rows or columns. In this case, the header cell displaying the dimension name will display a sort button, and clicking the button will trigger the sort. - -The following is an example of configuring sort in rows to enable sorting: - -```javascript livedemo template=vtable -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option = { - records: data, - rows: [ - { - dimensionKey: 'Category', - title: 'Category', - sort: true - }, - { - dimensionKey: 'Sub-Category', - title: 'Sub-Catogery', - sort: true - } - ], - columns: ['Region', 'Segment'], - indicators: [ - { - indicatorKey: 'Sales', - title: 'Sales' - }, - { - indicatorKey: 'Profit', - title: 'Profit' - } - ], - corner: { - titleOnDimension: 'row', - headerStyle: { - textStick: true - } - }, - defaultColWidth: 130 - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window['tableInstance'] = tableInstance; - }); -``` - -In the above code, `sort` is `true`, which means that the dimension values corresponding to the row headers can be sorted, and the cells in the corner headers will display the sort icon. - -### Sort by indicator value - -The sort configuration can be configured in indicators. At this time, the row header or column header cell displaying the indicator name will display a sort button, and clicking the button will trigger sorting. - -Here is an example of configuring sort in indicators to enable sorting: - -```javascript livedemo template=vtable -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option = { - records: data, - rows: ['Category', 'Sub-Category'], - columns: ['Region', 'Segment'], - indicators: [ - { - indicatorKey: 'Sales', - title: 'Sales', - sort: true - }, - { - indicatorKey: 'Profit', - title: 'Profit', - sort: true - } - ], - corner: { - titleOnDimension: 'row', - headerStyle: { - textStick: true - } - }, - defaultColWidth: 130 - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window['tableInstance'] = tableInstance; - }); -``` - -In the above code, `sort` is `true`, which means that sorting is supported by indicator value, and the cells in the row header or column header will display the sort icon. - -### Initialize sorting status - -Please configure data analysis dataConfig.sortRule to set the initial sorting state. - -The following example: - -```javascript livedemo template=vtable -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option = { - records: data, - rows: ['Category', 'Sub-Category'], - columns: ['Region', 'Segment'], - indicators: [ - { - indicatorKey: 'Sales', - title: 'Sales', - sort: true - }, - { - indicatorKey: 'Profit', - title: 'Profit', - sort: true - } - ], - dataConfig: { - sortRules: [ - { - sortField: 'Sub-Category', - sortByIndicator: 'Sales', - sortType: VTable.TYPES.SortType.DESC, - query: ['Central', 'Corporate'] - } - ] - }, - corner: { - titleOnDimension: 'row', - headerStyle: { - textStick: true - } - }, - defaultColWidth: 130 - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window['tableInstance'] = tableInstance; - }); -``` - -This example configures the initial sorting rule, which sorts the indicator values in descending order according to the column header dimension path of `['Central', 'Corporate', 'Sales']`. At the same time, the sorting icon in the corresponding header cell changes to the descending state icon. - -### Update sorting through the interface - -The update sorting interface of the pivot table is `updateSortRules`, which can be called to update the sorting status. - -Here is an example of updating the order through the interface: - -```javascript livedemo template=vtable -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option = { - records: data, - rows: ['Category', 'Sub-Category'], - columns: ['Region', 'Segment'], - indicators: [ - { - indicatorKey: 'Sales', - title: 'Sales', - sort: true - }, - { - indicatorKey: 'Profit', - title: 'Profit', - sort: true - } - ], - corner: { - titleOnDimension: 'row', - headerStyle: { - textStick: true - } - }, - defaultColWidth: 130 - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window['tableInstance'] = tableInstance; - tableInstance.updateSortRules([ - { - sortField: 'Sub-Category', - sortByIndicator: 'Sales', - sortType: VTable.TYPES.SortType.DESC, - query: ['Central', 'Corporate'] - } - ]); - }); -``` - -### Listen for sort icon click events - -The sort icon click event is monitored as `pivot_sort_click`. - -## Sorting by interface - -If you need to sort through the interface, you can update the sorting status by calling the `updateSortRules` interface. - -## Show only sort icons - -If there is a special setting panel in the business scenario, and there are special sorting options for users to operate, but the corresponding sorting status needs to be displayed in the table, you can configure `showSort: true` to display the sorting status. If there is a need to monitor icon clicks, you can monitor the event `pivot_sort_click`. - -At the same time, you can set pivotSortState on option to set the state of the initial sort icon. - -Let’s look at the usage example: - -```javascript livedemo template=vtable -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option = { - records: data, - rows: [ - { - dimensionKey: 'Category', - title: 'Category', - showSort: true - }, - { - dimensionKey: 'Sub-Category', - title: 'Sub-Catogery', - showSort: true - } - ], - columns: ['Region', 'Segment'], - indicators: [ - { - indicatorKey: 'Sales', - title: 'Sales', - showSort: true - }, - { - indicatorKey: 'Profit', - title: 'Profit', - showSort: true - } - ], - corner: { - titleOnDimension: 'row', - headerStyle: { - textStick: true - } - }, - pivotSortState: [ - { - dimensions: [ - { - dimensionKey: 'Category', - value: 'Furniture', - isPivotCorner: false, - indicatorKey: undefined - } - ], - order: 'desc' - }, - { - dimensions: [ - { - dimensionKey: 'Region', - value: 'Central', - isPivotCorner: false, - indicatorKey: undefined - }, - { - dimensionKey: 'Segment', - value: 'Consumer', - isPivotCorner: false, - indicatorKey: undefined - }, - { - indicatorKey: 'Sales', - value: 'Sales', - isPivotCorner: false - } - ], - order: 'asc' - } - ], - defaultColWidth: 130 - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window['tableInstance'] = tableInstance; - tableInstance.on('pivot_sort_click', e => { - console.log(e); - // 执行业务逻辑 ... - // 如果执行业务逻辑后还需要更新排序状态,可以先调用updateOption来更新配置,目前还未提供专门更新的接口 - }); - }); -``` - -In the above example, pivotSortState is configured with two sorting rules. It will display descending icons on cells with dimension path ['Furniture'] in the row header, and ascending icons on cells with dimension path ['Central', 'Consumer', 'Sales'] in the column header. - -## other - -Here I would like to emphasize again: **Do not mix several sorting methods**. For example, do not use the sortRule method when you customize the table header tree structure or configure showSort; do not use the pivotSortState configuration when you configure sort. - -In addition, the current sorting method is not very perfect, for example - -1. Configure the sorting method of `sort:true`. Sometimes you need to set a custom sorting function to execute the sorting logic -2. Missing `pivotSortState` configuration state update interface - -We will add to these later. diff --git a/docs/assets/guide/en/basic_function/update_option.md b/docs/assets/guide/en/basic_function/update_option.md index f1b653230..af546df94 100644 --- a/docs/assets/guide/en/basic_function/update_option.md +++ b/docs/assets/guide/en/basic_function/update_option.md @@ -3,17 +3,14 @@ When using the vtable component, updating configuration items is a common requirement. This tutorial will introduce three commonly used configuration item update methods and provide corresponding suggestions based on different usage scenarios. We will discuss the usage and applicable scenarios of full update, single update and batch update. ## Update all configuration items - Full update of configuration items is achieved by calling the updateOption() method. This method requires all configuration items to be provided, so it is suitable for situations where the entire configuration needs to be changed. Here is sample code: - -``` +`````` tableInstance. updateOption({ columns: [], theme: {}, ... }); -``` - +`````` Note: A full update will relayout and render the entire table. **Applicable scene:** @@ -22,12 +19,10 @@ When changes need to be made to multiple configuration items, using full updates ## Single item update configuration item -Single update configuration items are implemented by calling the corresponding interface, such as `updateTheme()`, `updateColumns()`, etc. These interfaces will automatically relayout and render the table after being called. Here is sample code: - +Single update configuration items are implemented by calling the corresponding interface, such as `updateTheme()`, `updateColumns()``, etc. These interfaces will automatically relayout and render the table after being called. Here is sample code: ``` tableInstance. updateTheme(newTheme); ``` - Note: Automatically layout and render after calling. **Applicable scene:** @@ -41,7 +36,6 @@ Batch update of configuration items is implemented through a special type of int For example `tableInstance.autoWrapText = true`, `tableInstance.theme = { bodyStyle: { color: 'red' } }`. The table will not be automatically re-rendered after these interfaces are called. You need to cooperate with the `tableInstance.renderWithRecreateCells()` method to manually re-layout and render. Here is sample code: - ``` tableInstance.theme = newThemeObj; tableInstance.widthMode = 'autoWidth'; @@ -49,7 +43,6 @@ tableInstance. heightMode = 'autoHeight; tableInstance. autoWrapText = true; tableInstance.renderWithRecreateCells(); ``` - Note: The above configuration items will not be re-layout and rendering after being updated using the assignment interface. You need to manually call the renderWithRecreateCells() method to re-layout and render the table to effectively improve the performance of the update logic. **Applicable scene:** @@ -57,7 +50,6 @@ Note: The above configuration items will not be re-layout and rendering after be When multiple configuration items need to be updated in batches, batch update can avoid multiple layouts and renderings and improve performance. ## Summarize: - This tutorial introduces three update methods for vtable component configuration items: full update, single update and batch update. Depending on different usage scenarios, choosing an appropriate update method can improve code efficiency and performance. Full update is suitable for situations where the entire configuration needs to be changed, single update is suitable for situations where a few configuration items are modified, and batch update is suitable for situations where multiple configuration items are updated in batches, which requires calling the interface to re-layout and render. -I hope this tutorial will help you understand the configuration item update of the vtable component. If you have any questions, please feel free to ask. +I hope this tutorial will help you understand the configuration item update of the vtable component. If you have any questions, please feel free to ask. \ No newline at end of file diff --git a/docs/assets/guide/en/components/tooltip.md b/docs/assets/guide/en/components/tooltip.md index 19b94f7bf..b0f0beac9 100644 --- a/docs/assets/guide/en/components/tooltip.md +++ b/docs/assets/guide/en/components/tooltip.md @@ -4,11 +4,11 @@ In table components, a tooltip is a common user interface element used to provid ## Tooltip usage scenarios -- Data interpretation and description: Data in some tables may require additional interpretation or description. Tooltip can be used to display these interpretations to help users understand the meaning, units, calculation methods or other relevant information of the data. +* Data interpretation and description: Data in some tables may require additional interpretation or description. Tooltip can be used to display these interpretations to help users understand the meaning, units, calculation methods or other relevant information of the data. -- Overflow content: When the text or data in the table exceeds the width of the cell, you can use tooltip to display the full content to prevent truncation or hide important information. +* Overflow content: When the text or data in the table exceeds the width of the cell, you can use tooltip to display the full content to prevent truncation or hide important information. -- Description of Interactive Elements: If the table contains interactive elements (such as links, buttons, or icons), Tooltip can be used to provide functional descriptions or action hints for those elements. +* Description of Interactive Elements: If the table contains interactive elements (such as links, buttons, or icons), Tooltip can be used to provide functional descriptions or action hints for those elements. ## Introduction to configuration items @@ -26,72 +26,12 @@ The configuration items are: }; } -## Tooltip prompt box style settings +## Turn on overflow content prompt -The style configuration of tooltip can be set through theme.tooltipStyle. The specific configuration is as follows: - -``` -export type TooltipStyle = { - fontFamily?: string; - fontSize?: number; - color?: string; - padding?: number[]; - bgColor?: string; - maxWidth?: number; - maxHeight?: number; -}; - -``` - -## Enable overflow content prompt - -By default, VTable enables the tooltip of overflow content: isShowOverflowTextTooltip defaults to true. If you need to delay disappearance so that the mouse can move to the tooltip content, you can configure overflowTextTooltipDisappearDelay. +VTable defaults to tooltip for overflow content: isShowOverflowTextTooltip defaults to true. ![image](https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/c0de7ff0a101bd4cb25c8170e.gif) -## Custom icon hover prompt - -For example, the configuration of the table header icon is as follows: - -``` -const tableInstance = new VTable.ListTable({ - columns: [ - { - field: 'orderID', - title: '订单编号', - headerIcon: { - type: 'svg', //指定svg格式图标,其他还支持path,image - svg: ` - - `, - width: 20, - height: 20, - name: 'filter', //定义图标的名称,在内部会作为缓存的key值 - positionType: VTable.TYPES.IconPosition.absoluteRight, // 指定位置,可以在文本的前后,或者在绝对定位在单元格的左侧右侧 - visibleTime: 'mouseenter_cell', // 显示时机, 'always' | 'mouseenter_cell' | 'click_cell' - hover: { - // 热区大小 - width: 26, - height: 26, - bgColor: 'rgba(22,44,66,0.5)' - }, - tooltip: { - style: { arrowMark: false }, - // 气泡框,按钮的的解释信息 - title: '过滤', - placement: VTable.TYPES.Placement.right, - disappearDelay: 1000, - } - } - } - ] -}); -``` - -The tooltip in headerIcon is the prompt box when the mouse hovers over the icon. At the same time, disappearDelay is configured to delay the disappearance of the pop-up box so that the mouse can move to the tooltip content. - -For detailed information about icon configuration, please refer to the tutorial: https://visactor.io/vtable/guide/custom_define/custom_icon. - ## Display tooltip custom information through the interface The interface showTooltip can actively display tooltip information, which is used as follows: (listen for cell hover events, call the interface) @@ -117,28 +57,3 @@ The interface showTooltip can actively display tooltip information, which is use Effect: ![image](https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/ffc3a9b5518762d274121ff05.gif) - -## Icon tooltip configuration - -When customizing the icon, you can display the prompt information by configuring the tooltip as follows: - -``` -VTable.register.icon('order', { - ... //其他配置 - tooltip: { - // 气泡框,按钮的的解释信息 - title:'Order ID is the unique identifier for each order', - style: { - fontSize: 14, - fontFamily: 'Arial', - padding: [10,10,10,10], - bgColor: 'black', - arrowMark: true, - color: 'white', - maxHeight: 100, - maxWidth: 200 - }, - disappearDelay: 1000 - } -}) -``` diff --git a/docs/assets/guide/en/custom_define/custom_icon.md b/docs/assets/guide/en/custom_define/custom_icon.md index 05f5f9d47..9f7fbe1e5 100644 --- a/docs/assets/guide/en/custom_define/custom_icon.md +++ b/docs/assets/guide/en/custom_define/custom_icon.md @@ -10,7 +10,7 @@ We can configure the cell icons displayed in the header and body through icon an - `icon` The icon used to configure the body cell. -The specific configuration content is an object of type `ColumnIconOption`. You can also pass a custom function to dynamically set the icon style of the cell. For the specific definition of ColumnIconOption, please refer to: https://visactor.io/vtable/option/ListTable-columns-text#icon +The specific content of the configuration is[ColumnIconOption]() Type objects can also dynamically set the icon style of the cell by passing a custom function. ### Header icon configuration example @@ -84,7 +84,7 @@ const tableInstance = new VTable.ListTable({ In this example, we configure a cell named `Avatar` Icon. The role of this icon is to display the avatar picture, and the value of the picture src is obtained from the field of the avator of records. -online demo:https://visactor.io/vtable/demo/custom-render/custom-icon +Effect picture: TODO ## How to register the icon and use it after registration @@ -192,7 +192,8 @@ VTable.register.icon('frozenCurrent', { }); ``` -The effect after replacement is as follows: https://visactor.io/vtable/demo/custom-render/custom-icon +The effect after replacement is as follows: +TODO In the same way, we can replace other functional icons. Several icons related to internal functions are built into VTable, such as sorting, fixed columns, drop-down menu icons, Expand folding icons, etc. @@ -228,6 +229,6 @@ The list of resettable internal icons is as follows: ] ``` -**At the same time, the icons registered in your own business do not need to configure `funcType`.** +At the same time, the icons registered in your own business do not need to configure `funcType`. At this point, the tutorial on how to use icons in VTable, register and replace function icons is all introduced. I hope this tutorial can help you better understand and use VTable, and create a more beautiful and practical data lake visualization table diff --git a/docs/assets/guide/en/custom_define/custom_layout.md b/docs/assets/guide/en/custom_define/custom_layout.md index 311024084..e818c1b15 100644 --- a/docs/assets/guide/en/custom_define/custom_layout.md +++ b/docs/assets/guide/en/custom_define/custom_layout.md @@ -41,7 +41,7 @@ Here is a configuration example, where VGroup, VImage, and VText are used, and f customLayout: args => { const { table, row, col, rect } = args; const { height, width } = rect ?? table.getCellRect(col, row); - const record = table.getCellOriginRecord(col, row); + const record = table.getRecordByCell(col, row); const container = ( - -

Custom subtotal total sample code

- - -Specific example: https://visactor.io/vtable/demo/data-analysis/pivot-analysis-custom-total - ### 2. Sorting rules -VTable's pivot table supports four sorting methods: natural sorting of dimension values, specified dimension value order, indicator value sorting, and custom sorting. - -For definitions, please refer to: - -[option description](../../option/PivotTable#dataConfig.sortRules) [Usage tutorial](../../guide/basic_function/sort/pivot_sort) - -The following is an example of the indicator value sorting configuration: +[option description](../../../option/PivotTable#dataConfig.sortRules) +Configuration example: ``` sortRules: [ @@ -137,8 +119,7 @@ Online demo:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-sort- ### 3. Filter rules -[option description](../../option/PivotTable#dataConfig.filterRules) - +[option description](../../../option/PivotTable#dataConfig.filterRules) Configuration example: ``` @@ -155,8 +136,7 @@ Online demo:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-filte ### 4. Aggregation method -[option description](../../option/PivotTable#dataConfig.aggregationRules) - +[option description](../../../option/PivotTable#dataConfig.aggregationRules) Configuration example: ``` @@ -188,48 +168,15 @@ Configuration example: indicatorKey: 'OrderSalesValue', //Indicator name field: 'Sales', //Indicator based on field aggregationType: VTable.TYPES.AggregationType.NONE, //don't aggregate - }, - { - indicatorKey: 'orderRecords', //Indicator name - field: 'Sales', //Indicator based on field - aggregationType: VTable.TYPES.AggregationType.RECORD, //don't aggregate. Match all the corresponding data as the value of the cell } ] ``` Online demo:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-aggregation -**Special Note:** - -1. AggregationType.NONE The usage scenario of the indicator without aggregation is mainly used to display the original data obtained according to the data record input by the user, such as: - -``` -records:[{ - region: 'Central South', - province: 'Guangxi', - year: '2016', - quarter: '2016-Q1', - sales: 'NULL', - profit: 1546 -}], -dataConfig:{ - aggregationRules:[ - { - indicatorKey: 'sales', //Indicator name - field: 'sales', //Indicator based field - aggregationType: VTable.TYPES.AggregationType.NONE, //Do not perform aggregation. Match the corresponding data to obtain the value of the corresponding field. - }] -} -``` - -The sales indicator in this record is a non-numeric value, and it is required to display `"NULL"` directly in the table cell. In this case, you can set `NONE` to require the internal aggregation logic of VTable to directly obtain the value of the sales field without aggregation. - -2. The usage scenario of AggregationType.RECORD indicator without aggregation is mainly used to match all data according to the data record passed by the user, and use it as the display data of the cell. The usage scenario is such as collecting data sets as mini-charts. For specific demo, see: https://visactor.io/vtable/demo/cell-type/pivot-sparkline - ### 5. Derive Field -[option description](../../option/PivotTable#dataConfig.derivedFieldRules) - +[option description](../../../option/PivotTable#dataConfig.derivedFieldRules) Configuration example: ``` @@ -247,34 +194,6 @@ Configuration example: Online demo:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-derivedField -### 6. Pivot table calculated fields - -[option description](../../option/PivotTable#dataConfig.calculatedFieldRules) - -Configuration example: - -``` -dataConfig: { - calculatedFieldRules:[ - { - key: 'AvgPrice', - dependIndicatorKeys: ['Quantity', 'Sales'], - calculateFun: dependValue => { - return dependValue.Sales / dependValue.Quantity; - } - } - ], -} -``` - -Configuration explanation: - -- key: The key unique identifier of the calculated field, which can be used as a new indicator and configured in indicators for display in the pivot table. -- dependIndicatorKeys: The indicators that the calculated field depends on, which can be the corresponding indicator fields in records. If the dependent indicator is not in records, it needs to be configured in aggregationRules, specifying the aggregation rules and indicatorKey to be used in dependIndicatorKeys. -- calculateFun: the calculation function of the calculated field, the function parameter is the value of the dependent indicator. - -Specific example: https://visactor.io/vtable/demo/data-analysis/pivot-analysis-calculatedField - ## Data analysis process Dependent configuration: dimensions, indicators and dataConfig. @@ -306,6 +225,8 @@ According to the above traversed structure, a dimension tree will be generated, Although multi-dimensional tables with analytical capabilities can automatically analyze the dimension values of each dimension to form a tree structure of row and column headers, and can be sorted according to `dataConfig.sortRules`, scenarios with complex business logic still expect to be able to **customize Row column header dimension value ** and order. Then these business requirement scenarios can be realized through rowTree and columnTree. +- enableDataAnalysis needs to be set to false to turn off the analysis of aggregated data within VTable. +

custom rowTree columnTree

@@ -378,7 +299,7 @@ const option = { ] }], indicators: ['sales', 'profit'], - + //enableDataAnalysis:true, corner: { titleOnDimension: 'none' }, @@ -453,6 +374,8 @@ VTable official website example: https://visactor.io/vtable/demo/table-type/pivo The complexity of the custom tree lies in the formation of the row, column and dimension trees. You can choose to use it according to the business scenario. If you have complex sorting, aggregation or paging rules, you can choose to use a custom method. +**Note: If you choose the custom tree configuration method, the data aggregation capability inside the VTable will not be enabled, that is, one of the matched data entries will be used as the cell indicator value. ** + ## Other related configurations ### Drilling up and down @@ -462,9 +385,3 @@ We only provide the display of the drill-down download button. If you need this Add the drillDown configuration item to the dimension configuration rows or columns to display the download button, listen to the icon button click event `drillmenu_click`, determine whether to drill down or roll up the dimension according to the event parameter `drillDown` or `drillUp`, determine the dimension to drill down or drill up according to the parameter `dimensionKey`, add or delete it to rows or columns, obtain the data source corresponding to the new dimension level, and call the interface `updateOption` to update the new option to the table. Specific demo: https://visactor.io/vtable/demo/data-analysis/pivot-analysis-table-drill - -## Related interfaces - -### getCellOriginRecord - -It can help to obtain the original data entry corresponding to the cell aggregate value. diff --git a/docs/assets/guide/en/edit/edit_cell.md b/docs/assets/guide/en/edit/edit_cell.md index 2ad32ea11..8839f67c8 100644 --- a/docs/assets/guide/en/edit/edit_cell.md +++ b/docs/assets/guide/en/edit/edit_cell.md @@ -6,8 +6,6 @@ When it comes to business scenarios of editing tables, the VTable library provid ## 1. Reference the editor package of VTable: -### Use the NPM package - First, make sure you have installed the VTable library and related editor packages correctly. You can install them using the following command: ```shell @@ -17,34 +15,22 @@ npm install @visactor/vtable-editors Introduce the required type of editor module into your code: ```javascript -import { DateInputEditor, InputEditor, TextareaEditor, ListEditor } from '@visactor/vtable-editors'; -``` - -### use CDN - -你还可以通过 CDN 获取构建好的 VTable-Editor 文件。 - -```html - - +import { DateInputEditor, InputEditor, ListEditor } from '@visactor/vtable-editors'; ``` ## 2. Create editor: -The VTable-ediotrs library currently provides four editor types, including text input boxes, textarea input boxes, date pickers, drop-down lists, etc. You can choose the appropriate editor according to your needs. +The VTable-ediotrs library currently provides three editor types, including text input boxes, date pickers, drop-down lists, etc. You can choose the appropriate editor according to your needs. Here is sample code to create an editor: ```javascript const inputEditor = new InputEditor(); -const textAreaEditor = new TextAreaEditor(); const dateInputEditor = new DateInputEditor(); const listEditor = new ListEditor({ values: ['Female', 'Male'] }); ``` -In the above example, we created a text input box editor (`InputEditor`), a multi-line text area editor (`TextAreaEditor`), a date picker editor (`DateInputEditor`) and a drop-down list editor (`ListEditor`). You can choose the appropriate editor type according to your actual needs. +In the above example, we created a text input box editor (`InputEditor`), a date picker editor (`DateInputEditor`) and a drop-down list editor (`ListEditor`). You can choose the appropriate editor type according to your actual needs. ## 3. Register and use the editor: @@ -54,7 +40,6 @@ Before using the editor, you need to register the editor instance into VTable: //Register editor to VTable VTable.register.editor('name-editor', inputEditor); VTable.register.editor('name-editor2', inputEditor2); -VTable.register.editor('textArea-editor', textAreaEditor); VTable.register.editor('number-editor', numberEditor); VTable.register.editor('date-editor', dateInputEditor); VTable.register.editor('list-editor', listEditor); @@ -72,7 +57,6 @@ columns: [ } }, { title: 'age', field: 'age', editor: 'number-editor' }, { title: 'gender', field: 'gender', editor: 'list-editor' }, - { title: 'address', field: 'address', editor: 'textArea-editor' }, { title: 'birthday', field: 'birthDate', editor: 'date-editor' }, ] ``` diff --git a/docs/assets/guide/en/export/excel.md b/docs/assets/guide/en/export/excel.md index b5f01addf..681942d2f 100644 --- a/docs/assets/guide/en/export/excel.md +++ b/docs/assets/guide/en/export/excel.md @@ -17,10 +17,10 @@ import { downloadExcel, exportVTableToExcel } from '@visactor/vtable-export'; const tableInstance = new VTable.ListTable(option); // donload csv file -downloadExcel(exportVTableToExcel(tableInstance, optionForExport), 'export-csv'); +downloadExcel(exportVTableToExcel(tableInstance), 'export-csv'); ``` -* `exportVTableToExcel`: Table output tool, outputs table instances as an ArrayBuffer in Excel format; option is an optional parameter, see below for configuration items +* `exportVTableToExcel`: Table output tool, outputs table instances as an ArrayBuffer in Excel format * `downloadExcel`: Download tool to download the ArrayBuffer in Excel format as a file in the browser environment * If it is a server environment, you can process the Excel format ArrayBuffer converted by `exportVTableToExcel` yourself. * The excel export function is currently being improved. Currently, it only supports the export of text-type cells, and will support more types such as sparkline in the future. @@ -40,72 +40,4 @@ Find the corresponding tool in the global variable `VTable.export` and use the s ```js const { downloadCsv, exportVTableToCsv } = VTable.export; // ...... -``` - -## Options - -### ignoreIcon - -By default, when the cell has an icon, the icon and text will be treated as an image when exporting. If you do not need to export the icon, you can set `ignoreIcon` to true, and only the text will be output. - -### formatExportOutput - -By default, when exporting, the text or image inside the exported cell will be output to Excel. If you need to customize the export content, you can set `formatExportOutput` to a function, and the return value of the function is the exported string. If the return value is `undefined`, the default export logic will be processed. - -```ts -type CellInfo = { - cellType: string; - cellValue: string; - table: IVTable; - col: number; - row: number; -}; - -type ExportVTableToExcelOptions = { - ignoreIcon?: boolean; - formatExportOutput?: (cellInfo: CellInfo) => string | undefined; -}; -``` - -```js -const excelOption = { - formatExportOutput: ({ cellType, cellValue, table, col, row }) => { - if (cellType === 'checkbox') { - return table.getCellCheckboxState(col, row) ? 'true' : 'false'; - } - } -}; -downloadExcel(await exportVTableToExcel(tableInstance, excelOption)); -``` - - -### formatExcelJSCell - -If you need to further customize the export style, you can set `formatExcelJSCell` to a function. The function parameters are cell information and ExcelJS cell objects. The function return value is the ExcelJS cell object. If `undefined` is returned, the default export logic is used. You can automatically set ExcelJS cell properties in the function. For details, please refer to https://github.com/exceljs/exceljs?tab=readme-ov-file#styles - -```ts -type CellInfo = { - cellType: string; - cellValue: string; - table: IVTable; - col: number; - row: number; -}; - -type ExportVTableToExcelOptions = { - // ...... - formatExceljsCell?: (cellInfo: CellInfo, cellInExceljs: ExcelJS.Cell) => ExcelJS.Cell; -}; -``` - -```js -const excelOption = { - formatExcelJSCell: (cellInfo, cell) => { - if (cellInfo.col === 1) { - cell.numFmt = '0.00%'; - } - return cell; - } -}; -downloadExcel(await exportVTableToExcel(tableInstance, excelOption)); -``` +``` \ No newline at end of file diff --git a/docs/assets/guide/en/interaction/scroll.md b/docs/assets/guide/en/interaction/scroll.md index cbabe40c7..c67736485 100644 --- a/docs/assets/guide/en/interaction/scroll.md +++ b/docs/assets/guide/en/interaction/scroll.md @@ -14,7 +14,6 @@ VTable provides rich scroll style configuration items, and users can customize t - scrollRailColor: Configure the color of the scrollbar track. - scrollSliderColor: Configure the color of the scroll bar slider. -- scrollSliderCornerRadius: The corner radius of the scroll bar slider - width: Configure the scroll bar width. - visible: Configure whether the scroll bar is visible, and can be configured with values: 'always' | 'scrolling' | 'none' | 'focus', which correspond to: resident display | display when scrolling | display | focus on the canvas. Default is'scrolling '. - hoverOn: Specifies whether the scroll bar is suspended on the container or independent of the container. The default is true to float on the container. diff --git a/docs/assets/guide/en/interaction/select.md b/docs/assets/guide/en/interaction/select.md index 29601f2ee..8a5ed330b 100644 --- a/docs/assets/guide/en/interaction/select.md +++ b/docs/assets/guide/en/interaction/select.md @@ -9,7 +9,6 @@ When using VTable for data analytics, individual cells can be selected with a mo As shown above, after clicking on cell (2,3), the cell is selected. Clicking on the header cell will select the entire row or column by default. If you only want to select the current cell, you can set select.headerSelectMode to 'cell'. - ## Mouse box selection In addition to clicking on a single cell, VTable also supports mouse box selection, which can select multiple cells by dragging the mouse. This feature allows the user to select multiple cells at once (Hold down ctrl or shift to make multiple selections). By default, VTable has mouse box selection turned on. @@ -19,29 +18,23 @@ In addition to clicking on a single cell, VTable also supports mouse box selecti As shown in the image above, the user selects multiple cells by dragging the mouse. ## Call interface selection - A certain business scenario, such as linkage selection with other modules, is not a manual mouse-triggered selection. The selection can be completed with the help of the interface. - ### Single cell selection Usage is as follows: - ``` // Select cells in 4 columns and 5 rows tableInstance.selectCell(4,5); ``` - ### Cell range selected Call the interface selectCells, the usage is as follows: - ``` // Two ranges in the table: from column 1, row 2 to column 4, row 2 and from column 3, row 5 to column 7, row 8 tableInstance.selectCells([{start:{col:1,row:2},end:{col:4,row:2}},{start:{col:3,row:5},end:{col:7 ,row:8}}]); ``` ### Clear current selection - call api `clearSelected`. ## Select style @@ -66,50 +59,6 @@ const = new VTable.ListTable({ As shown in the image above, the background color of the selected cell is purple. -## Select and highlight the entire row and column - -Clicking a cell may require highlighting the entire row or column, which can be achieved through the following configuration: - -``` - select: { - highlightMode: 'cross' // can be configured as 'cross' or 'row' or 'column' - } -``` - -Note: If you select multiple cells, the highlight effect will disappear. - -The highlighting style can be configured in the style. - -Global configuration: in `theme.selectionStyle`, the specific configuration method is: - -``` -theme:{ - selectionStyle:{ - inlineRowBgColor: 'rgb(160,207,245)', - inlineColumnBgColor: 'rgb(160,207,245)' - } -} -``` - -You can also configure headerStyle and bodyStyle separately. The specific configuration method is: - -``` -theme:{ - headerStyle: { - select: { - inlineRowBgColor: 'rgb(0,207,245)', - inlineColumnBgColor: 'rgb(0,207,245)' - } - }, - bodyStyle: { - select: { - inlineRowBgColor: 'rgb(0,207,245)', - inlineColumnBgColor: 'rgb(0,207,245)' - } - } -} -``` - ## Choose to copy cell contents VTable provides a copy shortcut function, users can set `keyboardOptions.copySelected` for `true`, to enable the shortcut copy function: @@ -130,13 +79,9 @@ There is an event called `copy_data` in conjunction with copying content. This e When operating on table data, the user may want to shortcut all the contents of the table. The Open Select All function allows the user to select all the contents of the table at once by holding down the Ctrl key and pressing the A key. It should be noted that this function is turned off by default, and the Select All function is turned on with the following configuration: -``` keyboardOptions: { - selectAllOnCtrlA?: boolean | SelectAllOnCtrlAOption; + selectAllOnCtrlA: false; } -``` - -If you do not want to select the table header or row number column at the same time, you can configure it according to `SelectAllOnCtrlAOption`. ## Disable Select Interaction diff --git a/docs/assets/guide/en/shortcut.md b/docs/assets/guide/en/shortcut.md index e46e7bbcc..e255b76d8 100644 --- a/docs/assets/guide/en/shortcut.md +++ b/docs/assets/guide/en/shortcut.md @@ -28,7 +28,7 @@ keyboardOptions: { /** The up, down, left and right direction keys are not enabled by default, which is false. If this configuration is turned on, if you are currently editing a cell, the arrow keys can move to the next cell and enter the editing state, instead of moving the cursor to edit the string within the text */ moveEditCellOnArrowKeys?: boolean; /** Enable shortcut key selection. Default: false */ - selectAllOnCtrlA?: boolean | SelectAllOnCtrlAOption; + selectAllOnCtrlA?: boolean; /** Shortcut key copy, default false, not enabled*/ copySelected?: boolean; //This copy is consistent with the browser’s shortcut keys /** Shortcut key to paste. Paste content to the specified location (that is, it needs to be selected). Batch paste is supported. Default: false */ diff --git a/docs/assets/guide/en/table_type/Pivot_table/custom_header.md b/docs/assets/guide/en/table_type/Pivot_table/custom_header.md index 433af3981..f8f9bda2a 100644 --- a/docs/assets/guide/en/table_type/Pivot_table/custom_header.md +++ b/docs/assets/guide/en/table_type/Pivot_table/custom_header.md @@ -80,6 +80,7 @@ const option = { } ], indicators: ['sales', 'profit'], + //enableDataAnalysis:true, corner: { titleOnDimension: 'none' }, @@ -158,81 +159,4 @@ The complexity of custom trees lies in the formation of row and column dimension If rowHierarchyType is set to tree and you expect to load lazily when you click to expand the node, you also need to use a pivot table with a custom header. For the specific demo, please refer to: https://visactor.io/vtable/demo/table-type/pivot-table-tree-lazy-load. -# Virtual header node - -In some scenarios of pivot table analysis, the table structure and data to be displayed do not match perfectly. For example, the pivot table may only have row dimensions and indicator values. When there are many fields for indicator values, you want to group the indicators by customizing column headers. In fact, the column headers are virtual, and the data records are not associated with corresponding dimension fields, and the number of levels is uncertain. - -Based on this scenario, VTable provides the function of virtual header node, through which the headers on the column can be grouped. For a specific example, see: URL_ADDRESS. - -Just add `virtual: true` when configuring the nodes in rowTree columnTree. - -like: - -``` -rowTree: [ - { - dimensionKey: 'Segment-1', - value: 'Segment-1 (virtual-node)', - virtual: true, - children: [ - { - indicatorKey: 'Quantity', - value: 'Quantity' - }, - { - indicatorKey: 'Sales', - value: 'Sales' - }, - { - indicatorKey: 'Profit', - value: 'Profit' - } - ] - } -], -``` - -Specific demo: https://visactor.io/vtable/demo/table-type/pivot-table-virtual-header - -# Custom tree completion indicator node - -By default, VTable will automatically complete the indicator node. For example, the user can pass in a dimension tree without an indicator node: - -``` -rowTree: [ - { - dimensionKey: 'Region', - value: 'North', - } -], -``` - -At the same time, the user configures indicator information in indicators: - -``` -indicators: ['Sales', 'Profit'], -indicatorsAsCol:false, -``` - -VTable will automatically complete the indicator nodes into the row dimension header tree: - -``` -rowTree: [ - { - dimensionKey: 'Region', - value: 'North', - children: [ - { - indicatorKey: 'Sales', - value: 'Sales' - }, - { - indicatorKey: 'Profit', - value: 'Profit' - } - ] - } -], -``` - -If you don't need to automatically complete indicator nodes, you can turn off automatic completion by setting `supplementIndicatorNodes: false`. +**Note: If you choose the configuration method of the custom tree, the data aggregation capability inside VTable will not be enabled, that is, one of the matched data entries will be used as the cell indicator value.** diff --git a/docs/assets/guide/en/table_type/Pivot_table/pivot_table_dataAnalysis.md b/docs/assets/guide/en/table_type/Pivot_table/pivot_table_dataAnalysis.md index cf2d66e8e..f4abcaa9f 100644 --- a/docs/assets/guide/en/table_type/Pivot_table/pivot_table_dataAnalysis.md +++ b/docs/assets/guide/en/table_type/Pivot_table/pivot_table_dataAnalysis.md @@ -224,6 +224,8 @@ According to the above traversed structure, a dimension tree will be generated, Although multi-dimensional tables with analytical capabilities can automatically analyze the dimension values of each dimension to form a tree structure of row and column headers, and can be sorted according to `dataConfig.sortRules`, scenarios with complex business logic still expect to be able to **customize Row column header dimension value ** and order. Then these business requirement scenarios can be realized through rowTree and columnTree. +- enableDataAnalysis needs to be set to false to turn off the analysis of aggregated data within VTable. +

custom rowTree columnTree

@@ -369,3 +371,5 @@ const option = { VTable official website example: https://visactor.io/vtable/demo/table-type/pivot-table. The complexity of the custom tree lies in the formation of the row, column and dimension trees. You can choose to use it according to the business scenario. If you have complex sorting, aggregation or paging rules, you can choose to use a custom method. + +**Note: If you choose the custom tree configuration method, the data aggregation capability inside the VTable will not be enabled, that is, one of the matched data entries will be used as the cell indicator value. ** diff --git a/docs/assets/guide/en/table_type/Pivot_table/pivot_table_useage.md b/docs/assets/guide/en/table_type/Pivot_table/pivot_table_useage.md index 741f1ac7a..fdbdeca89 100644 --- a/docs/assets/guide/en/table_type/Pivot_table/pivot_table_useage.md +++ b/docs/assets/guide/en/table_type/Pivot_table/pivot_table_useage.md @@ -23,6 +23,8 @@ The following are the Key Configurations items and their descriptions for using Here is a simple example of how to use a pivot table to present data: +- enableDataAnalysis needs to be set to true + ```javascript livedemo template=vtable const data = [ { @@ -817,6 +819,7 @@ const option = { } }, widthMode: 'standard', + enableDataAnalysis: true, defaultHeaderColWidth: 150, rowHierarchyIndent: 20, rowHierarchyTextStartAlignment: true @@ -828,6 +831,8 @@ const tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID In the following example, in order to make the display order of each dimension value of the table header meet the requirements, we set two fields: rowTree and columnTree, which represent the tree structure of the row header and column header respectively. You can see the difference in the display order of the tree structure latitude values analyzed by VTable above. +- enableDataAnalysis needs to be set to false + ```javascript livedemo template=vtable const data = [ { diff --git a/docs/assets/guide/en/theme_and_style/style.md b/docs/assets/guide/en/theme_and_style/style.md index 97651376a..176246a40 100644 --- a/docs/assets/guide/en/theme_and_style/style.md +++ b/docs/assets/guide/en/theme_and_style/style.md @@ -128,13 +128,7 @@ Contains the following configuration items: ### Maximum number of rows setting -- `lineClamp`: Set the maximum number of rows of the unit, you can set number or'auto ', set it to'auto', it will be automatically calculated - -### Cell padding - -- `padding`: defines the padding of the cell - -The width and height of a cell consists of two parts: padding and content. +- `lineamp`: Set the maximum number of rows of the unit, you can set number or'auto ', set it to'auto', it will be automatically calculated Through the above introduction, you have mastered the use of style in VTable, and then you can create a table with a personalized style according to your needs. diff --git a/docs/assets/guide/en/theme_and_style/theme.md b/docs/assets/guide/en/theme_and_style/theme.md index 04d2059a4..62f93c59c 100644 --- a/docs/assets/guide/en/theme_and_style/theme.md +++ b/docs/assets/guide/en/theme_and_style/theme.md @@ -73,7 +73,7 @@ The specific configuration content can be viewed at: https://github.com/VisActor The specific configuration content can be viewed at: https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/themes/ARCO.ts // 使用默认主题 - option.theme = VTable.themes.ARCO; + option.theme = vTable.themes.ARCO; const tableInstance = new VTable.ListTable(option); @@ -82,7 +82,7 @@ The specific configuration content can be viewed at: https://github.com/VisActor The specific configuration content can be viewed at: https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/themes/DARK.ts // 使用默认主题 - option.theme = VTable.themes.DARK; + option.theme = vTable.themes.DARK; const tableInstance = new VTable.ListTable(option); @@ -91,7 +91,7 @@ The specific configuration content can be viewed at: https://github.com/VisActor The specific configuration content can be viewed at: https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/themes/BRIGHT.ts // 使用默认主题 - option.theme = VTable.themes.BRIGHT; + option.theme = vTable.themes.BRIGHT; const tableInstance = new VTable.ListTable(option); @@ -100,7 +100,7 @@ The specific configuration content can be viewed at: https://github.com/VisActor The specific configuration content can be viewed at: https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/themes/SIMPLIFY.ts // 使用默认主题 - option.theme = VTable.themes.SIMPLIFY; + option.theme = vTable.themes.SIMPLIFY; const tableInstance = new VTable.ListTable(option); @@ -114,7 +114,7 @@ Such as extending for DEFAULT ``` -option.theme = VTable.themes.DEFAULT.extends({ headerStyle:{ color: 'red'}}) +option.theme = vTable.themes.DEFAULT.extends({ headerStyle:{ color: 'red'}}) const tableInstance = new vTable.ListTable(option); ``` diff --git a/docs/assets/guide/menu.json b/docs/assets/guide/menu.json index 83d1b12f0..6f84257cc 100644 --- a/docs/assets/guide/menu.json +++ b/docs/assets/guide/menu.json @@ -31,13 +31,6 @@ } ] }, - { - "path": "Contribution_Guide", - "title": { - "zh": "贡献指南", - "en": "Contribution Guide" - } - }, { "path": "table_type", "title": { @@ -226,29 +219,13 @@ "title": { "zh": "排序", "en": "sort" - }, - "children": [ - { - "path": "list_sort", - "title": { - "zh": "基本表格排序", - "en": "sort In ListTable" - } - }, - { - "path": "pivot_sort", - "title": { - "zh": "透视表格排序", - "en": "sort In PivotTable" - } - } - ] + } }, { - "path": "frozen_column_row", + "path": "frozen_column", "title": { "zh": "冻结", - "en": "frozen column & row" + "en": "frozen column" } }, { @@ -348,22 +325,6 @@ } ] }, - { - "path": "animation", - "title": { - "zh": "动画", - "en": "Animation" - }, - "children": [ - { - "path": "appear_animation", - "title": { - "zh": "入场动画", - "en": "appear animationt" - } - } - ] - }, { "path": "Event", "title": { @@ -551,13 +512,6 @@ } ] }, - { - "path": "Load_on_Demand", - "title": { - "zh": "按需加载", - "en": "Load on Demand" - } - }, { "path": "search", "title": { @@ -602,13 +556,6 @@ "en": "React-VTable" } }, - { - "path": "react-custom-component", - "title": { - "zh": "React自定义组件", - "en": "React Custom Component" - } - }, { "path": "openinula", "title": { diff --git a/docs/assets/guide/zh/Contribution_Guide.md b/docs/assets/guide/zh/Contribution_Guide.md deleted file mode 100644 index d95155c93..000000000 --- a/docs/assets/guide/zh/Contribution_Guide.md +++ /dev/null @@ -1,239 +0,0 @@ -# VTable 开源代码贡献指南 - -首先为你选择加入开源贡献行列的行为点赞 👍🏻。再者,十分感谢你选择参与到 VisActor 社区,为这个开源项目做出贡献。 - -## VTable 贡献指南 - -VisActor 团队通常在 github 上进行开发和 issue 维护,请打开 [Github 网站](https://github.com/),点击右上角 `Sign up` 按钮,注册一个自己的账号,开启你开源之旅的第一步。 - -如果因为特殊情况,你无法打开 Github 站点,也可以通过 [Gitee](https://gitee.com/VisActor/VTable) 进行项目开发。 - -在 [VTable 仓库](https://github.com/VisActor/VTable)中,我们有一份面向所有开源贡献者的[指南](https://github.com/VisActor/VTable/blob/develop/CONTRIBUTING.zh-CN.md),介绍了有关版本管理、分支管理等内容,**请花几分钟时间阅读了解一下**。 - -## 你的第一个 PullRequest - -### Step1:安装 Git - -Git 是一种版本控制系统,用于跟踪和管理软件开发项目中的代码变更。它帮助开发者记录和管理代码的历史记录,方便团队协作、代码版本控制、合并代码等操作。通过 Git,您可以追踪每个文件的每个版本,并轻松地在不同版本之间进行切换和比较。Git 还提供了分支管理功能,使得可以同时进行多个并行开发任务。 - -- 访问 Git 官方网站: -- 下载最新版本的 Git 安装程序。 -- 运行下载的安装程序,按照安装向导的提示进行安装。 -- 安装完成后,你可以通过命令行使用 `git version` 命令确认安装成功。 - -
- -
- -### Step2:Fork 项目 - -- 首先需要 fork 这个项目,进入[VTable 项目页面](https://github.com/VisActor/VTable),点击右上角的 Fork 按钮 - -
- -
- -- 你的 github 帐号中会出现 xxxx(你的 github 用户名)/VTable 这个项目 -- 在本地电脑上使用以下命令: 得到一个 VTable 文件夹 - -``` -// ssh -git clone git@github.com:xxxx(你的github用户名)/VTable.git -// https -git clone https://github.com/xxxx(你的github用户名)/VTable.git -``` - -### Step3:获取项目代码 - -- 进入 VTable 文件夹,添加 VTable 的远程地址 - -``` -git remote add upstream https://github.com/VisActor/VTable.git -``` - -- 获取 VTable 最新源码 - -``` -git pull upstream develop -``` - -### Step4:创建分支 - -- 好了,现在可以开始贡献我们的代码了。VTable 默认分支为 develop 分支。无论是功能开发、bug 修复、文档编写,都请新建立一个分支,再合并到 develop 分支上。使用以下代码创建分支: - -``` -// 创建功能开发分支 -git checkout -b feat/xxxx - -// 创建问题修复开发分支 -git checkout -b fix/xxxx - -// 创建文档、demo分支 -git checkout -b docs/add-funnel-demo -``` - -假设我们创建了文档修改分支 `docs/add-funnel-demo` - -- 现在我们可以在分支上更改代码了 -- 假设我们已经添加了一些代码,提交到代码库 -- git commit -a -m "docs: add custom funnel demo and related docs" 。VisActor 的 commit 提交信息遵循 [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) 规范 - - - `[optional scope]: ` - - 其中常用 `type`包括 docs(文档、日志修改)、feat(新功能)、fix(问题修复)、refactor(代码重构)等,请根据实际情况选择。 - - 请用简短精确的英文描述编写 description - - 提交 commit 之前,我们会进行 commit lint 检查,具体可以查看[检查规则](https://github.com/VisActor/VTable/blob/develop/common/autoinstallers/lint/commitlint.config.js) - -### Step5:合并修改 - -- 一个常见的问题是远程的 upstream (@visactor/VTable) 有了新的更新, 从而会导致我们提交的 Pull Request 时会导致冲突。 因此我们可以在提交前先把远程其他开发者的 commit 和我们的 commit 合并。使用以下代码切换到 develop 分支: - -``` -git checkout develop -``` - -- 使用以下代码拉出远程的最新代码: - -``` -git pull upstream develop -``` - -- 切换回自己的开发分支: - -``` -git checkout docs/add-funnel-demo -``` - -- 把 develop 的 commit 合并到 `add-funnel-demo`: - -``` -git rebase develop -``` - -- 把更新代码提交到自己的分支中: - -``` -git push origin docs/add-funnel-demo -``` - -### Step6:提交 Pull Request - -你可以在你的 github 代码仓库页面点击 `pull requests` 按钮,点击`New pull request`。 - -
- -
- -选择提交到 develop 分支。 - -按照模板填写本次提交的修改内容: - -- 勾选这是什么类型的修改 -
-
- -
-
- -- 填写关联的 issue -
-
- -
-
- -- 若有复杂变更,请说明背景和解决方案 -
-
- -
-
-相关信息填写完成后,点击 Create pull request 提交。 - -### 其他注意点 - -1. 单元测试: - -如果是涉及接口修改请在**tests**目录下添加单元测试,并运行`rushx test`命令进行测试。 - -当 push 推送代码前会自动进行单元测试的检查,如果全部通过会推送代码到远程,如果没有通过那么应该是代码逻辑有问题或者需求修改单测数据,请根据情况进行修正。 - -运行单元测试中如果遇到"Cannot find module '@visactor/vtable-editors'" 的错误,请先到 vtable-editors 项目中执行`rushx build`命令,然后再回到 vtable 项目中执行命令。 - -## Mini Task 开发指南 - -"**good first issue**" 是一个在开源社区常见的标签,这个标签的目的是帮助新贡献者找到适合入门的问题。 - -VTable 的入门问题,你可以通过 [issue 列表](https://github.com/VisActor/VTable/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) 查看,目前包括两类: - -- Demo 编写 -- bug 修复及简单功能开发 - -如果你当前**有时间和意愿**参与到社区贡献,可以在 issue 里看一看 **good first issue**,选择一个感兴趣、适合自己的认领。 - -相信你一定是一个有始有终的同学,所以,当你了解并决定认领一个 issue 后,请在 issue 下留言告知大家。 - -### Demo Task - -我们准备了一些在实际应用场景中常见的案例,需要思考如何利用 VTable 的能力实现。 - -你可以通过这类任务,上手对 VTable 的使用。VTable 提供了丰富的能力,每个人或许都有不同的实现思路,**你可以在 issue 下留言,和大家讨论自己的方案**。 - -任务完成后,你可以将自己制作的案例提交到官网 demo,让更多需要的人学习和使用。 - -所有的 demo 存放在 `docs/assets/demo` 目录下 - -1. 请基于 develop 分支,新拉一个 `docs/***`分支进行开发 - -1. (如果你已经安装,请跳过此步骤)全局安装 [@microsoft/rush](https://rushjs.io/pages/intro/get_started/):`npm i --global @microsoft/rush` - -1. 根目录下运行 `rush update` - -1. 运行`rush docs` 在本地预览目前 demo 内容 - -1. `docs` 目录下 - - 1. `docs/assets/demo/menu.json` 目录文件中添加你的 demo 信息 - 1. 在`zh`/`en`目录下分别完成中英文 demo 文档 - 1. 封面地址 cover 字段 可以联系 vtable 的团队成员帮忙上传。 - -1. 提交所有代码,并在 Github 创建 Pull Request,邀请其他人进行 review - -### Bug fix/Feature Task - -我们准备了一些简单、易上手的特性开发任务,如果你有一定的 Javascript / Typescript 基础,可以认领这类任务。 - -你可以通过 bug 的修复及需求的开发过程,从而更快地了解 VTable 代码架构。**你可以在 issue 下留言,和大家讨论自己的方案**。 - -1. 请基于 develop 分支,新拉一个 `feat/***` or `fix/***`分支进行开发 -1. (如果你已经安装,请跳过此步骤)全局安装 [@microsoft/rush](https://rushjs.io/pages/intro/get_started/):`npm i --global @microsoft/rush`。 - -常用的项目命令行如下: - -``` -# 注释:安装依赖。 install dependencies -$ rush update -# 注释:进入vtable目录。 enter vtable package -$ cd packages/vtable -# 注释:启动开发测试页面。 execute in file path: ./packages/vtable -$ rushx demo -# 注释:在外层目录启动官网页面。 start site development server, execute in file path: ./ -$ rush docs -# 注释:提交代码后生成changelog。 after execut git commit, please run the following command to update the change log. Please execute in file path: ./ -$ rush change-all -``` - -3. 提交所有代码,并在 Github 创建 Pull Request,邀请其他人进行 review - -## 拥抱 VisActor 社区 - -在你为 VisActor 贡献代码之余,我们鼓励你参与其他让社区更加繁荣的事情,比如: - -1. 为项目的发展、功能规划 等提建议 -1. 创作文章、视频,开办讲座来宣传 VisActor -1. 撰写推广计划,同团队一同执行 - -VisActor 也在努力帮助参与社区建设的同学一同成长,我们计划(但不限于,期待大家更多的建议)提供如下帮助: - -1. 以 VisActor 为基础的数据可视化研发培训,帮助参与的同学在编程技能、可视化理论、架构设计等多个方面快速成长。 -1. 定期评选“代码贡献奖”和“社区推广奖” -1. 组织社区成员参与开源活动 diff --git a/docs/assets/guide/zh/Developer_Ecology/openinula.md b/docs/assets/guide/zh/Developer_Ecology/openinula.md index 27dea1d88..f693daa58 100644 --- a/docs/assets/guide/zh/Developer_Ecology/openinula.md +++ b/docs/assets/guide/zh/Developer_Ecology/openinula.md @@ -29,7 +29,7 @@ yarn add @visactor/openinula-vtable 推荐使用 npm 包引入 ```js -import { ListTable } from '@visactor/openinula-vtable'; +import { ListTable } from "@visactor/openinula-vtable"; ``` ## 绘制一个简单的列表 @@ -41,50 +41,53 @@ import { ListTable } from '@visactor/openinula-vtable'; ```typescript import Openinula from 'openinula'; import OpeninulaDOM from 'openinula-dom/client'; -import { ListTable } from '@visactor/openinula-vtable'; +import { ListTable } from "@visactor/openinula-vtable"; const option = { columns: [ { - field: '0', - title: 'name' + field: "0", + caption: "name", }, { - field: '1', - title: 'age' + field: "1", + caption: "age", }, { - field: '2', - title: 'gender' + field: "2", + caption: "gender", }, { - field: '3', - title: 'hobby' - } + field: "3", + caption: "hobby", + }, ], - records: new Array(1000).fill(['John', 18, 'male', '🏀']) + records: new Array(1000).fill(["John", 18, "male", "🏀"]), }; -Inula.render(, document.getElementById('root')); +Inula.render( + , + document.getElementById('root') +); ``` 参考[demo](../../demo-openinula/usage/option) ## 使用方式 -Openinula-VTable 提供两种风格的组件供开发者使用,分别是统一标签与语法化标签。 +Openinula-VTable提供两种风格的组件供开发者使用,分别是统一标签与语法化标签。 ### 统一标签 -统一标签是指是使用一个 Table 标签,接收一个完整的`option`配置,如果项目中已经使用了 VTable ,这种方式可以快速使用 Openinula-VTable。上面的例子就是一个使用统一标签的[demo](../../demo-openinula/usage/grammatical-tag)。 +统一标签是指是使用一个 Table 标签,接收一个完整的`option`配置,如果项目中已经使用了 VTable ,这种方式可以快速使用Openinula-VTable。上面的例子就是一个使用统一标签的[demo](../../demo-openinula/usage/grammatical-tag)。 -与 VTable 相同 Openinula-VTable 提供三种表格类型: +与VTable相同Openinula-VTable提供三种表格类型: - ListTable: 列表表格,用于展示列表数据 [demo](../../demo-openinula/usage/grammatical-tag) - PivotTable: 透视表格,用于展示交叉透视数据 [demo](../../demo-openinula/grammatical-tag/pivot-table) - PivotChart: 透视图,用于展示交叉透视数据并以图表方式展示 [demo](../../demo-openinula/grammatical-tag/pivot-chart) -这三种 Openinula 组件,其 props 定义如下: +这三种Openinula组件,其props定义如下: ```ts interface VTableProps extends EventsProps { @@ -96,23 +99,23 @@ interface VTableProps extends EventsProps { } ``` -EventsProps 的定义参考事件绑定章节 +EventsProps的定义参考事件绑定章节 -onReady 是一个内置的回调事件,会在表格渲染或更新时触发,其入参分别代表表格实例对象,以及是否初次渲染。 +onReady是一个内置的回调事件,会在表格渲染或更新时触发,其入参分别代表表格实例对象,以及是否初次渲染。 -Openinula-VTable 统一标签几乎是 VTable 的对等功能,可以方便开发者进行 Openinula 版本的迁移,并且从社区或示例中心获得的 option 可以直接通过这种方式使用,开发者几乎没有额外的学习成本。 +Openinula-VTable统一标签几乎是VTable的对等功能,可以方便开发者进行Openinula版本的迁移,并且从社区或示例中心获得的option可以直接通过这种方式使用,开发者几乎没有额外的学习成本。 ### 语法化标签 -语法化标签是指 Openinula-VTable 将表格中的部分组件封装为 Openinula 组件导出给开发者,开发者可以通过更加语义化、更接近原生 Openinula 声明的方式来定义表格。需要说明的是语法化标签的定义内容,在多数场景下都是可以和表格描述`option`进行相互转化的。 +语法化标签是指Openinula-VTable将表格中的部分组件封装为Openinula组件导出给开发者,开发者可以通过更加语义化、更接近原生Openinula声明的方式来定义表格。需要说明的是语法化标签的定义内容,在多数场景下都是可以和表格描述`option`进行相互转化的。 -需要注意的是:虽然图表在定义上是通过 Openinula 组件的形式进行声明的,但实际实现中并不是将其解析为 DOM 进行渲染,因此假如使用审查元素时并不能看到各个图表组件对应的 DOM。 +需要注意的是:虽然图表在定义上是通过Openinula组件的形式进行声明的,但实际实现中并不是将其解析为DOM进行渲染,因此假如使用审查元素时并不能看到各个图表组件对应的DOM。 #### ListTable -ListTable 接受的 props 属性与 option 一致,ListTable 中的子组件如下 +ListTable接受的props属性与option一致,ListTable中的子组件如下 -- ListColumn: 列表列,同 option 中的 columns 的定义一致 [api](../../option/ListTable-columns-text#cellType) +- ListColumn: 列表列,同option中的columns的定义一致 [api](../../option/ListTable-columns-text#cellType) ```jsx import { ListTable, ListColumn } from '../../../src'; @@ -120,88 +123,87 @@ function App() { // ...... return ( - - - - + + + + ); } ``` -语法化标签 demo:[demo](../../demo-openinula/usage/grammatical-tag) +语法化标签demo:[demo](../../demo-openinula/usage/grammatical-tag) #### PivotTable&PivotChart -PivotTable&PivotChart 接受的 props 属性与 option 一致,子组件如下: +PivotTable&PivotChart接受的props属性与option一致,子组件如下: -- PivotColumnDimension: 列上的维度配置,同 option 中的 columns 的定义一致 [api](../../option/PivotTable-columns-text#headerType) -- PivotRowDimension: 行上的维度配置,同 option 中的 rows 的定义一致 [api](../../option/PivotTable-rows-text#headerType) -- PivotIndicator: 指标配置,同 option 中的 indicators 的定义一致 [api](../../option/PivotTable-indicators-text#cellType) -- PivotColumnHeaderTitle: 列表头标题配置,同 option 中的 columnHeaderTitle 的定义一致 [api](../../option/PivotTable#rowHeaderTitle) -- PivotRowHeaderTitle: 行头标题配置,同 option 中的 rowHeaderTitle 的定义一致 [api](../../option/PivotTable#columnHeaderTitle) -- PivotCorner: 角头配置,同 option 中的 corner 的定义一致 [api](../../option/PivotTable#corner) +- PivotColumnDimension: 列上的维度配置,同option中的columns的定义一致 [api](../../option/PivotTable-columns-text#headerType) +- PivotRowDimension: 行上的维度配置,同option中的rows的定义一致 [api](../../option/PivotTable-rows-text#headerType) +- PivotIndicator: 指标配置,同option中的indicators的定义一致 [api](../../option/PivotTable-indicators-text#cellType) +- PivotColumnHeaderTitle: 列表头标题配置,同option中的columnHeaderTitle的定义一致 [api](../../option/PivotTable#rowHeaderTitle) +- PivotRowHeaderTitle: 行头标题配置,同option中的rowHeaderTitle的定义一致 [api](../../option/PivotTable#columnHeaderTitle) +- PivotCorner: 角头配置,同option中的corner的定义一致 [api](../../option/PivotTable#corner) ```jsx -return ( - - - - - - - - - - -); -``` + return ( + + + + + + + + + + + ); -语法化标签 demo:[PivotTable demo](../../demo-openinula/grammatical-tag/pivot-table) [PivotChart demo](../../demo-openinula/grammatical-tag/pivot-chart) +``` +语法化标签demo:[PivotTable demo](../../demo-openinula/grammatical-tag/pivot-table) [PivotChart demo](../../demo-openinula/grammatical-tag/pivot-chart) #### 表格外组件 表格外组件目前支持: -- Menu: 下拉菜单组件,同 option 中的 menu 的定义一致 [api](../../option/ListTable#menu) -- Tooltip: tooltip 组件,同 option 中的 tooltip 的定义一致 [api](../../option/ListTable#tooltip) +- Menu: 下拉菜单组件,同option中的menu的定义一致 [api](../../option/ListTable#menu) +- Tooltip: tooltip组件,同option中的tooltip的定义一致 [api](../../option/ListTable#tooltip) ```jsx // ...... ``` ### 事件绑定 -统一标签或是语法化表格标签最外层表格组件,其 Props 上都继承了表格的事件处理回调 EventsProps。 - -EventsProps 的定义如下: +统一标签或是语法化表格标签最外层表格组件,其Props上都继承了表格的事件处理回调EventsProps。 +EventsProps的定义如下: ```ts interface EventsProps { onClickCell?: EventCallback; @@ -245,8 +247,7 @@ interface EventsProps { onMouseLeaveAxis?: EventCallback; onCheckboxStateChange?: EventCallback; - onRadioStateChange?: EventCallback; - onAfterRender?: EventCallback; + onRadioStateChange?: EventCallback; onAfterRender?: EventCallback; onInitialized?: EventCallback; // pivot table only @@ -259,7 +260,6 @@ interface EventsProps { ``` 事件使用示例: - ```jsx function App() { const option = { diff --git a/docs/assets/guide/zh/Developer_Ecology/react-custom-component.md b/docs/assets/guide/zh/Developer_Ecology/react-custom-component.md deleted file mode 100644 index b9fae0166..000000000 --- a/docs/assets/guide/zh/Developer_Ecology/react-custom-component.md +++ /dev/null @@ -1,235 +0,0 @@ -# React-VTable自定义组件 - -## 自定义单元格组件 - -为了方便react开发者快速实现自定义单元格内容,React-VTable 提供了封装组件并在单元格中使用的能力。 - -### 组件用法 - -自定义单元格组件在[自定义布局](../custom_define/custom_layout)的基础上封装而成,用法类似于自定义布局。在`ListColumn`中使用组件,自定义组件需要传入`role`属性,用于标识该组件为自定义单元格组件;其中`custom-layout`组件会在表格内容部分生效,`header-custom-layout`组件会在表格表头部分生效。每列中最多只能有一个`custom-layout`组件,最多只能有一个`header-custom-layout`组件。 - -```tsx - - - - - - // ...... - -``` - -### 组件封装 - -#### 默认属性 - -在组件中,除了用户定义的属性外,与自定义布局一样,react-vtable还提供了一些默认属性供组件使用 - -```tsx -interface CustomLayoutProps { - table: ListTable; // 表格实例 - row: number; // 行号 - col: number; // 列号 - value: FieldData; // 单元格展示数据 - dataValue: FieldData; // 单元格原始数据 - rect?: RectProps; // 单元格布局信息 -} -const CustomLayoutComponent = (props: CustomLayoutProps & UserProps) => { - const { table, row, col, rect, text } = props; - // ...... -} -``` - -#### 标签 - -组件返回的标签,必须是基于react-vtable提供的图元标签(不可以直接使用HTML标签或DOM react组件,如果需要使用,请参考下一节) - -```tsx -import { Group, Text } from '@visactor/react-vtable'; - -const CustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string }) => { - const { table, row, col, rect, text } = props; - if (!table || row === undefined || col === undefined) { - return null; - } - const { height, width } = rect || table.getCellRect(col, row); - const [hover, setHover] = useState(false); - - const fieldData = [ - { - value: 'a', - label: 'a' - }, - { - value: 'b', - label: 'b' - } - ]; - - const groupRef = useRef(null); - - return ( - - {fieldData.map(item => { - return ( - { - // eslint-disable-next-line no-console, no-undef - console.log('groupRef', groupRef.current); - setHover(true); - event.currentTarget.stage.renderNextFrame(); - }} - onMouseLeave={(event: any) => { - setHover(false); - event.currentTarget.stage.renderNextFrame(); - }} - /> - ); - })} - {hover && ( - - )} - - ); -}; -``` - -基础图元: - -* Text 文字 -* Rect 矩形 -* Image 图片 -* Line 线 -* Arc 弧形 -* Circle 圆 -* Group 图元组 - -基础组件: - -* Tag 文本标签 -* Radio 单选框 -* Checkbox 复选框 - -具体配置属性可以参考[`VRender图元配置`](https://visactor.io/vrender/option/Group),具体使用和布局可以参考[自定义布局](../custom_define/custom_layout),[参考示例](../../demo-react/component/custom-layout)。 - -
- -
- -#### 使用DOM react组件 - -如果需要在组件中使用DOM react组件,可以在图元组件的`attribute`属性中,指定`react`属性,并将react组件作为`element`属性传入: - -```tsx - - } - }} - onMouseEnter={(event) => { - setHover(true); - event.currentTarget.stage.renderNextFrame(); - }} - onMouseLeave={(event) => { - setHover(false); - event.currentTarget.stage.renderNextFrame(); - }} -> -// ... - -``` - -
- -
- -react中还支持配置以下属性: -* `pointerEvents` 是否响应鼠标事件 -* `container` 容器,用于限制滚动时组件显示区域在表格中,如果需要限制组件显示在表格内容区域,需要指定为`table.bodyDomContainer`;如果需要限制组件显示在表格表头区域,需要指定为`table.headerDomContainer`;如果是弹窗或菜单类组件,不需要配置该属性 -* `anchorType` 锚定类型,用于指定组件左上角相对于单元格的锚定位置 - * 'top' - * 'bottom' - * 'left' - * 'right' - * 'top-right' - * 'top-left' - * 'bottom-right' - * 'bottom-left' - * 'center' - -我们推荐用户在单元格内展示的内容,使用react-vtable提供的图元标签,单元格内触发的弹窗、菜单等组件,可以使用DOM react组件,这样是性能最优的方案。[参考示例](../../demo-react/component/custom-layout)。 - -如果需要在单元格内展示的内容,使用DOM react组件,需要按照限制组件显示在表格内容区域,指定`react.container`。需要注意,这样的方式需要频繁更新组件相关DOM,会对性能有一定影响,可以参考[自定义布局](../custom_define/custom_layout)。我们强烈推荐将单元格内的内容组件使用react-vtable提供的图元标签,这样是性能最优的方案。 - -## 自定义外部组件 - -为了方便在 React-VTable 组件上叠加外部组件,React-VTable 提供了`CustomComponent`工具组件,方便快速将外部组件定位到表格当中,可以用来快速实现弹窗、菜单等功能组件。 - -```jsx - - - - - -``` - -其中,`CustomComponent`作为一个容器,用于在表格中定位,并自动匹配尺寸(基于锚定的单元格),具体有两种使用方式: - -1. 绝对定位 - - 绝对定位的方式,需要指定`displayMode`为`position`, 需要指定`x`和`y`属性,用于将容器定位到表格中的指定像素位置(基于左上角),`width`和`height`属性指定容器的像素尺寸。 - -2. 相对定位 - - 相对定位的方式,需要指定`displayMode`为`cell`,容器相对为单元格定位、`col`和`row`属性用于指定锚定的单元格坐标,`anchor`属性指定容器相对于单元格的锚定位置,`dx`和`dy`属性指定容器相对于锚定单元格的偏移量,`width`和`height`属性指定容器的尺寸,其中`dx` `dy` `width`和`height`属性的均支持单位为像素或百分比,为百分比时,相对于单元格的尺寸进行计算。 - -### API - -```ts -interface CustomComponentProps { - children: React.ReactNode; - displayMode: 'position' | 'cell'; // 定位方式 - col?: number; // 锚定的列坐标 - row?: number; // 锚定的行坐标 - anchor?: - | 'top-left' - | 'top-center' - | 'top-right' - | 'middle-left' - | 'middle-center' - | 'middle-right' - | 'bottom-left' - | 'bottom-center' - | 'bottom-right'; // 锚定的位置 - dx?: number | string; // x方向的偏移 - dy?: number | string; // y方向的偏移 - width?: number | string; // 容器的宽度 - height?: number | string; // 容器的高度 -} -``` - -自定义外部组件 demo:[custom component demo](../../demo-react/component/custom-component) \ No newline at end of file diff --git a/docs/assets/guide/zh/Developer_Ecology/react.md b/docs/assets/guide/zh/Developer_Ecology/react.md index be0ab61bf..82c73e997 100644 --- a/docs/assets/guide/zh/Developer_Ecology/react.md +++ b/docs/assets/guide/zh/Developer_Ecology/react.md @@ -29,7 +29,7 @@ yarn add @visactor/react-vtable 推荐使用 npm 包引入 ```js -import { ListTable } from '@visactor/react-vtable'; +import { ListTable } from "@visactor/react-vtable"; ``` ## 绘制一个简单的列表 @@ -41,32 +41,32 @@ import { ListTable } from '@visactor/react-vtable'; ```typescript import React from 'react'; import ReactDOM from 'react-dom/client'; -import { ListTable } from '@visactor/react-vtable'; +import { ListTable } from "@visactor/react-vtable"; const option = { columns: [ { - field: '0', - title: 'name' + field: "0", + caption: "name", }, { - field: '1', - title: 'age' + field: "1", + caption: "age", }, { - field: '2', - title: 'gender' + field: "2", + caption: "gender", }, { - field: '3', - title: 'hobby' - } + field: "3", + caption: "hobby", + }, ], - records: new Array(1000).fill(['John', 18, 'male', '🏀']) + records: new Array(1000).fill(["John", 18, "male", "🏀"]), }; ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( - + ); ``` @@ -74,19 +74,19 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( ## 使用方式 -React-VTable 提供两种风格的组件供开发者使用,分别是统一标签与语法化标签。 +React-VTable提供两种风格的组件供开发者使用,分别是统一标签与语法化标签。 ### 统一标签 -统一标签是指是使用一个 Table 标签,接收一个完整的`option`配置,如果项目中已经使用了 VTable ,这种方式可以快速使用 React-VTable。上面的例子就是一个使用统一标签的[demo](../../demo-react/usage/option)。 +统一标签是指是使用一个 Table 标签,接收一个完整的`option`配置,如果项目中已经使用了 VTable ,这种方式可以快速使用React-VTable。上面的例子就是一个使用统一标签的[demo](../../demo-react/usage/option)。 -与 VTable 相同 React-VTable 提供三种表格类型: +与VTable相同React-VTable提供三种表格类型: - ListTable: 列表表格,用于展示列表数据 [demo](../../demo-react/usage/option) - PivotTable: 透视表格,用于展示交叉透视数据 [demo](../../demo-react/grammatical-tag/pivot-table) - PivotChart: 透视图,用于展示交叉透视数据并以图表方式展示 [demo](../../demo-react/grammatical-tag/pivot-chart) -这三种 React 组件,其 props 定义如下: +这三种React组件,其props定义如下: ```ts interface VTableProps extends EventsProps { @@ -98,23 +98,23 @@ interface VTableProps extends EventsProps { } ``` -EventsProps 的定义参考事件绑定章节 +EventsProps的定义参考事件绑定章节 -onReady 是一个内置的回调事件,会在表格渲染或更新时触发,其入参分别代表表格实例对象,以及是否初次渲染。 +onReady是一个内置的回调事件,会在表格渲染或更新时触发,其入参分别代表表格实例对象,以及是否初次渲染。 -React-VTable 统一标签几乎是 VTable 的对等功能,可以方便开发者进行 React 版本的迁移,并且从社区或示例中心获得的 option 可以直接通过这种方式使用,开发者几乎没有额外的学习成本。 +React-VTable统一标签几乎是VTable的对等功能,可以方便开发者进行React版本的迁移,并且从社区或示例中心获得的option可以直接通过这种方式使用,开发者几乎没有额外的学习成本。 ### 语法化标签 -语法化标签是指 React-VTable 将表格中的部分组件封装为 React 组件导出给开发者,开发者可以通过更加语义化、更接近原生 React 声明的方式来定义表格。需要说明的是语法化标签的定义内容,在多数场景下都是可以和表格描述`option`进行相互转化的。 +语法化标签是指React-VTable将表格中的部分组件封装为React组件导出给开发者,开发者可以通过更加语义化、更接近原生React声明的方式来定义表格。需要说明的是语法化标签的定义内容,在多数场景下都是可以和表格描述`option`进行相互转化的。 -需要注意的是:虽然图表在定义上是通过 React 组件的形式进行声明的,但实际实现中并不是将其解析为 DOM 进行渲染,因此假如使用审查元素时并不能看到各个图表组件对应的 DOM。 +需要注意的是:虽然图表在定义上是通过React组件的形式进行声明的,但实际实现中并不是将其解析为DOM进行渲染,因此假如使用审查元素时并不能看到各个图表组件对应的DOM。 #### ListTable -ListTable 接受的 props 属性与 option 一致,ListTable 中的子组件如下 +ListTable接受的props属性与option一致,ListTable中的子组件如下 -- ListColumn: 列表列,同 option 中的 columns 的定义一致 [api](../../option/ListTable-columns-text#cellType) +- ListColumn: 列表列,同option中的columns的定义一致 [api](../../option/ListTable-columns-text#cellType) ```jsx import { ListTable, ListColumn } from '../../../src'; @@ -122,88 +122,87 @@ function App() { // ...... return ( - - - - + + + + ); } ``` -语法化标签 demo:[demo](../../demo-react/usage/grammatical-tag) +语法化标签demo:[demo](../../demo-react/usage/grammatical-tag) #### PivotTable&PivotChart -PivotTable&PivotChart 接受的 props 属性与 option 一致,子组件如下: +PivotTable&PivotChart接受的props属性与option一致,子组件如下: -- PivotColumnDimension: 列上的维度配置,同 option 中的 columns 的定义一致 [api](../../option/PivotTable-columns-text#headerType) -- PivotRowDimension: 行上的维度配置,同 option 中的 rows 的定义一致 [api](../../option/PivotTable-rows-text#headerType) -- PivotIndicator: 指标配置,同 option 中的 indicators 的定义一致 [api](../../option/PivotTable-indicators-text#cellType) -- PivotColumnHeaderTitle: 列表头标题配置,同 option 中的 columnHeaderTitle 的定义一致 [api](../../option/PivotTable#rowHeaderTitle) -- PivotRowHeaderTitle: 行头标题配置,同 option 中的 rowHeaderTitle 的定义一致 [api](../../option/PivotTable#columnHeaderTitle) -- PivotCorner: 角头配置,同 option 中的 corner 的定义一致 [api](../../option/PivotTable#corner) +- PivotColumnDimension: 列上的维度配置,同option中的columns的定义一致 [api](../../option/PivotTable-columns-text#headerType) +- PivotRowDimension: 行上的维度配置,同option中的rows的定义一致 [api](../../option/PivotTable-rows-text#headerType) +- PivotIndicator: 指标配置,同option中的indicators的定义一致 [api](../../option/PivotTable-indicators-text#cellType) +- PivotColumnHeaderTitle: 列表头标题配置,同option中的columnHeaderTitle的定义一致 [api](../../option/PivotTable#rowHeaderTitle) +- PivotRowHeaderTitle: 行头标题配置,同option中的rowHeaderTitle的定义一致 [api](../../option/PivotTable#columnHeaderTitle) +- PivotCorner: 角头配置,同option中的corner的定义一致 [api](../../option/PivotTable#corner) ```jsx -return ( - - - - - - - - - - -); -``` + return ( + + + + + + + + + + + ); -语法化标签 demo:[PivotTable demo](../../demo-react/grammatical-tag/pivot-table) [PivotChart demo](../../demo-react/grammatical-tag/pivot-chart) +``` +语法化标签demo:[PivotTable demo](../../demo-react/grammatical-tag/pivot-table) [PivotChart demo](../../demo-react/grammatical-tag/pivot-chart) #### 表格外组件 表格外组件目前支持: -- Menu: 下拉菜单组件,同 option 中的 menu 的定义一致 [api](../../option/ListTable#menu) -- Tooltip: tooltip 组件,同 option 中的 tooltip 的定义一致 [api](../../option/ListTable#tooltip) +- Menu: 下拉菜单组件,同option中的menu的定义一致 [api](../../option/ListTable#menu) +- Tooltip: tooltip组件,同option中的tooltip的定义一致 [api](../../option/ListTable#tooltip) ```jsx // ...... ``` ### 事件绑定 -统一标签或是语法化表格标签最外层表格组件,其 Props 上都继承了表格的事件处理回调 EventsProps。 - -EventsProps 的定义如下: +统一标签或是语法化表格标签最外层表格组件,其Props上都继承了表格的事件处理回调EventsProps。 +EventsProps的定义如下: ```ts interface EventsProps { onClickCell?: EventCallback; @@ -211,7 +210,6 @@ interface EventsProps { onMouseDownCell?: EventCallback; onMouseUpCell?: EventCallback; onSelectedCell?: EventCallback; - onSelectedClear?: EventCallback; onKeyDown?: EventCallback; onMouseEnterTable?: EventCallback; onMouseLeaveTable?: EventCallback; @@ -262,7 +260,6 @@ interface EventsProps { ``` 事件使用示例: - ```jsx function App() { const option = { @@ -280,3 +277,43 @@ function App() { ``` 事件详细描述参考:[事件介绍](../../guide/Event/event_list) + +## 自定义外部组件 + +为了方便在React-VTable组件上叠加外部组件,React-VTable提供了`CustomComponent`工具组件,方便快速将外部组件定位到表格当中。 + +```jsx + + + + + +``` + +其中,`CustomComponent`作为一个容器,用于在表格中定位,并自动匹配尺寸(基于锚定的单元格),具体有两种使用方式: + +1. 绝对定位 + + 绝对定位的方式,需要指定`displayMode`为`position`, 需要指定`x`和`y`属性,用于将容器定位到表格中的指定像素位置(基于左上角),`width`和`height`属性指定容器的像素尺寸。 + +2. 相对定位 + + 相对定位的方式,需要指定`displayMode`为`cell`,容器相对为单元格定位、`col`和`row`属性用于指定锚定的单元格坐标,`anchor`属性指定容器相对于单元格的锚定位置,`dx`和`dy`属性指定容器相对于锚定单元格的偏移量,`width`和`height`属性指定容器的尺寸,其中`dx` `dy` `width`和`height`属性的均支持单位为像素或百分比,为百分比时,相对于单元格的尺寸进行计算。 + +### API + +```ts +interface CustomComponentProps { + children: React.ReactNode; + displayMode: 'position' | 'cell'; // 定位方式 + col?: number; // 锚定的列坐标 + row?: number; // 锚定的行坐标 + anchor?: 'top-left' | 'top-center' | 'top-right' |'middle-left' |'middle-center' |'middle-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'; // 锚定的位置 + dx?: number | string; // x方向的偏移 + dy?: number | string; // y方向的偏移 + width?: number | string; // 容器的宽度 + height?: number | string; // 容器的高度 +} +``` + +自定义外部组件demo:[custom component demo](../../demo-react/component/custom-component) diff --git a/docs/assets/guide/zh/Event/event_list.md b/docs/assets/guide/zh/Event/event_list.md index 0e1994bde..36cd1110a 100644 --- a/docs/assets/guide/zh/Event/event_list.md +++ b/docs/assets/guide/zh/Event/event_list.md @@ -20,7 +20,6 @@ | 鼠标按下 | MOUSEDOWN_CELL | 单元格鼠标按下事件 | | 鼠标松开 | MOUSEUP_CELL | 单元格鼠标松开事件 | | 选中状态改变 | SELECTED_CELL | 单元格选中状态改变事件 | -| 选中状态被清除 | SELECTED_CLEAR | 单元格选中状态全部清除事件 | | 鼠标进入 | MOUSEENTER_CELL | 鼠标进入单元格事件 | | 鼠标移动 | MOUSEMOVE_CELL | 鼠标在某个单元格上移动事件 | | 鼠标离开 | MOUSELEAVE_CELL | 鼠标离开单元格事件 | diff --git a/docs/assets/guide/zh/Getting_Started/Getting_Started.md b/docs/assets/guide/zh/Getting_Started/Getting_Started.md index 08438c188..b98588e21 100644 --- a/docs/assets/guide/zh/Getting_Started/Getting_Started.md +++ b/docs/assets/guide/zh/Getting_Started/Getting_Started.md @@ -24,9 +24,6 @@ yarn add @visactor/vtable ```html - ``` ## 引入 VTable @@ -38,9 +35,9 @@ yarn add @visactor/vtable ```js import * as VTable from '@visactor/vtable'; -or; +or -import { ListTable, PivotTable, TYPES, themes } from '@visactor/vtable'; +import {ListTable, PivotTable, TYPES, themes} from '@visactor/vtable'; ``` ### 使用 script 标签引入 @@ -50,7 +47,7 @@ import { ListTable, PivotTable, TYPES, themes } from '@visactor/vtable'; ```html ``` @@ -67,318 +64,319 @@ import { ListTable, PivotTable, TYPES, themes } from '@visactor/vtable'; 接下来,我们创建一个 `Vtable.ListTable` 实例,传入表格配置项: ```javascript livedemo template=vtable + const records = [ - { - 230517143221027: 'CA-2018-156720', - 230517143221030: 'JM-15580', - 230517143221032: 'Bagged Rubber Bands', - 230517143221023: 'Office Supplies', - 230517143221034: 'Fasteners', - 230517143221037: 'West', - 230517143221024: 'Loveland', - 230517143221029: '2018-12-30', - 230517143221042: '3', - 230517143221040: '3.024', - 230517143221041: '-0.605' +{ + "230517143221027": "CA-2018-156720", + "230517143221030": "JM-15580", + "230517143221032": "Bagged Rubber Bands", + "230517143221023": "Office Supplies", + "230517143221034": "Fasteners", + "230517143221037": "West", + "230517143221024": "Loveland", + "230517143221029": "2018-12-30", + "230517143221042": "3", + "230517143221040": "3.024", + "230517143221041": "-0.605" }, { - 230517143221027: 'CA-2018-115427', - 230517143221030: 'EB-13975', - 230517143221032: 'GBC Binding covers', - 230517143221023: 'Office Supplies', - 230517143221034: 'Binders', - 230517143221037: 'West', - 230517143221024: 'Fairfield', - 230517143221029: '2018-12-30', - 230517143221042: '2', - 230517143221040: '20.72', - 230517143221041: '6.475' + "230517143221027": "CA-2018-115427", + "230517143221030": "EB-13975", + "230517143221032": "GBC Binding covers", + "230517143221023": "Office Supplies", + "230517143221034": "Binders", + "230517143221037": "West", + "230517143221024": "Fairfield", + "230517143221029": "2018-12-30", + "230517143221042": "2", + "230517143221040": "20.72", + "230517143221041": "6.475" }, { - 230517143221027: 'CA-2018-115427', - 230517143221030: 'EB-13975', - 230517143221032: 'Cardinal Slant-D Ring Binder, Heavy Gauge Vinyl', - 230517143221023: 'Office Supplies', - 230517143221034: 'Binders', - 230517143221037: 'West', - 230517143221024: 'Fairfield', - 230517143221029: '2018-12-30', - 230517143221042: '2', - 230517143221040: '13.904', - 230517143221041: '4.519' + "230517143221027": "CA-2018-115427", + "230517143221030": "EB-13975", + "230517143221032": "Cardinal Slant-D Ring Binder, Heavy Gauge Vinyl", + "230517143221023": "Office Supplies", + "230517143221034": "Binders", + "230517143221037": "West", + "230517143221024": "Fairfield", + "230517143221029": "2018-12-30", + "230517143221042": "2", + "230517143221040": "13.904", + "230517143221041": "4.519" }, { - 230517143221027: 'CA-2018-143259', - 230517143221030: 'PO-18865', - 230517143221032: 'Wilson Jones Legal Size Ring Binders', - 230517143221023: 'Office Supplies', - 230517143221034: 'Binders', - 230517143221037: 'East', - 230517143221024: 'New York City', - 230517143221029: '2018-12-30', - 230517143221042: '3', - 230517143221040: '52.776', - 230517143221041: '19.791' + "230517143221027": "CA-2018-143259", + "230517143221030": "PO-18865", + "230517143221032": "Wilson Jones Legal Size Ring Binders", + "230517143221023": "Office Supplies", + "230517143221034": "Binders", + "230517143221037": "East", + "230517143221024": "New York City", + "230517143221029": "2018-12-30", + "230517143221042": "3", + "230517143221040": "52.776", + "230517143221041": "19.791" }, { - 230517143221027: 'CA-2018-143259', - 230517143221030: 'PO-18865', - 230517143221032: 'Gear Head AU3700S Headset', - 230517143221023: 'Technology', - 230517143221034: 'Phones', - 230517143221037: 'East', - 230517143221024: 'New York City', - 230517143221029: '2018-12-30', - 230517143221042: '7', - 230517143221040: '90.93', - 230517143221041: '2.728' + "230517143221027": "CA-2018-143259", + "230517143221030": "PO-18865", + "230517143221032": "Gear Head AU3700S Headset", + "230517143221023": "Technology", + "230517143221034": "Phones", + "230517143221037": "East", + "230517143221024": "New York City", + "230517143221029": "2018-12-30", + "230517143221042": "7", + "230517143221040": "90.93", + "230517143221041": "2.728" }, { - 230517143221027: 'CA-2018-143259', - 230517143221030: 'PO-18865', - 230517143221032: 'Bush Westfield Collection Bookcases, Fully Assembled', - 230517143221023: 'Furniture', - 230517143221034: 'Bookcases', - 230517143221037: 'East', - 230517143221024: 'New York City', - 230517143221029: '2018-12-30', - 230517143221042: '4', - 230517143221040: '323.136', - 230517143221041: '12.118' + "230517143221027": "CA-2018-143259", + "230517143221030": "PO-18865", + "230517143221032": "Bush Westfield Collection Bookcases, Fully Assembled", + "230517143221023": "Furniture", + "230517143221034": "Bookcases", + "230517143221037": "East", + "230517143221024": "New York City", + "230517143221029": "2018-12-30", + "230517143221042": "4", + "230517143221040": "323.136", + "230517143221041": "12.118" }, { - 230517143221027: 'CA-2018-126221', - 230517143221030: 'CC-12430', - 230517143221032: 'Eureka The Boss Plus 12-Amp Hard Box Upright Vacuum, Red', - 230517143221023: 'Office Supplies', - 230517143221034: 'Appliances', - 230517143221037: 'Central', - 230517143221024: 'Columbus', - 230517143221029: '2018-12-30', - 230517143221042: '2', - 230517143221040: '209.3', - 230517143221041: '56.511' + "230517143221027": "CA-2018-126221", + "230517143221030": "CC-12430", + "230517143221032": "Eureka The Boss Plus 12-Amp Hard Box Upright Vacuum, Red", + "230517143221023": "Office Supplies", + "230517143221034": "Appliances", + "230517143221037": "Central", + "230517143221024": "Columbus", + "230517143221029": "2018-12-30", + "230517143221042": "2", + "230517143221040": "209.3", + "230517143221041": "56.511" }, { - 230517143221027: 'US-2018-158526', - 230517143221030: 'KH-16360', - 230517143221032: 'Harbour Creations Steel Folding Chair', - 230517143221023: 'Furniture', - 230517143221034: 'Chairs', - 230517143221037: 'South', - 230517143221024: 'Louisville', - 230517143221029: '2018-12-29', - 230517143221042: '3', - 230517143221040: '258.75', - 230517143221041: '77.625' + "230517143221027": "US-2018-158526", + "230517143221030": "KH-16360", + "230517143221032": "Harbour Creations Steel Folding Chair", + "230517143221023": "Furniture", + "230517143221034": "Chairs", + "230517143221037": "South", + "230517143221024": "Louisville", + "230517143221029": "2018-12-29", + "230517143221042": "3", + "230517143221040": "258.75", + "230517143221041": "77.625" }, { - 230517143221027: 'US-2018-158526', - 230517143221030: 'KH-16360', - 230517143221032: 'Global Leather and Oak Executive Chair, Black', - 230517143221023: 'Furniture', - 230517143221034: 'Chairs', - 230517143221037: 'South', - 230517143221024: 'Louisville', - 230517143221029: '2018-12-29', - 230517143221042: '1', - 230517143221040: '300.98', - 230517143221041: '87.284' + "230517143221027": "US-2018-158526", + "230517143221030": "KH-16360", + "230517143221032": "Global Leather and Oak Executive Chair, Black", + "230517143221023": "Furniture", + "230517143221034": "Chairs", + "230517143221037": "South", + "230517143221024": "Louisville", + "230517143221029": "2018-12-29", + "230517143221042": "1", + "230517143221040": "300.98", + "230517143221041": "87.284" }, { - 230517143221027: 'US-2018-158526', - 230517143221030: 'KH-16360', - 230517143221032: 'Panasonic KP-350BK Electric Pencil Sharpener with Auto Stop', - 230517143221023: 'Office Supplies', - 230517143221034: 'Art', - 230517143221037: 'South', - 230517143221024: 'Louisville', - 230517143221029: '2018-12-29', - 230517143221042: '1', - 230517143221040: '34.58', - 230517143221041: '10.028' + "230517143221027": "US-2018-158526", + "230517143221030": "KH-16360", + "230517143221032": "Panasonic KP-350BK Electric Pencil Sharpener with Auto Stop", + "230517143221023": "Office Supplies", + "230517143221034": "Art", + "230517143221037": "South", + "230517143221024": "Louisville", + "230517143221029": "2018-12-29", + "230517143221042": "1", + "230517143221040": "34.58", + "230517143221041": "10.028" }, { - 230517143221027: 'US-2018-158526', - 230517143221030: 'KH-16360', - 230517143221032: 'GBC ProClick Spines for 32-Hole Punch', - 230517143221023: 'Office Supplies', - 230517143221034: 'Binders', - 230517143221037: 'South', - 230517143221024: 'Louisville', - 230517143221029: '2018-12-29', - 230517143221042: '1', - 230517143221040: '12.53', - 230517143221041: '5.889' + "230517143221027": "US-2018-158526", + "230517143221030": "KH-16360", + "230517143221032": "GBC ProClick Spines for 32-Hole Punch", + "230517143221023": "Office Supplies", + "230517143221034": "Binders", + "230517143221037": "South", + "230517143221024": "Louisville", + "230517143221029": "2018-12-29", + "230517143221042": "1", + "230517143221040": "12.53", + "230517143221041": "5.889" }, { - 230517143221027: 'US-2018-158526', - 230517143221030: 'KH-16360', - 230517143221032: 'DMI Arturo Collection Mission-style Design Wood Chair', - 230517143221023: 'Furniture', - 230517143221034: 'Chairs', - 230517143221037: 'South', - 230517143221024: 'Louisville', - 230517143221029: '2018-12-29', - 230517143221042: '8', - 230517143221040: '1207.84', - 230517143221041: '314.038' + "230517143221027": "US-2018-158526", + "230517143221030": "KH-16360", + "230517143221032": "DMI Arturo Collection Mission-style Design Wood Chair", + "230517143221023": "Furniture", + "230517143221034": "Chairs", + "230517143221037": "South", + "230517143221024": "Louisville", + "230517143221029": "2018-12-29", + "230517143221042": "8", + "230517143221040": "1207.84", + "230517143221041": "314.038" }, { - 230517143221027: 'CA-2018-130631', - 230517143221030: 'BS-11755', - 230517143221032: 'Hand-Finished Solid Wood Document Frame', - 230517143221023: 'Furniture', - 230517143221034: 'Furnishings', - 230517143221037: 'West', - 230517143221024: 'Edmonds', - 230517143221029: '2018-12-29', - 230517143221042: '2', - 230517143221040: '68.46', - 230517143221041: '20.538' + "230517143221027": "CA-2018-130631", + "230517143221030": "BS-11755", + "230517143221032": "Hand-Finished Solid Wood Document Frame", + "230517143221023": "Furniture", + "230517143221034": "Furnishings", + "230517143221037": "West", + "230517143221024": "Edmonds", + "230517143221029": "2018-12-29", + "230517143221042": "2", + "230517143221040": "68.46", + "230517143221041": "20.538" }, { - 230517143221027: 'CA-2018-130631', - 230517143221030: 'BS-11755', - 230517143221032: 'Acco Glide Clips', - 230517143221023: 'Office Supplies', - 230517143221034: 'Fasteners', - 230517143221037: 'West', - 230517143221024: 'Edmonds', - 230517143221029: '2018-12-29', - 230517143221042: '5', - 230517143221040: '19.6', - 230517143221041: '9.604' + "230517143221027": "CA-2018-130631", + "230517143221030": "BS-11755", + "230517143221032": "Acco Glide Clips", + "230517143221023": "Office Supplies", + "230517143221034": "Fasteners", + "230517143221037": "West", + "230517143221024": "Edmonds", + "230517143221029": "2018-12-29", + "230517143221042": "5", + "230517143221040": "19.6", + "230517143221041": "9.604" }, { - 230517143221027: 'CA-2018-146626', - 230517143221030: 'BP-11185', - 230517143221032: 'Nu-Dell Executive Frame', - 230517143221023: 'Furniture', - 230517143221034: 'Furnishings', - 230517143221037: 'West', - 230517143221024: 'Anaheim', - 230517143221029: '2018-12-29', - 230517143221042: '8', - 230517143221040: '101.12', - 230517143221041: '37.414' + "230517143221027": "CA-2018-146626", + "230517143221030": "BP-11185", + "230517143221032": "Nu-Dell Executive Frame", + "230517143221023": "Furniture", + "230517143221034": "Furnishings", + "230517143221037": "West", + "230517143221024": "Anaheim", + "230517143221029": "2018-12-29", + "230517143221042": "8", + "230517143221040": "101.12", + "230517143221041": "37.414" }, { - 230517143221027: 'CA-2018-158673', - 230517143221030: 'KB-16600', - 230517143221032: 'Xerox 1915', - 230517143221023: 'Office Supplies', - 230517143221034: 'Paper', - 230517143221037: 'Central', - 230517143221024: 'Grand Rapids', - 230517143221029: '2018-12-29', - 230517143221042: '2', - 230517143221040: '209.7', - 230517143221041: '100.656' + "230517143221027": "CA-2018-158673", + "230517143221030": "KB-16600", + "230517143221032": "Xerox 1915", + "230517143221023": "Office Supplies", + "230517143221034": "Paper", + "230517143221037": "Central", + "230517143221024": "Grand Rapids", + "230517143221029": "2018-12-29", + "230517143221042": "2", + "230517143221040": "209.7", + "230517143221041": "100.656" }, { - 230517143221027: 'US-2018-102638', - 230517143221030: 'MC-17845', - 230517143221032: 'Ideal Clamps', - 230517143221023: 'Office Supplies', - 230517143221034: 'Fasteners', - 230517143221037: 'East', - 230517143221024: 'New York City', - 230517143221029: '2018-12-29', - 230517143221042: '3', - 230517143221040: '6.03', - 230517143221041: '2.955' + "230517143221027": "US-2018-102638", + "230517143221030": "MC-17845", + "230517143221032": "Ideal Clamps", + "230517143221023": "Office Supplies", + "230517143221034": "Fasteners", + "230517143221037": "East", + "230517143221024": "New York City", + "230517143221029": "2018-12-29", + "230517143221042": "3", + "230517143221040": "6.03", + "230517143221041": "2.955" }, { - 230517143221027: 'CA-2018-118885', - 230517143221030: 'JG-15160', - 230517143221032: 'Adtran 1202752G1', - 230517143221023: 'Technology', - 230517143221034: 'Phones', - 230517143221037: 'West', - 230517143221024: 'Los Angeles', - 230517143221029: '2018-12-29', - 230517143221042: '3', - 230517143221040: '302.376', - 230517143221041: '22.678' + "230517143221027": "CA-2018-118885", + "230517143221030": "JG-15160", + "230517143221032": "Adtran 1202752G1", + "230517143221023": "Technology", + "230517143221034": "Phones", + "230517143221037": "West", + "230517143221024": "Los Angeles", + "230517143221029": "2018-12-29", + "230517143221042": "3", + "230517143221040": "302.376", + "230517143221041": "22.678" }, { - 230517143221027: 'CA-2018-118885', - 230517143221030: 'JG-15160', - 230517143221032: 'Global High-Back Leather Tilter, Burgundy', - 230517143221023: 'Furniture', - 230517143221034: 'Chairs', - 230517143221037: 'West', - 230517143221024: 'Los Angeles', - 230517143221029: '2018-12-29', - 230517143221042: '4', - 230517143221040: '393.568', - 230517143221041: '-44.276' + "230517143221027": "CA-2018-118885", + "230517143221030": "JG-15160", + "230517143221032": "Global High-Back Leather Tilter, Burgundy", + "230517143221023": "Furniture", + "230517143221034": "Chairs", + "230517143221037": "West", + "230517143221024": "Los Angeles", + "230517143221029": "2018-12-29", + "230517143221042": "4", + "230517143221040": "393.568", + "230517143221041": "-44.276" } ]; -const columns = [ - { - field: '230517143221027', - title: 'Order ID', - width: 'auto' - }, - { - field: '230517143221030', - title: 'Customer ID', - width: 'auto' - }, - { - field: '230517143221032', - title: 'Product Name', - width: 'auto' - }, - { - field: '230517143221023', - title: 'Category', - width: 'auto' - }, - { - field: '230517143221034', - title: 'Sub-Category', - width: 'auto' - }, - { - field: '230517143221037', - title: 'Region', - width: 'auto' - }, - { - field: '230517143221024', - title: 'City', - width: 'auto' - }, - { - field: '230517143221029', - title: 'Order Date', - width: 'auto' - }, - { - field: '230517143221042', - title: 'Quantity', - width: 'auto' - }, - { - field: '230517143221040', - title: 'Sales', - width: 'auto' - }, - { - field: '230517143221041', - title: 'Profit', - width: 'auto' - } +const columns =[ + { + "field": "230517143221027", + "title": "Order ID", + "width": "auto" + }, + { + "field": "230517143221030", + "title": "Customer ID", + "width": "auto" + }, + { + "field": "230517143221032", + "title": "Product Name", + "width": "auto" + }, + { + "field": "230517143221023", + "title": "Category", + "width": "auto" + }, + { + "field": "230517143221034", + "title": "Sub-Category", + "width": "auto" + }, + { + "field": "230517143221037", + "title": "Region", + "width": "auto" + }, + { + "field": "230517143221024", + "title": "City", + "width": "auto" + }, + { + "field": "230517143221029", + "title": "Order Date", + "width": "auto" + }, + { + "field": "230517143221042", + "title": "Quantity", + "width": "auto" + }, + { + "field": "230517143221040", + "title": "Sales", + "width": "auto" + }, + { + "field": "230517143221041", + "title": "Profit", + "width": "auto" + } ]; const option = { records, columns, - widthMode: 'standard' + widthMode:'standard' }; // 创建 VTable 实例 @@ -387,4 +385,4 @@ const tableInstance = new VTable.ListTable(document.getElementById(CONTAINER_ID) 至此,你已经成功绘制出了一个简单的表格! -希望这篇教程对你学习如何使用 VTable 有所帮助。接下来可以深入了解 VTable 的各种配置选项,定制出更加丰富多样的表格效果。 +希望这篇教程对你学习如何使用 VTable 有所帮助。接下来可以深入了解 VTable的各种配置选项,定制出更加丰富多样的表格效果。 diff --git a/docs/assets/guide/zh/Load_on_Demand.md b/docs/assets/guide/zh/Load_on_Demand.md deleted file mode 100644 index 3f834daa3..000000000 --- a/docs/assets/guide/zh/Load_on_Demand.md +++ /dev/null @@ -1,38 +0,0 @@ -# VTable 按需加载 - -默认从 `@visactor/vtable` 包中引入的 `ListTable` 、 `PivotTable` 和 `PivotChart` 包含所有的表格相关的组件,是一个完整的表格组件库。 - -为了满足包体积优化的需求,VTable提供了 `ListTableSimple` 和 `PivotTableSimple` 两个类型,分别是最简化的列表和透视表,只支持文字类型的显示,不包含菜单、标题等外部组件。如果需要部分功能,可以进行按需加载,使用方法如下: - -```js -// ListTableSimple, PivotTableSimple 是最简单的列表和透视表组件,不包除了文字之外的单元格类型和任何组件 -import {ListTableSimple, PivotTableSimple, registerTitle, registerTooltip} from '@visactor/vtable'; - -// 注册标题组件 -registerTitle(); - -// 注册tooltip组件 -registerTooltip(); -``` - -## 按需加载功能 - -### 功能组件 - -* registerAxis: 坐标轴组件 -* registerEmptyTip: 空白提示组件 -* registerLegend: 图例组件 -* registerMenu: 菜单组件 -* registerTitle: 标题组件 -* registerTooltip: tooltip组件 - -### 单元格类型 - -* registerChartCell: 图表单元格 -* registerCheckboxCell: 复选框单元格 -* registerImageCell: 图片单元格 -* registerProgressBarCell: 进度条单元格 -* registerRadioCell: 单选框单元格 -* registerSparkLineCell: 迷你图单元格 -* registerTextCell: 文字单元格 -* registerVideoCell: 视频单元格 \ No newline at end of file diff --git a/docs/assets/guide/zh/animation/appear_animation.md b/docs/assets/guide/zh/animation/appear_animation.md deleted file mode 100644 index 9034dc963..000000000 --- a/docs/assets/guide/zh/animation/appear_animation.md +++ /dev/null @@ -1,19 +0,0 @@ -# 表格入场动画 - -VTable 提供入场动画功能,支持在表格初始化时展示渐入效果,支持配置动画的方向、时长、延迟等。 - -
- -
- -## 入场动画配置项 - -option中`animationAppear`为入场动画的配置项,目前支持如下各项配置: - -可以配置true开启默认动画,也可以配置动画的参数: -- `type` 入场动画的类型,目前支持 `all` 和 `one-by-one`两种,默认为 `one-by-one` -- `direction` 入场动画的方向,目前支持 `row` 和 `column`两种,默认为 `row` -- `duration` 单个动画的时长,单位为毫秒,`one-by-one` 时,为一次动画的时长,默认为 500 -- `delay` 动画的延迟,单位为毫秒;`one-by-one` 时为两次动画直接的时间差,`all` 时为所有动画的延迟,默认为 0 - -具体使用参考[demo](../demo/animation/appear-animation) \ No newline at end of file diff --git a/docs/assets/guide/zh/basic_function/frozen_column_row.md b/docs/assets/guide/zh/basic_function/frozen_column.md similarity index 100% rename from docs/assets/guide/zh/basic_function/frozen_column_row.md rename to docs/assets/guide/zh/basic_function/frozen_column.md diff --git a/docs/assets/guide/zh/basic_function/row_series_number.md b/docs/assets/guide/zh/basic_function/row_series_number.md index b42186bbc..58114aa6a 100644 --- a/docs/assets/guide/zh/basic_function/row_series_number.md +++ b/docs/assets/guide/zh/basic_function/row_series_number.md @@ -29,8 +29,6 @@ export interface IRowSeriesNumber { // selectRangeInclude?: boolean; /** 是否可拖拽顺序 */ dragOrder?: boolean; - /** 是否禁止列宽调整 */ - disableColumnResize?: boolean; } ``` @@ -45,7 +43,6 @@ export interface IRowSeriesNumber { - headerIcon: 行序号 header 单元格图标 - icon: 行序号 body 单元格图标 - dragOrder: 是否可拖拽行序号顺序,默认为 false。如果设置为 true,会显示拖拽位置的图标,交互在该图标上可以拖拽来换位。如果需要替换该图标可以自行配置。可参考教程:https://visactor.io/vtable/guide/custom_define/custom_icon 中重置功能图标的章节。 -- disableColumnResize: 是否禁止列宽调整,默认为 false 其他被注释的配置项,后续会逐步完善,着急的同志们可参与共建开发。 diff --git a/docs/assets/guide/zh/basic_function/sort/list_sort.md b/docs/assets/guide/zh/basic_function/sort.md similarity index 97% rename from docs/assets/guide/zh/basic_function/sort/list_sort.md rename to docs/assets/guide/zh/basic_function/sort.md index bab9ef0f4..0e1d3c411 100644 --- a/docs/assets/guide/zh/basic_function/sort/list_sort.md +++ b/docs/assets/guide/zh/basic_function/sort.md @@ -1,9 +1,11 @@ -# 基本表格排序功能 +# 表格排序功能 在数据分析过程中,排序( 排序 )功能对数据的组织和协助分析非常重要。通过排序,用户可以快速将关心的数据排列在前面,提高数据查找和分析的效率,同时也能快速发现数据中的异常点和规律。 VTable 提供了丰富的排序功能,用户可以轻松地按需开启、自定义排序规则、设定初始排序状态等。 +**注**:该教程进针对基本表格 ListTable,透视表的排序教程可异步至:https://visactor.io/vtable/guide/table_type/Pivot_table/pivot_table_dataAnalysis + ## 开启排序 要使用 VTable 的排序功能,需要先对表格列进行配置。在 `columns` 中,每一列的配置项需要根据 cellType(列类型)进行设置。在本教程中,我们主要关注排序相关的配置。 @@ -386,9 +388,8 @@ const option = { // 创建 VTable 实例 const tableInstance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); window.tableInstance = tableInstance; -let clickCount = 0; +const clickCount = 0; tableInstance.on('sort_click', args => { - clickCount++; const sortState = clickCount % 3 === 0 ? 'desc' : clickCount % 3 === 1 ? 'asc' : 'normal'; sortRecords(args.field, sortState) .then(records => { @@ -481,7 +482,7 @@ const listTable = new ListTable({ ## 预排序 -在大数据量的情况下,首次排序可能会耗时较长,可以通过预排序来提升排序功能的性能。通过 setSortedIndexMap 方法,设置预排序的数据字段和排序顺序。 +在大数据量的情况下,首次排序可能会耗时较长,可以通过预排序来提升排序功能的性能。通过setSortedIndexMap方法,设置预排序的数据字段和排序顺序。 ```js interface ISortedMapItem { diff --git a/docs/assets/guide/zh/basic_function/sort/pivot_sort.md b/docs/assets/guide/zh/basic_function/sort/pivot_sort.md deleted file mode 100644 index 774282327..000000000 --- a/docs/assets/guide/zh/basic_function/sort/pivot_sort.md +++ /dev/null @@ -1,323 +0,0 @@ -# 透视表排序功能 - -透视表的排序能力以下几种实现方式: - -1. 透视表自定义表头的树形结构,rowTree 和 columnTree 都自行传入即可按照这个结构进行展示。这个时候即便配置了 sortRule 也不会起作用。 -2. 在维度或者指标配置中添加`sort:true`来开启排序,此时会显示排序按钮,点击按钮会触发排序。 -3. 通过接口的方式进行排序:自行调用接口`updateSortRules`来排序。 -4. 其他特殊需求:仅显示排序状态,不使用 VTable 的排序逻辑 - -第一种自行组织表头树形结构的方式在介绍透视表时已经讲过,可以参考教程:https://visactor.io/vtable/guide/table_type/Pivot_table/pivot_table_tree。 - -**注意几种排序方式不要混用** - -接下来主要介绍后面的几种实现方式和注意事项。 - -## 配置 sort 开启排序 - -### 按维度值排序 - -sort 的配置可以在 rows 或者 columns 中配置,此时显示维度名称的角头单元格会显示排序按钮,点击按钮会触发排序。 - -以下是一个在 rows 中配置 sort 开启排序功能的例子: - -```javascript livedemo template=vtable -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option = { - records: data, - rows: [ - { - dimensionKey: 'Category', - title: 'Category', - sort: true - }, - { - dimensionKey: 'Sub-Category', - title: 'Sub-Catogery', - sort: true - } - ], - columns: ['Region', 'Segment'], - indicators: [ - { - indicatorKey: 'Sales', - title: 'Sales' - }, - { - indicatorKey: 'Profit', - title: 'Profit' - } - ], - corner: { - titleOnDimension: 'row', - headerStyle: { - textStick: true - } - }, - defaultColWidth: 130 - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window['tableInstance'] = tableInstance; - }); -``` - -在上述代码中,`sort` 为 `true`,表示行表头对应维度值支持排序,角头的单元格会显示排序图标。 - -### 按指标值排序 - -sort 的配置可以在 indicators 中配置,此时显示指标名称的行表头或者列表头单元格会显示排序按钮,点击按钮会触发排序。 - -以下是一个在 indicators 中配置 sort 开启排序功能的例子: - -```javascript livedemo template=vtable -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option = { - records: data, - rows: ['Category', 'Sub-Category'], - columns: ['Region', 'Segment'], - indicators: [ - { - indicatorKey: 'Sales', - title: 'Sales', - sort: true - }, - { - indicatorKey: 'Profit', - title: 'Profit', - sort: true - } - ], - corner: { - titleOnDimension: 'row', - headerStyle: { - textStick: true - } - }, - defaultColWidth: 130 - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window['tableInstance'] = tableInstance; - }); -``` - -在上述代码中,`sort` 为 `true`,表示可以按指标值支持排序,行表头或者列表头的单元格会显示排序图标。 - -### 初始化排序状态 - -请配置数据分析 dataConfig.sortRule,可以设置初始排序状态。 - -如下示例: - -```javascript livedemo template=vtable -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option = { - records: data, - rows: ['Category', 'Sub-Category'], - columns: ['Region', 'Segment'], - indicators: [ - { - indicatorKey: 'Sales', - title: 'Sales', - sort: true - }, - { - indicatorKey: 'Profit', - title: 'Profit', - sort: true - } - ], - dataConfig: { - sortRules: [ - { - sortField: 'Sub-Category', - sortByIndicator: 'Sales', - sortType: VTable.TYPES.SortType.DESC, - query: ['Central', 'Corporate'] - } - ] - }, - corner: { - titleOnDimension: 'row', - headerStyle: { - textStick: true - } - }, - defaultColWidth: 130 - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window['tableInstance'] = tableInstance; - }); -``` - -该示例配置了初始排序规则,会按照列表头维度路径为`['Central', 'Corporate', 'Sales']` 指标值进行降序排序,同时相应的表头单元格中的排序图标变为了降序状态图标。 - -### 通过接口更新排序 - -透视表的更新排序接口为`updateSortRules`,通过调用该接口可以更新排序状态。 - -以下是一个通过接口更新排序的例子: - -```javascript livedemo template=vtable -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option = { - records: data, - rows: ['Category', 'Sub-Category'], - columns: ['Region', 'Segment'], - indicators: [ - { - indicatorKey: 'Sales', - title: 'Sales', - sort: true - }, - { - indicatorKey: 'Profit', - title: 'Profit', - sort: true - } - ], - corner: { - titleOnDimension: 'row', - headerStyle: { - textStick: true - } - }, - defaultColWidth: 130 - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window['tableInstance'] = tableInstance; - tableInstance.updateSortRules([ - { - sortField: 'Sub-Category', - sortByIndicator: 'Sales', - sortType: VTable.TYPES.SortType.DESC, - query: ['Central', 'Corporate'] - } - ]); - }); -``` - -### 监听排序图标点击事件 - -监听排序图标点击事件为`pivot_sort_click`。 - -## 通过接口进行排序 - -如果需要通过接口进行排序,可以通过调用`updateSortRules`接口来更新排序状态。 - -## 仅显示排序图标 - -如果业务场景中有专门的设置面板,有专门的排序选项提供给用户进行操作,但是需要在表格中显示对应的排序状态,那么可以配置`showSort: true`来显示排序状态。如果有监听图标点击需求,可以监听事件`pivot_sort_click`。 - -同时,可以设置 option 上的 pivotSortState 来设置初始排序图标的状态。 - -下面看用法示例: - -```javascript livedemo template=vtable -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option = { - records: data, - rows: [ - { - dimensionKey: 'Category', - title: 'Category', - showSort: true - }, - { - dimensionKey: 'Sub-Category', - title: 'Sub-Catogery', - showSort: true - } - ], - columns: ['Region', 'Segment'], - indicators: [ - { - indicatorKey: 'Sales', - title: 'Sales', - showSort: true - }, - { - indicatorKey: 'Profit', - title: 'Profit', - showSort: true - } - ], - corner: { - titleOnDimension: 'row', - headerStyle: { - textStick: true - } - }, - pivotSortState: [ - { - dimensions: [ - { - dimensionKey: 'Category', - value: 'Furniture', - isPivotCorner: false, - indicatorKey: undefined - } - ], - order: 'desc' - }, - { - dimensions: [ - { - dimensionKey: 'Region', - value: 'Central', - isPivotCorner: false, - indicatorKey: undefined - }, - { - dimensionKey: 'Segment', - value: 'Consumer', - isPivotCorner: false, - indicatorKey: undefined - }, - { - indicatorKey: 'Sales', - value: 'Sales', - isPivotCorner: false - } - ], - order: 'asc' - } - ], - defaultColWidth: 130 - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window['tableInstance'] = tableInstance; - tableInstance.on('pivot_sort_click', e => { - console.log(e); - // 执行业务逻辑 ... - // 如果执行业务逻辑后还需要更新排序状态,可以先调用updateOption来更新配置,目前还未提供专门更新的接口 - }); - }); -``` - -上述示例中 pivotSortState 配置了两个排序规则,会在行表头维度路径为`['Furniture']`的单元格上显示降序图标,同时会在列表头维度路径为`['Central', 'Consumer', 'Sales']`的单元格上显示升序图标。 - -## 其他 - -这里再强调一下:**几种排序方式不要混用**,例如:sortRule 的方式不要在自定义表头树结构的情况和配置 showSort 的情况下使用;pivotSortState 的配置也不要在配置 sort 的情况下使用。 - -另外,目前排序的方式并不是非常完善的,例如 - -1. 配置`sort:true`的排序方式,有时候需要设置自定义排序函数来执行排序逻辑 -2. 缺失`pivotSortState`配置状态的更新接口 - -这些后续我们都将补充。 diff --git a/docs/assets/guide/zh/basic_function/update_option.md b/docs/assets/guide/zh/basic_function/update_option.md index 8a80f7170..420aaa700 100644 --- a/docs/assets/guide/zh/basic_function/update_option.md +++ b/docs/assets/guide/zh/basic_function/update_option.md @@ -1,19 +1,16 @@ # 如何更新配置项? -在使用 vtable 组件时,配置项的更新是一个常见需求。本教程将介绍三种常用的配置项更新方法,并根据不同的使用场景提供相应的建议。我们将探讨全量更新、单项更新以及批量更新的用法和适用场景。 +在使用vtable组件时,配置项的更新是一个常见需求。本教程将介绍三种常用的配置项更新方法,并根据不同的使用场景提供相应的建议。我们将探讨全量更新、单项更新以及批量更新的用法和适用场景。 ## 全量更新配置项 - 全量更新配置项是通过调用 updateOption() 方法来实现的。该方法需要提供所有的配置项,因此适用于需要对整个配置进行更改的情况。以下是示例代码: - -``` +`````` tableInstance.updateOption({ columns: [], theme: {}, ... }); -``` - +`````` 注意:全量更新会重新布局和渲染整个表格。 **适用场景:** @@ -22,12 +19,10 @@ tableInstance.updateOption({ ## 单项更新配置项 -单项更新配置项是通过调用相应的接口来实现的,例如 `updateTheme()`、`updateColumns()` 等。这些接口在调用后会自动重新布局和渲染表格。以下是示例代码: - +单项更新配置项是通过调用相应的接口来实现的,例如 `updateTheme()`、`updateColumns()`` 等。这些接口在调用后会自动重新布局和渲染表格。以下是示例代码: ``` tableInstance.updateTheme(newTheme); ``` - 注意:调用后会自动布局和渲染。 **适用场景:** @@ -36,12 +31,11 @@ tableInstance.updateTheme(newTheme); ## 批量更新配置项 -批量更新配置项是通过一类特殊的接口来实现的:更新 table 实例属性的方式。这种更新式,我们尽量做到 option 中的每一项都可以更新,如果没有支持到但您有需要的接口可以联系我们或者直接提 issue。 +批量更新配置项是通过一类特殊的接口来实现的:更新table实例属性的方式。这种更新式,我们尽量做到option中的每一项都可以更新,如果没有支持到但您有需要的接口可以联系我们或者直接提issue。 例如 `tableInstance.autoWrapText = true`、`tableInstance.theme = { bodyStyle: { color: 'red' } }`。 这些接口调用后不会自动重新渲染表格,需要配合 `tableInstance.renderWithRecreateCells()` 方法来手动重新布局和渲染。以下是示例代码: - ``` tableInstance.theme = newThemeObj; tableInstance.widthMode = 'autoWidth'; @@ -49,7 +43,6 @@ tableInstance.heightMode = 'autoHeight; tableInstance.autoWrapText = true; tableInstance.renderWithRecreateCells(); ``` - 注意:上述的配置项采用赋值接口更新后不会重新布局及渲染,需要手动调用 renderWithRecreateCells() 方法来重新布局和渲染表格,以有效提高更新逻辑的性能。 **适用场景:** @@ -57,7 +50,6 @@ tableInstance.renderWithRecreateCells(); 当需要批量更新多个配置项时,使用批量更新的方式可以避免多次布局和渲染,提高性能。 ## 总结: +本教程介绍了vtable组件配置项的三种更新方法:全量更新、单项更新和批量更新。根据不同的使用场景,选择合适的更新方式可以提高代码效率和性能。全量更新适用于需要对整个配置进行更改的情况,单项更新适用于修改少数几个配置项的场景,而批量更新适用于批量更新多个配置项的情况,需要调用接口重新布局和渲染。 -本教程介绍了 vtable 组件配置项的三种更新方法:全量更新、单项更新和批量更新。根据不同的使用场景,选择合适的更新方式可以提高代码效率和性能。全量更新适用于需要对整个配置进行更改的情况,单项更新适用于修改少数几个配置项的场景,而批量更新适用于批量更新多个配置项的情况,需要调用接口重新布局和渲染。 - -希望本教程对你理解 vtable 组件的配置项更新有所帮助,如有疑问请随时提问。 +希望本教程对你理解vtable组件的配置项更新有所帮助,如有疑问请随时提问。 \ No newline at end of file diff --git a/docs/assets/guide/zh/components/tooltip.md b/docs/assets/guide/zh/components/tooltip.md index 0c5a7a881..a5f685847 100644 --- a/docs/assets/guide/zh/components/tooltip.md +++ b/docs/assets/guide/zh/components/tooltip.md @@ -1,106 +1,43 @@ -# tooltip 介绍 +# tooltip介绍 在表格组件中,tooltip(信息提示)是一种常见的用户界面元素,用于提供关于特定表格单元格或数据的额外信息。它以一个小型弹出窗口或浮动框的形式出现,当用户将鼠标悬停在特定单元格上或与特定元素交互时,显示相关的提示文本。 -## tooltip 的使用场景 +## tooltip的使用场景 -- 数据解释和描述:某些表格中的数据可能需要额外的解释或描述。Tooltip 可以用于显示这些解释,帮助用户理解数据的含义、单位、计算方法或其他相关信息。 +- 数据解释和描述:某些表格中的数据可能需要额外的解释或描述。Tooltip可以用于显示这些解释,帮助用户理解数据的含义、单位、计算方法或其他相关信息。 -- 溢出内容:当表格中的文本或数据超出单元格的宽度时,可以使用 tooltip 显示完整的内容,以防止截断或隐藏重要信息。 +- 溢出内容:当表格中的文本或数据超出单元格的宽度时,可以使用tooltip显示完整的内容,以防止截断或隐藏重要信息。 -- 可交互元素说明:如果表格中包含可交互的元素(如链接、按钮或图标),Tooltip 可以用于提供这些元素的功能说明或操作提示。 +- 可交互元素说明:如果表格中包含可交互的元素(如链接、按钮或图标),Tooltip可以用于提供这些元素的功能说明或操作提示。 ## 配置项介绍 配置项为: - ``` { /** 提示弹框的相关配置。消失时机:显示后鼠标移动到指定区域外或者进入新的单元格后自动消失*/ tooltip: { /** 渲染方式:如使用html具有较好灵活行,上层可以覆盖样式;canvas具有较好的跨平台展示稳定性 */ - renderMode?: 'html' | 'canvas'; - /** 是否显示缩略文字提示框 */ + renderMode: 'html' | 'canvas'; + /** 代替原来hover:isShowTooltip配置 */ isShowOverflowTextTooltip: boolean; - /** 缩略文字提示框 延迟消失时间 */ - overflowTextTooltipDisappearDelay?: number; /** 弹框是否需要限定在表格区域内 */ confine: boolean; }; } ``` -## tooltip 提示框的样式设置 - -tooltip 的样式配置可以通过 theme.tooltipStyle 来进行设置,具体配置如下: - -``` -export type TooltipStyle = { - fontFamily?: string; - fontSize?: number; - color?: string; - padding?: number[]; - bgColor?: string; - maxWidth?: number; - maxHeight?: number; -}; - -``` - ## 开启溢出内容提示 -VTable 默认开启溢出内容的 tooltip:isShowOverflowTextTooltip 默认为 true。如果需要延迟消失以使得鼠标可以移动到 tooltip 内容上,可以配置 overflowTextTooltipDisappearDelay。 - -![image](https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/c0de7ff0a101bd4cb25c8170e.gif) - -## 自定义图标 hover 提示 - -如配置表头 icon 图标具体如下: - -``` -const tableInstance = new VTable.ListTable({ - columns: [ - { - field: 'orderID', - title: '订单编号', - headerIcon: { - type: 'svg', //指定svg格式图标,其他还支持path,image - svg: ` - - `, - width: 20, - height: 20, - name: 'filter', //定义图标的名称,在内部会作为缓存的key值 - positionType: VTable.TYPES.IconPosition.absoluteRight, // 指定位置,可以在文本的前后,或者在绝对定位在单元格的左侧右侧 - visibleTime: 'mouseenter_cell', // 显示时机, 'always' | 'mouseenter_cell' | 'click_cell' - hover: { - // 热区大小 - width: 26, - height: 26, - bgColor: 'rgba(22,44,66,0.5)' - }, - tooltip: { - style: { arrowMark: false }, - // 气泡框,按钮的的解释信息 - title: '过滤', - placement: VTable.TYPES.Placement.right, - disappearDelay: 1000, - } - } - } - ] -}); -``` -其中 headerIcon 中的 tooltip 即是鼠标 hover 到 icon 上的提示框,同时配置了 disappearDelay 使弹出框可以延迟消失以便得鼠标可以移动到 tooltip 内容上。 +VTable默认开启溢出内容的tooltip:isShowOverflowTextTooltip默认为true。 -关于 icon 的配置具体参考教程:https://visactor.io/vtable/guide/custom_define/custom_icon。 +![image](https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/c0de7ff0a101bd4cb25c8170e.gif) -## 通过接口显示 tooltip 自定义信息 +## 通过接口显示tooltip自定义信息 -接口 showTooltip 可主动显示 tooltip 信息,如下使用方式:(监听单元格 hover 事件,调用接口) +接口showTooltip可主动显示tooltip信息,如下使用方式:(监听单元格hover事件,调用接口) [参考接口说明](https://visactor.io/vtable/option/Methods#showTooltip) - ``` tableInstance.on('mouseenter_cell', (args) => { const { col, row, targetIcon } = args; @@ -120,31 +57,5 @@ const tableInstance = new VTable.ListTable({ } }); ``` - 效果: ![image](https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/ffc3a9b5518762d274121ff05.gif) - -## icon 的 tooltip 配置 - -当自定义 icon 时,可以通过配置 tooltip 来显示提示信息,如下使用方式: - -``` -VTable.register.icon('order', { - ... //其他配置 - tooltip: { - // 气泡框,按钮的的解释信息 - title:'Order ID is the unique identifier for each order', - style: { - fontSize: 14, - fontFamily: 'Arial', - padding: [10,10,10,10], - bgColor: 'black', - arrowMark: true, - color: 'white', - maxHeight: 100, - maxWidth: 200 - }, - disappearDelay: 1000 - } -}) -``` diff --git a/docs/assets/guide/zh/custom_define/custom_icon.md b/docs/assets/guide/zh/custom_define/custom_icon.md index 600730526..5e4eb66b1 100644 --- a/docs/assets/guide/zh/custom_define/custom_icon.md +++ b/docs/assets/guide/zh/custom_define/custom_icon.md @@ -10,7 +10,7 @@ - `icon` 则用于配置 body 单元格的图标。 -配置具体内容为`ColumnIconOption`类型的对象,也可以通过传递一个自定义函数,动态设置单元格的图标样式。ColumnIconOption 具体定义可以参考:https://visactor.io/vtable/option/ListTable-columns-text#icon +配置具体内容为[ColumnIconOption]() 类型的对象,也可以通过传递一个自定义函数,动态设置单元格的图标样式。 ### 表头图标配置示例 @@ -84,7 +84,7 @@ const tableInstance = new VTable.ListTable({ 这个示例中,我们为单元格配置了一个名为 `Avatar` 的图标。该图标的作用是用来显示头像图片,图片 src 的值是从 records 的 avator 的字段中获取到的。 -在线 demo:https://visactor.io/vtable/demo/custom-render/custom-icon +效果图片:TODO ## 如何注册 icon 及注册后的使用 @@ -192,7 +192,8 @@ VTable.register.icon('frozenCurrent', { }); ``` -替换后的效果在 demo 中查看:https://visactor.io/vtable/demo/custom-render/custom-icon +替换后的效果如: +TODO 同样的方法,我们可以替换其他功能性图标。在 VTable 中内置了几种关联内部功能的图标,如排序,固定列,下拉菜单图标,展开折叠图标等。 @@ -228,6 +229,6 @@ VTable.register.icon('frozenCurrent', { ] ``` -**注意:同时自己业务中注册的图标,不需要配置`funcType`。** +同时自己业务中注册的图标,不需要配置`funcType`。 至此,关于 VTable 中 icon 的使用方法、注册和替换功能图标的教程就全部介绍完毕。希望本教程能帮助您更好地理解和使用 VTable,打造出更加优美、实用的数据可视化表格 diff --git a/docs/assets/guide/zh/custom_define/custom_layout.md b/docs/assets/guide/zh/custom_define/custom_layout.md index 5cbf85b32..b2e023076 100644 --- a/docs/assets/guide/zh/custom_define/custom_layout.md +++ b/docs/assets/guide/zh/custom_define/custom_layout.md @@ -41,7 +41,7 @@ customLayout 函数返回一个对象,该对象需要有:`rootContainer`来 customLayout: args => { const { table, row, col, rect } = args; const { height, width } = rect ?? table.getCellRect(col, row); - const record = table.getCellOriginRecord(col, row); + const record = table.getRecordByCell(col, row); const container = ( - -

自定义小计总计示例代码

-
- -具体示例:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-custom-total - ### 2. 排序规则 -VTable 的透视表支持四种排序方式:维度值自然排序、指定维度值顺序,指标值排序、自定义排序。 - -定义可以参考: - -[option 说明](../../option/PivotTable#dataConfig.sortRules) [使用教程](../../guide/basic_function/sort/pivot_sort) - -指标值排序配置示例如下: +[option 说明](../../../option/PivotTable#dataConfig.sortRules) +配置示例: ``` sortRules: [ @@ -137,8 +119,7 @@ VTable 的透视表支持四种排序方式:维度值自然排序、指定维 ### 3. 过滤规则 -[option 说明](../../option/PivotTable#dataConfig.filterRules) - +[option 说明](../../../option/PivotTable#dataConfig.filterRules) 配置示例: ``` @@ -155,8 +136,7 @@ filterRules: [ ### 4. 聚合方式 -[option 说明](../../option/PivotTable#dataConfig.aggregationRules) - +[option 说明](../../../option/PivotTable#dataConfig.aggregationRules) 配置示例: ``` @@ -188,49 +168,15 @@ filterRules: [ indicatorKey: 'OrderSalesValue', //指标名称 field: 'Sales', //指标依据字段 aggregationType: VTable.TYPES.AggregationType.NONE, //不做聚合 匹配到其中对应数据获取其对应field的值 - }, - { - indicatorKey: 'orderRecords', //指标名称 - field: 'Sales', //指标依据字段 - aggregationType: VTable.TYPES.AggregationType.RECORD, //不做聚合 匹配到其中对应的全部数据作为单元格的值 } ] ``` 具体示例:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-aggregation -**特别提示:** - -1. AggregationType.NONE 指标不做聚合的使用场景主要用于根据用户传入数据 record 获取的原始数据进行展示,如: - -``` -records:[{ - region: '中南', - province: '广西', - year: '2016', - quarter: '2016-Q1', - sales: 'NULL', - profit: 1546 -}], -dataConfig:{ - aggregationRules: [ - { - indicatorKey: 'sales', //指标名称 - field: 'sales', //指标依据字段 - aggregationType: VTable.TYPES.AggregationType.NONE, //不做聚合 匹配到其中对应数据获取其对应field的值 - } - ] -} -``` - -其中该条 record 中 sales 指标是个非数值型的值,而且需求要将`"NULL"`直接显示到表格单元格中,那么可以设置 NONE,要求 VTable 的内部聚合逻辑不聚合直接取`sales`字段值。 - -2. AggregationType.RECORD 指标不做聚合的使用场景主要用于根据用户传入数据 record 匹配到所有数据,将其作为单元格的展示数据,用法场景如需要搜集数据集作为迷你图展示,具体 demo 见:https://visactor.io/vtable/demo/cell-type/pivot-sparkline - ### 5. 派生字段 -[option 说明](../../option/PivotTable#dataConfig.derivedFieldRules) - +[option 说明](../../../option/PivotTable#dataConfig.derivedFieldRules) 配置示例: ``` @@ -248,34 +194,6 @@ dataConfig:{ 具体示例:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-derivedField -### 6. 透视表计算字段 - -[option 说明](../../option/PivotTable#dataConfig.calculatedFieldRules) - -配置示例: - -``` - dataConfig: { - calculatedFieldRules: [ - { - key: 'AvgPrice', - dependIndicatorKeys: ['Quantity', 'Sales'], - calculateFun: dependValue => { - return dependValue.Sales / dependValue.Quantity; - } - } - ], - } -``` - -配置解释说明: - -- key: 计算字段的 key 唯一标识,可以当做新指标,用于配置在 indicators 中在透视表中展示。 -- dependIndicatorKeys:计算字段依赖的指标,可以是在 records 中具体对应的指标字段。如果依赖的指标不在 records 中,则需要在 aggregationRules 中配置,具体指明聚合规则和 indicatorKey 以在 dependIndicatorKeys 所使用。 -- calculateFun:计算字段的计算函数,依赖的指标值作为参数传入,返回值作为计算字段的值。 - -具体示例:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-calculatedField - ## 数据分析过程 依赖配置:维度,指标及 dataConfig。 @@ -303,10 +221,20 @@ dataConfig:{

数据源条目和单元格的对应关系

+<<<<<<< HEAD + +### 自定义维度树 + +======= + ### 自定义表头维度树 +> > > > > > > origin/develop + 虽然具有分析能力的多维表格可以自动分析各个维度的维度值组成行列表头的树形结构,并且可以根据`dataConfig.sortRules`进行排序,但具有复杂业务逻辑的场景还是期望可以能够**自定义行列表头维度值**及顺序。那么可以通过 rowTree 和 columnTree 来实现这些业务需求场景。 +- enableDataAnalysis 需设置为 false 来关闭 VTable 内部聚合数据的分析,提升一定的性能。 +

custom rowTree columnTree

@@ -379,7 +307,7 @@ const option = { ] }], indicators: ['sales', 'profit'], - + //enableDataAnalysis:true, corner: { titleOnDimension: 'none' }, @@ -454,6 +382,8 @@ VTable 官网示例:https://visactor.io/vtable/demo/table-type/pivot-table. 自定义树的复杂在于组建行列维度树,可酌情根据业务场景来选择使用,如果具有复杂的排序、汇总或分页规则可选择使用自定义方式。 +**注意:如果选择自定义树的配置方式将不开启 VTable 内部的数据聚合能力,即匹配到的数据条目中的某一条作为单元格指标值。** + ## 其他相关配置 ### 上钻下钻 @@ -463,9 +393,3 @@ VTable 官网示例:https://visactor.io/vtable/demo/table-type/pivot-table. 在维度配置 rows 或者 columns 中加上 drillDown 的配置项来显示下载按钮,监听点击图标按钮事件`drillmenu_click`,根据事件参数`drillDown` 或者 `drillUp`来确定是维度下钻还是上卷,根据参数`dimensionKey`确定下钻或上钻的维度,将其添加或者删除到 rows 或者 columns 中,并获取新维度层级对应数据源,并调用接口`updateOption`将新的 option 更新至表格。 具体 demo:https://visactor.io/vtable/demo/data-analysis/pivot-analysis-table-drill - -## 相关接口 - -### getCellOriginRecord - -可以帮助获取单元格聚合值对应的原始数据条目。 diff --git a/docs/assets/guide/zh/edit/edit_cell.md b/docs/assets/guide/zh/edit/edit_cell.md index 99a8674ca..124b59528 100644 --- a/docs/assets/guide/zh/edit/edit_cell.md +++ b/docs/assets/guide/zh/edit/edit_cell.md @@ -6,8 +6,6 @@ ## 1. 引用 VTable 的编辑器包: -### 使用 NPM 包 - 首先,确保已经正确安装了 VTable 库@visactor/vtable 和相关的编辑器包@visactor/vtable-editors。你可以使用以下命令来安装它们: ```shell @@ -22,34 +20,22 @@ yarn add @visactor/vtable-editors 在代码中引入所需类型的编辑器模块: ```javascript -import { DateInputEditor, InputEditor, ListEditor, TextAreaEditor } from '@visactor/vtable-editors'; -``` - -### 使用 CDN - -你还可以通过 CDN 获取构建好的 VTable-Editor 文件。 - -```html - - +import { DateInputEditor, InputEditor, ListEditor } from '@visactor/vtable-editors'; ``` ## 2. 创建编辑器: -VTable-ediotrs 库中目前提供了四种编辑器类型,包括文本输入框、多行文本输入框、日期选择器、下拉列表等。你可以根据需要选择合适的编辑器。(下拉列表编辑器效果还在优化中,目前比较丑哈) +VTable-ediotrs 库中目前提供了三种编辑器类型,包括文本输入框、日期选择器、下拉列表等。你可以根据需要选择合适的编辑器。(下拉列表编辑器效果还在优化中,目前比较丑哈) 以下是创建编辑器的示例代码: ```javascript const inputEditor = new InputEditor(); -const textAreaEditor = new TextAreaEditor(); const dateInputEditor = new DateInputEditor(); const listEditor = new ListEditor({ values: ['女', '男'] }); ``` -在上面的示例中,我们创建了一个文本输入框编辑器(`InputEditor`)、一个多行文本框编辑器(`TextAreaEditor`)、 一个日期选择器编辑器(`DateInputEditor`)和一个下拉列表编辑器(`ListEditor`)。你可以根据实际需求选择适合的编辑器类型。 +在上面的示例中,我们创建了一个文本输入框编辑器(`InputEditor`)、一个日期选择器编辑器(`DateInputEditor`)和一个下拉列表编辑器(`ListEditor`)。你可以根据实际需求选择适合的编辑器类型。 ## 3. 注册并使用编辑器: @@ -59,7 +45,6 @@ const listEditor = new ListEditor({ values: ['女', '男'] }); // 注册编辑器到VTable VTable.register.editor('name-editor', inputEditor); VTable.register.editor('name-editor2', inputEditor2); -VTable.register.editor('textArea-editor', textAreaEditor); VTable.register.editor('number-editor', numberEditor); VTable.register.editor('date-editor', dateInputEditor); VTable.register.editor('list-editor', listEditor); @@ -77,7 +62,6 @@ columns: [ } }, { title: 'age', field: 'age', editor: 'number-editor' }, { title: 'gender', field: 'gender', editor: 'list-editor' }, - { title: 'address', field: 'address', editor: 'textArea-editor' }, { title: 'birthday', field: 'birthDate', editor: 'date-editor' }, ] ``` diff --git a/docs/assets/guide/zh/export/excel.md b/docs/assets/guide/zh/export/excel.md index e8b67640b..afe10713b 100644 --- a/docs/assets/guide/zh/export/excel.md +++ b/docs/assets/guide/zh/export/excel.md @@ -17,13 +17,13 @@ import { downloadExcel, exportVTableToExcel } from '@visactor/vtable-export'; const tableInstance = new VTable.ListTable(option); // donload csv file -downloadExcel(exportVTableToExcel(tableInstance, optionForExport), 'export-csv'); +downloadExcel(exportVTableToExcel(tableInstance), 'export-csv'); ``` -* `exportVTableToExcel`:表格输出工具,将表格实例输出为一个Excel格式的ArrayBuffer;option为可选参数,详见下方配置项 +* `exportVTableToExcel`:表格输出工具,将表格实例输出为一个Excel格式的ArrayBuffer * `downloadExcel`:下载工具,在浏览器环境中将Excel格式的ArrayBuffer下载为文件 * 如果是服务端环境,可以自行处理`exportVTableToExcel`转换出的Excel格式的ArrayBuffer -* 目前excel导出功能正在完善中,目前只支持文字类型的单元格导出,后续会支持迷你图等更多类型 +* 目前excel导出功能正在完善中,目前只支持文字类型的单元格导出,后续会支持迷你图等更多类型。 参考[demo](../../demo/export/table-export) @@ -40,71 +40,4 @@ downloadExcel(exportVTableToExcel(tableInstance, optionForExport), 'export-csv') ```js const { downloadCsv, exportVTableToCsv } = VTable.export; // ...... -``` - -## 配置项 - -### ignoreIcon - -默认情况下,单元格中有图标时,图标和文字会统一当做图片被导出;如果不需要导出图标,可以设置`ignoreIcon`为true,只输出文字 - -### formatExportOutput - -默认情况下,表格导出时,会将导出单元格的内文字或图片输出到Excel中,如果需要自定义导出内容,可以设置`formatExportOutput`为一个函数,函数的参数为单元格信息,函数的返回值为导出字符串,如果返回`undefined`,则按照默认导出逻辑处理 - -```ts -type CellInfo = { - cellType: string; - cellValue: string; - table: IVTable; - col: number; - row: number; -}; - -type ExportVTableToExcelOptions = { - // ...... - formatExportOutput?: (cellInfo: CellInfo) => string | undefined; -}; -``` - -```js -const excelOption = { - formatExportOutput: ({ cellType, cellValue, table, col, row }) => { - if (cellType === 'checkbox') { - return table.getCellCheckboxState(col, row) ? 'true' : 'false'; - } - } -}; -downloadExcel(await exportVTableToExcel(tableInstance, excelOption)); -``` - -### formatExcelJSCell - -对于导出样式有进一步的定制化需求的话,可以设置`formatExcelJSCell`为一个函数,函数的参数为单元格信息和ExcelJS的单元格对象,函数的返回值为ExcelJS的单元格对象,如果返回`undefined`,则按照默认导出逻辑处理。可以在函数中自动设置ExcelJS的单元格属性,具体可以参考 https://github.com/exceljs/exceljs?tab=readme-ov-file#styles - -```ts -type CellInfo = { - cellType: string; - cellValue: string; - table: IVTable; - col: number; - row: number; -}; - -type ExportVTableToExcelOptions = { - // ...... - formatExceljsCell?: (cellInfo: CellInfo, cellInExceljs: ExcelJS.Cell) => ExcelJS.Cell; -}; -``` - -```js -const excelOption = { - formatExcelJSCell: (cellInfo, cell) => { - if (cellInfo.col === 1) { - cell.numFmt = '0.00%'; - } - return cell; - } -}; -downloadExcel(await exportVTableToExcel(tableInstance, excelOption)); ``` \ No newline at end of file diff --git a/docs/assets/guide/zh/interaction/scroll.md b/docs/assets/guide/zh/interaction/scroll.md index 811b7e0e8..682194759 100644 --- a/docs/assets/guide/zh/interaction/scroll.md +++ b/docs/assets/guide/zh/interaction/scroll.md @@ -14,7 +14,6 @@ VTable 提供了丰富的滚动样式配置项,用户可以按照自己的需 - scrollRailColor: 配置滚动条轨道的颜色。 - scrollSliderColor:配置滚动条滑块的颜色。 -- scrollSliderCornerRadius:滚动条滑块的圆角半径 - width:配置滚动条宽度。 - visible:配置滚动条是否可见,可配值:'always' | 'scrolling' | 'none' | 'focus',分别对应:常驻显示|滚动时显示|显示|聚焦在画布上时。默认为‘scrolling’。 - hoverOn :指定滚动条是悬浮在容器上,还是独立于容器。默认为 true 即悬浮于容器上。 diff --git a/docs/assets/guide/zh/interaction/select.md b/docs/assets/guide/zh/interaction/select.md index 072ec4384..899b5619c 100644 --- a/docs/assets/guide/zh/interaction/select.md +++ b/docs/assets/guide/zh/interaction/select.md @@ -8,40 +8,33 @@ 如上图所示,点击单元格 (2, 3) 后,该单元格被选中。 -点击表头单元格的行为默认会选中整行或者整列,如果只想选中当前单元格可以设置 select.headerSelectMode 为'cell'。 - +点击表头单元格的行为默认会选中整行或者整列,如果只想选中当前单元格可以设置select.headerSelectMode为'cell'。 ## 鼠标框选 -除了点击单个单元格外,VTable 还支持鼠标框选,可以通过拖动鼠标选择多个单元格。此功能允许用户一次性选择并多个单元格(按住 ctrl 或者 shift 进行多选)。默认情况下,VTable 开启了鼠标框选功能。 +除了点击单个单元格外,VTable 还支持鼠标框选,可以通过拖动鼠标选择多个单元格。此功能允许用户一次性选择并多个单元格(按住ctrl或者shift进行多选)。默认情况下,VTable 开启了鼠标框选功能。 ![image](https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/eb08aeafba39ab34c8a08c60f.png) 如上图所示,用户通过拖动鼠标选择了多个元格。 ## 调用接口选择 - 某项业务场景,如与其他模块联动选择,并不是手动鼠标触发选择,可以借助接口来完成选中。 - ### 单个单元格选中 用法如下: - ``` // 选中4列5行的单元格 tableInstance.selectCell(4,5); ``` - ### 单元格范围选中 -调用接口 selectCells,用法如下: - +调用接口selectCells,用法如下: ``` // 表格中的两个范围:从列1行2到列4行2 从列3行5到列7行8 tableInstance.selectCells([{start:{col:1,row:2},end:{col:4,row:2}},{start:{col:3,row:5},end:{col:7,row:8}}]); ``` ### 清除当前选中 - 调用接口`clearSelected` ## 选中样式 @@ -66,50 +59,6 @@ const = new VTable.ListTable({ 如上图所示,选中的单元格背景颜色为紫色。 -## 选中高亮整行整列 - -点击单元格,可能有高亮整行或者整列的需求,可以通过如下配置实现: - -``` -select: { - highlightMode: 'cross' // 可以配置为'cross' 或者 'row' 或者 'column' -} -``` - -注意:如果选中多个单元格高亮效果会消失。 - -高亮的样式可在样式中配置。 - -全局配置:`theme.selectionStyle`中,具体配置方式: - -``` -theme:{ - selectionStyle:{ - inlineRowBgColor: 'rgb(160,207,245)', - inlineColumnBgColor: 'rgb(160,207,245)' - } -} -``` - -也可以按表头 headerStyle 及 bodyStyle 分别配置,具体配置方式: - -``` -theme:{ - headerStyle: { - select: { - inlineRowBgColor: 'rgb(0,207,245)', - inlineColumnBgColor: 'rgb(0,207,245)' - } - }, - bodyStyle: { - select: { - inlineRowBgColor: 'rgb(0,207,245)', - inlineColumnBgColor: 'rgb(0,207,245)' - } - } -} -``` - ## 选择复制单元格内容 VTable 提供了复制快捷键功能,用户可以通过设置 `keyboardOptions.copySelected` 为 `true`,来开启快捷键复制功能: @@ -130,13 +79,9 @@ const table = new VTable.ListTable({ 在对表格数据进行操作时,用户可能希望通过快捷键全选表格中的所有内容。开启全选功能允许用户通过按住 Ctrl 键并按下 A 键,一次性选择表格中的所有内容。需要注意的是,默认是关闭该功能的,使用以下配置开启全选功能: -``` keyboardOptions: { - selectAllOnCtrlA?: boolean | SelectAllOnCtrlAOption; + selectAllOnCtrlA: false; } -``` - -如果不想同时选中表头或者行号列 可以按照`SelectAllOnCtrlAOption`进行配置。 ## 禁止选择交互 @@ -164,6 +109,6 @@ const table = new VTable.ListTable({ 禁止选择交互后,用户无法通过点击或拖动鼠标来选择单元格。 -再有特殊需求不希望用户能够选择表格中的某些列。针对这种需求,VTable 提供了一个在列上的配置项 column.disableSelect 及 disableHeaderSelect,允许我们禁止某一列的选择【透视表无此配置】。 +再有特殊需求不希望用户能够选择表格中的某些列。针对这种需求,VTable 提供了一个在列上的配置项column.disableSelect及disableHeaderSelect,允许我们禁止某一列的选择【透视表无此配置】。 至此,我们已经介绍了 VTable 的选择单元格功能,包括鼠标点击选择、鼠标框选、禁止选择交互、选中样式以及选择复制单元格内容。通过掌握这些功能,您可以更便捷地在 VTable 中进行数据分析与处理。 diff --git a/docs/assets/guide/zh/shortcut.md b/docs/assets/guide/zh/shortcut.md index f902db744..92fd0232d 100644 --- a/docs/assets/guide/zh/shortcut.md +++ b/docs/assets/guide/zh/shortcut.md @@ -28,7 +28,7 @@ keyboardOptions: { /** 上下左右方向键,默认不开启即false。开启这个配置的话,如果当前是在编辑中的单元格,方向键可以移动到下个单元格并进入编辑状态,而不是编辑文本内字符串的光标移动 */ moveEditCellOnArrowKeys?: boolean; /** 开启快捷键全选 默认:false */ - selectAllOnCtrlA?: boolean | SelectAllOnCtrlAOption; + selectAllOnCtrlA?: boolean; /** 快捷键复制 默认false 不开启*/ copySelected?: boolean; //这个copy是和浏览器的快捷键一致的 /** 快捷键粘贴。粘贴内容到指定位置(即需要有选中状态),支持批量粘贴。 默认:false */ diff --git a/docs/assets/guide/zh/table_type/Pivot_table/custom_header.md b/docs/assets/guide/zh/table_type/Pivot_table/custom_header.md index d364960a3..42bd4c47e 100644 --- a/docs/assets/guide/zh/table_type/Pivot_table/custom_header.md +++ b/docs/assets/guide/zh/table_type/Pivot_table/custom_header.md @@ -80,7 +80,7 @@ const option = { } ], indicators: ['sales', 'profit'], - + //enableDataAnalysis:true, corner: { titleOnDimension: 'none' }, @@ -159,81 +159,4 @@ VTable 官网示例:https://visactor.io/vtable/demo/table-type/pivot-table. 如果 rowHierarchyType 设置为 tree,并且期望点击展开节点时懒加载,那么也需要使用自定义表头的透视表,具体 demo 可参考: https://visactor.io/vtable/demo/table-type/pivot-table-tree-lazy-load 。 -# 虚拟表头节点 - -在数据透视分析的一些场景中,并不是需要展示的表格结构和数据能完美匹配,例如:有可能透视表只有行维度和指标值,当指标值的字段又非常多的时候,希望通过自定义列头的形式对指标进行分组。而实际上列上的表头都是虚拟的,数据 records 并没有对应的维度字段来关联,层级数也不确定。 - -基于此场景下 VTable 提供了虚拟表头节点的功能,通过虚拟表头节点可以实现对列上的表头进行分组,具体示例可参考: URL_ADDRESS 。 - -只需要将 rowTree columnTree 中的节点配置时添加 `virtual: true` 即可。 - -如: - -``` - rowTree: [ - { - dimensionKey: 'Segment-1', - value: 'Segment-1 (virtual-node)', - virtual: true, - children: [ - { - indicatorKey: 'Quantity', - value: 'Quantity' - }, - { - indicatorKey: 'Sales', - value: 'Sales' - }, - { - indicatorKey: 'Profit', - value: 'Profit' - } - ] - } - ], -``` - -具体 demo:https://visactor.io/vtable/demo/table-type/pivot-table-virtual-header - -# 自定义树补全指标节点 - -默认情况下,VTable 会自动补全指标节点,如用户可以传入一个维度树,但是不带又指标节点: - -``` - rowTree: [ - { - dimensionKey: 'Region', - value: 'North', - } - ], -``` - -同时用户在 indicators 中配置了指标信息: - -``` -indicators: ['Sales', 'Profit'], -indicatorsAsCol:false, -``` - -VTable 会自动补全指标节点到行维度表头树中: - -``` - rowTree: [ - { - dimensionKey: 'Region', - value: 'North', - children: [ - { - indicatorKey: 'Sales', - value: 'Sales' - }, - { - indicatorKey: 'Profit', - value: 'Profit' - } - ] - } - ], -``` - -如果不需要自动补全指标节点,可通过设置 `supplementIndicatorNodes: false` 来关闭自动补全。 +**注意:如果选择自定义树的配置方式将不开启 VTable 内部的数据聚合能力,即匹配到的数据条目中的某一条作为单元格指标值。** diff --git a/docs/assets/guide/zh/table_type/Pivot_table/pivot_table_dataAnalysis.md b/docs/assets/guide/zh/table_type/Pivot_table/pivot_table_dataAnalysis.md index 6ca91bfc6..f74c007ee 100644 --- a/docs/assets/guide/zh/table_type/Pivot_table/pivot_table_dataAnalysis.md +++ b/docs/assets/guide/zh/table_type/Pivot_table/pivot_table_dataAnalysis.md @@ -224,6 +224,8 @@ filterRules: [ 虽然具有分析能力的多维表格可以自动分析各个维度的维度值组成行列表头的树形结构,并且可以根据`dataConfig.sortRules`进行排序,但具有复杂业务逻辑的场景还是期望可以能够**自定义行列表头维度值**及顺序。那么可以通过 rowTree 和 columnTree 来实现这些业务需求场景。 +- enableDataAnalysis 需设置为 false 来关闭 VTable 内部聚合数据的分析,提升一定的性能。 +

custom rowTree columnTree

@@ -369,3 +371,5 @@ const option = { VTable 官网示例:https://visactor.io/vtable/demo/table-type/pivot-table. 自定义树的复杂在于组建行列维度树,可酌情根据业务场景来选择使用,如果具有复杂的排序、汇总或分页规则可选择使用自定义方式。 + +**注意:如果选择自定义树的配置方式将不开启 VTable 内部的数据聚合能力,即匹配到的数据条目中的某一条作为单元格指标值。** diff --git a/docs/assets/guide/zh/table_type/Pivot_table/pivot_table_useage.md b/docs/assets/guide/zh/table_type/Pivot_table/pivot_table_useage.md index f68809600..0e789a9aa 100644 --- a/docs/assets/guide/zh/table_type/Pivot_table/pivot_table_useage.md +++ b/docs/assets/guide/zh/table_type/Pivot_table/pivot_table_useage.md @@ -23,6 +23,8 @@ 下面是一个简单的示例,演示如何使用透视表来展示数据: +- enableDataAnalysis 需设置为 true + ```javascript livedemo template=vtable const data = [ { @@ -817,6 +819,7 @@ const option = { } }, widthMode: 'standard', + enableDataAnalysis: true, defaultHeaderColWidth: 150, rowHierarchyIndent: 20, rowHierarchyTextStartAlignment: true @@ -828,6 +831,8 @@ const tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID 在下面示例中为了让表头各维度值的显示顺序符合需求,我们设置了 rowTree 和 columnTree 两个字段,分别表示行表头和列表头的树结构。可以看出和上面 VTable 分析出的树结构纬度值显示顺序的差别。 +- enableDataAnalysis 需设置为 false + ```javascript livedemo template=vtable const data = [ { diff --git a/docs/assets/guide/zh/theme_and_style/style.md b/docs/assets/guide/zh/theme_and_style/style.md index 48ec6b6b1..9bde5bc15 100644 --- a/docs/assets/guide/zh/theme_and_style/style.md +++ b/docs/assets/guide/zh/theme_and_style/style.md @@ -128,13 +128,7 @@ style 提供了一系列的单元格配置式,简要介绍如下。 ### 最大行数设置 -- `lineClamp`:设置单元的最大行数, 可设置 number 或者 'auto',设置为 'auto',则会自动计算 - -### 单元格内边距 - -- `padding`:定义单元格的内边距 - -单元格的宽高是包括了两部分,padding 内边距和内容 +- `lineamp`:设置单元的最大行数, 可设置 number 或者 'auto',设置为 'auto',则会自动计算 通过以上介绍,您已经掌握了 VTable 中样式 Style 的使用方法,接来就可以根据需求创建具有个性化风格的表格。 diff --git a/docs/assets/guide/zh/theme_and_style/theme.md b/docs/assets/guide/zh/theme_and_style/theme.md index 7b232debb..f81afee25 100644 --- a/docs/assets/guide/zh/theme_and_style/theme.md +++ b/docs/assets/guide/zh/theme_and_style/theme.md @@ -73,7 +73,7 @@ VTable 中内置一套默认主题/DEFAULT,一套 ARCO 风格,一套暗黑 具体配置内容可查看:https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/themes/ARCO.ts,注意改该主题有阴影占位,frameStyle中配置了shadowBlur的宽度。 // 使用默认主题 - option.theme = VTable.themes.ARCO; + option.theme = vTable.themes.ARCO; const tableInstance = new VTable.ListTable(option); @@ -82,7 +82,7 @@ VTable 中内置一套默认主题/DEFAULT,一套 ARCO 风格,一套暗黑 具体配置内容可查看:https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/themes/DARK.ts // 使用默认主题 - option.theme = VTable.themes.DARK; + option.theme = vTable.themes.DARK; const tableInstance = new VTable.ListTable(option); @@ -91,7 +91,7 @@ VTable 中内置一套默认主题/DEFAULT,一套 ARCO 风格,一套暗黑 具体配置内容可查看:https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/themes/BRIGHT.ts // 使用默认主题 - option.theme = VTable.themes.BRIGHT; + option.theme = vTable.themes.BRIGHT; const tableInstance = new VTable.ListTable(option); @@ -100,7 +100,7 @@ VTable 中内置一套默认主题/DEFAULT,一套 ARCO 风格,一套暗黑 具体配置内容可查看:https://github.com/VisActor/VTable/blob/develop/packages/vtable/src/themes/SIMPLIFY.ts // 使用默认主题 - option.theme = VTable.themes.SIMPLIFY; + option.theme = vTable.themes.SIMPLIFY; const tableInstance = new VTable.ListTable(option); @@ -114,7 +114,7 @@ VTable 中内置一套默认主题/DEFAULT,一套 ARCO 风格,一套暗黑 ``` -option.theme = VTable.themes.DEFAULT.extends({ headerStyle:{ color: 'red'}}) +option.theme = vTable.themes.DEFAULT.extends({ headerStyle:{ color: 'red'}}) const tableInstance = new vTable.ListTable(option); ``` diff --git a/docs/assets/option/en/column/base-column-type.md b/docs/assets/option/en/column/base-column-type.md index cfb81910b..4d6bc85c5 100644 --- a/docs/assets/option/en/column/base-column-type.md +++ b/docs/assets/option/en/column/base-column-type.md @@ -85,18 +85,16 @@ icon?: | ((args: CellInfo) => string | ColumnIconOption | (string | ColumnIconOption)[]); ``` -#${prefix} ColumnIconOption +#${prefix} ColumnIconOption definition: ``` type ColumnIconOption = ImageIcon | SvgIcon; ``` #${prefix} ImageIcon(Object) -type is set to 'image'. The image address needs to be set in src {{ use: image-icon( prefix = '##' + ${prefix}) }} #${prefix} SvgIcon(Object) -type is set to 'svg'. You need to configure the svg address or the complete svg file string in svg {{ use: svg-icon( prefix = '##' + ${prefix}) }} ${prefix} sort(boolean|Function) @@ -251,9 +249,4 @@ Data aggregation summary configuration to analyze the column data. Global options can also be configured to configure aggregation rules for each column. -Please refer to [the tutorial document](https://visactor.io/vtable/guide/data_analysis/list_table_dataAnalysis) - -${prefix} hide(boolean) = false -Not required. - -Weather hide column. \ No newline at end of file +Please refer to the tutorial document diff --git a/docs/assets/option/en/common/empty-tip-define.md b/docs/assets/option/en/common/empty-tip-define.md deleted file mode 100644 index 0e2807ad7..000000000 --- a/docs/assets/option/en/common/empty-tip-define.md +++ /dev/null @@ -1,23 +0,0 @@ -{{ target: common-emptyTip }} - -#${prefix} text(string) -Empty data describes the content. - -#${prefix} textStyle(object) -Describes the text style. - -- color: string configurable font color; -- fontSize:number configurable font size; -- fontFamily: string configurable font; - -fontWeight: string | number; -- fontVariant?: string; font weight -- lineHeight?: number line height -- underline?: number; underline -- lineThrough?: number; dash - -#${prefix} icon(object) -Empty data icon. - -- width?: number; icon height -- height?: number; the height of the icon -- image?: string; image URL or inline SVG content diff --git a/docs/assets/option/en/common/option-important.md b/docs/assets/option/en/common/option-important.md index 196f2db3b..fe0080625 100644 --- a/docs/assets/option/en/common/option-important.md +++ b/docs/assets/option/en/common/option-important.md @@ -3,3 +3,7 @@ #${prefix} container(HTMLElement) Container DOM, requires width. + +#${prefix} clearDOM(boolean) = true + +Whether to clear the container DOM. \ No newline at end of file diff --git a/docs/assets/option/en/common/option-secondary.md b/docs/assets/option/en/common/option-secondary.md index b5663dc8d..e5b17ae20 100644 --- a/docs/assets/option/en/common/option-secondary.md +++ b/docs/assets/option/en/common/option-secondary.md @@ -30,14 +30,6 @@ The height adaptable strategy in adaptive mode, default is 'only-body'. - 'only-body': Only the rows in the body part participate in the height adaptation calculation, and the height of the header part remains unchanged. - 'all': All columns participate in the height adaptation calculation. -#${prefix} columnWidthComputeMode('normal' | 'only-header' | 'only-body') = 'normal' - -When calculating the content width, the limited area participates in the calculation: - -- 'only-header': Only the header content is calculated. -- 'only-body': Only the body cell content is calculated. -- 'normal': Normal calculation, that is, calculating the header and body cell contents. - #${prefix} autoWrapText(boolean) = false Whether to automatically wrap text @@ -68,10 +60,6 @@ Minimum column width limit. If set to true, the column width will be limited to The number of frozen columns -#${prefix} frozenRowCount(number) = 0 - -The number of frozen columns(including the header) - #${prefix} rightFrozenColCount(number) = 0 Freeze Columns Right @@ -109,15 +97,8 @@ Default column width for row headers, can be set column by column. If not set, d Shortcut key function settings, specific configuration items: ##${prefix} selectAllOnCtrlA(boolean) = false -Enable the shortcut key Select All. -Supports `boolean` or specific configuration type `SelectAllOnCtrlAOption`. -``` -export interface SelectAllOnCtrlAOption { -disableHeaderSelect?: boolean; //Whether to disable header selection when the shortcut key is used to select all. -disableRowSeriesNumberSelect?: boolean; //Whether to disable the selection of row sequence numbers when the shortcut key is used to select all. -} -``` +Enable shortcut key to select all. ##${prefix} copySelected(boolean) = false @@ -174,7 +155,7 @@ Mouse hover over the cell bottom border can drag and adjust row height. This ope - 'header' Only adjustable in header cells - 'body' Only adjustable in body cells -#${prefix} dragHeaderMode(string) = 'none' +#${prefix} dragHeaderMode(string) = 'all' The switch of dragging the header to move the position. After selecting a cell, drag the cell to trigger the move. The range of replaceable cells is limited: @@ -217,14 +198,6 @@ Do not respond to mouse select interaction. Separately set the header not to respond to mouse select interaction. -##${prefix} blankAreaClickDeselect(boolean) = false - -Whether to cancel the selection when clicking the blank area. - -##${prefix} outsideClickDeselect(boolean) = true - -Whether to cancel the selection when clicking outside the table. - #${prefix} theme(Object) {{ use: common-theme( @@ -281,18 +254,6 @@ Set the selected state of the menu. Declaration type is `DropDownMenuHighlightIn prefix = '#' + ${prefix}, ) }} -#${prefix} emptyTip(Object) - -Table empty data prompt. - -You can directly configure `boolean` or `IEmptyTip` type objects. The default value is false, which means no prompt information is displayed. - -The IEmptyTip type is defined as follows: - -{{ use: common-emptyTip( -prefix = '#' + ${prefix}, -) }} - #${prefix} tooltip(Object) Tooltip related configuration. Specific configuration items are as follows: @@ -303,11 +264,7 @@ Html is currently more complete, default using html rendering method. Currently ##${prefix} isShowOverflowTextTooltip (boolean) -Whether to display overflow text content tooltip when hovering over the cell. Temporarily, renderMode needs to be configured as html to display, and canvas has not been developed yet. - -##${prefix} overflowTextTooltipDisappearDelay (number) - -The overflow text tooltip delays disappearance time. If you need to delay disappearance so that the mouse can move to the tooltip content, you can configure this configuration item. +Replace the original hover:isShowTooltip configuration. Temporarily need to set renderMode to html to display, canvas has not been developed yet. ##${prefix} confine (boolean) = true @@ -433,17 +390,7 @@ Custom cell style ``` { - customCellStyleArrangement: - { - cellPosition: { - row?: number; - col?: number; - range?: { - start: {row: number; col: number}; - end: {row: number; col: number} - } - }; - customStyleId: string}[] + customCellStyleArrangement: {cellPosition: {row?: number; col?: number; range?: {start: {row: number; col: number}; end: {row: number; col: number}}}; customStyleId: string} [] } ``` @@ -453,66 +400,3 @@ Custom cell style assignment - Single cell: `{ row: number, column: number }` - Cell range: `{ range: { start: { row: number, column: number }, end: { row: number, column: number} } }` - customStyleId: Custom style id, the same as the id defined when registering the custom style - -#${prefix} editor (string|Object|Function) - -Global configuration cell editor - -``` -editor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); -``` - -Among them, IEditor is the editor interface defined in @visactor/vtable-editors. For details, please refer to the source code: https://github.com/VisActor/VTable/blob/main/packages/vtable-editors/src/types.ts . - -#${prefix} headerEditor (string|Object|Function) - -Global configuration table header display title title editor - -``` -headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); -``` - -#${prefix} editCellTrigger('doubleclick' | 'click' | 'api') = 'doubleclick' - -The trigger timing for entering the editing state. - -``` - -/** Edit triggering time: double click event | single click event | api to manually start editing. Default is double click 'doubleclick' */ -editCellTrigger?: 'doubleclick' | 'click' | 'api'; -``` - -#${prefix} rowSeriesNumber(IRowSeriesNumber) - -set row serial number. -{{ use: row-series-number( - prefix = '###', -) }} - -#${prefix} enableLineBreak(boolean) = false - -Whether to enable line break, the default is false. - -#${prefix} clearDOM(boolean) = true - -Whether to clear the container DOM. - -#${prefix} animationAppear(boolean|Object|) - -Table entry animation configuration. - -``` -animationAppear?: boolean | { - type?: 'all' | 'one-by-one'; - direction?: 'row' | 'column'; - duration?: number; - delay?: number; -}; -``` - -You can configure true to enable the default animation, or you can configure the animation parameters: - -- `type` The type of the entry animation, currently supports `all` and `one-by-one`, and the default is `one-by-one` -- `direction` The direction of the entry animation, currently supports `row` and `column`, and the default is `row` -- `duration` The duration of a single animation, in milliseconds, for `one-by-one`, it is the duration of one animation, and the default is 500 -- `delay` The delay of the animation, in milliseconds; for `one-by-one`, it is the time difference between the two animations, for `all`, it is the delay of all animations, and the default is 0 diff --git a/docs/assets/option/en/common/pivot-corner.md b/docs/assets/option/en/common/pivot-corner.md index f1945b492..5d4fc075e 100644 --- a/docs/assets/option/en/common/pivot-corner.md +++ b/docs/assets/option/en/common/pivot-corner.md @@ -3,11 +3,9 @@ ${prefix} titleOnDimension(string) ='row' Corner header content display based on: - - 'column' The column dimension name is used as the corner header cell content - 'row' The row dimension name is used as the corner header cell content - 'none' The corner header cell content is empty -- 'all' means the header cell content is the concatenation of the row dimension name and the column dimension name ${prefix} headerType(string) @@ -19,4 +17,4 @@ Header cell style, the configuration items vary slightly depending on the header - For headerType 'text', refer to [headerStyle](../option/PivotTable-columns-text#headerStyle.bgColor) - For headerType 'link', refer to [headerStyle](../option/PivotTable-columns-link#headerStyle.bgColor) -- For headerType 'image', refer to [headerStyle](../option/PivotTable-columns-image#headerStyle.bgColor) +- For headerType 'image', refer to [headerStyle](../option/PivotTable-columns-image#headerStyle.bgColor) \ No newline at end of file diff --git a/docs/assets/option/en/common/row-series-number.md b/docs/assets/option/en/common/row-series-number.md index fb0d3d874..301d5a877 100644 --- a/docs/assets/option/en/common/row-series-number.md +++ b/docs/assets/option/en/common/row-series-number.md @@ -27,7 +27,3 @@ Table header cell style, please refer to: [headerStyle](../option/PivotTable-col ${prefix} style Body cell style, please refer to: [style](../option/ListTable-columns-text#style.bgColor) - -${prefix} disableColumnResize(boolean) - -Whether to disable row serial number width adjustment.The default is false. \ No newline at end of file diff --git a/docs/assets/option/en/common/scroll-style.md b/docs/assets/option/en/common/scroll-style.md index c26736946..da3410dd0 100644 --- a/docs/assets/option/en/common/scroll-style.md +++ b/docs/assets/option/en/common/scroll-style.md @@ -11,9 +11,6 @@ Color of the scroll bar rail ##${prefix} scrollSliderColor(string) Color of the scroll bar slider -##${prefix} scrollSliderCornerRadius(number) -The corner radius of the scroll bar slider - ##${prefix} width(number) Width of the scroll bar diff --git a/docs/assets/option/en/common/style.md b/docs/assets/option/en/common/style.md index 2cbbca695..bd9464c97 100644 --- a/docs/assets/option/en/common/style.md +++ b/docs/assets/option/en/common/style.md @@ -25,12 +25,6 @@ Define the text color of the cell prefix = ${prefix}, ) }} -#${prefix} strokeColor(ColorPropertyDefine) -Define the text stroke color of the cell -{{ use: common-color( - prefix = ${prefix}, -) }} - #${prefix} fontSize(FontSizePropertyDefine) Define the text size of the cell {{ use: common-font-size( diff --git a/docs/assets/option/en/common/theme-style.md b/docs/assets/option/en/common/theme-style.md index ed4c9eac5..f3307c0d6 100644 --- a/docs/assets/option/en/common/theme-style.md +++ b/docs/assets/option/en/common/theme-style.md @@ -26,26 +26,10 @@ Background color of the entire column in the interaction prefix = ${prefix} ) }} -#${prefix} select(Object) - -Select highlight style - -##${prefix} inlineRowBgColor(ColorPropertyDefine) -The highlight color of the entire row when selected -{{ use: common-color( -prefix = ${prefix} -) }} - -##${prefix} inlineColumnBgColor(ColorPropertyDefine) -The highlight color of the entire column when selected -{{ use: common-color( -prefix = ${prefix} -) }} - #${prefix} frameStyle(FrameStyle) Outer border style of the current section, such as the overall outer border of the body or the overall outer border of the header {{ use: common-frame-style( prefix = '#'+${prefix} - ) }} + ) }} \ No newline at end of file diff --git a/docs/assets/option/en/common/theme.md b/docs/assets/option/en/common/theme.md index 264f59bf3..9cf8f8ed1 100644 --- a/docs/assets/option/en/common/theme.md +++ b/docs/assets/option/en/common/theme.md @@ -1,15 +1,13 @@ {{ target: common-theme }} Table theme, which has built-in theme names DEFAULT, ARCO, BRIGHT, DARK, SIMPLIFY. The configuration can be made using built-in types or directly with string names: - - `VTable.themes.DEFAULT` - `VTable.themes.ARCO;` - `VTable.themes.BRIGHT` - `VTable.themes.DARK` - `VTable.themes.SIMPLIFY` - + or - - `'default'` - `'arco'` - `'bright'` @@ -144,14 +142,4 @@ Selection box border color ##${prefix} cellBorderLineWidth(number) Selection box border thickness -##${prefix} inlineRowBgColor(ColorPropertyDefine) -The highlight color of the entire row when selected -{{ use: common-color( -prefix = ${prefix} -) }} - -##${prefix} inlineColumnBgColor(ColorPropertyDefine) -The highlight color of the entire column when selected -{{ use: common-color( -prefix = ${prefix} -) }} +#${prefix} Example: [TODO](xxxx) \ No newline at end of file diff --git a/docs/assets/option/en/icon/base-icon.md b/docs/assets/option/en/icon/base-icon.md index e7d847e33..337a9061f 100644 --- a/docs/assets/option/en/icon/base-icon.md +++ b/docs/assets/option/en/icon/base-icon.md @@ -12,34 +12,6 @@ The height of the icon. ${prefix} positionType (IconPosition) IconPosition enumeration type. -``` -/** -* Icon location -* inlineFront: the front of the text content, -* inlineEnd: after the text content -* -*/ -export enum IconPosition { - /**Button on the left side of the cell and affected by padding */ - left = 'left', - /**The button on the right side of the cell is affected by padding, such as the pin chart */ - right = 'right', - /**The icon fixed on the right side does not occupy space, is not affected by padding, and may cover the content, such as dropDown */ - absoluteRight = 'absoluteRight', - /**The icon on the left side of the cell content block follows the text positioning and does not wrap with the text */ - contentLeft = 'contentLeft', - /**The icon on the right side of the cell content block follows the text positioning and does not wrap with the text */ - contentRight = 'contentRight', - /**Free positioning in the cell */ - absolute = 'absolute', - - /**The icon in front of the text line content follows the text positioning and wraps with the text */ - inlineFront = 'inlineFront', - /**The icon after the text line content, positioned with the text, and wrapped with the text. For example, the sort chart is placed in the first line of the text content */ - inlineEnd = 'inlineEnd', -} -``` - ${prefix} marginRight (number) The spacing distance from the right element, or the spacing distance from the cell boundary. @@ -56,7 +28,6 @@ When resetting the icon inside VTable, you need to specify the functional type o Especially for functional icons with toggleable states, please be sure to configure funcType, such as sorting function with funcType set to sort, and name set to sort_normal, sort_downward, or sort_upward. This way, the corresponding icon can be replaced accurately. IconFuncTypeEnum enumeration definition: - ``` enum IconFuncTypeEnum { frozen = 'frozen', @@ -103,7 +74,6 @@ Title of the tooltip. #${prefix} placement (Placement) Tooltip position, optional values are top, left, right, or bottom. Placement enumeration definition: - ``` enum Placement { top = 'top', @@ -113,9 +83,6 @@ Placement enumeration definition: } ``` -#${prefix} disappearDelay (number) -The delay time for the tooltip to disappear. If you need to move the mouse to the tooltip, please configure this parameter. - #${prefix} style (Object) The style of the tooltip. If not configured, the theme style will be used. @@ -134,11 +101,5 @@ Tooltip background color. ##${prefix} arrowMark (boolean) Whether the tooltip displays an arrow. -##${prefix} maxWidth (number) -The maximum width of the tooltip. - -##${prefix} maxHeight (number) -The maximum height of the tooltip. - ${prefix} interactive (boolean) -Whether it is interactive, default is true. Currently known non-interactive buttons are dropdown menu states. +Whether it is interactive, default is true. Currently known non-interactive buttons are dropdown menu states. \ No newline at end of file diff --git a/docs/assets/option/en/indicator/base-indicator-type.md b/docs/assets/option/en/indicator/base-indicator-type.md index 03a3bc489..f04e42f48 100644 --- a/docs/assets/option/en/indicator/base-indicator-type.md +++ b/docs/assets/option/en/indicator/base-indicator-type.md @@ -1,3 +1,4 @@ + {{ target: base-indicator-type }} ${prefix} indicatorKey(string) @@ -11,18 +12,16 @@ Indicator name ${prefix} format(FieldFormat) Indicator value formatting - ``` type FieldFormat = (value: number|string, col:number, row:number, table:PivotTable) => any; -``` + ``` ${prefix} headerFormat(FieldFormat) indicator title format - ``` type FieldFormat = (title: number|string, col:number, row:number, table:PivotTable) => any; -``` + ``` ${prefix} width(number|string) @@ -55,11 +54,9 @@ Header cell style. Configuration items vary slightly depending on the headerType ${prefix} style Body cell style, type declaration: - ``` style?: IStyleOption | ((styleArg: StylePropertyFunctionArg) => IStyleOption); ``` - {{ use: common-StylePropertyFunctionArg() }} IStyleOption type structure is as follows: @@ -95,19 +92,14 @@ icon?: | (string | ColumnIconOption)[] | ((args: CellInfo) => string | ColumnIconOption | (string | ColumnIconOption)[]); ``` - -#${prefix}ColumnIconOption - +#${prefix}ColumnIconOption_definition: ``` type ColumnIconOption = ImageIcon | SvgIcon; ``` - #${prefix}ImageIcon(Object) -type is set to 'image'. The image address needs to be set in src {{ use: image-icon( prefix = '##' + ${prefix}) }} #${prefix}SvgIcon(Object) -type is set to 'svg'. You need to configure the svg address or the complete svg file string in svg {{ use: svg-icon( prefix = '##' + ${prefix}) }} ${prefix} headerCustomRender(Function|Object) @@ -115,12 +107,11 @@ Custom rendering content definition for the indicator name header. For details, ${prefix} headerCustomLayout(Function) -Custom layout elements for the indicator name header cell. +Custom layout elements for the indicator name header cell. ``` (args: CustomRenderFunctionArg) => ICustomLayoutObj; ``` - {{ use: common-CustomRenderFunctionArg() }} {{ use: custom-layout( @@ -132,11 +123,9 @@ ${prefix} customRender(Function|Object) Custom rendering content definition for the indicator value body cell, either in function or object form. The type is `ICustomRenderFuc | ICustomRenderObj`. The ICustomRenderFuc is defined as follows: - ``` type ICustomRenderFuc = (args: CustomRenderFunctionArg) => ICustomRenderObj; ``` - {{ use: common-CustomRenderFunctionArg() }} {{ use: common-custom-render-object( @@ -150,7 +139,6 @@ Custom layout elements for the indicator value body cell. ``` (args: CustomRenderFunctionArg) => ICustomLayoutObj; ``` - {{ use: common-CustomRenderFunctionArg() }} {{ use: custom-layout( @@ -169,9 +157,7 @@ Whether to disable column width adjustment. If it is a transposed table or the i ${prefix} editor (string|Object|Function) Configure the indicator cell editor - ``` editor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); ``` - Among them, IEditor is the editor interface defined in @visactor/vtable-editors. For details, please refer to the source code: https://github.com/VisActor/VTable/blob/main/packages/vtable-editors/src/types.ts . diff --git a/docs/assets/option/en/register/theme.md b/docs/assets/option/en/register/theme.md index ec9cab4ea..6f6b6f5ae 100644 --- a/docs/assets/option/en/register/theme.md +++ b/docs/assets/option/en/register/theme.md @@ -15,7 +15,7 @@ CLICK_CELL tableInstance.on(CLICK_CELL, (args) => console.log(CLICK_CELL, args)); `` -Supported event types(not all): +Supported event types: `TABLE_EVENT_TYPE = { CLICK_CELL: 'click_cell', diff --git a/docs/assets/option/en/table/listTable.md b/docs/assets/option/en/table/listTable.md index 5b768db54..f36c88ca7 100644 --- a/docs/assets/option/en/table/listTable.md +++ b/docs/assets/option/en/table/listTable.md @@ -32,7 +32,6 @@ Whether to transpose, default is false Whether to display the table header. - ## pagination(IPagination) Pagination configuration. @@ -71,6 +70,35 @@ order: 'desc' | 'asc' | 'normal'; ``` +## editor (string|Object|Function) + +Global configuration cell editor +``` + +editor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); + +``` +Among them, IEditor is the editor interface defined in @visactor/vtable-editors. For details, please refer to the source code: https://github.com/VisActor/VTable/blob/main/packages/vtable-editors/src/types.ts . + +${prefix} headerEditor (string|Object|Function) + +Global configuration for the editor of the display title in the table header +``` + +headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); + +``` + +## editCellTrigger('doubleclick' | 'click' | 'api') = 'doubleclick' + +The trigger timing for entering the editing state. + +``` + +/\*_\_ Edit triggering time: double click event | single click event | api to manually start editing. Default is double click 'doubleclick' _/ +editCellTrigger?: 'doubleclick' | 'click' | 'api'; + +``` {{ use: common-option-secondary( prefix = '#', @@ -129,3 +157,10 @@ type CustomAggregation = { formatFun?: (value: number, col: number, row: number, table: BaseTableAPI) => string | number; }; ``` + +## rowSeriesNumber(IRowSeriesNumber) + +set row serial number. +{{ use: row-series-number( + prefix = '###', +) }} diff --git a/docs/assets/option/en/table/pivotChart.md b/docs/assets/option/en/table/pivotChart.md index 28be1ed1a..39ad71340 100644 --- a/docs/assets/option/en/table/pivotChart.md +++ b/docs/assets/option/en/table/pivotChart.md @@ -51,7 +51,7 @@ The currently supported data formats are, taking the sales of large supermarkets ## columnTree(Array) -List header tree, type:`(IDimensionHeaderNode|IIndicatorHeaderNode)[]`. Among them, IDimensionHeaderNode refers to the dimension value node of the dimension non-indicator, and IIndicatorHeaderNode refers to the indicator name node. +List header tree, type:`IDimensionHeaderNode|IIndicatorHeaderNode[]`. Among them, IDimensionHeaderNode refers to the dimension value node of the dimension non-indicator, and IIndicatorHeaderNode refers to the indicator name node. ** The specific configuration items of IDimensionHeaderNode are as follows:** @@ -63,8 +63,8 @@ export interface IDimensionHeaderNode { dimensionKey: string | number; /** dimension member value */ value: string; - /** Subdimension tree structure under dimension members. */ - children?: (IDimensionHeaderNode|IIndicatorHeaderNode)[] ; + /** Subdimension tree structure under dimension members */ + children?: IDimensionHeaderNode|IIndicatorHeaderNode[]; /** The collapsed state is used with the tree structure display. Note: only valid in rowTree */ hierarchyState?: HierarchyState; } @@ -156,11 +156,9 @@ Adjust the effective range of row height, configurable items: - `all`: All row heights are adjusted ## renderChartAsync(boolean) - Whether to enable asynchronous rendering of charts ## renderChartAsyncBatchCount(number) - Turn on asynchronous rendering of charts. The number of progressively rendered charts in each batch is recommended to be 5-10. The details can be adjusted depending on the overall effect. Default value is 5. {{ use: common-option-secondary( diff --git a/docs/assets/option/en/table/pivotTable.md b/docs/assets/option/en/table/pivotTable.md index fed69ddfe..18068aba4 100644 --- a/docs/assets/option/en/table/pivotTable.md +++ b/docs/assets/option/en/table/pivotTable.md @@ -49,9 +49,17 @@ Currently, it supports incoming flattened data formats, taking the sales of larg ] ``` +## enableDataAnalysis(boolean) + +Whether the pivot table enables data analysis. Default false. + +If the incoming data records are detailed data and VTable is required for aggregate analysis, enable this configuration. + +If the incoming data is aggregated, in order to improve performance, it is set to false and columnTree and rowTree are required to be passed in. + ## dataConfig(IDataConfig) -Data analysis related configuration . +Data analysis related configuration This configuration will be effective only after enableDataAnalysis is turned on. ``` /** @@ -220,7 +228,7 @@ export interface Total { ### derivedFieldRules(DerivedFieldRules) -Add a derived field. The vtable will generate a new field based on the rules defined by the derived field and add the new field to the data. The new field can be used as a dimension item or an indicator item. +Add derived fields ``` export type DerivedFieldRules = DerivedFieldRule[]; @@ -235,29 +243,9 @@ export interface DerivedFieldRule { } ``` -### calculatedFieldRules (CalculatedFieldRules) - -Calculated fields are similar to the calculated fields in Excel pivot tables. New indicator values can be calculated through calculated fields, and they are all recalculated based on the summary results. Note: Different from derived fields. - -``` -export type CalculateddFieldRules = CalculateddFieldRule[]; -``` - -``` -export interface CalculatedFieldRule { - /** Unique identifier, which can be used as the key of a new indicator and used to configure indicators to be displayed in a pivot table. */ - key: string; - /** The indicator that the calculated field depends on, which can be the corresponding indicator field in records or not the field in data records - * If the dependent indicator is not in records, it needs to be explicitly configured in aggregationRules, specifying the aggregation rule and indicatorKey to be used in dependIndicatorKeys. */ - dependIndicatorKeys: string[]; - /** The calculation function of the calculated field. The dependent indicator value is passed in as a parameter, and the return value is used as the value of the calculated field. */ - calculateFun?: (dependFieldsValue: any) => any; -} -``` - ## columnTree(Array) -Column header tree, type: `(IDimensionHeaderNode|IIndicatorHeaderNode)[]`. Among them, IDimensionHeaderNode refers to the dimension value node of non-indicator dimensions, and IIndicatorHeaderNode refers to the indicator name node. +Column header tree, type: `IDimensionHeaderNode|IIndicatorHeaderNode[]`. Among them, IDimensionHeaderNode refers to the dimension value node of non-indicator dimensions, and IIndicatorHeaderNode refers to the indicator name node. ** Specific configuration of IDimensionHeaderNode is as follows: ** @@ -269,12 +257,10 @@ export interface IDimensionHeaderNode { dimensionKey: string | number; /** Dimension member value */ value: string; - /** The tree structure of the sub-dimensions under the member. true is generally used to display the fold and expand buttons and to perform lazy loading to obtain data. */ - children?: (IDimensionHeaderNode|IIndicatorHeaderNode)[] | true; + /** The tree structure of the sub-dimensions under the member */ + children?: IDimensionHeaderNode|IIndicatorHeaderNode[]; /** Collapse status Used with tree structure display. Note: only valid in rowTree */ hierarchyState?: HierarchyState; - /** Whether it is a virtual node. If configured to true, this dimension field will be ignored when analyzing based on records data */ - virtual?: boolean; } ``` @@ -400,6 +386,38 @@ Set the sorting state, only corresponding to the display effect of the button wi tableType = 'pivotTable' ) }} -## supplementIndicatorNodes(boolean) = true +## editor (string|Object|Function) + +Global configuration cell editor + +``` +editor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); +``` + +Among them, IEditor is the editor interface defined in @visactor/vtable-editors. For details, please refer to the source code: https://github.com/VisActor/VTable/blob/main/packages/vtable-editors/src/types.ts . + +## editCellTrigger('doubleclick' | 'click' | 'api') = 'doubleclick' + +The trigger timing for entering the editing state. + +``` + +/** Edit triggering time: double click event | single click event | api to manually start editing. Default is double click 'doubleclick' */ +editCellTrigger?: 'doubleclick' | 'click' | 'api'; + +``` + +{{ use: common-option-secondary( + prefix = '#', + tableType = 'listTable' +) }} + +``` + +## rowSeriesNumber(IRowSeriesNumber) -Whether to add index nodes to the corresponding custom table headers such as rowTree or columnTree. Default is true +set row serial number. +{{ use: row-series-number( + prefix = '###', +) }} +``` diff --git a/docs/assets/option/zh/column/base-column-type.md b/docs/assets/option/zh/column/base-column-type.md index b018fbe95..8f9ab3bef 100644 --- a/docs/assets/option/zh/column/base-column-type.md +++ b/docs/assets/option/zh/column/base-column-type.md @@ -85,18 +85,16 @@ icon?: | ((args: CellInfo) => string | ColumnIconOption | (string | ColumnIconOption)[]); ``` -#${prefix}ColumnIconOption +#${prefix}ColumnIconOption 定义: ``` type ColumnIconOption = ImageIcon | SvgIcon; ``` #${prefix}ImageIcon(Object) -type 配置成 'image'。需要配置图片地址在 src 中 {{ use: image-icon( prefix = '##' + ${prefix}) }} #${prefix}SvgIcon(Object) -type 配置成 'svg'。需要配置 svg 地址或者 svg 完整文件字符串在 svg 中 {{ use: svg-icon( prefix = '##' + ${prefix}) }} ${prefix} sort(boolean|Function) @@ -253,10 +251,4 @@ ${prefix} aggregation(Aggregation | CustomAggregation | Array) 全局 option 也可以配置,对每一列都配置聚合规则。 -可参考[教程文档](https://visactor.io/vtable/guide/data_analysis/list_table_dataAnalysis) - - -${prefix} hide(boolean) = false -非必填。 - -是否隐藏列 \ No newline at end of file +可参考教程文档 diff --git a/docs/assets/option/zh/common/empty-tip-define.md b/docs/assets/option/zh/common/empty-tip-define.md deleted file mode 100644 index 970d413f8..000000000 --- a/docs/assets/option/zh/common/empty-tip-define.md +++ /dev/null @@ -1,23 +0,0 @@ -{{ target: common-emptyTip }} - -#${prefix} text(string) -空数据描述内容。 - -#${prefix} textStyle(object) -描述文字样式。 - -- color:string 可配置字体颜色; -- fontSize:number 可配置字体大小; -- fontFamily:string 可配置字体; -- fontWeight: string | number; -- fontVariant?: string;字体粗细 -- lineHeight?: number 行高 -- underline?: number; 下划线 -- lineThrough?: number; 中划线 - -#${prefix} icon(object) -空数据图标。 - -- width?: number;icon 的高度 -- height?: number; icon 的高度 -- image?: string;图片地址 或者 内联 SVG 内容 diff --git a/docs/assets/option/zh/common/option-important.md b/docs/assets/option/zh/common/option-important.md index f780b1e57..056641ad0 100644 --- a/docs/assets/option/zh/common/option-important.md +++ b/docs/assets/option/zh/common/option-important.md @@ -5,3 +5,7 @@ 容器 DOM,需要具有宽。 可放到初始化参数中。 + +#${prefix} clearDOM(boolean) = true + +是否清空容器 DOM。 \ No newline at end of file diff --git a/docs/assets/option/zh/common/option-secondary.md b/docs/assets/option/zh/common/option-secondary.md index 20eeec1d9..7765eb287 100644 --- a/docs/assets/option/zh/common/option-secondary.md +++ b/docs/assets/option/zh/common/option-secondary.md @@ -30,14 +30,6 @@ adaptive 模式下高度的适应策略,默认为 'only-body'。 - 'only-body':只有 body 部分的行参与高度适应计算,表头部分高度不变。 - 'all':所有列参与高度适应计算。 -#${prefix} columnWidthComputeMode('normal' | 'only-header' | 'only-body') = 'normal' - -计算内容宽度时限定区域参与计算: - -- 'only-header':只计算表头内容。 -- 'only-body':只计算 body 单元格内容。 -- 'normal':正常计算,即计算表头和 body 单元格内容。 - #${prefix} autoWrapText(boolean) = false 是否自动换行 @@ -68,10 +60,6 @@ adaptive 模式下高度的适应策略,默认为 'only-body'。 冻结列数 -#${prefix} frozenRowCount(number) = 0 - -冻结行数(包含表头) - #${prefix} rightFrozenColCount(number) = 0 右侧冻结列数 @@ -110,14 +98,6 @@ adaptive 模式下高度的适应策略,默认为 'only-body'。 ##${prefix} selectAllOnCtrlA(boolean) = false 开启快捷键全选。 -支持 `boolean` 或者具体配置类型`SelectAllOnCtrlAOption`。 - -``` -export interface SelectAllOnCtrlAOption { - disableHeaderSelect?: boolean; //快捷键全选时,是否禁止选中表头。 - disableRowSeriesNumberSelect?: boolean; //快捷键全选时,是否禁止选中行序列号。 -} -``` ##${prefix} copySelected(boolean) = false 开启快捷键复制,与浏览器的快捷键一致。 @@ -163,7 +143,7 @@ export interface SelectAllOnCtrlAOption { - 'header' 只能在表头处单元格调整 - 'body' 只能在 body 单元格调整 -#${prefix} rowResizeMode(string) = 'all' +#${prefix} rowResizeMode(string) = 'none' 鼠标 hover 到单元格下边界可拖拽调整行高。该操作可触发的范围: @@ -172,7 +152,7 @@ export interface SelectAllOnCtrlAOption { - 'header' 只能在表头处单元格调整 - 'body' 只能在 body 单元格调整 -#${prefix} dragHeaderMode(string) = 'none' +#${prefix} dragHeaderMode(string) = 'all' 控制拖拽表头移动位置的开关。选中某个单元格后,鼠标拖拽该单元格可触发移动。 可换位单元格范围限定: @@ -212,14 +192,6 @@ hover 交互响应模式:十字交叉、整列、整行或者单个单元格 单独设置表头不响应鼠标 select 交互。 -##${prefix} blankAreaClickDeselect(boolean) = false - -点击空白区域是否取消选中。 - -##${prefix} outsideClickDeselect(boolean) = true - -点击外部区域是否取消选中。 - #${prefix} theme(Object) {{ use: common-theme( @@ -275,18 +247,6 @@ DropDownMenuHighlightInfo 的定义如下: prefix = '#' + ${prefix}, ) }} -#${prefix} emptyTip(Object) - -表格空数据提示。 - -可以直接配置`boolean` 或者 `IEmptyTip`类型对象, 默认为 false,不显示提示信息。 - -`IEmptyTip`类型定如如下: - -{{ use: common-emptyTip( - prefix = '#' + ${prefix}, -) }} - #${prefix} tooltip(Object) tooltip 相关配置。具体配置如下: @@ -296,11 +256,7 @@ html 目前实现较完整,先默认使用 html 渲染方式。目前暂不支 ##${prefix} isShowOverflowTextTooltip (boolean) -是否需要在 hover 到单元格时显示溢出文本内容 tooltip。暂时需要将 renderMode 配置为 html 才能显示,canvas 的还未开发。 - -##${prefix} overflowTextTooltipDisappearDelay (number) - -溢出文本 tooltip 延时消失时间,如果需要延迟消失以使得鼠标可以移动到 tooltip 内容上,可以配置该配置项。 +代替原来 hover:isShowTooltip 配置。暂时需要将 renderMode 配置为 html 才能显示,canvas 的还未开发。 ##${prefix} confine (boolean) = true @@ -429,17 +385,7 @@ html 目前实现较完整,先默认使用 html 渲染方式。目前暂不支 ``` { - customCellStyleArrangement: - { - cellPosition: { - row?: number; - col?: number; - range?: { - start: {row: number; col: number}; - end: {row: number; col: number} - } - }; - customStyleId: string}[] + customCellStyleArrangement: {cellPosition: {row?: number; col?: number; range?: {start: {row: number; col: number}; end: {row: number; col: number}}}; customStyleId: string}[] } ``` @@ -449,67 +395,3 @@ html 目前实现较完整,先默认使用 html 渲染方式。目前暂不支 - 单个单元格:`{ row: number, column: number }` - 单元格区域:`{ range: { start: { row: number, column: number }, end: { row: number, column: number} } }` - customStyleId: 自定义样式 id,与注册自定义样式时定义的 id 相同 - -#${prefix} rowSeriesNumber(IRowSeriesNumber) - -配置行序号。 -{{ use: row-series-number( - prefix = '###', -) }} - -#${prefix} editor(string|Object|Function) - -全局配置单元格编辑器 - -``` -editor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); -``` - -其中 IEditor 是@visactor/vtable-editors 中定义的编辑器接口,具体可以参看源码:https://github.com/VisActor/VTable/blob/main/packages/vtable-editors/src/types.ts。 - -#${prefix} headerEditor (string|Object|Function) - -全局配置表头显示标题 title 的编辑器 - -``` -headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); -``` - -#${prefix} editCellTrigger('doubleclick' | 'click' | 'api') = 'doubleclick' - -进入编辑状态的触发时机。 - -``` - -/\*_ 编辑触发时机:双击事件 | 单击事件 | api 手动开启编辑。默认为双击'doubleclick' _/ -editCellTrigger?: 'doubleclick' | 'click' | 'api'; - -``` - -#${prefix} enableLineBreak(boolean) = false - -是否开启换行符解析,开启后,单元格内容中包含换行符时,会自动解析换行。 - -#${prefix} clearDOM(boolean) = true - -是否清空容器 DOM。 - -#${prefix} animationAppear(boolean|Object|) - -表格的入场动画配置。 - -``` -animationAppear?: boolean | { - type?: 'all' | 'one-by-one'; - direction?: 'row' | 'column'; - duration?: number; - delay?: number; -}; -``` - -可以配置 true 开启默认动画,也可以配置动画的参数: - -- `type` 入场动画的类型,目前支持 `all` 和 `one-by-one`两种,默认为 `one-by-one` -- `direction` 入场动画的方向,目前支持 `row` 和 `column`两种,默认为 `row` -- `duration` 单个动画的时长,单位为毫秒,`one-by-one` 时,为一次动画的时长,默认为 500 -- `delay` 动画的延迟,单位为毫秒;`one-by-one` 时为两次动画直接的时间差,`all` 时为所有动画的延迟,默认为 0 diff --git a/docs/assets/option/zh/common/pivot-corner.md b/docs/assets/option/zh/common/pivot-corner.md index c93492f5d..15629c2a1 100644 --- a/docs/assets/option/zh/common/pivot-corner.md +++ b/docs/assets/option/zh/common/pivot-corner.md @@ -1,13 +1,12 @@ + {{ target: pivot-corner-define }} ${prefix} titleOnDimension(string) ='row' 角头标题显示内容依据: - - 'column' 列维度名称作为角头单元格内容 - 'row' 行维度名称作为角头单元格内容 - 'none' 角头单元格内容为空 -- 'all' 角头单元格内容为行维度名称和列维度名称的拼接 ${prefix} headerType(string) @@ -15,8 +14,8 @@ ${prefix} headerType(string) ${prefix} headerStyle(TODO) -表头单元格样式,配置项根据 headerType 不同有略微差别。每种 headerStyle 的配置项可参考: +表头单元格样式,配置项根据headerType不同有略微差别。每种headerStyle的配置项可参考: -- headerType 为'text',对应[headerStyle](../option/PivotTable-columns-text#headerStyle.bgColor) -- headerType 为'link',对应[headerStyle](../option/PivotTable-columns-link#headerStyle.bgColor) -- headerType 为'image',对应[headerStyle](../option/PivotTable-columns-image#headerStyle.bgColor) +- headerType为'text',对应[headerStyle](../option/PivotTable-columns-text#headerStyle.bgColor) +- headerType为'link',对应[headerStyle](../option/PivotTable-columns-link#headerStyle.bgColor) +- headerType为'image',对应[headerStyle](../option/PivotTable-columns-image#headerStyle.bgColor) \ No newline at end of file diff --git a/docs/assets/option/zh/common/row-series-number.md b/docs/assets/option/zh/common/row-series-number.md index 4aba0ae4d..2a4fba35a 100644 --- a/docs/assets/option/zh/common/row-series-number.md +++ b/docs/assets/option/zh/common/row-series-number.md @@ -27,7 +27,3 @@ ${prefix} headerStyle(IStyleOption|Function) ${prefix} style body 单元格样式,可参考:[style](../option/ListTable-columns-text#style.bgColor) - -${prefix} disableColumnResize(boolean) - -是否禁止列宽调整,默认为 false \ No newline at end of file diff --git a/docs/assets/option/zh/common/scroll-style.md b/docs/assets/option/zh/common/scroll-style.md index daa88e82d..c69b2f353 100644 --- a/docs/assets/option/zh/common/scroll-style.md +++ b/docs/assets/option/zh/common/scroll-style.md @@ -11,9 +11,6 @@ ##${prefix} scrollSliderColor(string) 滚动条滑块的颜色 -##${prefix} scrollSliderCornerRadius(number) -滚动条滑块的圆角半径 - ##${prefix} width(number) 滚动条宽度大小 diff --git a/docs/assets/option/zh/common/style.md b/docs/assets/option/zh/common/style.md index 969ce580c..ca8dfc3ee 100644 --- a/docs/assets/option/zh/common/style.md +++ b/docs/assets/option/zh/common/style.md @@ -25,12 +25,6 @@ prefix = ${prefix}, ) }} -#${prefix} strokeColor(ColorPropertyDefine) -定义单元格的文字描边颜色 -{{ use: common-color( - prefix = ${prefix}, -) }} - #${prefix} fontSize(FontSizePropertyDefine) 定义单元格的文字大小 {{ use: common-font-size( diff --git a/docs/assets/option/zh/common/theme-style.md b/docs/assets/option/zh/common/theme-style.md index 1e39eb896..0c5d007a3 100644 --- a/docs/assets/option/zh/common/theme-style.md +++ b/docs/assets/option/zh/common/theme-style.md @@ -6,7 +6,7 @@ #${prefix} hover(Object) -hover 单元格时的效果 +hover单元格时的效果 ##${prefix} cellBgColor(ColorPropertyDefine) 交互所在单元格的背景颜色 @@ -26,26 +26,10 @@ hover 单元格时的效果 prefix = ${prefix} ) }} -#${prefix} select(Object) - -选择高亮样式 - -##${prefix} inlineRowBgColor(ColorPropertyDefine) -选中时整行高亮颜色 -{{ use: common-color( - prefix = ${prefix} - ) }} - -##${prefix} inlineColumnBgColor(ColorPropertyDefine) -选中时整列高亮颜色 -{{ use: common-color( - prefix = ${prefix} - ) }} - #${prefix} frameStyle(FrameStyle) -当前部分的外边框样式,如 body 整体外边框,或者表头整体外边框 +当前部分的外边框样式,如body整体外边框,或者表头整体外边框 {{ use: common-frame-style( prefix = '#'+${prefix} - ) }} + ) }} \ No newline at end of file diff --git a/docs/assets/option/zh/common/theme.md b/docs/assets/option/zh/common/theme.md index 619c375e3..a5235bade 100644 --- a/docs/assets/option/zh/common/theme.md +++ b/docs/assets/option/zh/common/theme.md @@ -1,22 +1,20 @@ {{ target: common-theme }} -表格主题,其中内置主题名称有 DEFAULT, ARCO, BRIGHT, DARK, SIMPLIFY,具体配置方式可用内置类型或者直接使用字符串名称配置: - +表格主题,其中内置主题名称有DEFAULT, ARCO, BRIGHT, DARK, SIMPLIFY,具体配置方式可用内置类型或者直接使用字符串名称配置: - `VTable.themes.DEFAULT` - `VTable.themes.ARCO;` - `VTable.themes.BRIGHT` - `VTable.themes.DARK` - `VTable.themes.SIMPLIFY` - + or - - `'default'` - `'arco'` - `'bright'` - `'dark'` - `'simplify'` -同时可以基于内置主题进行扩展,例如想基于 ARCO 主题改变字体: +同时可以基于内置主题进行扩展,例如想基于ARCO主题改变字体: ``` VTable.themes.ARCO.extend({ @@ -54,14 +52,14 @@ VTable.themes.ARCO.extend({ ``` #${prefix} underlayBackgroundColor(string) -表格绘制范围外的 canvas 上填充的颜色 +表格绘制范围外的canvas上填充的颜色 #${prefix} cellInnerBorder(boolean) -单元格是否绘制内边框,如果为 true,边界单元格靠近边界的边框会被隐藏 +单元格是否绘制内边框,如果为true,边界单元格靠近边界的边框会被隐藏 #${prefix} bodyStyle(Object) -body 单元格的样式配置 +body单元格的样式配置 {{ use: common-theme-style( prefix = '#' + ${prefix}, @@ -93,7 +91,7 @@ body 单元格的样式配置 #${prefix} defaultStyle(Object) -公共样式,如果 headerStyle,rowHeaderStyle, defaultStyle 都没有配置的项,则使用这个里面的配置项 +公共样式,如果headerStyle,rowHeaderStyle, defaultStyle都没有配置的项,则使用这个里面的配置项 {{ use: common-theme-style( prefix = '#' + ${prefix}, @@ -144,14 +142,4 @@ body 单元格的样式配置 ##${prefix} cellBorderLineWidth(number) 选择框边框粗细 -##${prefix} inlineRowBgColor(ColorPropertyDefine) -选中时整行高亮颜色 -{{ use: common-color( - prefix = ${prefix} - ) }} - -##${prefix} inlineColumnBgColor(ColorPropertyDefine) -选中时整列高亮颜色 -{{ use: common-color( - prefix = ${prefix} - ) }} +#${prefix} 示例:[TODO](xxxx) \ No newline at end of file diff --git a/docs/assets/option/zh/icon/base-icon.md b/docs/assets/option/zh/icon/base-icon.md index 04e1bdb01..62f5962dd 100644 --- a/docs/assets/option/zh/icon/base-icon.md +++ b/docs/assets/option/zh/icon/base-icon.md @@ -12,34 +12,6 @@ icon 的高度。 ${prefix} positionType (IconPosition) IconPosition 枚举类型。 -``` -/** - * icon 的位置 - * inlineFront:文本内容的前面, - * inlineEnd:文本内容后面 - * - */ -export enum IconPosition { - /**单元格左侧按钮 且受padding影响 */ - left = 'left', - /**单元格右侧按钮 受padding影响 如pin图表 */ - right = 'right', - /**固定在右侧的图标,不占位,不受padding影响,可能压盖内容 如 dropDown */ - absoluteRight = 'absoluteRight', - /**在单元格内容块的左侧的图标,跟随文本定位,不随文本折行 */ - contentLeft = 'contentLeft', - /**在单元格内容块的右侧的图标,跟随文本定位,不随文本折行 */ - contentRight = 'contentRight', - /**在单元格中自由定位 */ - absolute = 'absolute', - - /**文本行内容前面的图标,跟随文本定位,随文本折行 */ - inlineFront = 'inlineFront', - /**文本行内容后面的图标,跟随文本定位,随文本折行。如sort图表 放在文本内容的第一行 */ - inlineEnd = 'inlineEnd', -} -``` - ${prefix} marginRight (number) 和右侧元素间隔距离,或者与单元格边界的间隔距离。 @@ -51,12 +23,11 @@ icon 的名称,会作为内部缓存的 key。 ${prefix} funcType (IconFuncTypeEnum) -重置 VTable 内部的 icon 时需要指定 icon 的功能类型。 +重置VTable内部的icon时需要指定 icon 的功能类型。 -特别是具有切换状态的功能性的图标请务必配置上 funcType,例如排序功能 funcType 配置 sort,name 配置 sort_normal 或 sort_downward,或 sort_upward。这样才能准确替换到内部相应的 icon 图标。 - -IconFuncTypeEnum 枚举类型定义: +特别是具有切换状态的功能性的图标请务必配置上funcType,例如排序功能 funcType 配置 sort,name 配置 sort_normal 或 sort_downward,或 sort_upward。这样才能准确替换到内部相应的icon图标。 +IconFuncTypeEnum枚举类型定义: ``` enum IconFuncTypeEnum { frozen = 'frozen', @@ -102,8 +73,7 @@ ${prefix} tooltip (Object) #${prefix} placement (Placement) 气泡框位置,可选值为 top、left、right 或 bottom。 -Placement 枚举类型定义: - +Placement枚举类型定义: ``` enum Placement { top = 'top', @@ -113,9 +83,6 @@ Placement 枚举类型定义: } ``` -#${prefix} disappearDelay (number) -提示框消失延迟时间,如果有需要鼠标移动到 tooltip 上的需求,请配置上这个参数。 - #${prefix} style (Object) 气泡框的样式。如果不配置,会使用 theme 中的样式。 @@ -134,11 +101,5 @@ Placement 枚举类型定义: ##${prefix} arrowMark (boolean) 气泡框是否显示箭头。 -##${prefix} maxWidth (number) -tooltip 的最大宽度。 - -##${prefix} maxHeight (number) -tooltip 的最大高度。 - ${prefix} interactive (boolean) -是否可交互,默认为 true。目前已知不可交互按钮为下拉菜单状态。 +是否可交互,默认为 true。目前已知不可交互按钮为下拉菜单状态。 \ No newline at end of file diff --git a/docs/assets/option/zh/indicator/base-indicator-type.md b/docs/assets/option/zh/indicator/base-indicator-type.md index 9cbf9ccb3..b4b1febac 100644 --- a/docs/assets/option/zh/indicator/base-indicator-type.md +++ b/docs/assets/option/zh/indicator/base-indicator-type.md @@ -96,18 +96,16 @@ icon?: | ((args: CellInfo) => string | ColumnIconOption | (string | ColumnIconOption)[]); ``` -#${prefix}ColumnIconOption +#${prefix}ColumnIconOption 定义: ``` type ColumnIconOption = ImageIcon | SvgIcon; ``` #${prefix}ImageIcon(Object) -type 配置成 'image'。需要配置图片地址在 src 中 {{ use: image-icon( prefix = '##' + ${prefix}) }} #${prefix}SvgIcon(Object) -type 配置成 'svg'。需要配置 svg 地址或者 svg 完整文件字符串在 svg 中 {{ use: svg-icon( prefix = '##' + ${prefix}) }} ${prefix} headerCustomRender(Function|Object) diff --git a/docs/assets/option/zh/register/theme.md b/docs/assets/option/zh/register/theme.md index 840df79e9..d55dba657 100644 --- a/docs/assets/option/zh/register/theme.md +++ b/docs/assets/option/zh/register/theme.md @@ -16,7 +16,7 @@ tableInstance.on(CLICK_CELL, (args) => console.log(CLICK_CELL, args)); ``` -支持的事件类型(这里列的不是全部的,可以参考 api): +支持的事件类型: ``` TABLE_EVENT_TYPE = { @@ -215,7 +215,6 @@ TABLE_EVENT_TYPE = { viewHeight: number; } ``` - ## SCROLL_HORIZONTAL_END 横向滚动到右侧结束事件 @@ -232,7 +231,6 @@ TABLE_EVENT_TYPE = { viewHeight: number; } ``` - ## SCROLL_VERTICAL_END 竖向滚动条滚动到底部事件 diff --git a/docs/assets/option/zh/table/listTable.md b/docs/assets/option/zh/table/listTable.md index f2c1a6d81..441265aae 100644 --- a/docs/assets/option/zh/table/listTable.md +++ b/docs/assets/option/zh/table/listTable.md @@ -69,6 +69,33 @@ SortState { } ``` +## editor (string|Object|Function) + +全局配置单元格编辑器 + +``` +editor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); +``` + +其中 IEditor 是@visactor/vtable-editors 中定义的编辑器接口,具体可以参看源码:https://github.com/VisActor/VTable/blob/main/packages/vtable-editors/src/types.ts。 + +${prefix} headerEditor (string|Object|Function) + +全局配置表头显示标题 title 的编辑器 + +``` +headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); +``` + +## editCellTrigger('doubleclick' | 'click' | 'api') = 'doubleclick' + +进入编辑状态的触发时机。 + +``` +/** 编辑触发时机:双击事件 | 单击事件 | api手动开启编辑。默认为双击'doubleclick' */ +editCellTrigger?: 'doubleclick' | 'click' | 'api'; +``` + {{ use: common-option-secondary( prefix = '#', tableType = 'listTable' @@ -125,3 +152,10 @@ type CustomAggregation = { formatFun?: (value: number, col: number, row: number, table: BaseTableAPI) => string | number; }; ``` + +## rowSeriesNumber(IRowSeriesNumber) + +配置行序号。 +{{ use: row-series-number( + prefix = '###', +) }} diff --git a/docs/assets/option/zh/table/pivotChart.md b/docs/assets/option/zh/table/pivotChart.md index 5e1461337..2e4ae97de 100644 --- a/docs/assets/option/zh/table/pivotChart.md +++ b/docs/assets/option/zh/table/pivotChart.md @@ -51,7 +51,7 @@ ## columnTree(Array) -列表头树,类型为:`(IDimensionHeaderNode|IIndicatorHeaderNode)[]`。其中 IDimensionHeaderNode 指的是维度非指标的维度值节点,IIndicatorHeaderNode 指的是指标名称节点。 +列表头树,类型为:`IDimensionHeaderNode|IIndicatorHeaderNode[]`。其中 IDimensionHeaderNode 指的是维度非指标的维度值节点,IIndicatorHeaderNode 指的是指标名称节点。 ** IDimensionHeaderNode 具体配置项如下:** @@ -64,7 +64,7 @@ export interface IDimensionHeaderNode { /** 维度成员值 */ value: string; /** 维度成员下的子维度树结构 */ - children?: (IDimensionHeaderNode|IIndicatorHeaderNode)[]; + children?: IDimensionHeaderNode|IIndicatorHeaderNode[]; /** 折叠状态 配合树形结构展示使用。注意:仅在rowTree中有效 */ hierarchyState?: HierarchyState; } @@ -102,7 +102,7 @@ export interface IIndicatorHeaderNode { ## indicatorsAsCol(boolean) = true -指标显示在列上,默认是 true。如果配置为 false,则显示在行,指标以行展示 +指标显示在列上,默认是true。如果配置为false,则显示在行,指标以行展示 ## indicatorTitle(string) @@ -161,7 +161,7 @@ export interface IIndicatorHeaderNode { ## renderChartAsyncBatchCount(number) -开启图表异步渲染,每批次渐进渲染图表个数,建议 5-10 个,具体可以视整体效果调整。默认值 5. +开启图表异步渲染,每批次渐进渲染图表个数,建议5-10个,具体可以视整体效果调整。默认值5. {{ use: common-option-secondary( prefix = '#', diff --git a/docs/assets/option/zh/table/pivotTable.md b/docs/assets/option/zh/table/pivotTable.md index f72456cdc..dc926b9bb 100644 --- a/docs/assets/option/zh/table/pivotTable.md +++ b/docs/assets/option/zh/table/pivotTable.md @@ -49,9 +49,17 @@ ] ``` +## enableDataAnalysis(boolean) + +透视表是否开启数据分析。 默认 false + +如果传入的数据 records 是明细数据,需要 VTable 做聚合分析则开启该配置将其设置为 true。 + +如传入数据是经过聚合好的,为了提升性能这里设置为 false,同时呢要求传入自己组织好的行头树结构 columnTree 和 rowTree。 + ## dataConfig(IDataConfig) -数据分析相关配置 +数据分析相关配置 enableDataAnalysis 开启后该配置才会有效。 ``` /** @@ -224,7 +232,7 @@ export interface Total { ### derivedFieldRules(DerivedFieldRules) -增加派生字段,vtable 会基于派生字段定义的规则来生成新的字段,并将新字段加入到数据中。该新的字段可以作为维度项或者指标项。 +增加派生字段 ``` export type DerivedFieldRules = DerivedFieldRule[]; @@ -239,29 +247,9 @@ export interface DerivedFieldRule { } ``` -### calculatedFieldRules (CalculateddFieldRules) - -计算字段,类 Excel 透视表中的计算字段,可以通过计算字段来计算新的指标值,且都是在汇总结果基础上进行的再计算。注意:不同于派生字段。 - -``` -export type CalculateddFieldRules = CalculateddFieldRule[]; -``` - -``` -export interface CalculateddFieldRule { - /** 唯一标识,可以当做新指标的key,用于配置在 indicators 中在透视表中展示。 */ - key: string; - /** 计算字段依赖的指标,可以是在 records 中具体对应的指标字段 or 不是数据records 中的字段 - * 如果依赖的指标不在 records 中,则需要在 aggregationRules 中明确配置,具体指明聚合规则和 indicatorKey 以在 dependIndicatorKeys 所使用。 */ - dependIndicatorKeys: string[]; - /** 计算字段的计算函数,依赖的指标值作为参数传入,返回值作为计算字段的值。 */ - calculateFun?: (dependFieldsValue: any) => any; -} -``` - ## columnTree(Array) -列表头树,类型为:`(IDimensionHeaderNode|IIndicatorHeaderNode)[]`。其中 IDimensionHeaderNode 指的是维度非指标的维度值节点,IIndicatorHeaderNode 指的是指标名称节点。 +列表头树,类型为:`IDimensionHeaderNode|IIndicatorHeaderNode[]`。其中 IDimensionHeaderNode 指的是维度非指标的维度值节点,IIndicatorHeaderNode 指的是指标名称节点。 ** IDimensionHeaderNode 具体配置项如下:** @@ -273,12 +261,10 @@ export interface IDimensionHeaderNode { dimensionKey: string | number; /** 维度成员值 */ value: string; - /** 维度成员下的子维度树结构。 true一般是用在显示折叠展开按钮,进行懒加载获取数据的场景中。 */ - children?: (IDimensionHeaderNode|IIndicatorHeaderNode)[] | true; + /** 维度成员下的子维度树结构 */ + children?: IDimensionHeaderNode|IIndicatorHeaderNode[]; /** 折叠状态 配合树形结构展示使用。注意:仅在rowTree中有效 */ hierarchyState?: HierarchyState; - /** 是否为虚拟节点。 如果配置为true,则在基于records数据做分析时会忽略该维度字段 */ - virtual?: boolean; } ``` @@ -404,6 +390,33 @@ export interface IIndicatorHeaderNode { tableType = 'pivotTable' ) }} -## supplementIndicatorNodes(boolean) = true +## editor(string|Object|Function) + +全局配置单元格编辑器 -是否需要补充指标节点到对应的自定义表头中如 rowTree 或者 columnTree. 默认为 true +``` +editor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); +``` + +其中 IEditor 是@visactor/vtable-editors 中定义的编辑器接口,具体可以参看源码:https://github.com/VisActor/VTable/blob/main/packages/vtable-editors/src/types.ts。 + +## editCellTrigger('doubleclick' | 'click' | 'api') = 'doubleclick' + +进入编辑状态的触发时机。 + +``` +/** 编辑触发时机:双击事件 | 单击事件 | api手动开启编辑。默认为双击'doubleclick' */ +editCellTrigger?: 'doubleclick' | 'click' | 'api'; +``` + +{{ use: common-option-secondary( + prefix = '#', + tableType = 'listTable' +) }} + +## rowSeriesNumber(IRowSeriesNumber) + +配置行序号。 +{{ use: row-series-number( + prefix = '###', +) }} diff --git a/docs/package.json b/docs/package.json index 072c7bfcc..6b87cb66a 100644 --- a/docs/package.json +++ b/docs/package.json @@ -5,7 +5,6 @@ "private": true, "scripts": { "serve": "vite --host", - "build": "vite build && cp -r ./assets ./dist", "watch": "node ./libs/template-parse/build.js --env dev --watch", "start": "npx concurrently --kill-others \"npm:watch\" \"npm:serve\"" }, @@ -18,7 +17,7 @@ "@visactor/vtable-export": "workspace:*", "@visactor/vtable-search": "workspace:*", "buble": "^0.20.0", - "@visactor/vchart": "1.11.4", + "@visactor/vchart": "1.10.5", "markdown-it": "^13.0.0", "highlight.js": "^11.8.0", "axios": "^1.4.0", @@ -26,8 +25,7 @@ "react-dom": "^18.0.0", "react-router-dom": "6.9.0", "lodash": "4.17.21", - "openinula": "~0.1.2-SNAPSHOT", - "@visactor/vutils": "~0.18.9" + "openinula": "~0.1.2-SNAPSHOT" }, "devDependencies": { "@internal/eslint-config": "workspace:*", diff --git a/docs/src/main.tsx b/docs/src/main.tsx index a0b70518e..f97df93ed 100644 --- a/docs/src/main.tsx +++ b/docs/src/main.tsx @@ -10,11 +10,9 @@ import * as ReactVTable from '@visactor/react-vtable'; import * as InulaVTable from '@visactor/openinula-vtable'; import { App } from './app'; import * as ArcoDesign from '@arco-design/web-react'; -import * as ArcoDesignIcon from '@arco-design/web-react/icon'; import '@arco-design/web-react/dist/css/arco.css'; (window as any).ArcoDesign = ArcoDesign; -(window as any).ArcoDesignIcon = ArcoDesignIcon; (window as any).VTable = VTable; (window as any).VTable_editors = VTableEditors; (window as any).VChart = VChart.VChart; diff --git a/docs/vite.config.js b/docs/vite.config.js index 396f4d2ec..a400b3d03 100644 --- a/docs/vite.config.js +++ b/docs/vite.config.js @@ -22,7 +22,6 @@ export default { '@visactor/vtable-search': path.resolve('../packages/vtable-search/src/index.ts'), '@visactor/react-vtable': path.resolve('../packages/react-vtable/src/index.ts'), '@visactor/openinula-vtable': path.resolve('../packages/openinula-vtable/src/index.ts'), - '@vutils-extension': path.resolve(__dirname, '../packages/vtable/src/vutil-extension-temp'), '@src': path.resolve(__dirname, '../packages/vtable/src/'), // react: 'openinula', // 新增 diff --git a/packages/openinula-vtable/demo/src/pivot-table/pivot-table.tsx b/packages/openinula-vtable/demo/src/pivot-table/pivot-table.tsx index abc865ee4..388493e22 100644 --- a/packages/openinula-vtable/demo/src/pivot-table/pivot-table.tsx +++ b/packages/openinula-vtable/demo/src/pivot-table/pivot-table.tsx @@ -35,6 +35,7 @@ function App() { textStick: true } }, + // enableDataAnalysis: true, columns: [ { dimensionKey: '地区', diff --git a/packages/openinula-vtable/package.json b/packages/openinula-vtable/package.json index 350074c17..b66cc71c7 100644 --- a/packages/openinula-vtable/package.json +++ b/packages/openinula-vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/openinula-vtable", - "version": "1.5.0", + "version": "0.25.5", "description": "The openinula version of VTable", "keywords": [ "openinula", @@ -48,10 +48,10 @@ }, "dependencies": { "@visactor/vtable": "workspace:*", - "@visactor/vutils": "~0.18.9" + "@visactor/vutils": "~0.18.1" }, "devDependencies": { - "@visactor/vchart": "1.11.4", + "@visactor/vchart": "1.10.5", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", diff --git a/packages/openinula-vtable/src/eventsUtils.ts b/packages/openinula-vtable/src/eventsUtils.ts index d49554466..e4417affd 100644 --- a/packages/openinula-vtable/src/eventsUtils.ts +++ b/packages/openinula-vtable/src/eventsUtils.ts @@ -16,7 +16,6 @@ export interface EventsProps { onMouseDownCell?: EventCallback; onMouseUpCell?: EventCallback; onSelectedCell?: EventCallback; - onSelectedClear?: EventCallback; onKeyDown?: EventCallback; onMouseEnterTable?: EventCallback; onMouseLeaveTable?: EventCallback; @@ -81,7 +80,6 @@ export const TABLE_EVENTS = { onMouseDownCell: EVENT_TYPE.MOUSEDOWN_CELL, onMouseUpCell: EVENT_TYPE.MOUSEUP_CELL, onSelectedCell: EVENT_TYPE.SELECTED_CELL, - onSelectedClear: EVENT_TYPE.SELECTED_CLEAR, onKeyDown: EVENT_TYPE.KEYDOWN, onMouseEnterTable: EVENT_TYPE.MOUSEENTER_TABLE, onMouseLeaveTable: EVENT_TYPE.MOUSELEAVE_TABLE, diff --git a/packages/react-vtable/demo/src/App.tsx b/packages/react-vtable/demo/src/App.tsx index bbfe21696..81c6eea3a 100644 --- a/packages/react-vtable/demo/src/App.tsx +++ b/packages/react-vtable/demo/src/App.tsx @@ -14,11 +14,8 @@ import listTableEvent from './event/list-table'; import eventRebind from './event/event-rebind'; import componentContainer from './component/component-container'; -import customLayout from './component/custom-layout'; -import customLayoutDom from './component/custom-layout-dom'; -import customLayoutDomSite from './component/custom-layout-dom-site'; -import customLayoutDomSite1 from './component/custom-layout-dom-site-1'; +export default listTable; // export default listEditor; // export default listOptionRecord; // export default listComponent; @@ -34,7 +31,3 @@ import customLayoutDomSite1 from './component/custom-layout-dom-site-1'; // export default eventRebind; // export default componentContainer; -export default customLayout; -// export default customLayoutDom; -// export default customLayoutDomSite; -// export default customLayoutDomSite1; diff --git a/packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx b/packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx deleted file mode 100644 index 01c20fbcd..000000000 --- a/packages/react-vtable/demo/src/component/custom-layout-dom-site-1.tsx +++ /dev/null @@ -1,185 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import ReactDOM from 'react-dom/client'; -import type { CustomLayoutFunctionArg } from '../../../src'; -import { ListTable, ListColumn, CustomLayout, Group, Text, Tag, Image } from '../../../src'; -import { - Avatar, - Comment, - Card, - Popover, - Space, - Typography, - Button, - Popconfirm, - Message, - Notification -} from '@arco-design/web-react'; -import { IconHeart, IconMessage, IconStar, IconStarFill, IconHeartFill } from '@arco-design/web-react/icon'; -const { Meta } = Card; - -import '@arco-design/web-react/dist/css/arco.css'; - -const CommentComponent = (props: CustomLayoutFunctionArg) => { - const { table, row, col, rect, dataValue } = props; - if (!table || row === undefined || col === undefined) { - return null; - } - const { height, width } = rect || table.getCellRect(col, row); - const record = table.getRecordByCell(col, row); - - return ( - - } - }} - > - ); -}; - -const CommentReactComponent = (props: { name: string }) => { - const { name } = props; - const [like, setLike] = useState(); - const [star, setStar] = useState(); - const actions = [ - , - , - - ]; - return ( - -

Here is the description of this user.

- - } - > - {name.slice(0, 1)} - - } - content={
Comment body content.
} - datetime="1 hour" - style={{ marginTop: 10, marginLeft: 10 }} - /> - ); -}; - -const OperationComponent = (props: CustomLayoutFunctionArg) => { - const { table, row, col, rect, dataValue } = props; - if (!table || row === undefined || col === undefined) { - return null; - } - const { height, width } = rect || table.getCellRect(col, row); - const record = table.getRecordByCell(col, row); - - return ( - - } - }} - > - ); -}; - -const OperationReactComponent = () => { - return ( - - - { - Message.info({ - content: 'ok' - }); - }} - onCancel={() => { - Message.error({ - content: 'cancel' - }); - }} - > - - - - ); -}; - -function generateRandomString(length: number) { - let result = ''; - const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - for (let i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * characters.length)); - } - return result; -} - -function App() { - const records = []; - for (let i = 0; i < 50; i++) { - records.push({ - id: i, - name: generateRandomString(8) - }); - } - - return ( - { - // eslint-disable-next-line no-undef - // (window as any).tableInstance = table; - }} - ReactDOM={ReactDOM} - > - - - - - - - - - ); -} - -export default App; diff --git a/packages/react-vtable/demo/src/component/custom-layout-dom-site.tsx b/packages/react-vtable/demo/src/component/custom-layout-dom-site.tsx deleted file mode 100644 index 7191c10e9..000000000 --- a/packages/react-vtable/demo/src/component/custom-layout-dom-site.tsx +++ /dev/null @@ -1,227 +0,0 @@ -/* eslint-disable max-len */ -import { useEffect, useRef, useState } from 'react'; -import ReactDOM from 'react-dom/client'; -import type { CustomLayoutFunctionArg } from '../../../src'; -import { ListTable, ListColumn, CustomLayout, Group, Text, Tag, Image } from '../../../src'; -import { Avatar, Button, Card, Popover, Space, Typography } from '@arco-design/web-react'; -import { IconThumbUp, IconShareInternal, IconMore } from '@arco-design/web-react/icon'; -const { Meta } = Card; - -import '@arco-design/web-react/dist/css/arco.css'; - -const UserProfileComponent = (props: CustomLayoutFunctionArg) => { - const { table, row, col, rect, dataValue } = props; - if (!table || row === undefined || col === undefined) { - return null; - } - const { height, width } = rect || table.getCellRect(col, row); - const record = table.getRecordByCell(col, row); - - const [hover, setHover] = useState(false); - - return ( - - - } - }} - onMouseEnter={(event: any) => { - setHover(true); - event.currentTarget.stage.renderNextFrame(); // to do: auto execute in react-vtable - }} - onMouseLeave={(event: any) => { - setHover(false); - event.currentTarget.stage.renderNextFrame(); - }} - > - - - - - ); -}; - -const CardInfo = (props: { record: any; hover: boolean; row?: number }) => { - const { bloggerName, bloggerAvatar, introduction, city } = props.record; - return props.hover ? ( - - dessert -
- } - actions={[ - - - , - - - , - - - - ]} - > - - {city.slice(0, 1)} - {city} - - } - title={bloggerName} - description={introduction} - /> - - ) : null; -}; - -function App() { - const records = [ - { - bloggerId: 1, - bloggerName: 'Virtual Anchor Xiaohua', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg', - introduction: - 'Hi everyone, I am Xiaohua, the virtual host. I am a little fairy who likes games, animation and food. I hope to share happy moments with you through live broadcast.', - fansCount: 400, - worksCount: 10, - viewCount: 5, - city: 'Dream City', - tags: ['game', 'anime', 'food'] - }, - { - bloggerId: 2, - bloggerName: 'Virtual anchor little wolf', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg', - introduction: - 'Hello everyone, I am the virtual anchor Little Wolf. I like music, travel and photography, and I hope to explore the beauty of the world with you through live broadcast.', - fansCount: 800, - worksCount: 20, - viewCount: 15, - city: 'City of Music', - tags: ['music', 'travel', 'photography'] - }, - { - bloggerId: 3, - bloggerName: 'Virtual anchor bunny', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg', - introduction: - 'Hello everyone, I am the virtual anchor Xiaotu. I like painting, handicrafts and beauty makeup. I hope to share creativity and fashion with you through live broadcast.', - fansCount: 600, - worksCount: 15, - viewCount: 10, - city: 'City of Art', - tags: ['painting', 'handmade', 'beauty makeup'] - }, - { - bloggerId: 4, - bloggerName: 'Virtual anchor kitten', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg', - introduction: - 'Hello everyone, I am the virtual host Kitty. I am a lazy cat who likes dancing, fitness and cooking. I hope to live a healthy and happy life with everyone through the live broadcast.', - fansCount: 1000, - worksCount: 30, - viewCount: 20, - city: 'Health City', - tags: ['dance', 'fitness', 'cooking'] - }, - { - bloggerId: 5, - bloggerName: 'Virtual anchor Bear', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg', - introduction: - 'Hello everyone, I am the virtual host Xiaoxiong. A little wise man who likes movies, reading and philosophy, I hope to explore the meaning of life with you through live broadcast.', - fansCount: 1200, - worksCount: 25, - viewCount: 18, - city: 'City of Wisdom', - tags: ['Movie', 'Literature'] - }, - { - bloggerId: 6, - bloggerName: 'Virtual anchor bird', - bloggerAvatar: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg', - introduction: - 'Hello everyone, I am the virtual anchor Xiaoniao. I like singing, acting and variety shows. I hope to be happy with everyone through the live broadcast.', - fansCount: 900, - worksCount: 12, - viewCount: 8, - city: 'Happy City', - tags: ['music', 'performance', 'variety'] - } - ]; - - return ( - { - // eslint-disable-next-line no-undef - // (window as any).tableInstance = table; - }} - ReactDOM={ReactDOM} - > - - - - - - - - - ); -} - -export default App; diff --git a/packages/react-vtable/demo/src/component/custom-layout-dom.tsx b/packages/react-vtable/demo/src/component/custom-layout-dom.tsx deleted file mode 100644 index b74f63dd7..000000000 --- a/packages/react-vtable/demo/src/component/custom-layout-dom.tsx +++ /dev/null @@ -1,314 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import ReactDOM from 'react-dom/client'; -import type { CustomLayoutFunctionArg } from '../../../src'; -import { ListTable, ListColumn, CustomLayout, Group, Text, Tag, Image } from '../../../src'; -import { Avatar, Button, Card, Popover, Space, Typography } from '@arco-design/web-react'; -import { IconThumbUp, IconShareInternal, IconMore } from '@arco-design/web-react/icon'; -const { Meta } = Card; - -import '@arco-design/web-react/dist/css/arco.css'; - -function Tooltip(props: { value: string }) { - return ( -
- {`${props.value}(click to show more)`} -
- ); -} - -const CustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string }) => { - const { table, row, col, rect, text } = props; - if (!table || row === undefined || col === undefined) { - return null; - } - const { height, width } = rect || table.getCellRect(col, row); - const [hover, setHover] = useState(false); - // const row = 3; - // const width = 100; - // const height = 100; - const fieldData = [ - { - value: 'a', - label: 'a' - }, - { - value: 'b', - label: 'b' - } - ]; - - const groupRef = useRef(null); - - // useEffect(() => { - // flash(col, row, this); - // }, [hover]); - - return ( - - // } - react: { - pointerEvents: true, - element: ( - -

Here is the text content

-

Here is the text content

- - } - > - - {text} - -
- ) - } - }} - ref={groupRef} - > - {fieldData.map(item => { - return ( - row !== 2 && ( - { - // if (stateName === 'hover') { - // return { - // fill: 'red' - // }; - // } - // }} - onMouseEnter={(event: any) => { - // eslint-disable-next-line no-console, no-undef - console.log('groupRef', groupRef.current); - setHover(true); - event.currentTarget.stage.renderNextFrame(); // to do: auto execute in react-vtable - }} - onMouseLeave={(event: any) => { - setHover(false); - event.currentTarget.stage.renderNextFrame(); - }} - > - ) - ); - })} - {hover && ( - - )} -
- ); -}; - -const DomCustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string }) => { - const { table, row, col, rect, text } = props; - if (!table || row === undefined || col === undefined) { - return null; - } - const { height, width } = rect || table.getCellRect(col, row); - - const groupRef = useRef(null); - - return ( - - } - }} - ref={groupRef} - > - ); -}; - -const UserProfileComponent = (props: CustomLayoutFunctionArg & { text: string }) => { - const { table, row, col, rect, text } = props; - if (!table || row === undefined || col === undefined) { - return null; - } - const { height, width } = rect || table.getCellRect(col, row); - - const [hover, setHover] = useState(false); - - // if (row === 2) { - // setHover(true); - // } - - return ( - - - } - }} - onMouseEnter={(event: any) => { - setHover(true); - event.currentTarget.stage.renderNextFrame(); // to do: auto execute in react-vtable - }} - onMouseLeave={(event: any) => { - setHover(false); - event.currentTarget.stage.renderNextFrame(); - }} - > - - - - - ); -}; - -const CardInfo = (props: { text: string; hover: boolean; row?: number }) => { - return props.hover ? ( - - dessert -
- } - actions={[ - - - , - - - , - - - - ]} - > - - -

Here is the text content

-

Here is the text content

- - } - > - A -
- {props.text + props.row} - - } - title="Card Title" - description="This is the description" - /> - - ) : null; -}; - -function App() { - const records = new Array(2000).fill(['John', 18, 'male', '🏀']); - const [preStr, setPreStr] = useState('vt'); - - useEffect(() => { - // eslint-disable-next-line no-undef - setTimeout(() => { - setPreStr(preStr + '1'); - }, 1000); - }, []); - - return ( - { - // eslint-disable-next-line no-undef - (window as any).tableInstance = table; - }} - ReactDOM={ReactDOM} - > - - - - - {/* */} - {/* */} - - - - ); -} - -export default App; diff --git a/packages/react-vtable/demo/src/component/custom-layout.tsx b/packages/react-vtable/demo/src/component/custom-layout.tsx deleted file mode 100644 index b055434b3..000000000 --- a/packages/react-vtable/demo/src/component/custom-layout.tsx +++ /dev/null @@ -1,164 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import type { CustomLayoutFunctionArg } from '../../../src'; -import { ListTable, ListColumn, CustomLayout, Group, Text } from '../../../src'; - -type FieldData = { value: string; label: string }; - -const CustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string }) => { - const { table, row, col, rect, text } = props; - if (!table || row === undefined || col === undefined) { - return null; - } - const { height, width } = rect || table.getCellRect(col, row); - const [hover, setHover] = useState(false); - // const row = 3; - // const width = 100; - // const height = 100; - const fieldData = [ - { - value: 'a', - label: 'a' - }, - { - value: 'b', - label: 'b' - } - ]; - - const groupRef = useRef(null); - - // useEffect(() => { - // flash(col, row, this); - // }, [hover]); - - return ( - - {fieldData.map(item => { - return ( - row !== 2 && ( - { - // if (stateName === 'hover') { - // return { - // fill: 'red' - // }; - // } - // }} - onMouseEnter={(event: any) => { - // eslint-disable-next-line no-console, no-undef - console.log('groupRef', groupRef.current); - setHover(true); - event.currentTarget.stage.renderNextFrame(); // to do: auto execute in react-vtable - }} - onMouseLeave={(event: any) => { - setHover(false); - event.currentTarget.stage.renderNextFrame(); - }} - > - ) - ); - })} - {hover && ( - - )} - - ); -}; - -const HeaderCustomLayoutComponent = (props: CustomLayoutFunctionArg & { text: string }) => { - const { table, row, col, rect, text } = props; - if (!table || row === undefined || col === undefined) { - return null; - } - const { height, width } = rect || table.getCellRect(col, row); - const [hover, setHover] = useState(false); - - const groupRef = useRef(null); - - return ( - - { - // eslint-disable-next-line no-console, no-undef - console.log('groupRef-header', groupRef.current); - setHover(true); - event.currentTarget.stage.renderNextFrame(); - }} - onMouseLeave={(event: any) => { - setHover(false); - event.currentTarget.stage.renderNextFrame(); - }} - > - {hover && ( - - )} - - ); -}; - -function App() { - const records = new Array(1000).fill(['John', 18, 'male', '🏀']); - const [preStr, setPreStr] = useState('vt'); - - useEffect(() => { - // eslint-disable-next-line no-undef - setTimeout(() => { - setPreStr(preStr + '1'); - }, 1000); - }, []); - - return ( - - - - - - - - - - ); -} - -export default App; diff --git a/packages/react-vtable/demo/src/pivot-table/pivot-table.tsx b/packages/react-vtable/demo/src/pivot-table/pivot-table.tsx index abc865ee4..388493e22 100644 --- a/packages/react-vtable/demo/src/pivot-table/pivot-table.tsx +++ b/packages/react-vtable/demo/src/pivot-table/pivot-table.tsx @@ -35,6 +35,7 @@ function App() { textStick: true } }, + // enableDataAnalysis: true, columns: [ { dimensionKey: '地区', diff --git a/packages/react-vtable/demo/vite.config.ts b/packages/react-vtable/demo/vite.config.ts index 371704e05..f3d380d55 100644 --- a/packages/react-vtable/demo/vite.config.ts +++ b/packages/react-vtable/demo/vite.config.ts @@ -25,7 +25,6 @@ export default defineConfig({ }, resolve: { alias: { - '@visactor/vtable/src/vrender': path.resolve(__dirname, '../../vtable/src/vrender.ts'), '@visactor/vtable': path.resolve(__dirname, '../../vtable/src/index.ts'), '@src': path.resolve(__dirname, '../../vtable/src/'), '@vutils-extension': path.resolve(__dirname, '../../vtable/src/vutil-extension-temp') diff --git a/packages/react-vtable/package.json b/packages/react-vtable/package.json index a6af03740..a36e2a26e 100644 --- a/packages/react-vtable/package.json +++ b/packages/react-vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vtable", - "version": "1.5.0", + "version": "0.25.5", "description": "The react version of VTable", "keywords": [ "react", @@ -50,12 +50,11 @@ }, "dependencies": { "@visactor/vtable": "workspace:*", - "@visactor/vutils": "~0.18.9", - "react-is": "^18.2.0", - "react-reconciler": "0.29.2" + "@visactor/vutils": "~0.18.1", + "react-is": "^18.2.0" }, "devDependencies": { - "@visactor/vchart": "1.11.4", + "@visactor/vchart": "1.10.5", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", @@ -98,7 +97,6 @@ "form-data": "~4.0.0", "axios": "^1.4.0", "@types/react-is": "^17.0.3", - "@arco-design/web-react": "2.60.2", - "@types/react-reconciler": "0.28.8" + "@arco-design/web-react": "2.60.2" } } diff --git a/packages/react-vtable/src/components/base-component.tsx b/packages/react-vtable/src/components/base-component.tsx index 87cb3520d..7d8f365d9 100644 --- a/packages/react-vtable/src/components/base-component.tsx +++ b/packages/react-vtable/src/components/base-component.tsx @@ -1,4 +1,3 @@ -import type { ReactElement } from 'react'; import React, { useContext, useEffect } from 'react'; import { isEqual, isNil, pickWithout } from '@visactor/vutils'; @@ -6,14 +5,12 @@ import type { TableContextType } from '../context/table'; import RootTableContext from '../context/table'; import { bindEventsToTable } from '../eventsUtils'; import { uid } from '../util'; -import { CustomLayout } from './custom/custom-layout'; export interface BaseComponentProps { id?: string | number; - children?: React.ReactNode; } -type ComponentProps = BaseComponentProps & { updateId?: number; componentId?: number; componentIndex?: number }; +type ComponentProps = BaseComponentProps & { updateId?: number; componentId?: number }; export const createComponent = ( componentName: string, @@ -21,7 +18,7 @@ export const createComponent = ( supportedEvents?: Record | null, isSingle?: boolean ) => { - const ignoreKeys = ['id', 'updateId', 'componentId', 'componentIndex', 'children']; + const ignoreKeys = ['id', 'updateId', 'componentId']; const notOptionKeys = supportedEvents ? Object.keys(supportedEvents).concat(ignoreKeys) : ignoreKeys; const Comp: React.FC = (props: T) => { @@ -61,15 +58,6 @@ export const createComponent = ( }; }, []); - // children are all custom layout temply - // return props.children - // ? React.cloneElement(props.children as ReactElement, { componentIndex: props.componentIndex }) - // : null; - if (props.children) { - return React.Children.map(props.children as ReactElement, (child: ReactElement) => { - return React.createElement(CustomLayout, { componentIndex: props.componentIndex }, child); - }); - } return null; }; @@ -78,22 +66,6 @@ export const createComponent = ( (Comp as any).parseOption = (props: T & { updateId?: number; componentId?: string }) => { const newComponentOption: Partial = pickWithout(props, notOptionKeys); - // deal width customLayout - if (props.children) { - const { children } = props; - React.Children.map(children as ReactElement, (child: ReactElement) => { - if (child.props.role === 'custom-layout') { - (newComponentOption as any).customLayout = 'react-custom-layout'; - } - if (child.props.role === 'header-custom-layout') { - (newComponentOption as any).headerCustomLayout = 'react-custom-layout'; - } - }); - } - // if (props.children && (props.children as React.ReactElement).props.role === 'custom-layout') { - // (newComponentOption as any).customLayout = 'react-custom-layout'; - // } - return { option: newComponentOption, optionName, diff --git a/packages/react-vtable/src/components/custom/component.ts b/packages/react-vtable/src/components/custom/component.ts deleted file mode 100644 index 9496f6152..000000000 --- a/packages/react-vtable/src/components/custom/component.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { ReactElement, ReactNode, Ref, JSXElementConstructor } from 'react'; -import type { VRender } from '@visactor/vtable'; -type IGraphic = VRender.IGraphic; -type TagAttributes = VRender.TagAttributes; -type RadioAttributes = VRender.RadioAttributes; -type CheckboxAttributes = VRender.CheckboxAttributes; -type IEventParamsType = VRender.IEventParamsType; - -type GraphicProps = { - attribute: IGraphicGraphicAttribute; - ref?: Ref; - children?: ReactNode; -} & IEventParamsType; - -export const Tag: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = 'tag' as any; - -export const Radio: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = 'radio' as any; - -export const Checkbox: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = - 'checkbox' as any; diff --git a/packages/react-vtable/src/components/custom/custom-layout.tsx b/packages/react-vtable/src/components/custom/custom-layout.tsx deleted file mode 100644 index f6ef5838e..000000000 --- a/packages/react-vtable/src/components/custom/custom-layout.tsx +++ /dev/null @@ -1,144 +0,0 @@ -/* eslint-disable react-hooks/rules-of-hooks */ -import type { PropsWithChildren } from 'react'; -import React, { isValidElement, useCallback, useContext, useLayoutEffect, useRef } from 'react'; -import RootTableContext from '../../context/table'; -import { VRender } from '@visactor/vtable'; -import type { ICustomLayoutFuc, CustomRenderFunctionArg } from '@visactor/vtable/src/ts-types'; -import type { FiberRoot } from 'react-reconciler'; -import { reconcilor } from './reconciler'; -import { LegacyRoot } from 'react-reconciler/constants'; - -const { Group } = VRender; -type CustomLayoutProps = { componentIndex?: number }; - -export type CustomLayoutFunctionArg = Partial & { - role?: 'custom-layout' | 'header-custom-layout'; -}; - -export const CustomLayout: React.FC = (props: PropsWithChildren, ref) => { - const { componentIndex, children } = props; - if (!isValidElement(children)) { - return null; - } - const context = useContext(RootTableContext); - const { table } = context; - - const isHeaderCustomLayout = children.props.role === 'header-custom-layout'; - - // react customLayout component container cache - const container = useRef>(new Map()); - - // customLayout function for vtable - const createGraphic: ICustomLayoutFuc = useCallback( - args => { - const key = `${args.col}-${args.row}`; - let group; - if (container.current.has(key)) { - const currentContainer = container.current.get(key); - // reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); - reconcilorUpdateContainer(children, currentContainer, group, args); - group = currentContainer.containerInfo; - } else { - group = new Group({}); - const currentContainer = reconcilor.createContainer(group, LegacyRoot, null, null, null, 'custom', null, null); - container.current.set(key, currentContainer); - reconcilorUpdateContainer(children, currentContainer, group, args); - // const ele = React.cloneElement(children, { ...args }); - // reconcilor.updateContainer(ele, currentContainer, null); - } - - return { - rootContainer: group, - renderDefault: false - }; - }, - [children] - ); - - const removeContainer = useCallback((col: number, row: number) => { - const key = `${col}-${row}`; - if (container.current.has(key)) { - const currentContainer = container.current.get(key); - reconcilor.updateContainer(null, currentContainer, null); - // group = currentContainer.containerInfo; - container.current.delete(key); - } - }, []); - - useLayoutEffect(() => { - // init and release - // eslint-disable-next-line no-undef - console.log('init', props, table); - // table && (table._reactCreateGraphic = createGraphic); // never go to here - // table?.renderWithRecreateCells(); - return () => { - // eslint-disable-next-line no-undef - console.log('release', props, table); - }; - }, []); - - useLayoutEffect(() => { - // update props - // eslint-disable-next-line no-undef - console.log('update props', props, table); - - table?.checkReactCustomLayout(); // init reactCustomLayout component - if (table && !table.reactCustomLayout?.hasReactCreateGraphic(componentIndex, isHeaderCustomLayout)) { - table.reactCustomLayout?.setReactCreateGraphic( - componentIndex, - createGraphic, - // container.current, - isHeaderCustomLayout - ); // set customLayout function - table.reactCustomLayout?.setReactRemoveGraphic(componentIndex, removeContainer, isHeaderCustomLayout); // set customLayout function - table.reactCustomLayout?.updateCustomCell(componentIndex, isHeaderCustomLayout); // update cell content - } else if (table) { - // update all container - container.current.forEach((value, key) => { - const [col, row] = key.split('-').map(Number); - const width = table.getColWidth(col); // to be fixed: may be merge cell - const height = table.getRowHeight(row); // to be fixed: may be merge cell - const currentContainer = value; - const args = { - col, - row, - dataValue: table.getCellOriginValue(col, row), - value: table.getCellValue(col, row) || '', - rect: { - left: 0, - top: 0, - right: width, - bottom: height, - width, - height - }, - table - }; - // update element in container - const group = currentContainer.containerInfo; - reconcilorUpdateContainer(children, currentContainer, group, args); - // reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); - table.scenegraph.updateNextFrame(); - }); - } - }); - - return null; -}; - -function reconcilorUpdateContainer(children, currentContainer, group, args) { - reconcilor.updateContainer(React.cloneElement(children, { ...args }), currentContainer, null); - // group = group.firstChild; - // if (isReactElement(group.attribute.html?.dom)) { - // const div = document.createElement('div'); - // const root = ReactDOM.createRoot(div as HTMLElement); - // root.render(group.attribute.html.dom); - // group.attribute.html.dom = div; - // // debugger; - // // group.html.dom = div; - // } -} - -function isReactElement(obj) { - return obj && obj.$$typeof === Symbol.for('react.element'); -} diff --git a/packages/react-vtable/src/components/custom/graphic.ts b/packages/react-vtable/src/components/custom/graphic.ts deleted file mode 100644 index b7851f97d..000000000 --- a/packages/react-vtable/src/components/custom/graphic.ts +++ /dev/null @@ -1,85 +0,0 @@ -// export const Group = 'group'; -// export const Rect = 'rect'; -// export const Text = 'text'; - -import type { ReactElement, ReactNode, Ref, JSXElementConstructor } from 'react'; -import type { VRender } from '@visactor/vtable'; - -type IGraphic = VRender.IGraphic; -type IGroupGraphicAttribute = VRender.IGroupGraphicAttribute; -type ITextGraphicAttribute = VRender.ITextGraphicAttribute; -type IEventParamsType = VRender.IEventParamsType; -type IArcGraphicAttribute = VRender.IArcGraphicAttribute; -type ICircleGraphicAttribute = VRender.ICircleGraphicAttribute; -type IImageGraphicAttribute = VRender.IImageGraphicAttribute; -type ILineGraphicAttribute = VRender.ILineGraphicAttribute; -type IPathGraphicAttribute = VRender.IPathGraphicAttribute; -type IRectGraphicAttribute = VRender.IRectGraphicAttribute; -type ISymbolGraphicAttribute = VRender.ISymbolGraphicAttribute; -type IRichTextGraphicAttribute = VRender.IRichTextGraphicAttribute; -type IPolygonGraphicAttribute = VRender.IPolygonGraphicAttribute; - -type GraphicProps = { - attribute: IGraphicGraphicAttribute; - ref?: Ref; - children?: ReactNode; -} & IEventParamsType; - -export const Group: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = - 'group' as any; - -export const Text: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = - 'text' as any; - -export const Arc: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = - 'arc' as any; - -export const Circle: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = - 'circle' as any; - -export const Image: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = - 'image' as any; - -export const Line: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = - 'line' as any; - -export const Path: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = - 'path' as any; - -export const Rect: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = - 'rect' as any; - -export const Symbol: ( - props: GraphicProps -) => ReactElement, JSXElementConstructor>> = - 'symbol' as any; - -export const RichText: ( - props: GraphicProps -) => ReactElement< - GraphicProps, - JSXElementConstructor> -> = 'richtext' as any; - -export const Polygon: ( - props: GraphicProps -) => ReactElement< - GraphicProps, - JSXElementConstructor> -> = 'polygon' as any; diff --git a/packages/react-vtable/src/components/custom/reconciler.ts b/packages/react-vtable/src/components/custom/reconciler.ts deleted file mode 100644 index 51d2833e9..000000000 --- a/packages/react-vtable/src/components/custom/reconciler.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { VRender } from '@visactor/vtable'; -import { isFunction } from '@visactor/vutils'; -import React from 'react'; -import ReactReconciler from 'react-reconciler'; -import { DefaultEventPriority } from 'react-reconciler/constants.js'; - -const { application, createText, REACT_TO_CANOPUS_EVENTS, Tag } = VRender; -type Graphic = VRender.Graphic; -type Instance = Graphic; - -export const reconcilor = ReactReconciler({ - supportsMutation: true, - supportsPersistence: false, - - createInstance: (type: string, props: any, instance) => { - const graphic = createGraphic(type, props); - if (graphic) { - bindEventsToGraphic(graphic, props); - } else { - return undefined; - // createInstance - // graphic = createGraphic('group', {}); - } - return graphic; - }, - - createTextInstance: (text, instance) => { - // const textGraphic = createText({ text }); - // return textGraphic; - // debugger; - // return document.createTextNode(text); - return undefined; - }, - - appendInitialChild: (parentInstance: Instance, childInstance: Instance) => { - parentInstance.add(childInstance); - }, - - finalizeInitialChildren: () => false, - - prepareUpdate: () => true, - - shouldSetTextContent: () => false, - - getRootHostContext: () => null, - - getChildHostContext: () => null, - - getPublicInstance: (instance: Instance) => { - return instance; - }, - - prepareForCommit: () => null, - - resetAfterCommit: () => undefined, - - preparePortalMount: () => null, - - // eslint-disable-next-line no-undef - scheduleTimeout: setTimeout, - // eslint-disable-next-line no-undef - cancelTimeout: clearTimeout, - - noTimeout: -1, - isPrimaryRenderer: false, - - getCurrentEventPriority: () => DefaultEventPriority, - - getInstanceFromNode: node => null, - - beforeActiveInstanceBlur: () => undefined, - - afterActiveInstanceBlur: () => undefined, - - prepareScopeUpdate: () => undefined, - - getInstanceFromScope: () => undefined, - - detachDeletedInstance: () => undefined, - - supportsHydration: false, - - appendChild: (parentInstance: Instance, child: Instance) => { - parentInstance.add(child); - }, - appendChildToContainer: (container: Instance, child: Instance) => { - container.add(child); - }, - - insertBefore: (parentInstance: Instance, child: Instance, beforeChild: Instance) => { - parentInstance.insertBefore(child, beforeChild); - }, - - insertInContainerBefore: (parentInstance: Instance, child: Instance, beforeChild: Instance) => { - parentInstance.insertBefore(child, beforeChild); - }, - - removeChild: (parentInstance: Instance, child: Instance) => { - child.delete(); - }, - - removeChildFromContainer: (parentInstance: Instance, child: Instance) => { - child.delete(); - }, - - commitUpdate: (instance, updatePayload, type, oldProps, newProps) => { - updateGraphicProps(instance, newProps, oldProps); - }, - - hideInstance: (instance: Instance) => { - instance.setAttribute('visible', false); - }, - - unhideInstance: (instance, props) => { - instance.setAttribute('visible', true); - }, - - clearContainer: (container: Instance) => { - container.removeAllChild(); - }, - - commitTextUpdate: (textInstance: any, oldText: string, newText: string) => { - // debugger; - } -}); - -reconcilor.injectIntoDevTools({ - // findFiberByHostInstance: () => {}, - // @ts-ignore - // eslint-disable-next-line no-undef - bundleType: process.env.NODE_ENV !== 'production' ? 1 : 0, - version: React.version, - rendererPackageName: 'react-vtable' -}); - -function createGraphic(type: string, props: any) { - // may have unwanted onxxx prop - if (type === 'tag') { - const tag = new Tag(props.attribute); - return tag; - } else if (!application.graphicService.creator[type]) { - return; - } - const graphic = application.graphicService.creator[type]((props as any).attribute); - return graphic; -} - -function isEventProp(key: string, props: any) { - return key.startsWith('on') && isFunction(props[key]); -} - -function bindEventsToGraphic(graphic: Graphic, props: any) { - for (const key in props) { - if (isEventProp(key, props)) { - graphic.addEventListener(REACT_TO_CANOPUS_EVENTS[key], props[key]); - } - } -} - -function updateGraphicProps(graphic: Graphic, newProps: any, oldProps: any) { - // deal width event update - for (const propKey in oldProps) { - if (isEventProp(propKey, oldProps) && oldProps[propKey] !== newProps[propKey]) { - graphic.removeEventListener(REACT_TO_CANOPUS_EVENTS[propKey], oldProps[propKey]); - } - } - for (const propKey in newProps) { - if (isEventProp(propKey, newProps) && oldProps[propKey] !== newProps[propKey]) { - graphic.addEventListener(REACT_TO_CANOPUS_EVENTS[propKey], newProps[propKey]); - } - } - - // update all attribute - graphic.initAttributes(newProps.attribute); - if (graphic.type === 'image') { - graphic.loadImage(newProps.attribute.image); - } -} diff --git a/packages/react-vtable/src/components/custom/vtable-browser-env-contribution.ts b/packages/react-vtable/src/components/custom/vtable-browser-env-contribution.ts deleted file mode 100644 index 49271ece3..000000000 --- a/packages/react-vtable/src/components/custom/vtable-browser-env-contribution.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { getTargetCell, VRender } from '@visactor/vtable'; -import { isString } from '@visactor/vutils'; - -const { ContainerModule, EnvContribution, BrowserEnvContribution } = VRender; -type CreateDOMParamsType = VRender.CreateDOMParamsType; - -export const reactEnvModule = new ContainerModule((bind, unbind, isBound, rebind) => { - bind(VTableBrowserEnvContribution).toSelf().inSingletonScope(); - if (isBound(EnvContribution)) { - rebind(EnvContribution).toService(VTableBrowserEnvContribution); - } else { - bind(EnvContribution).toService(VTableBrowserEnvContribution); - } -}); - -class VTableBrowserEnvContribution extends BrowserEnvContribution { - updateDom(dom: HTMLElement, params: CreateDOMParamsType): boolean { - const tableDiv = dom.parentElement; - if (tableDiv) { - const top = parseInt(params.style.top, 10); - const left = parseInt(params.style.left, 10); - - let domWidth; - let domHeight; - if ((dom.style.display = 'none')) { - const cellGroup = getTargetCell(params.graphic); - domWidth = cellGroup.attribute.width ?? 1; - domHeight = cellGroup.attribute.height ?? 1; - } else { - domWidth = dom.offsetWidth; - domHeight = dom.offsetHeight; - } - if (top + domHeight < 0 || left + domWidth < 0 || top > tableDiv.offsetHeight || left > tableDiv.offsetWidth) { - dom.style.display = 'none'; - return false; - } - } - - const { width, height, style } = params; - - if (style) { - if (isString(style)) { - dom.setAttribute('style', style); - } else { - Object.keys(style).forEach(k => { - dom.style[k] = style[k]; - }); - } - } - if (width != null) { - dom.style.width = `${width}px`; - } - if (height != null) { - dom.style.height = `${height}px`; - } - - return true; - } -} diff --git a/packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts b/packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts deleted file mode 100644 index 69a573a5d..000000000 --- a/packages/react-vtable/src/components/custom/vtable-react-attribute-plugin.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { VRender } from '@visactor/vtable'; -import { calculateAnchorOfBounds, isFunction, isNil, isObject, isString, styleStringToObject } from '@visactor/vutils'; - -const { ReactAttributePlugin, application } = VRender; -type CommonDomOptions = VRender.CommonDomOptions; -type CreateDOMParamsType = VRender.CreateDOMParamsType; -type IGraphic = VRender.CreateDOMParamsType; -type IStage = VRender.CreateDOMParamsType; -type IText = VRender.CreateDOMParamsType; -type SimpleDomStyleOptions = VRender.CreateDOMParamsType; - -export class VTableReactAttributePlugin extends ReactAttributePlugin { - removeElement(id: string) { - super.removeElement(id); - delete this.htmlMap[id]; - } - - renderGraphicHTML(graphic: IGraphic) { - const { react } = graphic.attribute; - if (!react) { - return; - } - const stage = graphic.stage; - if (!stage) { - return; - } - const ReactDOM = stage.params.ReactDOM; - const { element, container } = react; - if (!(element && ReactDOM && ReactDOM.createRoot)) { - return; - } - const id = isNil(react.id) ? `${graphic.id ?? graphic._uid}_react` : react.id; - - if (this.htmlMap && this.htmlMap[id] && container && container !== this.htmlMap[id].container) { - this.removeElement(id); - } - - if (!this.htmlMap || !this.htmlMap[id]) { - // createa a wrapper contianer to be the root of react element - const { wrapContainer, nativeContainer } = this.getWrapContainer(stage, container); - - if (wrapContainer) { - const root = ReactDOM.createRoot(wrapContainer); - root.render(element); - - if (!this.htmlMap) { - this.htmlMap = {}; - } - - this.htmlMap[id] = { root, wrapContainer, nativeContainer, container, renderId: this.renderId }; - } - } else { - // update react element - this.htmlMap[id].root.render(element); - } - - if (!this.htmlMap || !this.htmlMap[id]) { - return; - } - - const { wrapContainer, nativeContainer } = this.htmlMap[id]; - - this.updateStyleOfWrapContainer(graphic, stage, wrapContainer, nativeContainer, react); - this.htmlMap[id].renderId = this.renderId; - } - - getWrapContainer(stage: IStage, userContainer?: string | HTMLElement | null, domParams?: CreateDOMParamsType) { - let nativeContainer; - if (userContainer) { - if (typeof userContainer === 'string') { - nativeContainer = application.global.getElementById(userContainer); - } else { - nativeContainer = userContainer; - } - } else { - nativeContainer = stage.window.getContainer(); - } - // 创建wrapGroup - return { - wrapContainer: application.global.createDom({ tagName: 'div', parent: nativeContainer, ...domParams }), - nativeContainer - }; - } - - updateStyleOfWrapContainer( - graphic: IGraphic, - stage: IStage, - wrapContainer: HTMLElement, - nativeContainer: HTMLElement, - options: SimpleDomStyleOptions & CommonDomOptions - ) { - const { pointerEvents } = options; - let calculateStyle = this.parseDefaultStyleFromGraphic(graphic); - - calculateStyle.display = graphic.attribute.visible !== false ? 'block' : 'none'; - // 事件穿透 - calculateStyle.pointerEvents = pointerEvents === true ? 'all' : pointerEvents ? pointerEvents : 'none'; - // 定位wrapGroup - if (!wrapContainer.style.position) { - wrapContainer.style.position = 'absolute'; - nativeContainer.style.position = 'relative'; - } - let left: number = 0; - let top: number = 0; - const b = graphic.globalAABBBounds; - - let anchorType = options.anchorType; - - if (isNil(anchorType)) { - anchorType = graphic.type === 'text' ? 'position' : 'boundsLeftTop'; - } - - if (anchorType === 'boundsLeftTop') { - // 兼容老的配置,统一配置 - anchorType = 'top-left'; - } - if (anchorType === 'position' || b.empty()) { - const matrix = graphic.globalTransMatrix; - left = matrix.e; - top = matrix.f; - } else { - const anchor = calculateAnchorOfBounds(b, anchorType); - - left = anchor.x; - top = anchor.y; - } - - // 查看wrapGroup的位置 - // const wrapGroupTL = application.global.getElementTopLeft(wrapGroup, false); - const containerTL = application.global.getElementTopLeft(nativeContainer, false); - const windowTL = stage.window.getTopLeft(false); - const offsetX = left + windowTL.left - containerTL.left; - const offsetTop = top + windowTL.top - containerTL.top; - // wrapGroup.style.transform = `translate(${offsetX}px, ${offsetTop}px)`; - calculateStyle.left = `${offsetX}px`; - calculateStyle.top = `${offsetTop}px`; - - if (graphic.type === 'text' && anchorType === 'position') { - calculateStyle = { - ...calculateStyle, - ...this.getTransformOfText(graphic as IText) - }; - } - - if (isFunction(options.style)) { - const userStyle = options.style( - { top: offsetTop, left: offsetX, width: b.width(), height: b.height() }, - graphic, - wrapContainer - ); - - if (userStyle) { - calculateStyle = { ...calculateStyle, ...userStyle }; - } - } else if (isObject(options.style)) { - calculateStyle = { ...calculateStyle, ...options.style }; - } else if (isString(options.style) && options.style) { - calculateStyle = { ...calculateStyle, ...styleStringToObject(options.style as string) }; - } - - // 更新样式 - application.global.updateDom(wrapContainer, { - width: options.width, - height: options.width, - style: calculateStyle, - graphic - }); - } -} diff --git a/packages/react-vtable/src/components/index.ts b/packages/react-vtable/src/components/index.ts index 859f59761..908de112f 100644 --- a/packages/react-vtable/src/components/index.ts +++ b/packages/react-vtable/src/components/index.ts @@ -8,9 +8,6 @@ export { Menu } from './component/menu'; export { Tooltip } from './component/tooltip'; export { CustomComponent } from './custom-component'; -export { CustomLayout, type CustomLayoutFunctionArg } from './custom/custom-layout'; -export * from './custom/graphic'; -export * from './custom/component'; type Props = { updateId?: number }; diff --git a/packages/react-vtable/src/eventsUtils.ts b/packages/react-vtable/src/eventsUtils.ts index d49554466..e4417affd 100644 --- a/packages/react-vtable/src/eventsUtils.ts +++ b/packages/react-vtable/src/eventsUtils.ts @@ -16,7 +16,6 @@ export interface EventsProps { onMouseDownCell?: EventCallback; onMouseUpCell?: EventCallback; onSelectedCell?: EventCallback; - onSelectedClear?: EventCallback; onKeyDown?: EventCallback; onMouseEnterTable?: EventCallback; onMouseLeaveTable?: EventCallback; @@ -81,7 +80,6 @@ export const TABLE_EVENTS = { onMouseDownCell: EVENT_TYPE.MOUSEDOWN_CELL, onMouseUpCell: EVENT_TYPE.MOUSEUP_CELL, onSelectedCell: EVENT_TYPE.SELECTED_CELL, - onSelectedClear: EVENT_TYPE.SELECTED_CLEAR, onKeyDown: EVENT_TYPE.KEYDOWN, onMouseEnterTable: EVENT_TYPE.MOUSEENTER_TABLE, onMouseLeaveTable: EVENT_TYPE.MOUSELEAVE_TABLE, diff --git a/packages/react-vtable/src/index.ts b/packages/react-vtable/src/index.ts index a8295390a..9f2eccb9f 100644 --- a/packages/react-vtable/src/index.ts +++ b/packages/react-vtable/src/index.ts @@ -1,5 +1,7 @@ +import * as VTable from '@visactor/vtable'; + export * from './tables'; export * from './components'; -export * from './vtable'; +export { VTable }; export const version = __VERSION__; diff --git a/packages/react-vtable/src/tables/base-table.tsx b/packages/react-vtable/src/tables/base-table.tsx index 079f7c395..b04c08c3e 100644 --- a/packages/react-vtable/src/tables/base-table.tsx +++ b/packages/react-vtable/src/tables/base-table.tsx @@ -1,6 +1,5 @@ /* eslint-disable react/display-name */ -// import * as VTable from '@visactor/vtable'; -import { VTable } from '../vtable'; +import * as VTable from '@visactor/vtable'; import React, { useState, useEffect, useRef, useImperativeHandle, useCallback } from 'react'; import type { ContainerProps } from '../containers/withContainer'; import withContainer from '../containers/withContainer'; @@ -22,9 +21,6 @@ import type { // TableLifeCycleEventProps } from '../eventsUtils'; import { bindEventsToTable, TABLE_EVENTS_KEYS, TABLE_EVENTS } from '../eventsUtils'; -import { VTableReactAttributePlugin } from '../components/custom/vtable-react-attribute-plugin'; -import { reactEnvModule } from '../components/custom/vtable-browser-env-contribution'; -const { container, isBrowserEnv } = VTable.VRender; export type IVTable = VTable.ListTable | VTable.PivotTable | VTable.PivotChart; export type IOption = @@ -46,19 +42,12 @@ export interface BaseTableProps extends EventsProps { height?: number; skipFunctionDiff?: boolean; - ReactDOM?: any; - /** 表格渲染完成事件 */ onReady?: (instance: IVTable, isInitial: boolean) => void; /** throw error when chart run into an error */ onError?: (err: Error) => void; } -// for react-vtable -if (isBrowserEnv()) { - container.load(reactEnvModule); -} - type Props = React.PropsWithChildren; const notOptionKeys = [ @@ -140,10 +129,7 @@ const BaseTable: React.FC = React.forwardRef((props, ref) => { records: props.records, ...prevOption.current, ...optionFromChildren.current, - clearDOM: false, - customConfig: { - createReactContainer: true - } + clearDOM: false // ...tableContext.current?.optionFromChildren } as IOption; }, @@ -160,10 +146,6 @@ const BaseTable: React.FC = React.forwardRef((props, ref) => { } else { vtable = new VTable.ListTable(props.container, parseOption(props)); } - // vtable.scenegraph.stage.enableReactAttribute(ReactDOM); - vtable.scenegraph.stage.reactAttribute = props.ReactDOM; - vtable.scenegraph.stage.pluginService.register(new VTableReactAttributePlugin()); - vtable.scenegraph.stage.params.ReactDOM = props.ReactDOM; tableContext.current = { ...tableContext.current, table: vtable }; isUnmount.current = false; }, @@ -292,8 +274,7 @@ const BaseTable: React.FC = React.forwardRef((props, ref) => { {React.cloneElement(child as React.ReactElement>, { updateId: updateId, - componentId: childId, - componentIndex: index + componentId: childId })} ); diff --git a/packages/react-vtable/src/vtable.ts b/packages/react-vtable/src/vtable.ts deleted file mode 100644 index 552cc5503..000000000 --- a/packages/react-vtable/src/vtable.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as VTable from '@visactor/vtable'; - -export { VTable }; diff --git a/packages/vtable-editors/package.json b/packages/vtable-editors/package.json index fd6739732..b5349e946 100644 --- a/packages/vtable-editors/package.json +++ b/packages/vtable-editors/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-editors", - "version": "1.5.0", + "version": "0.25.5", "description": "", "sideEffects": false, "main": "cjs/index.js", diff --git a/packages/vtable-editors/src/date-input-editor.ts b/packages/vtable-editors/src/date-input-editor.ts index fa086a8a9..d26b2f105 100644 --- a/packages/vtable-editors/src/date-input-editor.ts +++ b/packages/vtable-editors/src/date-input-editor.ts @@ -1,9 +1,13 @@ -import type { InputEditorConfig } from './input-editor'; import { InputEditor } from './input-editor'; import type { IEditor } from './types'; +export interface DateInputEditorConfig { + max?: number; + min?: number; +} + export class DateInputEditor extends InputEditor implements IEditor { editorType: string = 'DateInput'; - constructor(editorConfig?: InputEditorConfig) { + constructor(editorConfig?: DateInputEditorConfig) { super(editorConfig); this.editorConfig = editorConfig; } diff --git a/packages/vtable-editors/src/index.ts b/packages/vtable-editors/src/index.ts index 30a8200c7..3579152c2 100644 --- a/packages/vtable-editors/src/index.ts +++ b/packages/vtable-editors/src/index.ts @@ -1,6 +1,5 @@ import { InputEditor } from './input-editor'; import { DateInputEditor } from './date-input-editor'; import { ListEditor } from './list-editor'; -import { TextAreaEditor } from './textArea-editor'; -export { InputEditor, DateInputEditor, ListEditor, TextAreaEditor }; +export { InputEditor, DateInputEditor, ListEditor }; export * from './types'; diff --git a/packages/vtable-editors/src/input-editor.ts b/packages/vtable-editors/src/input-editor.ts index 5c4e00bab..1e7a15178 100644 --- a/packages/vtable-editors/src/input-editor.ts +++ b/packages/vtable-editors/src/input-editor.ts @@ -1,7 +1,8 @@ -import type { EditContext, IEditor, RectProps } from './types'; +import type { EditContext, IEditor, Placement, RectProps } from './types'; export interface InputEditorConfig { - readonly?: boolean; + max?: number; + min?: number; } export class InputEditor implements IEditor { @@ -18,11 +19,6 @@ export class InputEditor implements IEditor { createElement() { const input = document.createElement('input'); input.setAttribute('type', 'text'); - - if (this.editorConfig?.readonly) { - input.setAttribute('readonly', `${this.editorConfig.readonly}`); - } - input.style.position = 'absolute'; input.style.padding = '4px'; input.style.width = '100%'; diff --git a/packages/vtable-editors/src/textArea-editor.ts b/packages/vtable-editors/src/textArea-editor.ts deleted file mode 100644 index 360c695a0..000000000 --- a/packages/vtable-editors/src/textArea-editor.ts +++ /dev/null @@ -1,89 +0,0 @@ -import type { EditContext, IEditor, RectProps } from './types'; - -export interface TextAreaEditorConfig { - readonly?: boolean; -} - -export class TextAreaEditor implements IEditor { - editorType: string = 'TextArea'; - editorConfig: TextAreaEditorConfig; - container: HTMLElement; - successCallback?: () => void; - element?: HTMLTextAreaElement; - - constructor(editorConfig?: TextAreaEditorConfig) { - this.editorConfig = editorConfig || {}; - } - - createElement() { - const input = document.createElement('textArea') as HTMLTextAreaElement; - if (this.editorConfig?.readonly) { - input.setAttribute('readonly', `${this.editorConfig.readonly}`); - } - input.style.resize = 'none'; - input.style.position = 'absolute'; - input.style.padding = '4px'; - input.style.width = '100%'; - input.style.height = '100%'; - input.style.boxSizing = 'border-box'; - this.element = input; - - this.container.appendChild(input); - - // 监听键盘事件 - input.addEventListener('keydown', (e: KeyboardEvent) => { - const _isSelectAll = e.key === 'a' && (e.ctrlKey || e.metaKey); - const _isTextAreaNewLine = e.key === 'Enter' && e.shiftKey; - if (_isSelectAll || _isTextAreaNewLine) { - // 阻止冒泡 防止处理成表格全选事件 - e.stopPropagation(); - } - }); - } - - setValue(value: string) { - this.element.value = typeof value !== 'undefined' ? value : ''; - } - - getValue() { - return this.element.value; - } - - onStart({ value, referencePosition, container, endEdit }: EditContext) { - this.container = container; - this.successCallback = endEdit; - if (!this.element) { - this.createElement(); - - if (value !== undefined && value !== null) { - this.setValue(value); - } - if (referencePosition?.rect) { - this.adjustPosition(referencePosition.rect); - } - } - this.element.focus(); - // do nothing - } - - adjustPosition(rect: RectProps) { - this.element.style.top = rect.top + 'px'; - this.element.style.left = rect.left + 'px'; - this.element.style.width = rect.width + 'px'; - this.element.style.height = rect.height + 'px'; - } - - endEditing() { - // do nothing - } - - onEnd() { - // do nothing - this.container.removeChild(this.element); - this.element = undefined; - } - - isEditorElement(target: HTMLElement) { - return target === this.element; - } -} diff --git a/packages/vtable-export/demo/list/list-checkbox.ts b/packages/vtable-export/demo/list/list-checkbox.ts deleted file mode 100644 index b16b650c6..000000000 --- a/packages/vtable-export/demo/list/list-checkbox.ts +++ /dev/null @@ -1,80 +0,0 @@ -import * as VTable from '@visactor/vtable'; -const CONTAINER_ID = 'vTable'; -const generatePersons = count => { - return Array.from(new Array(count)).map((_, i) => ({ - id: i + 1, - email1: `${i + 1}@xxx.com`, - name: `小明${i + 1}`, - lastName: '王', - date1: '2022年9月1日', - tel: '000-0000-0000', - sex: i % 2 === 0 ? 'boy' : 'girl', - work: i % 2 === 0 ? 'back-end engineer' : 'front-end engineer', - city: 'beijing' - })); -}; - -export function createTable() { - const records = [ - { productName: 'aaaa', price: 20, check: { text: 'unchecked', checked: false, disable: false } }, - { productName: 'bbbb', price: 18, check: { text: 'checked', checked: true, disable: false } }, - { productName: 'cccc', price: 16, check: { text: 'disable', checked: true, disable: true } }, - { productName: 'cccc', price: 14, check: { text: 'disable', checked: false, disable: true } }, - { productName: 'eeee', price: 12, check: { text: 'checked', checked: false, disable: false } }, - { productName: 'ffff', price: 10, check: { text: 'checked', checked: false, disable: false } }, - { productName: 'gggg', price: 10, check: { text: 'checked', checked: false, disable: false } } - ]; - - const columns = [ - { - field: 'isCheck', - title: '', - width: 60, - headerType: 'checkbox', - cellType: 'checkbox' - }, - { - field: 'productName', - title: 'productName', - width: 120 - }, - { - field: 'price', - title: 'checkbox', - width: 120, - cellType: 'checkbox', - disable: true, - checked: true - }, - { - field: 'check', - title: 'checkbox', - width: 120, - cellType: 'checkbox' - // disable: true - } - ]; - const option = { - records, - columns - }; - const tableInstance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); - window.tableInstance = tableInstance; - window.excelOption = { - formatExportOutput: ({ cellType, cellValue, table, col, row }) => { - if (cellType === 'checkbox') { - return table.getCellCheckboxState(col, row) ? 'true' : 'false'; - } - } - }; - // tableInstance.on('sort_click', args => { - // tableInstance.updateSortState( - // { - // field: args.field, - // order: Date.now() % 3 === 0 ? 'desc' : Date.now() % 3 === 1 ? 'asc' : 'normal' - // }, - // false - // ); - // return false; //return false代表不执行内部排序逻辑 - // }); -} diff --git a/packages/vtable-export/demo/list/list-tree.ts b/packages/vtable-export/demo/list/list-tree.ts deleted file mode 100644 index 07a80b307..000000000 --- a/packages/vtable-export/demo/list/list-tree.ts +++ /dev/null @@ -1,208 +0,0 @@ -import * as VTable from '@visactor/vtable'; -const CONTAINER_ID = 'vTable'; -const generatePersons = count => { - return Array.from(new Array(count)).map((_, i) => ({ - id: i + 1, - email1: `${i + 1}@xxx.com`, - name: `小明${i + 1}`, - lastName: '王', - date1: '2022年9月1日', - tel: '000-0000-0000', - sex: i % 2 === 0 ? 'boy' : 'girl', - work: i % 2 === 0 ? 'back-end engineer' : 'front-end engineer', - city: 'beijing' - })); -}; - -export function createTable() { - const data = [ - { - 类别: '办公用品', - 销售额: '129.696', - 数量: '2', - 利润: '-60.704', - children: [ - { - 类别: '信封', // 对应原子类别 - 销售额: '125.44', - 数量: '2', - 利润: '42.56', - children: [ - { - 类别: '黄色信封', - 销售额: '125.44', - 数量: '2', - 利润: '42.56' - }, - { - 类别: '白色信封', - 销售额: '1375.92', - 数量: '3', - 利润: '550.2' - } - ] - }, - { - 类别: '器具', // 对应原子类别 - 销售额: '1375.92', - 数量: '3', - 利润: '550.2', - children: [ - { - 类别: '订书机', - 销售额: '125.44', - 数量: '2', - 利润: '42.56' - }, - { - 类别: '计算器', - 销售额: '1375.92', - 数量: '3', - 利润: '550.2' - } - ] - } - ] - }, - { - 类别: '技术', - 销售额: '229.696', - 数量: '20', - 利润: '90.704', - children: [ - { - 类别: '设备', // 对应原子类别 - 销售额: '225.44', - 数量: '5', - 利润: '462.56' - }, - { - 类别: '配件', // 对应原子类别 - 销售额: '375.92', - 数量: '8', - 利润: '550.2' - }, - { - 类别: '复印机', // 对应原子类别 - 销售额: '425.44', - 数量: '7', - 利润: '342.56' - }, - { - 类别: '电话', // 对应原子类别 - 销售额: '175.92', - 数量: '6', - 利润: '750.2' - } - ] - }, - { - 类别: '家具', - 销售额: '129.696', - 数量: '2', - 利润: '-60.704', - children: [ - { - 类别: '桌子', // 对应原子类别 - 销售额: '125.44', - 数量: '2', - 利润: '42.56', - children: [ - { - 类别: '黄色桌子', - 销售额: '125.44', - 数量: '2', - 利润: '42.56' - }, - { - 类别: '白色桌子', - 销售额: '1375.92', - 数量: '3', - 利润: '550.2' - } - ] - }, - { - 类别: '椅子', // 对应原子类别 - 销售额: '1375.92', - 数量: '3', - 利润: '550.2', - children: [ - { - 类别: '老板椅', - 销售额: '125.44', - 数量: '2', - 利润: '42.56' - }, - { - 类别: '沙发椅', - 销售额: '1375.92', - 数量: '3', - 利润: '550.2' - } - ] - } - ] - }, - { - 类别: '生活家电(懒加载)', - 销售额: '229.696', - 数量: '20', - 利润: '90.704' - } - ]; - const option = { - container: document.getElementById(CONTAINER_ID), - columns: [ - { - field: '类别', - tree: true, - title: '类别', - width: 'auto', - sort: true - }, - { - field: '销售额', - title: '销售额', - width: 'auto', - sort: true - // tree: true, - }, - { - field: '利润', - title: '利润', - width: 'auto', - sort: true - } - ], - showPin: true, //显示VTable内置冻结列图标 - widthMode: 'standard', - allowFrozenColCount: 2, - records: data, - - hierarchyIndent: 20, - hierarchyExpandLevel: 2, - hierarchyTextStartAlignment: true, - sortState: { - field: '销售额', - order: 'asc' - }, - theme: VTable.themes.BRIGHT, - defaultRowHeight: 32 - }; - const tableInstance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); - window.tableInstance = tableInstance; - window.excelOption = { - ignoreIcon: true - }; - // tableInstance.on('sort_click', args => { - // tableInstance.updateSortState( - // { - // field: args.field, - // order: Date.now() % 3 === 0 ? 'desc' : Date.now() % 3 === 1 ? 'asc' : 'normal' - // }, - // false - // ); - // return false; //return false代表不执行内部排序逻辑 - // }); -} diff --git a/packages/vtable-export/demo/main.ts b/packages/vtable-export/demo/main.ts index 1d4579990..80f9319c8 100644 --- a/packages/vtable-export/demo/main.ts +++ b/packages/vtable-export/demo/main.ts @@ -143,13 +143,13 @@ function bindExport() { exportCsvButton.addEventListener('click', () => { if (window.tableInstance) { - downloadCsv(exportVTableToCsv(window.tableInstance, window.csvOption), 'export'); + downloadCsv(exportVTableToCsv(window.tableInstance), 'export'); } }); exportExcelButton.addEventListener('click', async () => { if (window.tableInstance) { - downloadExcel(await exportVTableToExcel(window.tableInstance, window.excelOption), 'export'); + downloadExcel(await exportVTableToExcel(window.tableInstance), 'export'); } }); } diff --git a/packages/vtable-export/demo/menu.ts b/packages/vtable-export/demo/menu.ts index 01ac1cfe1..75e9b4918 100644 --- a/packages/vtable-export/demo/menu.ts +++ b/packages/vtable-export/demo/menu.ts @@ -29,14 +29,6 @@ export const menus = [ { path: 'list', name: 'list-large' - }, - { - path: 'list', - name: 'list-tree' - }, - { - path: 'list', - name: 'list-checkbox' } ] }, diff --git a/packages/vtable-export/demo/vite.config.js b/packages/vtable-export/demo/vite.config.js index 55080a87d..8a37d730b 100644 --- a/packages/vtable-export/demo/vite.config.js +++ b/packages/vtable-export/demo/vite.config.js @@ -14,8 +14,7 @@ module.exports = { resolve: { alias: { '@visactor/vtable': path.resolve(__dirname, '../../vtable/src/index.ts'), - '@src': path.resolve(__dirname, '../../vtable/src/'), - '@vutils-extension': path.resolve(__dirname, '../../vtable/src/vutil-extension-temp') + '@src': path.resolve(__dirname, '../../vtable/src/') } }, plugins: [ diff --git a/packages/vtable-export/package.json b/packages/vtable-export/package.json index 1993710b2..8c3a5f381 100644 --- a/packages/vtable-export/package.json +++ b/packages/vtable-export/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-export", - "version": "1.5.0", + "version": "0.25.5", "description": "The export util of VTable", "author": { "name": "VisActor", @@ -36,13 +36,13 @@ }, "dependencies": { "@visactor/vtable": "workspace:*", - "@visactor/vutils": "~0.18.9", + "@visactor/vutils": "~0.18.1", "file-saver": "2.0.5", "@types/file-saver": "2.0.7", "exceljs": "4.4.0" }, "devDependencies": { - "@visactor/vchart": "1.11.4", + "@visactor/vchart": "1.10.5", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", diff --git a/packages/vtable-export/src/csv/index.ts b/packages/vtable-export/src/csv/index.ts index c5ce305cc..a8ab20702 100644 --- a/packages/vtable-export/src/csv/index.ts +++ b/packages/vtable-export/src/csv/index.ts @@ -1,5 +1,4 @@ import type * as VTable from '@visactor/vtable'; -import type { CellInfo } from '../excel'; type IVTable = VTable.ListTable | VTable.PivotTable | VTable.PivotChart; type CellRange = VTable.TYPES.CellRange; @@ -7,11 +6,7 @@ type CellRange = VTable.TYPES.CellRange; const newLine = '\r\n'; const separator = ','; -export type ExportVTableToCsvOptions = { - formatExportOutput?: (cellInfo: CellInfo) => string | undefined; -}; - -export function exportVTableToCsv(tableInstance: IVTable, option?: ExportVTableToCsvOptions): string { +export function exportVTableToCsv(tableInstance: IVTable): string { const minRow = 0; const maxRow = tableInstance.rowCount - 1; const minCol = 0; @@ -20,7 +15,7 @@ export function exportVTableToCsv(tableInstance: IVTable, option?: ExportVTableT let copyValue = ''; for (let row = minRow; row <= maxRow; row++) { for (let col = minCol; col <= maxCol; col++) { - const copyCellValue = getCopyCellValue(col, row, tableInstance, option); + const copyCellValue = getCopyCellValue(col, row, tableInstance); if (typeof Promise !== 'undefined' && copyCellValue instanceof Promise) { // not support async } else { @@ -38,22 +33,7 @@ export function exportVTableToCsv(tableInstance: IVTable, option?: ExportVTableT return copyValue; } -function getCopyCellValue( - col: number, - row: number, - tableInstance: IVTable, - option?: ExportVTableToCsvOptions -): string | Promise | void { - if (option?.formatExportOutput) { - const cellInfo = { cellType: '', cellValue: '', table: tableInstance, col, row }; - const formattedValue = option.formatExportOutput(cellInfo); - if (formattedValue !== undefined) { - if (typeof formattedValue === 'string') { - return '"' + formattedValue + '"'; - } - return formattedValue; - } - } +function getCopyCellValue(col: number, row: number, tableInstance: IVTable): string | Promise | void { const cellRange: CellRange = tableInstance.getCellRange(col, row); const copyStartCol = cellRange.start.col; const copyStartRow = cellRange.start.row; @@ -63,9 +43,5 @@ function getCopyCellValue( } const value = tableInstance.getCellValue(col, row); - - if (typeof value === 'string') { - return '"' + value + '"'; - } return value; } diff --git a/packages/vtable-export/src/excel/index.ts b/packages/vtable-export/src/excel/index.ts index e47e48348..056fc8898 100644 --- a/packages/vtable-export/src/excel/index.ts +++ b/packages/vtable-export/src/excel/index.ts @@ -5,23 +5,8 @@ import { getCellAlignment, getCellBorder, getCellFill, getCellFont } from './sty import { updateCell, renderChart, graphicUtil } from '@visactor/vtable'; import { isArray } from '@visactor/vutils'; import type { ColumnDefine, IRowSeriesNumber } from '@visactor/vtable/src/ts-types'; -import { getHierarchyOffset } from '../util/indent'; -export type CellInfo = { - cellType: string; - cellValue: string; - table: IVTable; - col: number; - row: number; -}; - -export type ExportVTableToExcelOptions = { - ignoreIcon?: boolean; - formatExportOutput?: (cellInfo: CellInfo) => string | undefined; - formatExcelJSCell?: (cellInfo: CellInfo, cellInExcelJS: ExcelJS.Cell) => ExcelJS.Cell; -}; - -export async function exportVTableToExcel(tableInstance: IVTable, options?: ExportVTableToExcelOptions) { +export async function exportVTableToExcel(tableInstance: IVTable) { const workbook = new ExcelJS.Workbook(); const worksheet = workbook.addWorksheet('sheet1'); worksheet.properties.defaultRowHeight = 40; @@ -45,7 +30,7 @@ export async function exportVTableToExcel(tableInstance: IVTable, options?: Expo worksheetRow.height = rowHeight; } - addCell(col, row, tableInstance, worksheet, workbook, options); + addCell(col, row, tableInstance, worksheet, workbook); const cellRange = tableInstance.getCellRange(col, row); if (cellRange.start.col !== cellRange.end.col || cellRange.start.row !== cellRange.end.row) { @@ -100,8 +85,7 @@ function addCell( row: number, tableInstance: IVTable, worksheet: ExcelJS.Worksheet, - workbook: ExcelJS.Workbook, - options?: ExportVTableToExcelOptions + workbook: ExcelJS.Workbook ) { const { layoutMap } = tableInstance.internalProps; const cellType = tableInstance.getCellType(col, row); @@ -129,36 +113,13 @@ function addCell( customLayout = (define as ColumnDefine)?.customLayout; } - if (options?.formatExportOutput) { - const cellInfo = { cellType, cellValue, table: tableInstance, col, row }; - const formattedValue = options.formatExportOutput(cellInfo); - if (formattedValue !== undefined) { - let cell = worksheet.getCell(encodeCellAddress(col, row)); - cell.value = formattedValue; - cell.font = getCellFont(cellStyle, cellType); - cell.fill = getCellFill(cellStyle); - cell.border = getCellBorder(cellStyle); - const offset = getHierarchyOffset(col, row, tableInstance as any); - cell.alignment = getCellAlignment(cellStyle, Math.ceil(offset / cell.font.size)); - - if (cell && options.formatExcelJSCell) { - const formatedCell = options.formatExcelJSCell({ cellType, cellValue, table: tableInstance, col, row }, cell); - if (formatedCell) { - cell = formatedCell; - } - } - return cell; - } - } - - let cell; if ( cellType === 'image' || cellType === 'video' || cellType === 'progressbar' || cellType === 'sparkline' || layoutMap.isAxisCell(col, row) || - (!options?.ignoreIcon && isArray(icons) && icons.length) || + (isArray(icons) && icons.length) || customRender || customLayout ) { @@ -174,13 +135,12 @@ function addCell( // ext: { width: tableInstance.getColWidth(col), height: tableInstance.getRowHeight(row) } }); } else if (cellType === 'text' || cellType === 'link') { - cell = worksheet.getCell(encodeCellAddress(col, row)); + const cell = worksheet.getCell(encodeCellAddress(col, row)); cell.value = getCellValue(cellValue, cellType); cell.font = getCellFont(cellStyle, cellType); cell.fill = getCellFill(cellStyle); cell.border = getCellBorder(cellStyle); - const offset = getHierarchyOffset(col, row, tableInstance as any); - cell.alignment = getCellAlignment(cellStyle, Math.ceil(offset / cell.font.size)); + cell.alignment = getCellAlignment(cellStyle); } else if (cellType === 'chart') { const cellGroup = tableInstance.scenegraph.getCell(col, row); renderChart(cellGroup.firstChild as any); // render chart first @@ -197,14 +157,6 @@ function addCell( }); tableInstance.scenegraph.updateNextFrame(); // rerender chart to avoid display error } - - if (cell && options.formatExcelJSCell) { - const formatedCell = options.formatExcelJSCell({ cellType, cellValue, table: tableInstance, col, row }, cell); - if (formatedCell) { - cell = formatedCell; - } - } - return cell; } function getCellValue(cellValue: string, cellType: CellType) { @@ -223,7 +175,6 @@ function exportCellImg(col: number, row: number, tableInstance: IVTable) { let needRemove = false; if (cellGroup.role === 'empty') { cellGroup = updateCell(col, row, tableInstance as any, true); - cellGroup.setStage(tableInstance.scenegraph.stage); needRemove = true; } const oldStroke = cellGroup.attribute.stroke; @@ -231,7 +182,7 @@ function exportCellImg(col: number, row: number, tableInstance: IVTable) { const canvas = graphicUtil.drawGraphicToCanvas(cellGroup as any, tableInstance.scenegraph.stage) as HTMLCanvasElement; cellGroup.attribute.stroke = oldStroke; if (needRemove) { - cellGroup.parent?.removeChild(cellGroup); + cellGroup.parent.removeChild(cellGroup); } return canvas.toDataURL(); } diff --git a/packages/vtable-export/src/excel/style.ts b/packages/vtable-export/src/excel/style.ts index d51a9d2a4..246309a5a 100644 --- a/packages/vtable-export/src/excel/style.ts +++ b/packages/vtable-export/src/excel/style.ts @@ -93,12 +93,11 @@ function getBorderStyle(lineWidth: number, borderLineDash: LineDashsDef): ExcelJ return 'thick'; } -export function getCellAlignment(cellStyle: CellStyle, indent: number): Partial { +export function getCellAlignment(cellStyle: CellStyle): Partial { return { horizontal: cellStyle.textAlign || 'left', vertical: cellStyle.textBaseline || 'middle', - wrapText: cellStyle.autoWrapText || false, - indent: indent || 0 + wrapText: cellStyle.autoWrapText || false } as any; } diff --git a/packages/vtable-export/src/util/indent.ts b/packages/vtable-export/src/util/indent.ts deleted file mode 100644 index bc7300b1f..000000000 --- a/packages/vtable-export/src/util/indent.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { isValid } from '@visactor/vutils'; -import type { IVTable } from './type'; -import type { ColumnDefine } from '@visactor/vtable'; - -export function getHierarchyOffset(col: number, row: number, table: IVTable): number { - // 处理树形展开 - let cellHierarchyIndent = 0; - const layoutMap = table.internalProps.layoutMap; - //判断是否为表头 - if (layoutMap.isHeader(col, row)) { - const hd = layoutMap.getHeader(col, row) as any; - if (isValid(hd?.hierarchyLevel)) { - cellHierarchyIndent = (hd.hierarchyLevel ?? 0) * ((layoutMap as any).rowHierarchyIndent ?? 0); - } - } else { - // 基本表格表身body单元格 如果是树形展开 需要考虑缩进值 - // const cellHierarchyState = table.getHierarchyState(col, row); - const define = table.getBodyColumnDefine(col, row); - if ((define as ColumnDefine)?.tree) { - const indexArr = table.dataSource.getIndexKey(table.getRecordShowIndexByCell(col, row)); - cellHierarchyIndent = - Array.isArray(indexArr) && table.getHierarchyState(col, row) !== 'none' - ? (indexArr.length - 1) * ((layoutMap as any).hierarchyIndent ?? 0) - : 0; - } - } - - return cellHierarchyIndent; -} diff --git a/packages/vtable-search/README.md b/packages/vtable-search/README.md index 456ef1467..969fd10dd 100644 --- a/packages/vtable-search/README.md +++ b/packages/vtable-search/README.md @@ -22,32 +22,51 @@ VTable is not just a high-performance multidimensional data analysis table, but ## Installation -[npm package](https://www.npmjs.com/package/@visactor/vtable-search) +[npm package](https://www.npmjs.com/package/@visactor/vtable-export) ```bash // npm -npm install @visactor/vtable-search +npm install @visactor/vtable-export // yarn -yarn add @visactor/vtable-search +yarn add @visactor/vtable-export ``` ## Quick Start ```jsx +import * as VTable from '@visactor/vtable'; +import { downloadCsv, exportVTableToCsv, downloadExcel, exportVTableToExcel } from '@visactor/vtable-export'; + const option = { - container: document.getElementById(CONTAINER_ID), - records, - columns, + header: [ + { + field: "0", + caption: "name", + }, + { + field: "1", + caption: "age", + }, + { + field: "2", + caption: "gender", + }, + { + field: "3", + caption: "hobby", + }, + ], + records: new Array(1000).fill(["John", 18, "male", "🏀"]), }; + const tableInstance = new VTable.ListTable(option); -window.tableInstance = tableInstance; -const search = new SearchComponent({ - table: tableInstance, - autoJump: true -}); -window.search = search; +// donload csv file +downloadCsv(exportVTableToCsv(tableInstance), 'export-csv'); + +// donload excel file +downloadExcel(await exportVTableToExcel(tableInstance), 'export-excel'); ``` diff --git a/packages/vtable-search/demo/list/list.ts b/packages/vtable-search/demo/list/list.ts index 3d4cf978f..346241e5a 100644 --- a/packages/vtable-search/demo/list/list.ts +++ b/packages/vtable-search/demo/list/list.ts @@ -113,8 +113,4 @@ export function createTable() { // ); // return false; //return false代表不执行内部排序逻辑 // }); - - setTimeout(() => { - tableInstance.updateOption(option); - }, 2000); } diff --git a/packages/vtable-search/demo/vite.config.js b/packages/vtable-search/demo/vite.config.js index 55080a87d..8a37d730b 100644 --- a/packages/vtable-search/demo/vite.config.js +++ b/packages/vtable-search/demo/vite.config.js @@ -14,8 +14,7 @@ module.exports = { resolve: { alias: { '@visactor/vtable': path.resolve(__dirname, '../../vtable/src/index.ts'), - '@src': path.resolve(__dirname, '../../vtable/src/'), - '@vutils-extension': path.resolve(__dirname, '../../vtable/src/vutil-extension-temp') + '@src': path.resolve(__dirname, '../../vtable/src/') } }, plugins: [ diff --git a/packages/vtable-search/package.json b/packages/vtable-search/package.json index 54c09e4ce..81896bef1 100644 --- a/packages/vtable-search/package.json +++ b/packages/vtable-search/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable-search", - "version": "1.5.0", + "version": "0.25.5", "description": "The search util of VTable", "author": { "name": "VisActor", @@ -35,10 +35,10 @@ }, "dependencies": { "@visactor/vtable": "workspace:*", - "@visactor/vutils": "~0.18.9" + "@visactor/vutils": "~0.18.1" }, "devDependencies": { - "@visactor/vchart": "1.11.4", + "@visactor/vchart": "1.10.5", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", diff --git a/packages/vtable-search/src/search-component/search-component.ts b/packages/vtable-search/src/search-component/search-component.ts index 03e3a710d..f5f0ba1e5 100644 --- a/packages/vtable-search/src/search-component/search-component.ts +++ b/packages/vtable-search/src/search-component/search-component.ts @@ -116,12 +116,6 @@ export class SearchComponent { if (!this.queryResult) { return; } - if (!this.table.hasCustomCellStyle('__search_component_highlight')) { - this.table.registerCustomCellStyle('__search_component_highlight', this.highlightCellStyle as any); - } - if (!this.table.hasCustomCellStyle('__search_component_focuse')) { - this.table.registerCustomCellStyle('__search_component_focuse', this.focuseHighlightCellStyle as any); - } for (let i = 0; i < this.queryResult.length; i++) { const { col, row } = this.queryResult[i]; this.table.arrangeCustomCellStyle( diff --git a/packages/vtable/CHANGELOG.json b/packages/vtable/CHANGELOG.json index ab478d672..e832d6fd5 100644 --- a/packages/vtable/CHANGELOG.json +++ b/packages/vtable/CHANGELOG.json @@ -1,531 +1,6 @@ { "name": "@visactor/vtable", "entries": [ - { - "version": "1.5.0", - "tag": "@visactor/vtable_v1.5.0", - "date": "Fri, 05 Jul 2024 10:43:51 GMT", - "comments": { - "none": [ - { - "comment": "feat: add showMoverLine and hideMoverLine api #2009\n\n" - }, - { - "comment": "fix: pivot chart select state #2017\n\n" - }, - { - "comment": "fix: disable select and edit input should move when input is outside of table #2039\n\n" - }, - { - "comment": "fix: last column resize width error #2040\n\n" - }, - { - "comment": "fix: fix test judgement in customMergeCell #2031" - }, - { - "comment": "fix: fix selected highlight update when scrolling #2028" - }, - { - "comment": "fix: fix select-rect update when scroll #2015" - }, - { - "comment": "fix: fix frozen cell update problem in sort #1997" - } - ], - "minor": [ - { - "comment": "feat: add formatExcelJSCell config in vtable-export #1989" - }, - { - "comment": "feat: optimize package size & add load on demand feature" - } - ] - } - }, - { - "version": "1.4.2", - "tag": "@visactor/vtable_v1.4.2", - "date": "Tue, 02 Jul 2024 12:48:08 GMT", - "comments": { - "none": [ - { - "comment": "feat: corner title can display row and column diemensionTitle #1926\n\n" - }, - { - "comment": "fix: when not exit edit state then can not select other cells #1974\n\n" - }, - { - "comment": "fix: selected_clear event trigger #1981\n\n" - }, - { - "comment": "feat: add column hide config #1991\n\n" - }, - { - "comment": "refactor: sparkline cellType set aggregationType None automatically #1999\n\n" - }, - { - "comment": "fix: pivotTable virtual node edit value not work #2002\n\n" - }, - { - "comment": "fix: tooltip content can not be selected #2003\n\n" - }, - { - "comment": "feat: add getCellAtRelativePosition api" - }, - { - "comment": "fix: fix vrender export module" - }, - { - "comment": "fix: fix merge cell update performance problem #1972" - }, - { - "comment": "fix: fix regexp format for webpack 3 #2005" - }, - { - "comment": "fix: fix width computation in shrinkSparklineFirst mode" - } - ] - } - }, - { - "version": "1.4.1", - "tag": "@visactor/vtable_v1.4.1", - "date": "Mon, 24 Jun 2024 08:48:40 GMT", - "comments": { - "none": [ - { - "comment": "fix: fix editingEditor missing problem" - } - ] - } - }, - { - "version": "1.4.0", - "tag": "@visactor/vtable_v1.4.0", - "date": "Fri, 21 Jun 2024 10:26:08 GMT", - "comments": { - "none": [ - { - "comment": "fix: updateSortState api occor error #1939\n\n" - }, - { - "comment": "feat: support corner header cell edit value #1945\n\n" - }, - { - "comment": "fix: when setRecords should update emptyTip #1953\n\n" - }, - { - "comment": "fix: getCellRect api when cell is frozen get bounds error #1955\n\n" - }, - { - "comment": "fix: when drag cell and enter edit state but can not exit edit rightly #1956\n\n" - }, - { - "comment": "chore: update vrender version\n\n" - }, - { - "comment": "feat: add indent in vtable-export" - }, - { - "comment": "feat: add CustomComponent in react-vtable" - }, - { - "comment": "feat: add CustomLayout component in react-vtable" - }, - { - "comment": "fix: fix custom width problem #1905" - }, - { - "comment": "fix: fix content judgement in getCellRange() #1911" - }, - { - "comment": "fix: fix size update problem in pivot table sort #1958" - } - ], - "minor": [ - { - "comment": "feat: support calculate field for PivotTable #1941\n\n" - } - ] - } - }, - { - "version": "1.3.3", - "tag": "@visactor/vtable_v1.3.3", - "date": "Thu, 20 Jun 2024 12:19:07 GMT", - "comments": { - "none": [ - { - "comment": "fix: fix column update problem #1951" - } - ] - } - }, - { - "version": "1.3.2", - "tag": "@visactor/vtable_v1.3.2", - "date": "Mon, 17 Jun 2024 11:51:18 GMT", - "comments": { - "none": [ - { - "comment": "fix: cellIsInVisualView api error #1864\n\n" - }, - { - "comment": "refactor: tooltip support scroll #1887\n\n" - }, - { - "comment": "fix: if set style autoWrapText, this config not wort when resize column width #1892\n\n" - }, - { - "comment": "refactor: when not records pivot table can show corner header #1895\n\n" - }, - { - "comment": "refactor: when rowTree children not set value can supplement indicators #1924\n\n" - }, - { - "comment": "feat: add blankAreaClickDeselect and outsideClickDeselect config\n\n" - } - ] - } - }, - { - "version": "1.3.1", - "tag": "@visactor/vtable_v1.3.1", - "date": "Thu, 13 Jun 2024 12:35:49 GMT", - "comments": { - "none": [ - { - "comment": "fix: fix frozenColCount large than colCount error #1872\n\n" - }, - { - "comment": "docs: update changlog of rush\n\n" - }, - { - "comment": "fix: fix merge cell size update #1869" - }, - { - "comment": "fix: optimize row height update when useOneRowHeightFillAll" - } - ] - } - }, - { - "version": "1.3.0", - "tag": "@visactor/vtable_v1.3.0", - "date": "Wed, 12 Jun 2024 12:30:16 GMT", - "comments": { - "none": [ - { - "comment": "refactor: memory release logic optimization #1856\n\n" - }, - { - "comment": "refactor: arrow key with shift ctrl key to select cells #1873\n\n" - }, - { - "comment": "fix: icon inlineEnd inlineFront x position compute error #1882\n\n" - }, - { - "comment": "fix: drill down icon can not be click #1899\n\n" - }, - { - "comment": "feat: add ignoreIcon&formatExportOutput config in vtable-export #1813" - }, - { - "comment": "feat: add textArea editor\n\n" - }, - { - "comment": "feat: add strokeColor style #1847" - }, - { - "comment": "feat: add dx&dy in title component #1874" - }, - { - "comment": "fix: fix frozenColCount large than colCount error #1872" - }, - { - "comment": "feat: add shrinkSparklineFirst config #1862" - }, - { - "comment": "fix: fix ellipsis error in _disableColumnAndRowSizeRound mode #1884" - } - ], - "minor": [ - { - "comment": "feat: tooltip disappear delay time #1848\n\n" - }, - { - "comment": "feat: add sort config for pivotTable #1865\n\n" - } - ] - } - }, - { - "version": "1.2.0", - "tag": "@visactor/vtable_v1.2.0", - "date": "Thu, 06 Jun 2024 02:34:10 GMT", - "comments": { - "none": [ - { - "comment": "feat: support select highlightMode effect #1167\n\n" - }, - { - "comment": "feat: add isAggregation api #1803\n\n" - }, - { - "comment": "fix: when has no records should not has aggregation row #1804\n\n" - }, - { - "comment": "refactor: update pixelRatio when resize #1823\n\n" - }, - { - "comment": "fix: updateColumns set editor error #1828\n\n" - }, - { - "comment": "chore: update vrender version\n\n" - }, - { - "comment": "refactor: selectAllOnCtrlA option\n\n" - }, - { - "comment": "feat: optimize large column performance #1840 #1824" - }, - { - "comment": "fix: fix maxCharactersNumber effect #1830" - } - ], - "minor": [ - { - "comment": "feat: add merge cell custom graphic attribute sync #1718" - } - ] - } - }, - { - "version": "1.1.2", - "tag": "@visactor/vtable_v1.1.2", - "date": "Fri, 31 May 2024 08:56:27 GMT", - "comments": { - "none": [ - { - "comment": "chore: update vrender version\n\n" - } - ] - } - }, - { - "version": "1.1.1", - "tag": "@visactor/vtable_v1.1.1", - "date": "Thu, 30 May 2024 08:07:33 GMT", - "comments": { - "none": [ - { - "comment": "refactor: dimension value same with indicator key cell value error #1817\n\n" - }, - { - "comment": "fix: when set emptyTip interaction not work well with has records #1818\n\n" - }, - { - "comment": "fix: fix table frame corner radius display problem #1783" - } - ] - } - }, - { - "version": "1.1.0", - "tag": "@visactor/vtable_v1.1.0", - "date": "Tue, 28 May 2024 12:24:56 GMT", - "comments": { - "none": [ - { - "comment": "fix: add update delete record api should maintain beforeChangedRecordsMap #1780\n\n" - }, - { - "comment": "fix: when set disableSelect table should support drag header #1800\n\n" - }, - { - "comment": "fix: fix tree create problem in getDataCellPath()" - }, - { - "comment": "fix: fix left axis index in horizontal pivot chart" - } - ], - "minor": [ - { - "comment": "feat: add empty tip #1782\n\n" - } - ] - } - }, - { - "version": "1.0.3", - "tag": "@visactor/vtable_v1.0.3", - "date": "Fri, 24 May 2024 10:31:16 GMT", - "comments": { - "none": [ - { - "comment": "refactor: legends support ser array form #1740\n\n" - }, - { - "comment": "fix: first col tree mode compute col width error #1778\n\n" - } - ] - } - }, - { - "version": "1.0.2", - "tag": "@visactor/vtable_v1.0.2", - "date": "Fri, 24 May 2024 10:08:07 GMT", - "comments": { - "none": [ - { - "comment": "fix: use table option in hasAutoImageColumn()" - }, - { - "comment": "fix: axis size align with vrender-component #1784" - }, - { - "comment": "fix: fix lineClamp config in computeRowsHeight() #1772" - }, - { - "comment": "fix: fix progress cell create problem in vtable-export #1787" - }, - { - "comment": "fix: ignore cell merge in selectCells()" - }, - { - "comment": "feat: add setRowHeight&setColWidth api" - } - ] - } - }, - { - "version": "1.0.1", - "tag": "@visactor/vtable_v1.0.1", - "date": "Wed, 22 May 2024 12:21:05 GMT", - "comments": { - "none": [ - { - "comment": "feat: tree mode can set icon #1697\n\n" - }, - { - "comment": "fix: ignore cell merge in selectCells()" - }, - { - "comment": "feat: add setRowHeight&setColWidth api" - } - ] - } - }, - { - "version": "1.0.0", - "tag": "@visactor/vtable_v1.0.0", - "date": "Tue, 21 May 2024 12:41:50 GMT", - "comments": { - "none": [ - { - "comment": "feat: rows and tree can combined use #1644\n\n" - } - ], - "major": [ - { - "comment": "feat: add virtual option for rowTree and columnTree #1644\n\n BREAKING CHANGE: getCellOriginRecord will return an array of source data." - } - ] - } - }, - { - "version": "0.25.9", - "tag": "@visactor/vtable_v0.25.9", - "date": "Tue, 21 May 2024 12:33:13 GMT", - "comments": { - "none": [ - { - "comment": "fix: when body cell is blank string,compute row height error #1752\n\n" - }, - { - "comment": "fix: fix custom merge cell display problem when select header" - } - ] - } - }, - { - "version": "0.25.8", - "tag": "@visactor/vtable_v0.25.8", - "date": "Tue, 21 May 2024 11:19:27 GMT", - "comments": { - "none": [ - { - "comment": "feat: add scrollSliderCornerRadius config #1369\n\n" - }, - { - "comment": "fix: when set hideRowHeader, body cell value is blank #1732\n\n" - }, - { - "comment": "fix: setTableColumnsEditor occor error when not set columns #1747\n\n" - }, - { - "comment": "feat: add disableBackground & disableBorder in exportCellImg() #1733" - }, - { - "comment": "feat: add disableColumnResize for rowSeriesNumber\n\n" - }, - { - "comment": "fix: fix col & row order in cellInRanges()" - }, - { - "comment": "fix: add string mark in csv-export #1730" - } - ] - } - }, - { - "version": "0.25.7", - "tag": "@visactor/vtable_v0.25.7", - "date": "Fri, 17 May 2024 12:08:43 GMT", - "comments": {} - }, - { - "version": "0.25.6", - "tag": "@visactor/vtable_v0.25.6", - "date": "Fri, 17 May 2024 10:50:13 GMT", - "comments": { - "none": [ - { - "comment": "feat: add selected_clear event #1705\n\n" - }, - { - "comment": "fix: mouse down on scroll rail trigger mousedown_table #1706\n\n" - }, - { - "comment": "fix: merge cell value can be edited #1711\n\n" - }, - { - "comment": "fix: sub colunms can not be edit when set editor instance #1711\n\n" - }, - { - "comment": "feat: add mergeCellInfo arg in event #1667" - }, - { - "comment": "fix: fix checkbox and radio state update when change row index #1712" - }, - { - "comment": "fix: fix veritial offset in text stick" - }, - { - "comment": "fix: fix column width may be zero #1708" - }, - { - "comment": "fix: fix getCell performance" - }, - { - "comment": "fix: fix header hide func in pivot table" - }, - { - "comment": "fix: lineDash judgement in group-contribution-render #1696" - } - ] - } - }, { "version": "0.25.5", "tag": "@visactor/vtable_v0.25.5", diff --git a/packages/vtable/CHANGELOG.md b/packages/vtable/CHANGELOG.md index b145187a7..38cecc926 100644 --- a/packages/vtable/CHANGELOG.md +++ b/packages/vtable/CHANGELOG.md @@ -1,375 +1,6 @@ # Change Log - @visactor/vtable -This log was last generated on Fri, 05 Jul 2024 10:43:51 GMT and should not be manually modified. - -## 1.5.0 -Fri, 05 Jul 2024 10:43:51 GMT - -### Minor changes - -- feat: add formatExcelJSCell config in vtable-export #1989 -- feat: optimize package size & add load on demand feature - -### Updates - -- feat: add showMoverLine and hideMoverLine api #2009 - - -- fix: pivot chart select state #2017 - - -- fix: disable select and edit input should move when input is outside of table #2039 - - -- fix: last column resize width error #2040 - - -- fix: fix test judgement in customMergeCell #2031 -- fix: fix selected highlight update when scrolling #2028 -- fix: fix select-rect update when scroll #2015 -- fix: fix frozen cell update problem in sort #1997 - -## 1.4.2 -Tue, 02 Jul 2024 12:48:08 GMT - -### Updates - -- feat: corner title can display row and column diemensionTitle #1926 - - -- fix: when not exit edit state then can not select other cells #1974 - - -- fix: selected_clear event trigger #1981 - - -- feat: add column hide config #1991 - - -- refactor: sparkline cellType set aggregationType None automatically #1999 - - -- fix: pivotTable virtual node edit value not work #2002 - - -- fix: tooltip content can not be selected #2003 - - -- feat: add getCellAtRelativePosition api -- fix: fix vrender export module -- fix: fix merge cell update performance problem #1972 -- fix: fix regexp format for webpack 3 #2005 -- fix: fix width computation in shrinkSparklineFirst mode - -## 1.4.1 -Mon, 24 Jun 2024 08:48:40 GMT - -### Updates - -- fix: fix editingEditor missing problem - -## 1.4.0 -Fri, 21 Jun 2024 10:26:08 GMT - -### Minor changes - -- feat: support calculate field for PivotTable #1941 - - - -### Updates - -- fix: updateSortState api occor error #1939 - - -- feat: support corner header cell edit value #1945 - - -- fix: when setRecords should update emptyTip #1953 - - -- fix: getCellRect api when cell is frozen get bounds error #1955 - - -- fix: when drag cell and enter edit state but can not exit edit rightly #1956 - - -- chore: update vrender version - - -- feat: add indent in vtable-export -- feat: add CustomComponent in react-vtable -- feat: add CustomLayout component in react-vtable -- fix: fix custom width problem #1905 -- fix: fix content judgement in getCellRange() #1911 -- fix: fix size update problem in pivot table sort #1958 - -## 1.3.3 -Thu, 20 Jun 2024 12:19:07 GMT - -### Updates - -- fix: fix column update problem #1951 - -## 1.3.2 -Mon, 17 Jun 2024 11:51:18 GMT - -### Updates - -- fix: cellIsInVisualView api error #1864 - - -- refactor: tooltip support scroll #1887 - - -- fix: if set style autoWrapText, this config not wort when resize column width #1892 - - -- refactor: when not records pivot table can show corner header #1895 - - -- refactor: when rowTree children not set value can supplement indicators #1924 - - -- feat: add blankAreaClickDeselect and outsideClickDeselect config - - - -## 1.3.1 -Thu, 13 Jun 2024 12:35:49 GMT - -### Updates - -- fix: fix frozenColCount large than colCount error #1872 - - -- docs: update changlog of rush - - -- fix: fix merge cell size update #1869 -- fix: optimize row height update when useOneRowHeightFillAll - -## 1.3.0 -Wed, 12 Jun 2024 12:30:16 GMT - -### Minor changes - -- feat: tooltip disappear delay time #1848 - - -- feat: add sort config for pivotTable #1865 - - - -### Updates - -- refactor: memory release logic optimization #1856 - - -- refactor: arrow key with shift ctrl key to select cells #1873 - - -- fix: icon inlineEnd inlineFront x position compute error #1882 - - -- fix: drill down icon can not be click #1899 - - -- feat: add ignoreIcon&formatExportOutput config in vtable-export #1813 -- feat: add textArea editor - - -- feat: add strokeColor style #1847 -- feat: add dx&dy in title component #1874 -- fix: fix frozenColCount large than colCount error #1872 -- feat: add shrinkSparklineFirst config #1862 -- fix: fix ellipsis error in _disableColumnAndRowSizeRound mode #1884 - -## 1.2.0 -Thu, 06 Jun 2024 02:34:10 GMT - -### Minor changes - -- feat: add merge cell custom graphic attribute sync #1718 - -### Updates - -- feat: support select highlightMode effect #1167 - - -- feat: add isAggregation api #1803 - - -- fix: when has no records should not has aggregation row #1804 - - -- refactor: update pixelRatio when resize #1823 - - -- fix: updateColumns set editor error #1828 - - -- chore: update vrender version - - -- refactor: selectAllOnCtrlA option - - -- feat: optimize large column performance #1840 #1824 -- fix: fix maxCharactersNumber effect #1830 - -## 1.1.2 -Fri, 31 May 2024 08:56:27 GMT - -### Updates - -- chore: update vrender version - - - -## 1.1.1 -Thu, 30 May 2024 08:07:33 GMT - -### Updates - -- refactor: dimension value same with indicator key cell value error #1817 - - -- fix: when set emptyTip interaction not work well with has records #1818 - - -- fix: fix table frame corner radius display problem #1783 - -## 1.1.0 -Tue, 28 May 2024 12:24:56 GMT - -### Minor changes - -- feat: add empty tip #1782 - - - -### Updates - -- fix: add update delete record api should maintain beforeChangedRecordsMap #1780 - - -- fix: when set disableSelect table should support drag header #1800 - - -- fix: fix tree create problem in getDataCellPath() -- fix: fix left axis index in horizontal pivot chart - -## 1.0.3 -Fri, 24 May 2024 10:31:16 GMT - -### Updates - -- refactor: legends support ser array form #1740 - - -- fix: first col tree mode compute col width error #1778 - - - -## 1.0.2 -Fri, 24 May 2024 10:08:07 GMT - -### Updates - -- fix: use table option in hasAutoImageColumn() -- fix: axis size align with vrender-component #1784 -- fix: fix lineClamp config in computeRowsHeight() #1772 -- fix: fix progress cell create problem in vtable-export #1787 -- fix: ignore cell merge in selectCells() -- feat: add setRowHeight&setColWidth api - -## 1.0.1 -Wed, 22 May 2024 12:21:05 GMT - -### Updates - -- feat: tree mode can set icon #1697 - - -- fix: ignore cell merge in selectCells() -- feat: add setRowHeight&setColWidth api - -## 1.0.0 -Tue, 21 May 2024 12:41:50 GMT - -### Breaking changes - -- feat: add virtual option for rowTree and columnTree #1644 - - BREAKING CHANGE: getCellOriginRecord will return an array of source data. - -### Updates - -- feat: rows and tree can combined use #1644 - - - -## 0.25.9 -Tue, 21 May 2024 12:33:13 GMT - -### Updates - -- fix: when body cell is blank string,compute row height error #1752 - - -- fix: fix custom merge cell display problem when select header - -## 0.25.8 -Tue, 21 May 2024 11:19:27 GMT - -### Updates - -- feat: add scrollSliderCornerRadius config #1369 - - -- fix: when set hideRowHeader, body cell value is blank #1732 - - -- fix: setTableColumnsEditor occor error when not set columns #1747 - - -- feat: add disableBackground & disableBorder in exportCellImg() #1733 -- feat: add disableColumnResize for rowSeriesNumber - - -- fix: fix col & row order in cellInRanges() -- fix: add string mark in csv-export #1730 - -## 0.25.7 -Fri, 17 May 2024 12:08:43 GMT - -_Version update only_ - -## 0.25.6 -Fri, 17 May 2024 10:50:13 GMT - -### Updates - -- feat: add selected_clear event #1705 - - -- fix: mouse down on scroll rail trigger mousedown_table #1706 - - -- fix: merge cell value can be edited #1711 - - -- fix: sub colunms can not be edit when set editor instance #1711 - - -- feat: add mergeCellInfo arg in event #1667 -- fix: fix checkbox and radio state update when change row index #1712 -- fix: fix veritial offset in text stick -- fix: fix column width may be zero #1708 -- fix: fix getCell performance -- fix: fix header hide func in pivot table -- fix: lineDash judgement in group-contribution-render #1696 +This log was last generated on Mon, 13 May 2024 13:47:37 GMT and should not be manually modified. ## 0.25.5 Mon, 13 May 2024 13:47:37 GMT diff --git a/packages/vtable/__tests__/api/listTable-getCellRect.test.ts b/packages/vtable/__tests__/api/listTable-getCellRect.test.ts deleted file mode 100644 index dad3cca5d..000000000 --- a/packages/vtable/__tests__/api/listTable-getCellRect.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -// @ts-nocheck -// 有问题可对照demo unitTestListTable -import records from '../data/marketsales.json'; -import { ListTable } from '../../src'; -import { createDiv } from '../dom'; -global.__VERSION__ = 'none'; -describe('listTable getCellRect test', () => { - const containerDom: HTMLElement = createDiv(); - containerDom.style.position = 'relative'; - containerDom.style.width = '1000px'; - containerDom.style.height = '800px'; - const columns = [ - { - field: '订单 ID', - caption: '订单 ID', - sort: true, - width: 'auto', - description: '这是订单的描述信息', - style: { - fontFamily: 'Arial', - fontSize: 14 - } - }, - { - field: '订单日期', - caption: '订单日期' - }, - { - field: '发货日期', - caption: '发货日期' - }, - { - field: '客户名称', - caption: '客户名称', - style: { - padding: [10, 0, 10, 60] - } - } - ]; - const option = { - columns, - defaultColWidth: 150, - allowFrozenColCount: 5, - rightFrozenColCount: 1 - }; - - option.container = containerDom; - option.records = records; - const listTable = new ListTable(option); - test('listTable getCellValue', () => { - expect(listTable.getCellRect(3, 3)).toEqual({ - bounds: { - x1: 451, - x2: 601, - y1: 120, - y2: 160 - } - }); - }); -}); diff --git a/packages/vtable/__tests__/api/listTable-getCellRelativePosition.test.ts b/packages/vtable/__tests__/api/listTable-getCellRelativePosition.test.ts deleted file mode 100644 index 900f3ebbf..000000000 --- a/packages/vtable/__tests__/api/listTable-getCellRelativePosition.test.ts +++ /dev/null @@ -1,253 +0,0 @@ -// @ts-nocheck -// 有问题可对照demo unitTestListTable -import records from '../data/marketsales.json'; -import { ListTable } from '../../src'; -import { createDiv } from '../dom'; -global.__VERSION__ = 'none'; -describe('listTable getCellRect test', () => { - const containerDom: HTMLElement = createDiv(); - containerDom.style.position = 'relative'; - containerDom.style.width = '1000px'; - containerDom.style.height = '800px'; - const columns = [ - { - field: '订单 ID', - caption: '订单 ID', - sort: true, - width: 'auto', - description: '这是订单的描述信息', - style: { - fontFamily: 'Arial', - fontSize: 14 - } - }, - { - field: '订单日期', - caption: '订单日期' - }, - { - field: '发货日期', - caption: '发货日期' - }, - { - field: '客户名称', - caption: '客户名称', - style: { - padding: [10, 0, 10, 60] - } - } - ]; - const option = { - columns: [...columns, ...columns, ...columns, ...columns], - defaultColWidth: 150, - allowFrozenColCount: 5, - frozenColCount: 1, - bottomFrozenRowCount: 2, - rightFrozenColCount: 2 - }; - - option.container = containerDom; - option.records = records; - const listTable = new ListTable(option); - test('listTable getCellAtRelativePosition init', () => { - expect(listTable.getCellAtRelativePosition(100, 220)).toEqual({ - row: 5, - col: 0, - rect: { - left: 0, - right: 151, - top: 200, - bottom: 240, - width: 151, - height: 40 - } - }); - - expect(listTable.getCellAtRelativePosition(800, 220)).toEqual({ - row: 5, - col: 14, - rect: { - top: 200, - bottom: 240, - height: 40 - } - }); - - expect(listTable.getCellAtRelativePosition(400, 220)).toEqual({ - row: 5, - col: 2, - rect: { - left: 301, - right: 451, - top: 200, - bottom: 240, - width: 150, - height: 40 - } - }); - - expect(listTable.getCellAtRelativePosition(100, 740)).toEqual({ - row: 38, - col: 0, - rect: { - left: 0, - right: 151, - width: 151 - } - }); - - expect(listTable.getCellAtRelativePosition(800, 740)).toEqual({ - row: 38, - col: 14, - rect: {} - }); - - expect(listTable.getCellAtRelativePosition(400, 740)).toEqual({ - row: 38, - col: 2, - rect: { - left: 301, - right: 451, - width: 150 - } - }); - - expect(listTable.getCellAtRelativePosition(100, 20)).toEqual({ - row: 0, - col: 0, - rect: { - left: 0, - right: 151, - top: 0, - bottom: 40, - width: 151, - height: 40 - } - }); - - expect(listTable.getCellAtRelativePosition(800, 20)).toEqual({ - row: 0, - col: 14, - rect: { - top: 0, - bottom: 40, - height: 40 - } - }); - - expect(listTable.getCellAtRelativePosition(400, 20)).toEqual({ - row: 0, - col: 2, - rect: { - left: 301, - right: 451, - top: 0, - bottom: 40, - width: 150, - height: 40 - } - }); - }); - - test('listTable getCellAtRelativePosition scroll', () => { - listTable.scrollLeft = 500; - listTable.scrollTop = 500; - expect(listTable.getCellAtRelativePosition(100, 220)).toEqual({ - row: 17, - col: 0, - rect: { - left: 0, - right: 151, - top: 680, - bottom: 720, - width: 151, - height: 40 - } - }); - - expect(listTable.getCellAtRelativePosition(800, 220)).toEqual({ - row: 17, - col: 14, - rect: { - top: 680, - bottom: 720, - height: 40 - } - }); - - expect(listTable.getCellAtRelativePosition(400, 220)).toEqual({ - row: 17, - col: 5, - rect: { - left: 752, - right: 902, - top: 680, - bottom: 720, - width: 150, - height: 40 - } - }); - - expect(listTable.getCellAtRelativePosition(100, 740)).toEqual({ - row: 38, - col: 0, - rect: { - left: 0, - right: 151, - width: 151 - } - }); - - expect(listTable.getCellAtRelativePosition(800, 740)).toEqual({ - row: 38, - col: 14, - rect: {} - }); - - expect(listTable.getCellAtRelativePosition(400, 740)).toEqual({ - row: 38, - col: 5, - rect: { - left: 752, - right: 902, - width: 150 - } - }); - - expect(listTable.getCellAtRelativePosition(100, 20)).toEqual({ - row: 0, - col: 0, - rect: { - left: 0, - right: 151, - top: 0, - bottom: 40, - width: 151, - height: 40 - } - }); - - expect(listTable.getCellAtRelativePosition(800, 20)).toEqual({ - row: 0, - col: 14, - rect: { - top: 0, - bottom: 40, - height: 40 - } - }); - - expect(listTable.getCellAtRelativePosition(400, 20)).toEqual({ - row: 0, - col: 5, - rect: { - left: 752, - right: 902, - top: 0, - bottom: 40, - width: 150, - height: 40 - } - }); - }); -}); diff --git a/packages/vtable/__tests__/columns/listTable-cellType-function.test.ts b/packages/vtable/__tests__/columns/listTable-cellType-function.test.ts index 6d6012798..832014eef 100644 --- a/packages/vtable/__tests__/columns/listTable-cellType-function.test.ts +++ b/packages/vtable/__tests__/columns/listTable-cellType-function.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-cellType-function init test', () => { @@ -270,6 +270,7 @@ fruit and seeds. They are also highly intelligent and social, and are considered expect(listTable.getBodyColumnType(2, 1)).toBe('image'); expect(listTable.getBodyColumnType(2, 2)).toBe('link'); expect(listTable.getBodyColumnType(2, 3)).toBe('text'); - listTable.release(); }); + + listTable.release(); }); diff --git a/packages/vtable/__tests__/columns/listTable-cellType.test.ts b/packages/vtable/__tests__/columns/listTable-cellType.test.ts index f1629a7e9..f582fa1a0 100644 --- a/packages/vtable/__tests__/columns/listTable-cellType.test.ts +++ b/packages/vtable/__tests__/columns/listTable-cellType.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-cellType init test', () => { @@ -273,6 +273,6 @@ fruit and seeds. They are also highly intelligent and social, and are considered col: -1, row: -1 }); - listTable.release(); }); + listTable.release(); }); diff --git a/packages/vtable/__tests__/columns/listTable-checkbox.test.ts b/packages/vtable/__tests__/columns/listTable-checkbox.test.ts index 246245068..f94eb66e9 100644 --- a/packages/vtable/__tests__/columns/listTable-checkbox.test.ts +++ b/packages/vtable/__tests__/columns/listTable-checkbox.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-checkbox init test', () => { @@ -126,6 +126,6 @@ describe('listTable-checkbox init test', () => { test('listTable-checkbox getCheckboxState', () => { expect(listTable.stateManager?.checkedState.length).toEqual(101); expect(listTable.getCheckboxState().length).toEqual(2000); - listTable.release(); }); + listTable.release(); }); diff --git a/packages/vtable/__tests__/columns/listTable-custom-layout.test.ts b/packages/vtable/__tests__/columns/listTable-custom-layout.test.ts index 5f39d66d4..a93150ca1 100644 --- a/packages/vtable/__tests__/columns/listTable-custom-layout.test.ts +++ b/packages/vtable/__tests__/columns/listTable-custom-layout.test.ts @@ -1,7 +1,7 @@ /* eslint-disable max-len */ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import * as VTable from '../../src/index'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; @@ -318,6 +318,6 @@ describe('listTable-custom-layout init test', () => { expect(rectBound.right).toBe(410); expect(rectBound.top).toBe(160); expect(rectBound.bottom).toBe(240); - listTable.release(); }); + listTable.release(); }); diff --git a/packages/vtable/__tests__/columns/listTable-dragHeader.test.ts b/packages/vtable/__tests__/columns/listTable-dragHeader.test.ts index f7249a9e5..05a0db9f8 100644 --- a/packages/vtable/__tests__/columns/listTable-dragHeader.test.ts +++ b/packages/vtable/__tests__/columns/listTable-dragHeader.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; const generatePersons = count => { @@ -121,6 +121,6 @@ describe('listTable-cellType-function init test', () => { { field: 'work', title: 'job' }, { field: 'city', title: 'city' } ]); - listTable.release(); }); + listTable.release(); }); diff --git a/packages/vtable/__tests__/components/listTable-legend.test.ts b/packages/vtable/__tests__/components/listTable-legend.test.ts index 34f9b8b10..0bd93c4bc 100644 --- a/packages/vtable/__tests__/components/listTable-legend.test.ts +++ b/packages/vtable/__tests__/components/listTable-legend.test.ts @@ -153,6 +153,6 @@ describe('listTable-legend init test', () => { }) ); expect(listTable.getCellStyle(0, 2).bgColor).toBe('rgba(255, 127, 14, .2)'); - listTable.release(); }); + listTable.release(); }); diff --git a/packages/vtable/__tests__/components/listTable-menu.test.ts b/packages/vtable/__tests__/components/listTable-menu.test.ts index 16eba25e5..2f41c7bc8 100644 --- a/packages/vtable/__tests__/components/listTable-menu.test.ts +++ b/packages/vtable/__tests__/components/listTable-menu.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-menu init test', () => { @@ -146,6 +146,6 @@ describe('listTable-menu init test', () => { }); expect(listTable.stateManager.menu.isShow).toBe(true); - listTable.release(); }); + listTable.release(); }); diff --git a/packages/vtable/__tests__/components/listTable-title.test.ts b/packages/vtable/__tests__/components/listTable-title.test.ts index aa0f73f55..e23d5c46a 100644 --- a/packages/vtable/__tests__/components/listTable-title.test.ts +++ b/packages/vtable/__tests__/components/listTable-title.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-title init test', () => { @@ -95,6 +95,6 @@ describe('listTable-title init test', () => { expect(cell01AABB.y1).toBe(0); expect(cell01AABB.x2).toBe(151); expect(cell01AABB.y2).toBe(40); - listTable.release(); }); + listTable.release(); }); diff --git a/packages/vtable/__tests__/components/listTable-tooltip.test.ts b/packages/vtable/__tests__/components/listTable-tooltip.test.ts index f378fd162..057c4d0a0 100644 --- a/packages/vtable/__tests__/components/listTable-tooltip.test.ts +++ b/packages/vtable/__tests__/components/listTable-tooltip.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import * as VTable from '../../src/index'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; diff --git a/packages/vtable/__tests__/components/pivotTable-size-legend.test.ts b/packages/vtable/__tests__/components/pivotTable-size-legend.test.ts index 2d5cae569..11b9d3892 100644 --- a/packages/vtable/__tests__/components/pivotTable-size-legend.test.ts +++ b/packages/vtable/__tests__/components/pivotTable-size-legend.test.ts @@ -322,6 +322,6 @@ describe('PivotTable-size-legend init test', () => { //TODO 这个对应的例子pivotTable-size-legend 没有问题 // const layerChild = pivotTable.scenegraph.stage.children[0].children; // expect(layerChild[layerChild.length - 1].name).toBe('legend'); - pivotTable.release(); }); + pivotTable.release(); }); diff --git a/packages/vtable/__tests__/edit/pivotTable.test.ts b/packages/vtable/__tests__/edit/pivotTable.test.ts deleted file mode 100644 index e4820e3f2..000000000 --- a/packages/vtable/__tests__/edit/pivotTable.test.ts +++ /dev/null @@ -1,498 +0,0 @@ -/* eslint-disable prettier/prettier */ -// @ts-nocheck -// 有问题可对照demo unitTestPivotTable -import records from '../data/marketsales.json'; -import { PivotTable } from '../../src'; -import { register } from '../../src'; -import { InputEditor } from '@visactor/vtable-editors'; -import { createDiv } from '../dom'; -global.__VERSION__ = 'none'; -const input_editor = new InputEditor({}); -register.editor('input', input_editor); -describe('pivotTable init test', () => { - const containerDom: HTMLElement = createDiv(); - containerDom.style.position = 'relative'; - containerDom.style.width = '500px'; - containerDom.style.height = '500px'; - - const rowTree = [ - { - dimensionKey: '地区', - value: '东北', - children: [ - { - dimensionKey: '省/自治区', - value: '吉林' - }, - { - dimensionKey: '省/自治区', - value: '辽宁' - }, - { - dimensionKey: '省/自治区', - value: '黑龙江' - } - ] - }, - { - dimensionKey: '地区', - value: '中南', - children: [ - { - dimensionKey: '省/自治区', - value: '广东' - }, - { - dimensionKey: '省/自治区', - value: '广西' - }, - { - dimensionKey: '省/自治区', - value: '河南' - }, - { - dimensionKey: '省/自治区', - value: '海南' - }, - { - dimensionKey: '省/自治区', - value: '湖北' - }, - { - dimensionKey: '省/自治区', - value: '湖南' - } - ] - }, - { - dimensionKey: '地区', - value: '华东', - children: [ - { - dimensionKey: '省/自治区', - value: '上海' - }, - { - dimensionKey: '省/自治区', - value: '安徽' - }, - { - dimensionKey: '省/自治区', - value: '山东' - }, - { - dimensionKey: '省/自治区', - value: '江苏' - }, - { - dimensionKey: '省/自治区', - value: '江西' - }, - { - dimensionKey: '省/自治区', - value: '浙江' - }, - { - dimensionKey: '省/自治区', - value: '福建' - } - ] - }, - { - dimensionKey: '地区', - value: '华北', - children: [ - { - dimensionKey: '省/自治区', - value: '内蒙古' - }, - { - dimensionKey: '省/自治区', - value: '北京' - }, - { - dimensionKey: '省/自治区', - value: '天津' - }, - { - dimensionKey: '省/自治区', - value: '山西' - }, - { - dimensionKey: '省/自治区', - value: '河北' - } - ] - }, - { - dimensionKey: '地区', - value: '西北', - children: [ - { - dimensionKey: '省/自治区', - value: '宁夏' - }, - { - dimensionKey: '省/自治区', - value: '新疆' - }, - { - dimensionKey: '省/自治区', - value: '甘肃' - }, - { - dimensionKey: '省/自治区', - value: '陕西' - }, - { - dimensionKey: '省/自治区', - value: '青海' - } - ] - }, - { - dimensionKey: '地区', - value: '西南', - children: [ - { - dimensionKey: '省/自治区', - value: '云南' - }, - { - dimensionKey: '省/自治区', - value: '四川' - }, - { - dimensionKey: '省/自治区', - value: '海南' - }, - { - dimensionKey: '省/自治区', - value: '西藏自治区' - }, - { - dimensionKey: '省/自治区', - value: '贵州' - }, - { - dimensionKey: '省/自治区', - value: '重庆' - } - ] - } - ]; - const columnTree = [ - { - dimensionKey: '子类别', - value: '书架', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '信封', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '器具', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '复印机', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '收纳具', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '标签', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '桌子', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '椅子', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '用具', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '用品', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '电话', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '系固件', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '纸张', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '美术', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '装订机', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '设备', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - }, - { - dimensionKey: '子类别', - value: '配件', - children: [ - { - indicatorKey: '利润' - }, - { - indicatorKey: '销售额' - } - ] - } - ]; - const rows = [ - { - dimensionKey: '地区', - title: '地区', - headerStyle: { - textStick: true, - color: 'red', - bgColor: 'yellow' - }, - width: 'auto', - showSort: false - }, - { - dimensionKey: '省/自治区', - title: '省/自治区', - width: 'auto', - showSort: false, - headerStyle: { - textStick: true, - color: 'red', - bgColor: 'yellow', - marked(arg) { - const cellHeaderPaths = arg.table.getCellHeaderPaths(arg.col, arg.row); - if (cellHeaderPaths.rowHeaderPaths[1].value === '辽宁') { - return true; - } - return false; - } - } - } - ]; - const columns = [ - { - dimensionKey: '子类别', - title: '子类别', - headerStyle: { - textStick: true - }, - showSort: false - } - ]; - const indicators = [ - { - indicatorKey: '利润', - title: '利润', - width: 'auto', - style: { - borderColor: 'red', - bgColor(arg) { - if (Number(Math.ceil(arg.row)) % 2 === 1) { - return 'gray'; - } - return '#f6d7b8'; - } - } - }, - { - indicatorKey: '销售额', - title: '销售额', - width: 'auto' - } - ]; - const option = { - rowTree, - columnTree, - rows, - columns, - indicators, - corner: { - titleOnDimension: 'row' - }, - headerEditor: 'input', - showColumnHeader: true, - showRowHeader: true, - hideIndicatorName: false, - defaultColWidth: 150, - heightMode: 'autoHeight', - autoWrapText: true, - dragHeaderMode: 'all' - }; - - option.container = containerDom; - option.records = records; - const pivotTable = new PivotTable(option); - test('pivotTable change_cell_value args', () => { - let count = 0; - pivotTable.on('change_cell_value', arg => { - if (count === 0) { - expect(arg).toEqual({ - col: 0, - row: 0, - rawValue: '地区', - currentValue: '地区', - changedValue: '1' - }); - } else { - expect(arg).toEqual({ - col: 0, - row: 1, - rawValue: '地区', - currentValue: '地区', - changedValue: '1' - }); - } - count++; - }); - pivotTable.changeCellValues(0, 0, [['1'], ['1']]); - }); -}); diff --git a/packages/vtable/__tests__/layout/get-data-cell-path.test.ts b/packages/vtable/__tests__/layout/get-data-cell-path.test.ts index beeac72e7..e3f41658d 100644 --- a/packages/vtable/__tests__/layout/get-data-cell-path.test.ts +++ b/packages/vtable/__tests__/layout/get-data-cell-path.test.ts @@ -1398,5756 +1398,6 @@ const data = { '231010113100069': '技术' }; -const optionNoTree = { - widthMode: 'adaptive', - heightMode: 'adaptive', - rowTree: [], - columnTree: [], - rows: [], - columns: [], - defaultHeaderRowHeight: 'auto', - indicatorTitle: ' ', - autoWrapText: true, - eventOptions: { - preventDefaultContextMenu: false - }, - corner: { - titleOnDimension: 'row' - }, - title: { - text: '', - align: 'center', - orient: 'top', - padding: [0, 0, 0, 0], - textStyle: { - fontSize: 12, - fill: '#333333', - fontWeight: 'bold' - } - }, - defaultHeaderColWidth: ['auto'], - padding: 0, - labelLayout: 'region', - data: [ - { - id: 'data', - values: [ - [ - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '0', - '240318124021958': '2024-03-01', - '240423133933368': '0' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '0', - '240318124021958': '2024-03-02', - '240423133933368': '0' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '0', - '240318124021958': '2024-03-03', - '240423133933368': '0' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '29', - '240318124021958': '2024-03-04', - '240423133933368': '29' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '32', - '240318124021958': '2024-03-05', - '240423133933368': '32' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '41', - '240318124021958': '2024-03-06', - '240423133933368': '41' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '46', - '240318124021958': '2024-03-07', - '240423133933368': '46' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '41', - '240318124021958': '2024-03-08', - '240423133933368': '41' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2', - '240318124021958': '2024-03-09', - '240423133933368': '2' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '6', - '240318124021958': '2024-03-10', - '240423133933368': '6' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '67', - '240318124021958': '2024-03-11', - '240423133933368': '67' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '58', - '240318124021958': '2024-03-12', - '240423133933368': '58' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '82', - '240318124021958': '2024-03-13', - '240423133933368': '82' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '48', - '240318124021958': '2024-03-14', - '240423133933368': '48' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '28', - '240318124021958': '2024-03-15', - '240423133933368': '28' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3', - '240318124021958': '2024-03-16', - '240423133933368': '3' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '8', - '240318124021958': '2024-03-17', - '240423133933368': '8' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '143', - '240318124021958': '2024-03-18', - '240423133933368': '143' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '141', - '240318124021958': '2024-03-19', - '240423133933368': '141' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '121', - '240318124021958': '2024-03-20', - '240423133933368': '121' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '119', - '240318124021958': '2024-03-21', - '240423133933368': '119' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '114', - '240318124021958': '2024-03-22', - '240423133933368': '114' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '48', - '240318124021958': '2024-03-23', - '240423133933368': '48' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '53', - '240318124021958': '2024-03-24', - '240423133933368': '53' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '120', - '240318124021958': '2024-03-25', - '240423133933368': '120' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '249', - '240318124021958': '2024-03-26', - '240423133933368': '249' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '336', - '240318124021958': '2024-03-27', - '240423133933368': '336' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '689', - '240318124021958': '2024-03-28', - '240423133933368': '689' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '949', - '240318124021958': '2024-03-29', - '240423133933368': '949' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '420', - '240318124021958': '2024-03-30', - '240423133933368': '420' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '317', - '240318124021958': '2024-03-31', - '240423133933368': '317' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1035', - '240318124021958': '2024-04-01', - '240423133933368': '1035' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1201', - '240318124021958': '2024-04-02', - '240423133933368': '1201' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1053', - '240318124021958': '2024-04-03', - '240423133933368': '1053' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '461', - '240318124021958': '2024-04-04', - '240423133933368': '461' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '397', - '240318124021958': '2024-04-05', - '240423133933368': '397' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '378', - '240318124021958': '2024-04-06', - '240423133933368': '378' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '956', - '240318124021958': '2024-04-07', - '240423133933368': '956' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1157', - '240318124021958': '2024-04-08', - '240423133933368': '1157' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1324', - '240318124021958': '2024-04-09', - '240423133933368': '1324' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1920', - '240318124021958': '2024-04-10', - '240423133933368': '1920' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2024', - '240318124021958': '2024-04-11', - '240423133933368': '2024' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1762', - '240318124021958': '2024-04-12', - '240423133933368': '1762' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1016', - '240318124021958': '2024-04-13', - '240423133933368': '1016' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '845', - '240318124021958': '2024-04-14', - '240423133933368': '845' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1893', - '240318124021958': '2024-04-15', - '240423133933368': '1893' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1868', - '240318124021958': '2024-04-16', - '240423133933368': '1868' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1876', - '240318124021958': '2024-04-17', - '240423133933368': '1876' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1754', - '240318124021958': '2024-04-18', - '240423133933368': '1754' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1730', - '240318124021958': '2024-04-19', - '240423133933368': '1730' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1055', - '240318124021958': '2024-04-20', - '240423133933368': '1055' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '899', - '240318124021958': '2024-04-21', - '240423133933368': '899' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1791', - '240318124021958': '2024-04-22', - '240423133933368': '1791' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1726', - '240318124021958': '2024-04-23', - '240423133933368': '1726' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2666', - '240318124021958': '2024-04-24', - '240423133933368': '2666' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3184', - '240318124021958': '2024-04-25', - '240423133933368': '3184' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2878', - '240318124021958': '2024-04-26', - '240423133933368': '2878' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1999', - '240318124021958': '2024-04-27', - '240423133933368': '1999' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2834', - '240318124021958': '2024-04-28', - '240423133933368': '2834' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3350', - '240318124021958': '2024-04-29', - '240423133933368': '3350' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2402', - '240318124021958': '2024-04-30', - '240423133933368': '2402' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1273', - '240318124021958': '2024-05-01', - '240423133933368': '1273' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1480', - '240318124021958': '2024-05-02', - '240423133933368': '1480' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1481', - '240318124021958': '2024-05-03', - '240423133933368': '1481' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1825', - '240318124021958': '2024-05-04', - '240423133933368': '1825' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1907', - '240318124021958': '2024-05-05', - '240423133933368': '1907' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3131', - '240318124021958': '2024-05-06', - '240423133933368': '3131' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3330', - '240318124021958': '2024-05-07', - '240423133933368': '3330' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3351', - '240318124021958': '2024-05-08', - '240423133933368': '3351' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4794', - '240318124021958': '2024-05-09', - '240423133933368': '4794' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '5826', - '240318124021958': '2024-05-10', - '240423133933368': '5826' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '5100', - '240318124021958': '2024-05-11', - '240423133933368': '5100' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3127', - '240318124021958': '2024-05-12', - '240423133933368': '3127' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4744', - '240318124021958': '2024-05-13', - '240423133933368': '4744' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4663', - '240318124021958': '2024-05-14', - '240423133933368': '4663' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4495', - '240318124021958': '2024-05-15', - '240423133933368': '4495' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4425', - '240318124021958': '2024-05-16', - '240423133933368': '4425' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4104', - '240318124021958': '2024-05-17', - '240423133933368': '4104' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2908', - '240318124021958': '2024-05-18', - '240423133933368': '2908' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2869', - '240318124021958': '2024-05-19', - '240423133933368': '2869' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4017', - '240318124021958': '2024-05-20', - '240423133933368': '4017' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4336', - '240318124021958': '2024-05-21', - '240423133933368': '4336' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4524', - '240318124021958': '2024-05-22', - '240423133933368': '4524' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4477', - '240318124021958': '2024-05-23', - '240423133933368': '4477' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4161', - '240318124021958': '2024-05-24', - '240423133933368': '4161' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2982', - '240318124021958': '2024-05-25', - '240423133933368': '2982' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2965', - '240318124021958': '2024-05-26', - '240423133933368': '2965' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4739', - '240318124021958': '2024-05-27', - '240423133933368': '4739' - } - ], - [ - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '0', - '240318124021958': '2024-03-01', - '240430210432450': '0' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '0', - '240318124021958': '2024-03-02', - '240430210432450': '0' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '0', - '240318124021958': '2024-03-03', - '240430210432450': '0' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '20', - '240318124021958': '2024-03-04', - '240430210432450': '20' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '19', - '240318124021958': '2024-03-05', - '240430210432450': '19' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '23', - '240318124021958': '2024-03-06', - '240430210432450': '23' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '26', - '240318124021958': '2024-03-07', - '240430210432450': '26' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '28', - '240318124021958': '2024-03-08', - '240430210432450': '28' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3', - '240318124021958': '2024-03-09', - '240430210432450': '3' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '4', - '240318124021958': '2024-03-10', - '240430210432450': '4' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '50', - '240318124021958': '2024-03-11', - '240430210432450': '50' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '41', - '240318124021958': '2024-03-12', - '240430210432450': '41' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '65', - '240318124021958': '2024-03-13', - '240430210432450': '65' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '33', - '240318124021958': '2024-03-14', - '240430210432450': '33' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '16', - '240318124021958': '2024-03-15', - '240430210432450': '16' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '0', - '240318124021958': '2024-03-16', - '240430210432450': '0' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1', - '240318124021958': '2024-03-17', - '240430210432450': '1' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '107', - '240318124021958': '2024-03-18', - '240430210432450': '107' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '103', - '240318124021958': '2024-03-19', - '240430210432450': '103' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '83', - '240318124021958': '2024-03-20', - '240430210432450': '83' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '84', - '240318124021958': '2024-03-21', - '240430210432450': '84' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '79', - '240318124021958': '2024-03-22', - '240430210432450': '79' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '44', - '240318124021958': '2024-03-23', - '240430210432450': '44' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '39', - '240318124021958': '2024-03-24', - '240430210432450': '39' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '79', - '240318124021958': '2024-03-25', - '240430210432450': '79' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '171', - '240318124021958': '2024-03-26', - '240430210432450': '171' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '250', - '240318124021958': '2024-03-27', - '240430210432450': '250' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '524', - '240318124021958': '2024-03-28', - '240430210432450': '524' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '760', - '240318124021958': '2024-03-29', - '240430210432450': '760' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '343', - '240318124021958': '2024-03-30', - '240430210432450': '343' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '263', - '240318124021958': '2024-03-31', - '240430210432450': '263' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '796', - '240318124021958': '2024-04-01', - '240430210432450': '796' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '922', - '240318124021958': '2024-04-02', - '240430210432450': '922' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '779', - '240318124021958': '2024-04-03', - '240430210432450': '779' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '343', - '240318124021958': '2024-04-04', - '240430210432450': '343' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '291', - '240318124021958': '2024-04-05', - '240430210432450': '291' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '282', - '240318124021958': '2024-04-06', - '240430210432450': '282' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '708', - '240318124021958': '2024-04-07', - '240430210432450': '708' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '862', - '240318124021958': '2024-04-08', - '240430210432450': '862' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '998', - '240318124021958': '2024-04-09', - '240430210432450': '998' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1470', - '240318124021958': '2024-04-10', - '240430210432450': '1470' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1539', - '240318124021958': '2024-04-11', - '240430210432450': '1539' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1323', - '240318124021958': '2024-04-12', - '240430210432450': '1323' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '788', - '240318124021958': '2024-04-13', - '240430210432450': '788' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '640', - '240318124021958': '2024-04-14', - '240430210432450': '640' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1394', - '240318124021958': '2024-04-15', - '240430210432450': '1394' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1431', - '240318124021958': '2024-04-16', - '240430210432450': '1431' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1430', - '240318124021958': '2024-04-17', - '240430210432450': '1430' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1326', - '240318124021958': '2024-04-18', - '240430210432450': '1326' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1283', - '240318124021958': '2024-04-19', - '240430210432450': '1283' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '833', - '240318124021958': '2024-04-20', - '240430210432450': '833' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '711', - '240318124021958': '2024-04-21', - '240430210432450': '711' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1316', - '240318124021958': '2024-04-22', - '240430210432450': '1316' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1278', - '240318124021958': '2024-04-23', - '240430210432450': '1278' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1909', - '240318124021958': '2024-04-24', - '240430210432450': '1909' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2271', - '240318124021958': '2024-04-25', - '240430210432450': '2271' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2004', - '240318124021958': '2024-04-26', - '240430210432450': '2004' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1426', - '240318124021958': '2024-04-27', - '240430210432450': '1426' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2013', - '240318124021958': '2024-04-28', - '240430210432450': '2013' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2502', - '240318124021958': '2024-04-29', - '240430210432450': '2502' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1750', - '240318124021958': '2024-04-30', - '240430210432450': '1750' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '948', - '240318124021958': '2024-05-01', - '240430210432450': '948' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1103', - '240318124021958': '2024-05-02', - '240430210432450': '1103' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1118', - '240318124021958': '2024-05-03', - '240430210432450': '1118' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1394', - '240318124021958': '2024-05-04', - '240430210432450': '1394' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1414', - '240318124021958': '2024-05-05', - '240430210432450': '1414' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2260', - '240318124021958': '2024-05-06', - '240430210432450': '2260' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2372', - '240318124021958': '2024-05-07', - '240430210432450': '2372' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2445', - '240318124021958': '2024-05-08', - '240430210432450': '2445' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3241', - '240318124021958': '2024-05-09', - '240430210432450': '3241' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '4038', - '240318124021958': '2024-05-10', - '240430210432450': '4038' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3714', - '240318124021958': '2024-05-11', - '240430210432450': '3714' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2247', - '240318124021958': '2024-05-12', - '240430210432450': '2247' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3308', - '240318124021958': '2024-05-13', - '240430210432450': '3308' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3361', - '240318124021958': '2024-05-14', - '240430210432450': '3361' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3302', - '240318124021958': '2024-05-15', - '240430210432450': '3302' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3236', - '240318124021958': '2024-05-16', - '240430210432450': '3236' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3069', - '240318124021958': '2024-05-17', - '240430210432450': '3069' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2206', - '240318124021958': '2024-05-18', - '240430210432450': '2206' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2205', - '240318124021958': '2024-05-19', - '240430210432450': '2205' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2828', - '240318124021958': '2024-05-20', - '240430210432450': '2828' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3162', - '240318124021958': '2024-05-21', - '240430210432450': '3162' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3245', - '240318124021958': '2024-05-22', - '240430210432450': '3245' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3180', - '240318124021958': '2024-05-23', - '240430210432450': '3180' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3013', - '240318124021958': '2024-05-24', - '240430210432450': '3013' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2187', - '240318124021958': '2024-05-25', - '240430210432450': '2187' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2274', - '240318124021958': '2024-05-26', - '240430210432450': '2274' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3405', - '240318124021958': '2024-05-27', - '240430210432450': '3405' - } - ], - [ - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-01', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-02', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-03', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '11', - '240318124021958': '2024-03-04', - '240423133933373': '11' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '11', - '240318124021958': '2024-03-05', - '240423133933373': '11' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '15', - '240318124021958': '2024-03-06', - '240423133933373': '15' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '17', - '240318124021958': '2024-03-07', - '240423133933373': '17' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '15', - '240318124021958': '2024-03-08', - '240423133933373': '15' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-09', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '4', - '240318124021958': '2024-03-10', - '240423133933373': '4' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '16', - '240318124021958': '2024-03-11', - '240423133933373': '16' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '12', - '240318124021958': '2024-03-12', - '240423133933373': '12' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '25', - '240318124021958': '2024-03-13', - '240423133933373': '25' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '11', - '240318124021958': '2024-03-14', - '240423133933373': '11' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '4', - '240318124021958': '2024-03-15', - '240423133933373': '4' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-16', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-17', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '81', - '240318124021958': '2024-03-18', - '240423133933373': '81' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '83', - '240318124021958': '2024-03-19', - '240423133933373': '83' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '58', - '240318124021958': '2024-03-20', - '240423133933373': '58' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '52', - '240318124021958': '2024-03-21', - '240423133933373': '52' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '55', - '240318124021958': '2024-03-22', - '240423133933373': '55' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '28', - '240318124021958': '2024-03-23', - '240423133933373': '28' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '34', - '240318124021958': '2024-03-24', - '240423133933373': '34' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '56', - '240318124021958': '2024-03-25', - '240423133933373': '56' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '119', - '240318124021958': '2024-03-26', - '240423133933373': '119' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '167', - '240318124021958': '2024-03-27', - '240423133933373': '167' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '290', - '240318124021958': '2024-03-28', - '240423133933373': '290' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '398', - '240318124021958': '2024-03-29', - '240423133933373': '398' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '203', - '240318124021958': '2024-03-30', - '240423133933373': '203' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '162', - '240318124021958': '2024-03-31', - '240423133933373': '162' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '389', - '240318124021958': '2024-04-01', - '240423133933373': '389' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '477', - '240318124021958': '2024-04-02', - '240423133933373': '477' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '380', - '240318124021958': '2024-04-03', - '240423133933373': '380' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '177', - '240318124021958': '2024-04-04', - '240423133933373': '177' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '165', - '240318124021958': '2024-04-05', - '240423133933373': '165' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '173', - '240318124021958': '2024-04-06', - '240423133933373': '173' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '347', - '240318124021958': '2024-04-07', - '240423133933373': '347' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '477', - '240318124021958': '2024-04-08', - '240423133933373': '477' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '525', - '240318124021958': '2024-04-09', - '240423133933373': '525' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '702', - '240318124021958': '2024-04-10', - '240423133933373': '702' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '763', - '240318124021958': '2024-04-11', - '240423133933373': '763' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '650', - '240318124021958': '2024-04-12', - '240423133933373': '650' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '379', - '240318124021958': '2024-04-13', - '240423133933373': '379' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '342', - '240318124021958': '2024-04-14', - '240423133933373': '342' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '680', - '240318124021958': '2024-04-15', - '240423133933373': '680' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '747', - '240318124021958': '2024-04-16', - '240423133933373': '747' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '787', - '240318124021958': '2024-04-17', - '240423133933373': '787' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '726', - '240318124021958': '2024-04-18', - '240423133933373': '726' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '734', - '240318124021958': '2024-04-19', - '240423133933373': '734' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '494', - '240318124021958': '2024-04-20', - '240423133933373': '494' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '462', - '240318124021958': '2024-04-21', - '240423133933373': '462' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '752', - '240318124021958': '2024-04-22', - '240423133933373': '752' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '739', - '240318124021958': '2024-04-23', - '240423133933373': '739' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '953', - '240318124021958': '2024-04-24', - '240423133933373': '953' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1099', - '240318124021958': '2024-04-25', - '240423133933373': '1099' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1013', - '240318124021958': '2024-04-26', - '240423133933373': '1013' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '679', - '240318124021958': '2024-04-27', - '240423133933373': '679' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1102', - '240318124021958': '2024-04-28', - '240423133933373': '1102' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1251', - '240318124021958': '2024-04-29', - '240423133933373': '1251' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '943', - '240318124021958': '2024-04-30', - '240423133933373': '943' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '551', - '240318124021958': '2024-05-01', - '240423133933373': '551' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '607', - '240318124021958': '2024-05-02', - '240423133933373': '607' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '598', - '240318124021958': '2024-05-03', - '240423133933373': '598' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '716', - '240318124021958': '2024-05-04', - '240423133933373': '716' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '741', - '240318124021958': '2024-05-05', - '240423133933373': '741' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1191', - '240318124021958': '2024-05-06', - '240423133933373': '1191' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1240', - '240318124021958': '2024-05-07', - '240423133933373': '1240' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1308', - '240318124021958': '2024-05-08', - '240423133933373': '1308' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1466', - '240318124021958': '2024-05-09', - '240423133933373': '1466' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1867', - '240318124021958': '2024-05-10', - '240423133933373': '1867' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1803', - '240318124021958': '2024-05-11', - '240423133933373': '1803' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1055', - '240318124021958': '2024-05-12', - '240423133933373': '1055' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1525', - '240318124021958': '2024-05-13', - '240423133933373': '1525' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1660', - '240318124021958': '2024-05-14', - '240423133933373': '1660' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1671', - '240318124021958': '2024-05-15', - '240423133933373': '1671' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1661', - '240318124021958': '2024-05-16', - '240423133933373': '1661' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1618', - '240318124021958': '2024-05-17', - '240423133933373': '1618' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1178', - '240318124021958': '2024-05-18', - '240423133933373': '1178' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1205', - '240318124021958': '2024-05-19', - '240423133933373': '1205' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1472', - '240318124021958': '2024-05-20', - '240423133933373': '1472' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1612', - '240318124021958': '2024-05-21', - '240423133933373': '1612' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1726', - '240318124021958': '2024-05-22', - '240423133933373': '1726' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1573', - '240318124021958': '2024-05-23', - '240423133933373': '1573' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '670', - '240318124021958': '2024-05-24', - '240423133933373': '670' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '38', - '240318124021958': '2024-05-25', - '240423133933373': '38' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '12', - '240318124021958': '2024-05-26', - '240423133933373': '12' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '508', - '240318124021958': '2024-05-27', - '240423133933373': '508' - } - ] - ], - fields: { - '10001': { - alias: '指标名称 ' - }, - '20001': { - alias: '图例项 ', - domain: ['活跃DAU', '生成DAU', '导出DAU'], - sortIndex: 0, - lockStatisticsByDomain: true - }, - '110002': { - alias: '指标值 ' - }, - '210002': { - alias: '指标值 ' - }, - '010002': { - alias: '指标值 ' - }, - '240318124021958': { - alias: 'p_date', - domain: [ - '2024-03-01', - '2024-03-02', - '2024-03-03', - '2024-03-04', - '2024-03-05', - '2024-03-06', - '2024-03-07', - '2024-03-08', - '2024-03-09', - '2024-03-10', - '2024-03-11', - '2024-03-12', - '2024-03-13', - '2024-03-14', - '2024-03-15', - '2024-03-16', - '2024-03-17', - '2024-03-18', - '2024-03-19', - '2024-03-20', - '2024-03-21', - '2024-03-22', - '2024-03-23', - '2024-03-24', - '2024-03-25', - '2024-03-26', - '2024-03-27', - '2024-03-28', - '2024-03-29', - '2024-03-30', - '2024-03-31', - '2024-04-01', - '2024-04-02', - '2024-04-03', - '2024-04-04', - '2024-04-05', - '2024-04-06', - '2024-04-07', - '2024-04-08', - '2024-04-09', - '2024-04-10', - '2024-04-11', - '2024-04-12', - '2024-04-13', - '2024-04-14', - '2024-04-15', - '2024-04-16', - '2024-04-17', - '2024-04-18', - '2024-04-19', - '2024-04-20', - '2024-04-21', - '2024-04-22', - '2024-04-23', - '2024-04-24', - '2024-04-25', - '2024-04-26', - '2024-04-27', - '2024-04-28', - '2024-04-29', - '2024-04-30', - '2024-05-01', - '2024-05-02', - '2024-05-03', - '2024-05-04', - '2024-05-05', - '2024-05-06', - '2024-05-07', - '2024-05-08', - '2024-05-09', - '2024-05-10', - '2024-05-11', - '2024-05-12', - '2024-05-13', - '2024-05-14', - '2024-05-15', - '2024-05-16', - '2024-05-17', - '2024-05-18', - '2024-05-19', - '2024-05-20', - '2024-05-21', - '2024-05-22', - '2024-05-23', - '2024-05-24', - '2024-05-25', - '2024-05-26', - '2024-05-27' - ], - sortIndex: 0, - lockStatisticsByDomain: true - }, - '240423133933368': { - alias: '活跃DAU' - }, - '240423133933373': { - alias: '导出DAU' - }, - '240430210432450': { - alias: '生成DAU' - } - } - } - ], - axes: [ - { - type: 'band', - tick: { - visible: false - }, - grid: { - visible: false, - style: { - zIndex: 150, - stroke: '#DADCDD', - lineWidth: 1, - lineDash: [4, 2] - } - }, - orient: 'bottom', - visible: true, - domainLine: { - visible: true, - style: { - lineWidth: 1, - stroke: '#989999' - } - }, - title: { - visible: false, - space: 5, - text: 'p_date', - style: { - fontSize: 12, - fill: '#363839', - fontWeight: 'normal' - } - }, - maxHeight: null, - autoIndent: false, - sampling: false, - zIndex: 200, - label: { - visible: true, - space: 4, - style: { - fontSize: 12, - fill: '#6F6F6F', - angle: 0, - fontWeight: 'normal', - direction: 'horizontal', - maxLineWidth: 174 - }, - autoHide: true, - autoHideMethod: 'greedy', - flush: true, - lastVisible: true - }, - hover: true, - background: { - visible: true, - state: { - hover: { - fillOpacity: 0.08, - fill: '#141414' - }, - hover_reverse: { - fillOpacity: 0.08, - fill: '#141414' - } - } - }, - paddingInner: [0.15, 0.1], - paddingOuter: [0.075, 0.1] - } - ], - legends: [ - { - type: 'discrete', - visible: false - } - ], - records: { - '0': [ - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '0', - '240318124021958': '2024-03-01', - '240423133933368': '0' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '0', - '240318124021958': '2024-03-02', - '240423133933368': '0' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '0', - '240318124021958': '2024-03-03', - '240423133933368': '0' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '29', - '240318124021958': '2024-03-04', - '240423133933368': '29' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '32', - '240318124021958': '2024-03-05', - '240423133933368': '32' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '41', - '240318124021958': '2024-03-06', - '240423133933368': '41' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '46', - '240318124021958': '2024-03-07', - '240423133933368': '46' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '41', - '240318124021958': '2024-03-08', - '240423133933368': '41' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2', - '240318124021958': '2024-03-09', - '240423133933368': '2' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '6', - '240318124021958': '2024-03-10', - '240423133933368': '6' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '67', - '240318124021958': '2024-03-11', - '240423133933368': '67' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '58', - '240318124021958': '2024-03-12', - '240423133933368': '58' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '82', - '240318124021958': '2024-03-13', - '240423133933368': '82' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '48', - '240318124021958': '2024-03-14', - '240423133933368': '48' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '28', - '240318124021958': '2024-03-15', - '240423133933368': '28' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3', - '240318124021958': '2024-03-16', - '240423133933368': '3' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '8', - '240318124021958': '2024-03-17', - '240423133933368': '8' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '143', - '240318124021958': '2024-03-18', - '240423133933368': '143' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '141', - '240318124021958': '2024-03-19', - '240423133933368': '141' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '121', - '240318124021958': '2024-03-20', - '240423133933368': '121' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '119', - '240318124021958': '2024-03-21', - '240423133933368': '119' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '114', - '240318124021958': '2024-03-22', - '240423133933368': '114' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '48', - '240318124021958': '2024-03-23', - '240423133933368': '48' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '53', - '240318124021958': '2024-03-24', - '240423133933368': '53' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '120', - '240318124021958': '2024-03-25', - '240423133933368': '120' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '249', - '240318124021958': '2024-03-26', - '240423133933368': '249' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '336', - '240318124021958': '2024-03-27', - '240423133933368': '336' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '689', - '240318124021958': '2024-03-28', - '240423133933368': '689' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '949', - '240318124021958': '2024-03-29', - '240423133933368': '949' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '420', - '240318124021958': '2024-03-30', - '240423133933368': '420' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '317', - '240318124021958': '2024-03-31', - '240423133933368': '317' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1035', - '240318124021958': '2024-04-01', - '240423133933368': '1035' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1201', - '240318124021958': '2024-04-02', - '240423133933368': '1201' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1053', - '240318124021958': '2024-04-03', - '240423133933368': '1053' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '461', - '240318124021958': '2024-04-04', - '240423133933368': '461' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '397', - '240318124021958': '2024-04-05', - '240423133933368': '397' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '378', - '240318124021958': '2024-04-06', - '240423133933368': '378' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '956', - '240318124021958': '2024-04-07', - '240423133933368': '956' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1157', - '240318124021958': '2024-04-08', - '240423133933368': '1157' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1324', - '240318124021958': '2024-04-09', - '240423133933368': '1324' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1920', - '240318124021958': '2024-04-10', - '240423133933368': '1920' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2024', - '240318124021958': '2024-04-11', - '240423133933368': '2024' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1762', - '240318124021958': '2024-04-12', - '240423133933368': '1762' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1016', - '240318124021958': '2024-04-13', - '240423133933368': '1016' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '845', - '240318124021958': '2024-04-14', - '240423133933368': '845' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1893', - '240318124021958': '2024-04-15', - '240423133933368': '1893' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1868', - '240318124021958': '2024-04-16', - '240423133933368': '1868' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1876', - '240318124021958': '2024-04-17', - '240423133933368': '1876' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1754', - '240318124021958': '2024-04-18', - '240423133933368': '1754' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1730', - '240318124021958': '2024-04-19', - '240423133933368': '1730' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1055', - '240318124021958': '2024-04-20', - '240423133933368': '1055' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '899', - '240318124021958': '2024-04-21', - '240423133933368': '899' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1791', - '240318124021958': '2024-04-22', - '240423133933368': '1791' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1726', - '240318124021958': '2024-04-23', - '240423133933368': '1726' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2666', - '240318124021958': '2024-04-24', - '240423133933368': '2666' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3184', - '240318124021958': '2024-04-25', - '240423133933368': '3184' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2878', - '240318124021958': '2024-04-26', - '240423133933368': '2878' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1999', - '240318124021958': '2024-04-27', - '240423133933368': '1999' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2834', - '240318124021958': '2024-04-28', - '240423133933368': '2834' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3350', - '240318124021958': '2024-04-29', - '240423133933368': '3350' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2402', - '240318124021958': '2024-04-30', - '240423133933368': '2402' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1273', - '240318124021958': '2024-05-01', - '240423133933368': '1273' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1480', - '240318124021958': '2024-05-02', - '240423133933368': '1480' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1481', - '240318124021958': '2024-05-03', - '240423133933368': '1481' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1825', - '240318124021958': '2024-05-04', - '240423133933368': '1825' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '1907', - '240318124021958': '2024-05-05', - '240423133933368': '1907' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3131', - '240318124021958': '2024-05-06', - '240423133933368': '3131' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3330', - '240318124021958': '2024-05-07', - '240423133933368': '3330' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3351', - '240318124021958': '2024-05-08', - '240423133933368': '3351' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4794', - '240318124021958': '2024-05-09', - '240423133933368': '4794' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '5826', - '240318124021958': '2024-05-10', - '240423133933368': '5826' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '5100', - '240318124021958': '2024-05-11', - '240423133933368': '5100' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '3127', - '240318124021958': '2024-05-12', - '240423133933368': '3127' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4744', - '240318124021958': '2024-05-13', - '240423133933368': '4744' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4663', - '240318124021958': '2024-05-14', - '240423133933368': '4663' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4495', - '240318124021958': '2024-05-15', - '240423133933368': '4495' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4425', - '240318124021958': '2024-05-16', - '240423133933368': '4425' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4104', - '240318124021958': '2024-05-17', - '240423133933368': '4104' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2908', - '240318124021958': '2024-05-18', - '240423133933368': '2908' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2869', - '240318124021958': '2024-05-19', - '240423133933368': '2869' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4017', - '240318124021958': '2024-05-20', - '240423133933368': '4017' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4336', - '240318124021958': '2024-05-21', - '240423133933368': '4336' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4524', - '240318124021958': '2024-05-22', - '240423133933368': '4524' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4477', - '240318124021958': '2024-05-23', - '240423133933368': '4477' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4161', - '240318124021958': '2024-05-24', - '240423133933368': '4161' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2982', - '240318124021958': '2024-05-25', - '240423133933368': '2982' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '2965', - '240318124021958': '2024-05-26', - '240423133933368': '2965' - }, - { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '4739', - '240318124021958': '2024-05-27', - '240423133933368': '4739' - } - ], - '1': [ - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '0', - '240318124021958': '2024-03-01', - '240430210432450': '0' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '0', - '240318124021958': '2024-03-02', - '240430210432450': '0' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '0', - '240318124021958': '2024-03-03', - '240430210432450': '0' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '20', - '240318124021958': '2024-03-04', - '240430210432450': '20' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '19', - '240318124021958': '2024-03-05', - '240430210432450': '19' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '23', - '240318124021958': '2024-03-06', - '240430210432450': '23' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '26', - '240318124021958': '2024-03-07', - '240430210432450': '26' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '28', - '240318124021958': '2024-03-08', - '240430210432450': '28' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3', - '240318124021958': '2024-03-09', - '240430210432450': '3' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '4', - '240318124021958': '2024-03-10', - '240430210432450': '4' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '50', - '240318124021958': '2024-03-11', - '240430210432450': '50' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '41', - '240318124021958': '2024-03-12', - '240430210432450': '41' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '65', - '240318124021958': '2024-03-13', - '240430210432450': '65' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '33', - '240318124021958': '2024-03-14', - '240430210432450': '33' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '16', - '240318124021958': '2024-03-15', - '240430210432450': '16' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '0', - '240318124021958': '2024-03-16', - '240430210432450': '0' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1', - '240318124021958': '2024-03-17', - '240430210432450': '1' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '107', - '240318124021958': '2024-03-18', - '240430210432450': '107' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '103', - '240318124021958': '2024-03-19', - '240430210432450': '103' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '83', - '240318124021958': '2024-03-20', - '240430210432450': '83' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '84', - '240318124021958': '2024-03-21', - '240430210432450': '84' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '79', - '240318124021958': '2024-03-22', - '240430210432450': '79' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '44', - '240318124021958': '2024-03-23', - '240430210432450': '44' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '39', - '240318124021958': '2024-03-24', - '240430210432450': '39' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '79', - '240318124021958': '2024-03-25', - '240430210432450': '79' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '171', - '240318124021958': '2024-03-26', - '240430210432450': '171' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '250', - '240318124021958': '2024-03-27', - '240430210432450': '250' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '524', - '240318124021958': '2024-03-28', - '240430210432450': '524' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '760', - '240318124021958': '2024-03-29', - '240430210432450': '760' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '343', - '240318124021958': '2024-03-30', - '240430210432450': '343' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '263', - '240318124021958': '2024-03-31', - '240430210432450': '263' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '796', - '240318124021958': '2024-04-01', - '240430210432450': '796' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '922', - '240318124021958': '2024-04-02', - '240430210432450': '922' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '779', - '240318124021958': '2024-04-03', - '240430210432450': '779' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '343', - '240318124021958': '2024-04-04', - '240430210432450': '343' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '291', - '240318124021958': '2024-04-05', - '240430210432450': '291' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '282', - '240318124021958': '2024-04-06', - '240430210432450': '282' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '708', - '240318124021958': '2024-04-07', - '240430210432450': '708' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '862', - '240318124021958': '2024-04-08', - '240430210432450': '862' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '998', - '240318124021958': '2024-04-09', - '240430210432450': '998' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1470', - '240318124021958': '2024-04-10', - '240430210432450': '1470' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1539', - '240318124021958': '2024-04-11', - '240430210432450': '1539' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1323', - '240318124021958': '2024-04-12', - '240430210432450': '1323' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '788', - '240318124021958': '2024-04-13', - '240430210432450': '788' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '640', - '240318124021958': '2024-04-14', - '240430210432450': '640' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1394', - '240318124021958': '2024-04-15', - '240430210432450': '1394' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1431', - '240318124021958': '2024-04-16', - '240430210432450': '1431' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1430', - '240318124021958': '2024-04-17', - '240430210432450': '1430' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1326', - '240318124021958': '2024-04-18', - '240430210432450': '1326' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1283', - '240318124021958': '2024-04-19', - '240430210432450': '1283' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '833', - '240318124021958': '2024-04-20', - '240430210432450': '833' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '711', - '240318124021958': '2024-04-21', - '240430210432450': '711' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1316', - '240318124021958': '2024-04-22', - '240430210432450': '1316' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1278', - '240318124021958': '2024-04-23', - '240430210432450': '1278' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1909', - '240318124021958': '2024-04-24', - '240430210432450': '1909' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2271', - '240318124021958': '2024-04-25', - '240430210432450': '2271' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2004', - '240318124021958': '2024-04-26', - '240430210432450': '2004' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1426', - '240318124021958': '2024-04-27', - '240430210432450': '1426' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2013', - '240318124021958': '2024-04-28', - '240430210432450': '2013' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2502', - '240318124021958': '2024-04-29', - '240430210432450': '2502' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1750', - '240318124021958': '2024-04-30', - '240430210432450': '1750' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '948', - '240318124021958': '2024-05-01', - '240430210432450': '948' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1103', - '240318124021958': '2024-05-02', - '240430210432450': '1103' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1118', - '240318124021958': '2024-05-03', - '240430210432450': '1118' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1394', - '240318124021958': '2024-05-04', - '240430210432450': '1394' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '1414', - '240318124021958': '2024-05-05', - '240430210432450': '1414' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2260', - '240318124021958': '2024-05-06', - '240430210432450': '2260' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2372', - '240318124021958': '2024-05-07', - '240430210432450': '2372' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2445', - '240318124021958': '2024-05-08', - '240430210432450': '2445' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3241', - '240318124021958': '2024-05-09', - '240430210432450': '3241' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '4038', - '240318124021958': '2024-05-10', - '240430210432450': '4038' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3714', - '240318124021958': '2024-05-11', - '240430210432450': '3714' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2247', - '240318124021958': '2024-05-12', - '240430210432450': '2247' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3308', - '240318124021958': '2024-05-13', - '240430210432450': '3308' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3361', - '240318124021958': '2024-05-14', - '240430210432450': '3361' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3302', - '240318124021958': '2024-05-15', - '240430210432450': '3302' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3236', - '240318124021958': '2024-05-16', - '240430210432450': '3236' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3069', - '240318124021958': '2024-05-17', - '240430210432450': '3069' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2206', - '240318124021958': '2024-05-18', - '240430210432450': '2206' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2205', - '240318124021958': '2024-05-19', - '240430210432450': '2205' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2828', - '240318124021958': '2024-05-20', - '240430210432450': '2828' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3162', - '240318124021958': '2024-05-21', - '240430210432450': '3162' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3245', - '240318124021958': '2024-05-22', - '240430210432450': '3245' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3180', - '240318124021958': '2024-05-23', - '240430210432450': '3180' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3013', - '240318124021958': '2024-05-24', - '240430210432450': '3013' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2187', - '240318124021958': '2024-05-25', - '240430210432450': '2187' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '2274', - '240318124021958': '2024-05-26', - '240430210432450': '2274' - }, - { - '10001': '生成DAU', - '10003': '240430210432450', - '20001': '生成DAU', - '110002': '3405', - '240318124021958': '2024-05-27', - '240430210432450': '3405' - } - ], - '2': [ - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-01', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-02', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-03', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '11', - '240318124021958': '2024-03-04', - '240423133933373': '11' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '11', - '240318124021958': '2024-03-05', - '240423133933373': '11' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '15', - '240318124021958': '2024-03-06', - '240423133933373': '15' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '17', - '240318124021958': '2024-03-07', - '240423133933373': '17' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '15', - '240318124021958': '2024-03-08', - '240423133933373': '15' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-09', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '4', - '240318124021958': '2024-03-10', - '240423133933373': '4' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '16', - '240318124021958': '2024-03-11', - '240423133933373': '16' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '12', - '240318124021958': '2024-03-12', - '240423133933373': '12' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '25', - '240318124021958': '2024-03-13', - '240423133933373': '25' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '11', - '240318124021958': '2024-03-14', - '240423133933373': '11' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '4', - '240318124021958': '2024-03-15', - '240423133933373': '4' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-16', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '0', - '240318124021958': '2024-03-17', - '240423133933373': '0' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '81', - '240318124021958': '2024-03-18', - '240423133933373': '81' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '83', - '240318124021958': '2024-03-19', - '240423133933373': '83' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '58', - '240318124021958': '2024-03-20', - '240423133933373': '58' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '52', - '240318124021958': '2024-03-21', - '240423133933373': '52' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '55', - '240318124021958': '2024-03-22', - '240423133933373': '55' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '28', - '240318124021958': '2024-03-23', - '240423133933373': '28' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '34', - '240318124021958': '2024-03-24', - '240423133933373': '34' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '56', - '240318124021958': '2024-03-25', - '240423133933373': '56' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '119', - '240318124021958': '2024-03-26', - '240423133933373': '119' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '167', - '240318124021958': '2024-03-27', - '240423133933373': '167' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '290', - '240318124021958': '2024-03-28', - '240423133933373': '290' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '398', - '240318124021958': '2024-03-29', - '240423133933373': '398' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '203', - '240318124021958': '2024-03-30', - '240423133933373': '203' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '162', - '240318124021958': '2024-03-31', - '240423133933373': '162' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '389', - '240318124021958': '2024-04-01', - '240423133933373': '389' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '477', - '240318124021958': '2024-04-02', - '240423133933373': '477' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '380', - '240318124021958': '2024-04-03', - '240423133933373': '380' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '177', - '240318124021958': '2024-04-04', - '240423133933373': '177' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '165', - '240318124021958': '2024-04-05', - '240423133933373': '165' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '173', - '240318124021958': '2024-04-06', - '240423133933373': '173' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '347', - '240318124021958': '2024-04-07', - '240423133933373': '347' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '477', - '240318124021958': '2024-04-08', - '240423133933373': '477' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '525', - '240318124021958': '2024-04-09', - '240423133933373': '525' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '702', - '240318124021958': '2024-04-10', - '240423133933373': '702' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '763', - '240318124021958': '2024-04-11', - '240423133933373': '763' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '650', - '240318124021958': '2024-04-12', - '240423133933373': '650' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '379', - '240318124021958': '2024-04-13', - '240423133933373': '379' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '342', - '240318124021958': '2024-04-14', - '240423133933373': '342' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '680', - '240318124021958': '2024-04-15', - '240423133933373': '680' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '747', - '240318124021958': '2024-04-16', - '240423133933373': '747' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '787', - '240318124021958': '2024-04-17', - '240423133933373': '787' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '726', - '240318124021958': '2024-04-18', - '240423133933373': '726' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '734', - '240318124021958': '2024-04-19', - '240423133933373': '734' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '494', - '240318124021958': '2024-04-20', - '240423133933373': '494' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '462', - '240318124021958': '2024-04-21', - '240423133933373': '462' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '752', - '240318124021958': '2024-04-22', - '240423133933373': '752' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '739', - '240318124021958': '2024-04-23', - '240423133933373': '739' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '953', - '240318124021958': '2024-04-24', - '240423133933373': '953' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1099', - '240318124021958': '2024-04-25', - '240423133933373': '1099' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1013', - '240318124021958': '2024-04-26', - '240423133933373': '1013' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '679', - '240318124021958': '2024-04-27', - '240423133933373': '679' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1102', - '240318124021958': '2024-04-28', - '240423133933373': '1102' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1251', - '240318124021958': '2024-04-29', - '240423133933373': '1251' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '943', - '240318124021958': '2024-04-30', - '240423133933373': '943' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '551', - '240318124021958': '2024-05-01', - '240423133933373': '551' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '607', - '240318124021958': '2024-05-02', - '240423133933373': '607' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '598', - '240318124021958': '2024-05-03', - '240423133933373': '598' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '716', - '240318124021958': '2024-05-04', - '240423133933373': '716' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '741', - '240318124021958': '2024-05-05', - '240423133933373': '741' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1191', - '240318124021958': '2024-05-06', - '240423133933373': '1191' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1240', - '240318124021958': '2024-05-07', - '240423133933373': '1240' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1308', - '240318124021958': '2024-05-08', - '240423133933373': '1308' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1466', - '240318124021958': '2024-05-09', - '240423133933373': '1466' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1867', - '240318124021958': '2024-05-10', - '240423133933373': '1867' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1803', - '240318124021958': '2024-05-11', - '240423133933373': '1803' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1055', - '240318124021958': '2024-05-12', - '240423133933373': '1055' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1525', - '240318124021958': '2024-05-13', - '240423133933373': '1525' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1660', - '240318124021958': '2024-05-14', - '240423133933373': '1660' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1671', - '240318124021958': '2024-05-15', - '240423133933373': '1671' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1661', - '240318124021958': '2024-05-16', - '240423133933373': '1661' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1618', - '240318124021958': '2024-05-17', - '240423133933373': '1618' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1178', - '240318124021958': '2024-05-18', - '240423133933373': '1178' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1205', - '240318124021958': '2024-05-19', - '240423133933373': '1205' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1472', - '240318124021958': '2024-05-20', - '240423133933373': '1472' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1612', - '240318124021958': '2024-05-21', - '240423133933373': '1612' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1726', - '240318124021958': '2024-05-22', - '240423133933373': '1726' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '1573', - '240318124021958': '2024-05-23', - '240423133933373': '1573' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '670', - '240318124021958': '2024-05-24', - '240423133933373': '670' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '38', - '240318124021958': '2024-05-25', - '240423133933373': '38' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '12', - '240318124021958': '2024-05-26', - '240423133933373': '12' - }, - { - '10001': '导出DAU', - '10003': '240423133933373', - '20001': '导出DAU', - '210002': '508', - '240318124021958': '2024-05-27', - '240423133933373': '508' - } - ] - }, - indicatorsAsCol: false, - indicators: [ - { - indicatorKey: '0', - width: 'auto', - title: '', - cellType: 'chart', - chartModule: 'vchart', - chartSpec: { - type: 'line', - xField: ['240318124021958'], - yField: ['010002'], - direction: 'vertical', - seriesField: '20001', - axes: [ - { - id: '0', - type: 'linear', - tick: { - visible: false, - tickMode: 'd3', - style: { - stroke: '#989999' - } - }, - niceType: 'accurateFirst', - zIndex: 200, - grid: { - visible: true, - style: { - zIndex: 150, - stroke: '#DADCDD', - lineWidth: 1, - lineDash: [4, 2] - } - }, - orient: 'left', - visible: true, - domainLine: { - visible: true, - style: { - lineWidth: 1, - stroke: '#989999' - } - }, - title: { - visible: false, - text: '活跃DAU', - space: 8, - style: { - fontSize: 12, - fill: '#363839', - fontWeight: 'normal' - } - }, - autoIndent: false, - sampling: false, - label: { - visible: true, - space: 6, - flush: true, - padding: 0, - style: { - fontSize: 12, - maxLineWidth: 174, - fill: '#6F6F6F', - angle: 0, - fontWeight: 'normal', - dy: 0, - direction: 'horizontal' - }, - autoHide: true, - autoHideMethod: 'greedy' - }, - hover: false, - background: { - visible: true, - state: { - hover: { - fillOpacity: 0.08, - fill: '#141414' - }, - hover_reverse: { - fillOpacity: 0.08, - fill: '#141414' - } - } - }, - innerOffset: { - top: 4.4311346272637895 - }, - zero: false, - nice: true - } - ], - data: { - id: 'data', - fields: { - '10001': { - alias: '指标名称 ' - }, - '20001': { - alias: '图例项 ', - domain: ['活跃DAU', '生成DAU', '导出DAU'], - sortIndex: 0, - lockStatisticsByDomain: true - }, - '110002': { - alias: '指标值 ' - }, - '210002': { - alias: '指标值 ' - }, - '010002': { - alias: '指标值 ' - }, - '240318124021958': { - alias: 'p_date', - domain: [ - '2024-03-01', - '2024-03-02', - '2024-03-03', - '2024-03-04', - '2024-03-05', - '2024-03-06', - '2024-03-07', - '2024-03-08', - '2024-03-09', - '2024-03-10', - '2024-03-11', - '2024-03-12', - '2024-03-13', - '2024-03-14', - '2024-03-15', - '2024-03-16', - '2024-03-17', - '2024-03-18', - '2024-03-19', - '2024-03-20', - '2024-03-21', - '2024-03-22', - '2024-03-23', - '2024-03-24', - '2024-03-25', - '2024-03-26', - '2024-03-27', - '2024-03-28', - '2024-03-29', - '2024-03-30', - '2024-03-31', - '2024-04-01', - '2024-04-02', - '2024-04-03', - '2024-04-04', - '2024-04-05', - '2024-04-06', - '2024-04-07', - '2024-04-08', - '2024-04-09', - '2024-04-10', - '2024-04-11', - '2024-04-12', - '2024-04-13', - '2024-04-14', - '2024-04-15', - '2024-04-16', - '2024-04-17', - '2024-04-18', - '2024-04-19', - '2024-04-20', - '2024-04-21', - '2024-04-22', - '2024-04-23', - '2024-04-24', - '2024-04-25', - '2024-04-26', - '2024-04-27', - '2024-04-28', - '2024-04-29', - '2024-04-30', - '2024-05-01', - '2024-05-02', - '2024-05-03', - '2024-05-04', - '2024-05-05', - '2024-05-06', - '2024-05-07', - '2024-05-08', - '2024-05-09', - '2024-05-10', - '2024-05-11', - '2024-05-12', - '2024-05-13', - '2024-05-14', - '2024-05-15', - '2024-05-16', - '2024-05-17', - '2024-05-18', - '2024-05-19', - '2024-05-20', - '2024-05-21', - '2024-05-22', - '2024-05-23', - '2024-05-24', - '2024-05-25', - '2024-05-26', - '2024-05-27' - ], - sortIndex: 0, - lockStatisticsByDomain: true - }, - '240423133933368': { - alias: '活跃DAU' - }, - '240423133933373': { - alias: '导出DAU' - }, - '240430210432450': { - alias: '生成DAU' - } - } - }, - markOverlap: true, - percent: false, - stackInverse: true, - background: 'rgba(255, 255, 255, 0)', - region: [ - { - clip: true - } - ], - color: { - field: '20001', - type: 'ordinal', - range: ['#5685f6', '#a1b5e6', '#45b4d6'], - specified: {}, - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - tooltip: { - handler: {} - }, - crosshair: { - xField: { - visible: true, - line: { - type: 'rect', - style: { - fillOpacity: 0.2, - fill: '#b2bacf' - } - } - }, - gridZIndex: 100 - }, - line: { - style: { - curveType: { - type: 'ordinal', - field: '20001', - range: ['monotoneX'], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - lineWidth: { - type: 'ordinal', - field: '20001', - range: [2], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - lineDash: { - type: 'ordinal', - field: '20001', - range: [[0, 0]], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - } - } - }, - area: { - style: { - curveType: { - type: 'ordinal', - field: '20001', - range: ['monotoneX'], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - } - } - }, - point: { - style: { - shape: { - type: 'ordinal', - field: '20001', - range: ['circle'], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - size: { - type: 'ordinal', - field: '20001', - range: [7.0898154036220635], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - fill: 'white', - stroke: { - field: '20001', - type: 'ordinal', - range: ['#5685f6', '#a1b5e6', '#45b4d6'], - specified: {}, - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - strokeOpacity: { - type: 'ordinal', - field: '20001', - range: [0], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - fillOpacity: { - type: 'ordinal', - field: '20001', - range: [0], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - } - }, - state: { - hover: { - lineWidth: 2, - fillOpacity: 1, - strokeOpacity: 1, - scaleX: 1.5, - scaleY: 1.5 - } - } - }, - invalidType: 'break', - hover: { - enable: true - }, - select: { - enable: true - }, - bar: { - state: { - hover: { - cursor: 'pointer', - fillOpacity: 0.8, - stroke: '#58595B', - lineWidth: 1, - zIndex: 500 - }, - selected: { - cursor: 'pointer', - fillOpacity: 1, - stroke: '#58595B', - lineWidth: 1 - }, - selected_reverse: { - fillOpacity: 0.3, - lineWidth: 0.3 - } - } - }, - animation: false, - label: { - visible: true, - offset: 3, - overlap: { - hideOnHit: true, - avoidBaseMark: false, - strategy: [ - { - type: 'position', - position: [] - } - ], - clampForce: true - }, - style: { - fontSize: 12, - fontWeight: 'normal', - zIndex: 400, - lineHeight: '100%', - boundsPadding: [1, 0, 0, 0], - fill: '#363839', - stroke: 'rgba(255, 255, 255, 0.8)', - lineWidth: 2, - strokeOpacity: 1 - }, - position: 'top', - smartInvert: false - }, - markLine: [] - } - }, - { - indicatorKey: '1', - width: 'auto', - title: '', - cellType: 'chart', - chartModule: 'vchart', - chartSpec: { - type: 'line', - xField: ['240318124021958'], - yField: ['110002'], - direction: 'vertical', - seriesField: '20001', - axes: [ - { - id: '1', - type: 'linear', - tick: { - visible: false, - tickMode: 'd3', - style: { - stroke: '#989999' - } - }, - niceType: 'accurateFirst', - zIndex: 200, - grid: { - visible: true, - style: { - zIndex: 150, - stroke: '#DADCDD', - lineWidth: 1, - lineDash: [4, 2] - } - }, - orient: 'left', - visible: true, - domainLine: { - visible: true, - style: { - lineWidth: 1, - stroke: '#989999' - } - }, - title: { - visible: false, - text: '生成DAU', - space: 8, - style: { - fontSize: 12, - fill: '#363839', - fontWeight: 'normal' - } - }, - autoIndent: false, - sampling: false, - label: { - visible: true, - space: 6, - flush: true, - padding: 0, - style: { - fontSize: 12, - maxLineWidth: 174, - fill: '#6F6F6F', - angle: 0, - fontWeight: 'normal', - dy: 0, - direction: 'horizontal' - }, - autoHide: true, - autoHideMethod: 'greedy' - }, - hover: false, - background: { - visible: true, - state: { - hover: { - fillOpacity: 0.08, - fill: '#141414' - }, - hover_reverse: { - fillOpacity: 0.08, - fill: '#141414' - } - } - }, - innerOffset: { - top: 4.4311346272637895 - }, - zero: false, - nice: true - } - ], - data: { - id: 'data', - fields: { - '10001': { - alias: '指标名称 ' - }, - '20001': { - alias: '图例项 ', - domain: ['活跃DAU', '生成DAU', '导出DAU'], - sortIndex: 0, - lockStatisticsByDomain: true - }, - '110002': { - alias: '指标值 ' - }, - '210002': { - alias: '指标值 ' - }, - '010002': { - alias: '指标值 ' - }, - '240318124021958': { - alias: 'p_date', - domain: [ - '2024-03-01', - '2024-03-02', - '2024-03-03', - '2024-03-04', - '2024-03-05', - '2024-03-06', - '2024-03-07', - '2024-03-08', - '2024-03-09', - '2024-03-10', - '2024-03-11', - '2024-03-12', - '2024-03-13', - '2024-03-14', - '2024-03-15', - '2024-03-16', - '2024-03-17', - '2024-03-18', - '2024-03-19', - '2024-03-20', - '2024-03-21', - '2024-03-22', - '2024-03-23', - '2024-03-24', - '2024-03-25', - '2024-03-26', - '2024-03-27', - '2024-03-28', - '2024-03-29', - '2024-03-30', - '2024-03-31', - '2024-04-01', - '2024-04-02', - '2024-04-03', - '2024-04-04', - '2024-04-05', - '2024-04-06', - '2024-04-07', - '2024-04-08', - '2024-04-09', - '2024-04-10', - '2024-04-11', - '2024-04-12', - '2024-04-13', - '2024-04-14', - '2024-04-15', - '2024-04-16', - '2024-04-17', - '2024-04-18', - '2024-04-19', - '2024-04-20', - '2024-04-21', - '2024-04-22', - '2024-04-23', - '2024-04-24', - '2024-04-25', - '2024-04-26', - '2024-04-27', - '2024-04-28', - '2024-04-29', - '2024-04-30', - '2024-05-01', - '2024-05-02', - '2024-05-03', - '2024-05-04', - '2024-05-05', - '2024-05-06', - '2024-05-07', - '2024-05-08', - '2024-05-09', - '2024-05-10', - '2024-05-11', - '2024-05-12', - '2024-05-13', - '2024-05-14', - '2024-05-15', - '2024-05-16', - '2024-05-17', - '2024-05-18', - '2024-05-19', - '2024-05-20', - '2024-05-21', - '2024-05-22', - '2024-05-23', - '2024-05-24', - '2024-05-25', - '2024-05-26', - '2024-05-27' - ], - sortIndex: 0, - lockStatisticsByDomain: true - }, - '240423133933368': { - alias: '活跃DAU' - }, - '240423133933373': { - alias: '导出DAU' - }, - '240430210432450': { - alias: '生成DAU' - } - } - }, - markOverlap: true, - percent: false, - stackInverse: true, - background: 'rgba(255, 255, 255, 0)', - region: [ - { - clip: true - } - ], - color: { - field: '20001', - type: 'ordinal', - range: ['#5685f6', '#a1b5e6', '#45b4d6'], - specified: {}, - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - tooltip: { - handler: {} - }, - crosshair: { - xField: { - visible: true, - line: { - type: 'rect', - style: { - fillOpacity: 0.2, - fill: '#b2bacf' - } - } - }, - gridZIndex: 100 - }, - line: { - style: { - curveType: { - type: 'ordinal', - field: '20001', - range: ['monotoneX'], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - lineWidth: { - type: 'ordinal', - field: '20001', - range: [2], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - lineDash: { - type: 'ordinal', - field: '20001', - range: [[0, 0]], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - } - } - }, - area: { - style: { - curveType: { - type: 'ordinal', - field: '20001', - range: ['monotoneX'], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - } - } - }, - point: { - style: { - shape: { - type: 'ordinal', - field: '20001', - range: ['circle'], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - size: { - type: 'ordinal', - field: '20001', - range: [7.0898154036220635], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - fill: 'white', - stroke: { - field: '20001', - type: 'ordinal', - range: ['#5685f6', '#a1b5e6', '#45b4d6'], - specified: {}, - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - strokeOpacity: { - type: 'ordinal', - field: '20001', - range: [0], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - fillOpacity: { - type: 'ordinal', - field: '20001', - range: [0], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - } - }, - state: { - hover: { - lineWidth: 2, - fillOpacity: 1, - strokeOpacity: 1, - scaleX: 1.5, - scaleY: 1.5 - } - } - }, - invalidType: 'break', - hover: { - enable: true - }, - select: { - enable: true - }, - bar: { - state: { - hover: { - cursor: 'pointer', - fillOpacity: 0.8, - stroke: '#58595B', - lineWidth: 1, - zIndex: 500 - }, - selected: { - cursor: 'pointer', - fillOpacity: 1, - stroke: '#58595B', - lineWidth: 1 - }, - selected_reverse: { - fillOpacity: 0.3, - lineWidth: 0.3 - } - } - }, - animation: false, - label: { - visible: true, - offset: 3, - overlap: { - hideOnHit: true, - avoidBaseMark: false, - strategy: [ - { - type: 'position', - position: [] - } - ], - clampForce: true - }, - style: { - fontSize: 12, - fontWeight: 'normal', - zIndex: 400, - lineHeight: '100%', - boundsPadding: [1, 0, 0, 0], - fill: '#363839', - stroke: 'rgba(255, 255, 255, 0.8)', - lineWidth: 2, - strokeOpacity: 1 - }, - position: 'top', - smartInvert: false - }, - markLine: [] - } - }, - { - indicatorKey: '2', - width: 'auto', - title: '', - cellType: 'chart', - chartModule: 'vchart', - chartSpec: { - type: 'line', - xField: ['240318124021958'], - yField: ['210002'], - direction: 'vertical', - seriesField: '20001', - axes: [ - { - id: '2', - type: 'linear', - tick: { - visible: false, - tickMode: 'd3', - style: { - stroke: '#989999' - } - }, - niceType: 'accurateFirst', - zIndex: 200, - grid: { - visible: true, - style: { - zIndex: 150, - stroke: '#DADCDD', - lineWidth: 1, - lineDash: [4, 2] - } - }, - orient: 'left', - visible: true, - domainLine: { - visible: true, - style: { - lineWidth: 1, - stroke: '#989999' - } - }, - title: { - visible: false, - text: '导出DAU', - space: 8, - style: { - fontSize: 12, - fill: '#363839', - fontWeight: 'normal' - } - }, - autoIndent: false, - sampling: false, - label: { - visible: true, - space: 6, - flush: true, - padding: 0, - style: { - fontSize: 12, - maxLineWidth: 174, - fill: '#6F6F6F', - angle: 0, - fontWeight: 'normal', - dy: 0, - direction: 'horizontal' - }, - autoHide: true, - autoHideMethod: 'greedy' - }, - hover: false, - background: { - visible: true, - state: { - hover: { - fillOpacity: 0.08, - fill: '#141414' - }, - hover_reverse: { - fillOpacity: 0.08, - fill: '#141414' - } - } - }, - innerOffset: { - top: 4.4311346272637895 - }, - zero: false, - nice: true - } - ], - data: { - id: 'data', - fields: { - '10001': { - alias: '指标名称 ' - }, - '20001': { - alias: '图例项 ', - domain: ['活跃DAU', '生成DAU', '导出DAU'], - sortIndex: 0, - lockStatisticsByDomain: true - }, - '110002': { - alias: '指标值 ' - }, - '210002': { - alias: '指标值 ' - }, - '010002': { - alias: '指标值 ' - }, - '240318124021958': { - alias: 'p_date', - domain: [ - '2024-03-01', - '2024-03-02', - '2024-03-03', - '2024-03-04', - '2024-03-05', - '2024-03-06', - '2024-03-07', - '2024-03-08', - '2024-03-09', - '2024-03-10', - '2024-03-11', - '2024-03-12', - '2024-03-13', - '2024-03-14', - '2024-03-15', - '2024-03-16', - '2024-03-17', - '2024-03-18', - '2024-03-19', - '2024-03-20', - '2024-03-21', - '2024-03-22', - '2024-03-23', - '2024-03-24', - '2024-03-25', - '2024-03-26', - '2024-03-27', - '2024-03-28', - '2024-03-29', - '2024-03-30', - '2024-03-31', - '2024-04-01', - '2024-04-02', - '2024-04-03', - '2024-04-04', - '2024-04-05', - '2024-04-06', - '2024-04-07', - '2024-04-08', - '2024-04-09', - '2024-04-10', - '2024-04-11', - '2024-04-12', - '2024-04-13', - '2024-04-14', - '2024-04-15', - '2024-04-16', - '2024-04-17', - '2024-04-18', - '2024-04-19', - '2024-04-20', - '2024-04-21', - '2024-04-22', - '2024-04-23', - '2024-04-24', - '2024-04-25', - '2024-04-26', - '2024-04-27', - '2024-04-28', - '2024-04-29', - '2024-04-30', - '2024-05-01', - '2024-05-02', - '2024-05-03', - '2024-05-04', - '2024-05-05', - '2024-05-06', - '2024-05-07', - '2024-05-08', - '2024-05-09', - '2024-05-10', - '2024-05-11', - '2024-05-12', - '2024-05-13', - '2024-05-14', - '2024-05-15', - '2024-05-16', - '2024-05-17', - '2024-05-18', - '2024-05-19', - '2024-05-20', - '2024-05-21', - '2024-05-22', - '2024-05-23', - '2024-05-24', - '2024-05-25', - '2024-05-26', - '2024-05-27' - ], - sortIndex: 0, - lockStatisticsByDomain: true - }, - '240423133933368': { - alias: '活跃DAU' - }, - '240423133933373': { - alias: '导出DAU' - }, - '240430210432450': { - alias: '生成DAU' - } - } - }, - markOverlap: true, - percent: false, - stackInverse: true, - background: 'rgba(255, 255, 255, 0)', - region: [ - { - clip: true - } - ], - color: { - field: '20001', - type: 'ordinal', - range: ['#5685f6', '#a1b5e6', '#45b4d6'], - specified: {}, - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - tooltip: { - handler: {} - }, - crosshair: { - xField: { - visible: true, - line: { - type: 'rect', - style: { - fillOpacity: 0.2, - fill: '#b2bacf' - } - } - }, - gridZIndex: 100 - }, - line: { - style: { - curveType: { - type: 'ordinal', - field: '20001', - range: ['monotoneX'], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - lineWidth: { - type: 'ordinal', - field: '20001', - range: [2], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - lineDash: { - type: 'ordinal', - field: '20001', - range: [[0, 0]], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - } - } - }, - area: { - style: { - curveType: { - type: 'ordinal', - field: '20001', - range: ['monotoneX'], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - } - } - }, - point: { - style: { - shape: { - type: 'ordinal', - field: '20001', - range: ['circle'], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - size: { - type: 'ordinal', - field: '20001', - range: [7.0898154036220635], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - fill: 'white', - stroke: { - field: '20001', - type: 'ordinal', - range: ['#5685f6', '#a1b5e6', '#45b4d6'], - specified: {}, - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - strokeOpacity: { - type: 'ordinal', - field: '20001', - range: [0], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - }, - fillOpacity: { - type: 'ordinal', - field: '20001', - range: [0], - domain: ['活跃DAU', '生成DAU', '导出DAU'] - } - }, - state: { - hover: { - lineWidth: 2, - fillOpacity: 1, - strokeOpacity: 1, - scaleX: 1.5, - scaleY: 1.5 - } - } - }, - invalidType: 'break', - hover: { - enable: true - }, - select: { - enable: true - }, - bar: { - state: { - hover: { - cursor: 'pointer', - fillOpacity: 0.8, - stroke: '#58595B', - lineWidth: 1, - zIndex: 500 - }, - selected: { - cursor: 'pointer', - fillOpacity: 1, - stroke: '#58595B', - lineWidth: 1 - }, - selected_reverse: { - fillOpacity: 0.3, - lineWidth: 0.3 - } - } - }, - animation: false, - label: { - visible: true, - offset: 3, - overlap: { - hideOnHit: true, - avoidBaseMark: false, - strategy: [ - { - type: 'position', - position: [] - } - ], - clampForce: true - }, - style: { - fontSize: 12, - fontWeight: 'normal', - zIndex: 400, - lineHeight: '100%', - boundsPadding: [1, 0, 0, 0], - fill: '#363839', - stroke: 'rgba(255, 255, 255, 0.8)', - lineWidth: 2, - strokeOpacity: 1 - }, - position: 'top', - smartInvert: false - }, - markLine: [] - } - } - ], - animation: false, - theme: { - underlayBackgroundColor: 'rgba(255,255,255,0)', - bodyStyle: { - borderColor: 'rgba(0,4,20,0.2)', - borderLineWidth: [0, 0, 2, 0], - bgColor: 'rgba(255,255,255,0)', - padding: [0, 0, 1, 0] - }, - headerStyle: { - borderColor: 'rgba(0,4,20,0.2)', - fontSize: 12, - color: '#333333', - textAlign: 'center', - borderLineWidth: 0, - bgColor: 'rgba(255,255,255,0)', - hover: { - cellBgColor: 'rgba(178,186,207, 0.2)' - } - }, - rowHeaderStyle: { - borderColor: 'rgba(0,4,20,0.2)', - fontSize: 12, - color: '#333333', - borderLineWidth: 0, - bgColor: 'rgba(255,255,255,0)', - hover: { - cellBgColor: 'rgba(178,186,207, 0.2)' - } - }, - cornerHeaderStyle: { - borderColor: 'rgba(0,4,20,0.2)', - textAlign: 'center', - fontSize: 12, - color: '#333333', - fontWeight: 'bold', - borderLineWidth: [0, 0, 0, 0], - bgColor: 'rgba(255,255,255,0)', - hover: { - cellBgColor: '' - } - }, - cornerRightTopCellStyle: { - borderColor: 'rgba(0,4,20,0.2)', - borderLineWidth: 0, - bgColor: 'rgba(255,255,255,0)', - hover: { - cellBgColor: '' - } - }, - cornerLeftBottomCellStyle: { - borderColor: 'rgba(0,4,20,0.2)', - borderLineWidth: 0, - bgColor: 'rgba(255,255,255,0)', - hover: { - cellBgColor: '' - } - }, - cornerRightBottomCellStyle: { - borderColor: 'rgba(0,4,20,0.2)', - borderLineWidth: 0, - bgColor: 'rgba(255,255,255,0)', - hover: { - cellBgColor: '' - } - }, - rightFrozenStyle: { - borderColor: 'rgba(0,4,20,0.2)', - borderLineWidth: 0, - bgColor: 'rgba(255,255,255,0)', - hover: { - cellBgColor: 'rgba(178,186,207, 0.2)' - } - }, - bottomFrozenStyle: { - borderColor: 'rgba(0,4,20,0.2)', - borderLineWidth: 0, - bgColor: 'rgba(255,255,255,0)', - hover: { - cellBgColor: 'rgba(178,186,207, 0.2)' - } - }, - selectionStyle: { - cellBgColor: '', - cellBorderColor: '' - }, - frameStyle: { - borderLineWidth: 0, - bgColor: 'rgba(255,255,255,0)' - } - }, - hash: '4c22d25221569c0352e4ff0d2584109f' -}; - -const datumNoTree = { - '10001': '活跃DAU', - '10003': '240423133933368', - '20001': '活跃DAU', - '010002': '5826', - '240318124021958': '2024-05-10', - '240423133933368': '5826' -}; - describe('get-data-cell-path test', () => { test('get-data-cell-path result', () => { const path = getDataCellPath(option, data); @@ -7171,17 +1421,4 @@ describe('get-data-cell-path test', () => { cellLocation: 'body' }); }); - test('get-data-cell-path no tree result', () => { - const path = getDataCellPath(optionNoTree, datumNoTree); - expect(path).toEqual({ - colHeaderPaths: [], - rowHeaderPaths: [ - { - indicatorKey: '0', - value: '' - } - ], - cellLocation: 'body' - }); - }); }); diff --git a/packages/vtable/__tests__/layout/pivot-header-layout.test.ts b/packages/vtable/__tests__/layout/pivot-header-layout.test.ts index fb0bef7cc..a19078e40 100644 --- a/packages/vtable/__tests__/layout/pivot-header-layout.test.ts +++ b/packages/vtable/__tests__/layout/pivot-header-layout.test.ts @@ -2634,6 +2634,68 @@ describe('pivot-header-layout test', () => { size: 1 } ]); + expect(layout.rowTree).toEqual([ + { + dimensionKey: '231012120511053', + value: '公司', + children: [ + { + indicatorKey: '10002', + value: '', + level: 1, + startIndex: 0, + startInTotal: 0, + id: 8, + size: 1 + } + ], + level: 0, + startIndex: 0, + startInTotal: 0, + id: 7, + size: 1 + }, + { + dimensionKey: '231012120511053', + value: '小型企业', + children: [ + { + indicatorKey: '10002', + value: '', + level: 1, + startIndex: 0, + startInTotal: 1, + id: 10, + size: 1 + } + ], + level: 0, + startIndex: 1, + startInTotal: 1, + id: 9, + size: 1 + }, + { + dimensionKey: '231012120511053', + value: '消费者', + children: [ + { + indicatorKey: '10002', + value: '', + level: 1, + startIndex: 0, + startInTotal: 2, + id: 12, + size: 1 + } + ], + level: 0, + startIndex: 2, + startInTotal: 2, + id: 11, + size: 1 + } + ]); }); test('pivot-header-layout count', () => { @@ -2868,6 +2930,7 @@ describe('pivot-header-layout test', () => { expect(layout.isEmpty(0, 4)).toBe(true); expect(layout.isEmpty(2, 4)).toBe(false); expect(layout.isEmpty(2, 1)).toBe(false); - tableInstance.release(); }); + + tableInstance.release(); }); diff --git a/packages/vtable/__tests__/listTable-1W.test.ts b/packages/vtable/__tests__/listTable-1W.test.ts index 9c018758e..c021d39e1 100644 --- a/packages/vtable/__tests__/listTable-1W.test.ts +++ b/packages/vtable/__tests__/listTable-1W.test.ts @@ -1,6 +1,6 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable -import { ListTable } from '../src'; +import { ListTable } from '../src/ListTable'; import * as VTable from '../src/index'; import { createDiv } from './dom'; global.__VERSION__ = 'none'; diff --git a/packages/vtable/__tests__/listTable.test.ts b/packages/vtable/__tests__/listTable.test.ts index d76fc9508..d03407e79 100644 --- a/packages/vtable/__tests__/listTable.test.ts +++ b/packages/vtable/__tests__/listTable.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from './data/marketsales.json'; -import { ListTable } from '../src'; +import { ListTable } from '../src/ListTable'; import { createDiv } from './dom'; global.__VERSION__ = 'none'; describe('listTable init test', () => { @@ -118,7 +118,6 @@ describe('listTable init test', () => { expect(listTable.getScrollLeft()).toBe(901); expect(listTable.getScrollTop()).toBe(720); expect(listTable.getCellStyle(6, 16)).toStrictEqual({ - strokeColor: undefined, textAlign: 'left', textBaseline: 'middle', bgColor: '#FFF', @@ -190,9 +189,9 @@ describe('listTable init test', () => { ]); expect(listTable.stateManager?.select.ranges).toEqual([ - { start: { col: 1, row: 3 }, end: { col: 4, row: 6 }, skipBodyMerge: true }, - { start: { col: 0, row: 4 }, end: { col: 7, row: 4 }, skipBodyMerge: true }, - { start: { col: 4, row: 36 }, end: { col: 7, row: 36 }, skipBodyMerge: true } + { start: { col: 1, row: 3 }, end: { col: 4, row: 6 } }, + { start: { col: 0, row: 4 }, end: { col: 7, row: 4 } }, + { start: { col: 4, row: 36 }, end: { col: 7, row: 36 } } ]); expect(listTable.getScrollTop()).toBe(scrollTop); }); diff --git a/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts b/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts deleted file mode 100644 index efc31f54c..000000000 --- a/packages/vtable/__tests__/options/listTable-api-with-frozen.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -// @ts-nocheck -// 有问题可对照demo unitTestListTable -import records from '../data/marketsales.json'; -import { ListTable } from '../../src'; -import { createDiv } from '../dom'; -global.__VERSION__ = 'none'; -describe('listTable init test', () => { - const containerDom: HTMLElement = createDiv(); - containerDom.style.position = 'relative'; - containerDom.style.width = '1000px'; - containerDom.style.height = '800px'; - const columns = [ - { - field: '订单 ID', - caption: '订单 ID', - sort: true, - width: 'auto', - description: '这是订单的描述信息', - style: { - fontFamily: 'Arial', - fontSize: 14 - } - }, - { - field: '订单日期', - caption: '订单日期' - }, - { - field: '发货日期', - caption: '发货日期' - }, - { - field: '客户名称', - caption: '客户名称', - style: { - padding: [10, 0, 10, 60] - } - }, - { - field: '邮寄方式', - caption: '邮寄方式' - }, - { - field: '省/自治区', - caption: '省/自治区' - }, - { - field: '产品名称', - caption: '产品名称' - }, - { - field: '类别', - caption: '类别' - }, - { - field: '子类别', - caption: '子类别' - }, - { - field: '销售额', - caption: '销售额' - }, - { - field: '数量', - caption: '数量' - }, - { - field: '折扣', - caption: '折扣' - }, - { - field: '利润', - caption: '利润' - } - ]; - const option = { - columns, - defaultColWidth: 150, - frozenColCount: 2, - rightFrozenColCount: 2, - bottomFrozenRowCount: 2 - }; - - option.container = containerDom; - option.records = records; - const listTable = new ListTable(option); - test('listTable cellIsInVisualView', () => { - expect(listTable.cellIsInVisualView(3, 0)).toBe(true); - expect(listTable.cellIsInVisualView(0, 3)).toBe(true); - expect(listTable.cellIsInVisualView(5, 3)).toBe(false); - expect(listTable.cellIsInVisualView(4, 3)).toBe(false); - expect(listTable.cellIsInVisualView(3, 3)).toBe(true); - expect(listTable.cellIsInVisualView(3, 39)).toBe(true); - expect(listTable.cellIsInVisualView(3, 38)).toBe(true); - - expect(listTable.cellIsInVisualView(12, 3)).toBe(true); - expect(listTable.cellIsInVisualView(11, 3)).toBe(true); - expect(listTable.cellIsInVisualView(10, 3)).toBe(false); - - expect(listTable.cellIsInVisualView(3, 37)).toBe(false); - }); - - test('listTable scroll cellIsInVisualView', () => { - listTable.scrollTop = 100; - listTable.scrollLeft = 100; - expect(listTable.cellIsInVisualView(3, 5)).toBe(true); - expect(listTable.cellIsInVisualView(2, 5)).toBe(false); - expect(listTable.cellIsInVisualView(5, 5)).toBe(false); - expect(listTable.cellIsInVisualView(4, 5)).toBe(true); - expect(listTable.cellIsInVisualView(12, 5)).toBe(true); - - expect(listTable.cellIsInVisualView(3, 19)).toBe(true); - expect(listTable.cellIsInVisualView(3, 20)).toBe(false); - expect(listTable.cellIsInVisualView(2, 19)).toBe(false); - - expect(listTable.cellIsInVisualView(3, 39)).toBe(true); - expect(listTable.cellIsInVisualView(3, 38)).toBe(true); - }); -}); diff --git a/packages/vtable/__tests__/options/listTable-autoRowHeight.test.ts b/packages/vtable/__tests__/options/listTable-autoRowHeight.test.ts index a65b85c7d..e424d87b8 100644 --- a/packages/vtable/__tests__/options/listTable-autoRowHeight.test.ts +++ b/packages/vtable/__tests__/options/listTable-autoRowHeight.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import { createDiv, removeDom } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-autoRowHeight init test', () => { @@ -143,6 +143,6 @@ describe('listTable-autoRowHeight init test', () => { test('listTable-autoRowHeight API getCellLocation', () => { expect(listTable.getCellLocation(5, 3)).toEqual('body'); expect(listTable.getCellLocation(5, 0)).toEqual('columnHeader'); - listTable.release(); }); + listTable.release(); }); diff --git a/packages/vtable/__tests__/options/listTable-frozen.test.ts b/packages/vtable/__tests__/options/listTable-frozen.test.ts index 47ed49543..1c48de5ee 100644 --- a/packages/vtable/__tests__/options/listTable-frozen.test.ts +++ b/packages/vtable/__tests__/options/listTable-frozen.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable-frozen init test', () => { @@ -89,6 +89,6 @@ describe('listTable-frozen init test', () => { test('listTable frozenColCount set', () => { listTable.frozenColCount = 4; expect(listTable.frozenColCount).toBe(4); - listTable.release(); }); + listTable.release(); }); diff --git a/packages/vtable/__tests__/options/listTable-icon.test.ts b/packages/vtable/__tests__/options/listTable-icon.test.ts index e09c2228c..53c8f94da 100644 --- a/packages/vtable/__tests__/options/listTable-icon.test.ts +++ b/packages/vtable/__tests__/options/listTable-icon.test.ts @@ -448,6 +448,6 @@ describe('listTable-icon init test', () => { expect(moreAABBBounds.y1).toBe(27); expect(moreAABBBounds.x2).toBe(114); expect(moreAABBBounds.y2).toBe(43); - listTable.release(); }); + listTable.release(); }); diff --git a/packages/vtable/__tests__/options/listTable-sort.test.ts b/packages/vtable/__tests__/options/listTable-sort.test.ts index fcf83b756..2cf8ba3de 100644 --- a/packages/vtable/__tests__/options/listTable-sort.test.ts +++ b/packages/vtable/__tests__/options/listTable-sort.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestListTable import records from '../data/marketsales.json'; -import { ListTable } from '../../src'; +import { ListTable } from '../../src/ListTable'; import { createDiv } from '../dom'; global.__VERSION__ = 'none'; describe('listTable init test', () => { @@ -88,6 +88,9 @@ describe('listTable init test', () => { const listTable = new ListTable(option); test('listTable getCellValue', () => { expect(listTable.getCellValue(6, 3)).toBe('Sauder 书架, 金属'); - listTable.release(); }); + + // setTimeout(() => { + // listTable.release(); + // }, 1000); }); diff --git a/packages/vtable/__tests__/pivotTable-analysis.test.ts b/packages/vtable/__tests__/pivotTable-analysis.test.ts index ffff4f483..693aac6a8 100644 --- a/packages/vtable/__tests__/pivotTable-analysis.test.ts +++ b/packages/vtable/__tests__/pivotTable-analysis.test.ts @@ -1,7 +1,7 @@ // @ts-nocheck // 有问题可对照demo unitTestPivotTable import records from './data/marketsales.json'; -import { PivotTable } from '../src'; +import { PivotTable } from '../src/PivotTable'; import * as VTable from '../src/index'; import { createDiv } from './dom'; global.__VERSION__ = 'none'; @@ -46,6 +46,7 @@ describe('pivotTable-analysis init test', () => { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, corner: { titleOnDimension: 'row' }, @@ -375,6 +376,6 @@ describe('pivotTable-analysis init test', () => { }); test('pivotTable-analysis cellValue', () => { expect(pivotTable.getCellValue(7, 4)).toBe(999); - pivotTable.release(); }); + pivotTable.release(); }); diff --git a/packages/vtable/__tests__/pivotTable-tree.test.ts b/packages/vtable/__tests__/pivotTable-tree.test.ts index 38531f7c2..630fd585e 100644 --- a/packages/vtable/__tests__/pivotTable-tree.test.ts +++ b/packages/vtable/__tests__/pivotTable-tree.test.ts @@ -2,7 +2,7 @@ // @ts-nocheck // 有问题可对照demo unitTestPivotTable import records from './data/North_American_Superstore_pivot_extension_rows.json'; -import { PivotTable } from '../src'; +import { PivotTable } from '../src/PivotTable'; import { createDiv } from './dom'; global.__VERSION__ = 'none'; describe('pivotTableTree init test', () => { @@ -506,6 +506,6 @@ describe('pivotTableTree init test', () => { } ]) ).toEqual({ col: 2, row: 0 }); - pivotTableTree.release(); }); + pivotTableTree.release(); }); diff --git a/packages/vtable/__tests__/pivotTable.test.ts b/packages/vtable/__tests__/pivotTable.test.ts index 9fcf5b10c..2e990dd77 100644 --- a/packages/vtable/__tests__/pivotTable.test.ts +++ b/packages/vtable/__tests__/pivotTable.test.ts @@ -2,7 +2,7 @@ // @ts-nocheck // 有问题可对照demo unitTestPivotTable import records from './data/marketsales.json'; -import { PivotTable } from '../src'; +import { PivotTable } from '../src/PivotTable'; import { createDiv } from './dom'; global.__VERSION__ = 'none'; describe('pivotTable init test', () => { @@ -697,31 +697,29 @@ describe('pivotTable init test', () => { }; pivotTable.updateOption(option1); expect(pivotTable.getCellValue(6, 6)).toEqual('0元'); - expect(pivotTable.getCellOriginValue(6, 4)).toEqual(550.2); - expect(pivotTable.getCellOriginRecord(6, 4)).toEqual([ - { - '行 ID': '5', - '订单 ID': 'CN-2018-2975416', - 订单日期: '2018/5/31', - 发货日期: '2018/6/2', - 邮寄方式: '二级', - '客户 ID': '万兰-15730', - 客户名称: '万兰', - 细分: '消费者', - 城市: '汕头', - '省/自治区': '广东', - '国家/地区': '中国', - 地区: '中南', - '产品 ID': '办公用-器具-10003452', - 类别: '办公用品', - 子类别: '器具', - 产品名称: 'KitchenAid 搅拌机, 黑色', - 销售额: '1375.92', - 数量: '3', - 折扣: '0', - 利润: '550.2' - } - ]); - pivotTable.release(); + expect(pivotTable.getCellOriginValue(6, 4)).toEqual('550.2'); + expect(pivotTable.getCellOriginRecord(6, 4)).toEqual({ + '行 ID': '5', + '订单 ID': 'CN-2018-2975416', + 订单日期: '2018/5/31', + 发货日期: '2018/6/2', + 邮寄方式: '二级', + '客户 ID': '万兰-15730', + 客户名称: '万兰', + 细分: '消费者', + 城市: '汕头', + '省/自治区': '广东', + '国家/地区': '中国', + 地区: '中南', + '产品 ID': '办公用-器具-10003452', + 类别: '办公用品', + 子类别: '器具', + 产品名称: 'KitchenAid 搅拌机, 黑色', + 销售额: '1375.92', + 数量: '3', + 折扣: '0', + 利润: '550.2' + }); }); + pivotTable.release(); }); diff --git a/packages/vtable/examples/business/background-image.ts b/packages/vtable/examples/business/background-image.ts deleted file mode 100644 index a0bbca9d6..000000000 --- a/packages/vtable/examples/business/background-image.ts +++ /dev/null @@ -1,173 +0,0 @@ -/* eslint-disable */ -import { ListTableConstructorOptions } from '../../cjs/ts-types'; -import * as VTable from '../../src'; -import { theme } from '../../src/register'; -const ListTable = VTable.ListTable; -const CONTAINER_ID = 'vTable'; -function getBackgroundColor(args): string { - const { row, table } = args; - const index = row - table.frozenRowCount; - if (!(index & 1)) { - return 'rgba(255,255,255,0.2)'; - } - return 'rgba(255,255,255,0.5)'; -} -export function createTable() { - const container = document.getElementById(CONTAINER_ID); - container!.style.padding = '50px'; - container!.style.backgroundImage = `url('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/background-image-music.jpeg')`; - container!.style.backgroundRepeat = 'no-repeat'; - container!.style.backgroundSize = 'cover'; - container!.style.backgroundPosition = 'center center'; - const options: ListTableConstructorOptions = { - columns: [ - { - field: 'music_name', - title: '歌曲名', - width: 'auto', - icon: { - type: 'image', - src: 'music_image', - name: 'music_image', - shape: 'circle', - //定义文本内容行内图标,第一个字符展示 - width: 50, // Optional - height: 50, - positionType: VTable.TYPES.IconPosition.contentLeft, - marginRight: 20, - marginLeft: 0, - cursor: 'pointer' - } - }, - { - field: 'singer', - title: '歌手', - - width: 'auto', - icon: { - type: 'image', - src: 'singer_image', - name: 'singer_image', - shape: 'circle', - //定义文本内容行内图标,第一个字符展示 - width: 50, // Optional - height: 50, - positionType: VTable.TYPES.IconPosition.contentLeft, - marginRight: 20, - marginLeft: 0, - cursor: 'pointer' - } - }, - - { - field: 'public_year', - title: '发行时间', - width: 'auto' - }, - { - field: 'play_count', - title: '播放次数', - width: 'auto' - } - ], - records: [ - { - music_name: '小美满', - music_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/xiaomeiman.jpeg', - singer: '周深', - singer_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/zhoushen.jpeg', - public_year: '2024', - play_count: 400 - }, - { - music_name: 'I Am You', - music_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/iamyou.jpeg', - singer: 'Kim Taylor', - singer_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/KimTaylor.png', - public_year: '2008', - play_count: 380 - }, - { - music_name: 'Reality', - music_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/reality.jpeg', - singer: 'Lost Frequencies', - singer_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/LostFrequencies.png', - public_year: '2015', - play_count: 370 - }, - { - music_name: '无名的人', - music_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/wumingderen.webp', - singer: '毛不易', - singer_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/maobuyi.webp', - public_year: '2021', - play_count: 360 - }, - { - music_name: 'My love', - music_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/mylove.jpeg', - singer: 'Westlife', - singer_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/Westlife.jpeg', - public_year: '2000', - play_count: 330 - }, - { - music_name: '彩虹的微笑', - music_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/caihongdeweixiao.jpeg', - singer: '王心凌', - singer_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/wangxinling.jpeg', - public_year: '2006', - play_count: 300 - }, - { - music_name: '手心的太阳', - music_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/shouxindetaiyang.jpeg', - singer: '张韶涵', - singer_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/zhangshaohan.jpeg', - public_year: '2004', - play_count: 230 - }, - { - music_name: '明明就', - music_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/mingmingjiu.jpeg', - singer: '周杰伦', - singer_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/zhoujielun.jpeg', - public_year: '2012', - play_count: 130 - }, - { - music_name: '声声慢', - music_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/shengshengman.jpeg', - singer: '崔开潮', - singer_image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/media/cuikaichao.jpeg', - public_year: '2017', - play_count: 30 - } - ], - heightMode: 'autoHeight', - theme: { - underlayBackgroundColor: 'rgba(255,255,255,0)', - headerStyle: { - bgColor: '#f58d17', - color: '#FFF', - borderLineWidth: 0, - fontSize: 26 - }, - bodyStyle: { - bgColor: getBackgroundColor, - color: '#FFF', - borderLineWidth: 0, - fontSize: 22 - }, - frameStyle: { - borderColor: 'rgba(255,255,255,0.2)', - borderLineWidth: 20, - cornerRadius: 8 - } - } - }; - const instance = new ListTable(container!, options); - - // 只为了方便控制太调试用,不要拷贝 - window.tableInstance = instance; -} diff --git a/packages/vtable/examples/business/sales-bubble.ts b/packages/vtable/examples/business/sales-bubble.ts index f7ec95eb9..90a7c8e64 100644 --- a/packages/vtable/examples/business/sales-bubble.ts +++ b/packages/vtable/examples/business/sales-bubble.ts @@ -65,6 +65,7 @@ fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American isShowOverflowTextTooltip: true }, hideIndicatorName: true, + enableDataAnalysis: true, defaultHeaderRowHeight: 30, defaultRowHeight: 40, defaultColWidth: 60, diff --git a/packages/vtable/examples/business/testPerformanceMoreColumn.ts b/packages/vtable/examples/business/testPerformanceMoreColumn.ts index 4772b5b2f..51f7b1d15 100644 --- a/packages/vtable/examples/business/testPerformanceMoreColumn.ts +++ b/packages/vtable/examples/business/testPerformanceMoreColumn.ts @@ -194,7 +194,7 @@ export function createTable() { } }, records, - + enableDataAnalysis: false, autoRowHeight: true, widthMode: 'standard', disableColumnResize: false, diff --git a/packages/vtable/examples/business/three.ts b/packages/vtable/examples/business/three.ts index d6ffcd911..193daaa25 100644 --- a/packages/vtable/examples/business/three.ts +++ b/packages/vtable/examples/business/three.ts @@ -5,6 +5,7 @@ const CONTAINER_ID = 'vTable'; export function createTable() { const options = { + enableDataAnalysis: false, heightMode: 'autoHeight', widthMode: 'standard', disableColumnResize: false, diff --git a/packages/vtable/examples/cell-move/pivot-move.ts b/packages/vtable/examples/cell-move/pivot-move.ts index a408ef1b4..4f385bb3a 100644 --- a/packages/vtable/examples/cell-move/pivot-move.ts +++ b/packages/vtable/examples/cell-move/pivot-move.ts @@ -5,6 +5,7 @@ const CONTAINER_ID = 'vTable'; export function createTable() { const option = { + enableDataAnalysis: false, allowRangePaste: true, columnTree: [ { diff --git a/packages/vtable/examples/custom/custom-header.ts b/packages/vtable/examples/custom/custom-header.ts index 9d9e5a74f..9e2cdf994 100644 --- a/packages/vtable/examples/custom/custom-header.ts +++ b/packages/vtable/examples/custom/custom-header.ts @@ -9,6 +9,7 @@ const padding = [10, 20, 10, 20]; export function createTable() { const option = { + enableDataAnalysis: false, autoRowHeight: true, widthMode: 'standard', heightMode: 'autoHeight', diff --git a/packages/vtable/examples/custom/custom-layout.ts b/packages/vtable/examples/custom/custom-layout.ts index 7e030a506..b776a0c8c 100644 --- a/packages/vtable/examples/custom/custom-layout.ts +++ b/packages/vtable/examples/custom/custom-layout.ts @@ -192,33 +192,28 @@ export function createTable() { } }, { - title: 'sum', - columns: [ - { - field: 'fansCount', - title: '粉丝数', - style: { - fontFamily: 'Arial', - fontSize: 12, - fontWeight: 'bold' - }, - fieldFormat(rec) { - return rec.fansCount + 'w'; - } - }, - { - field: 'viewCount', - title: '播放量', - fieldFormat(rec) { - return rec.fansCount + 'w'; - }, - style: { - fontFamily: 'Arial', - fontSize: 12, - fontWeight: 'bold' - } - } - ] + field: 'fansCount', + title: '粉丝数', + style: { + fontFamily: 'Arial', + fontSize: 12, + fontWeight: 'bold' + }, + fieldFormat(rec) { + return rec.fansCount + 'w'; + } + }, + { + field: 'viewCount', + title: '播放量', + fieldFormat(rec) { + return rec.fansCount + 'w'; + }, + style: { + fontFamily: 'Arial', + fontSize: 12, + fontWeight: 'bold' + } }, { field: 'viewCount', @@ -352,96 +347,7 @@ export function createTable() { field: '', title: '操作', width: 100, - icon: ['favorite', 'message'], - headerCustomLayout: args => { - const { table, row, col, rect } = args; - const { height, width } = rect || table.getCellRect(col, row); - const percentCalc = VTable.CustomLayout.percentCalc; - const container = new VTable.CustomLayout.Group({ - height, - width, - display: 'flex', - flexDirection: 'row', - flexWrap: 'nowrap' - }); - const containerLeft = new VTable.CustomLayout.Group({ - height: percentCalc(100), - width: 160, - display: 'flex', - direction: 'column', - alignContent: 'center', - alignItems: 'center', - justifyContent: 'space-around', - fill: 'blue', - // dx: 200 - x: 200 - }); - container.add(containerLeft); - - containerLeft.addEventListener('click', () => { - containerLeft.setAttributes({ fill: 'red' }); - }); - - const containerRight = new VTable.CustomLayout.Group({ - height: percentCalc(100), - width: percentCalc(100, -50), - display: 'flex', - direction: 'column' - // justifyContent: 'center' - }); - container.add(containerRight); - - const containerRightTop = new VTable.CustomLayout.Group({ - id: 'containerRightTop', - height: percentCalc(50), - width: percentCalc(100), - display: 'flex', - alignItems: 'center', - flexWrap: 'nowrap' - }); - - const containerRightBottom = new VTable.CustomLayout.Group({ - height: percentCalc(50), - width: percentCalc(100), - display: 'flex', - alignItems: 'center' - }); - - containerRight.add(containerRightTop); - containerRight.add(containerRightBottom); - - const bloggerName = new VTable.CustomLayout.Text({ - text: 'record.bloggerName', - fontSize: 13, - fontFamily: 'sans-serif', - fill: 'black', - marginLeft: 10 - }); - containerRightTop.add(bloggerName); - - const location = new VTable.CustomLayout.Icon({ - id: 'location', - iconName: 'location', - width: 15, - height: 15, - marginLeft: 10 - }); - containerRightTop.add(location); - - const locationName = new VTable.CustomLayout.Text({ - text: 'record.city', - fontSize: 11, - fontFamily: 'sans-serif', - fill: '#6f7070', - boundsPadding: [0, 10, 0, 0] - }); - containerRightTop.add(locationName); - - return { - rootContainer: container, - renderDefault: false - }; - } + icon: ['favorite', 'message'] } ], records: [ @@ -513,112 +419,7 @@ export function createTable() { } ], editor: 'input', - defaultRowHeight: 80, - customMergeCell: (col, row, table) => { - if (col >= 0 && col < table.colCount && row === table.rowCount - 2) { - return { - range: { - start: { - col: 0, - row: table.rowCount - 2 - }, - end: { - col: table.colCount - 1, - row: table.rowCount - 2 - } - }, - customLayout: args => { - const { table, row, col, rect } = args; - const { height, width } = rect || table.getCellRect(col, row); - const percentCalc = VTable.CustomLayout.percentCalc; - const container = new VTable.CustomLayout.Group({ - height, - width, - display: 'flex', - flexDirection: 'row', - flexWrap: 'nowrap' - }); - const containerLeft = new VTable.CustomLayout.Group({ - height: percentCalc(100), - width: 160, - display: 'flex', - direction: 'column', - alignContent: 'center', - alignItems: 'center', - justifyContent: 'space-around', - fill: 'blue', - // dx: 200 - x: 200 - }); - container.add(containerLeft); - - containerLeft.addEventListener('click', () => { - containerLeft.setAttributes({ fill: 'red' }); - }); - - const containerRight = new VTable.CustomLayout.Group({ - height: percentCalc(100), - width: percentCalc(100, -50), - display: 'flex', - direction: 'column' - // justifyContent: 'center' - }); - container.add(containerRight); - - const containerRightTop = new VTable.CustomLayout.Group({ - id: 'containerRightTop', - height: percentCalc(50), - width: percentCalc(100), - display: 'flex', - alignItems: 'center', - flexWrap: 'nowrap' - }); - - const containerRightBottom = new VTable.CustomLayout.Group({ - height: percentCalc(50), - width: percentCalc(100), - display: 'flex', - alignItems: 'center' - }); - - containerRight.add(containerRightTop); - containerRight.add(containerRightBottom); - - const bloggerName = new VTable.CustomLayout.Text({ - text: 'record.bloggerName', - fontSize: 13, - fontFamily: 'sans-serif', - fill: 'black', - marginLeft: 10 - }); - containerRightTop.add(bloggerName); - - const location = new VTable.CustomLayout.Icon({ - id: 'location', - iconName: 'location', - width: 15, - height: 15, - marginLeft: 10 - }); - containerRightTop.add(location); - - const locationName = new VTable.CustomLayout.Text({ - text: 'record.city', - fontSize: 11, - fontFamily: 'sans-serif', - fill: '#6f7070', - boundsPadding: [0, 10, 0, 0] - }); - containerRightTop.add(locationName); - - return { - rootContainer: container, - renderDefault: false - }; - } - }; - } - } + defaultRowHeight: 80 }; const instance = new ListTable(option); @@ -626,10 +427,10 @@ export function createTable() { customGrapicKeys: ['role'] }); - // const { MOUSEMOVE_CELL } = VTable.ListTable.EVENT_TYPE; - // instance.addEventListener(MOUSEMOVE_CELL, (...args) => { - // console.log('MOUSEMOVE_CELL', args[0]?.target); - // }); + const { MOUSEMOVE_CELL } = VTable.ListTable.EVENT_TYPE; + instance.addEventListener(MOUSEMOVE_CELL, (...args) => { + console.log('MOUSEMOVE_CELL', args[0]?.target); + }); // 只为了方便控制太调试用,不要拷贝 window.tableInstance = instance; diff --git a/packages/vtable/examples/debug/animation.ts b/packages/vtable/examples/debug/animation.ts deleted file mode 100644 index 07991b68d..000000000 --- a/packages/vtable/examples/debug/animation.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable */ -import * as VTable from '../../src'; -import VChart from '@visactor/vchart'; -import { bindDebugTool } from '../../src/scenegraph/debug-tool'; - -const CONTAINER_ID = 'vTable'; -VTable.register.chartModule('vchart', VChart); -export function createTable() { - const option = { - columns: [ - { - field: '0', - caption: '名称' - }, - { - field: '1', - caption: '年龄' - }, - { - field: '2', - caption: '性别' - }, - { - field: '3', - caption: '爱好' - } - ], - records: new Array(10).fill(['张三', 18, '男', '🏀']), - animationAppear: { - duration: 1000, - delay: 500, - type: 'one-by-one', // all - direction: 'row' // colunm - } - }; - - // document.getElementById(CONTAINER_ID).parentElement.style.display = 'none'; - const instance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); - window.tableInstance = instance; - - bindDebugTool(tableInstance.scenegraph.stage, { - customGrapicKeys: ['col', 'row'] - }); -} diff --git a/packages/vtable/examples/debug/bugserver.ts b/packages/vtable/examples/debug/bugserver.ts index 9dc87013e..efe66c94a 100644 --- a/packages/vtable/examples/debug/bugserver.ts +++ b/packages/vtable/examples/debug/bugserver.ts @@ -21,6 +21,7 @@ import('https://unpkg.com/@visactor/vchart@latest/build/index.min.js') rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, dataConfig: { diff --git a/packages/vtable/examples/debug/scroll.ts b/packages/vtable/examples/debug/scroll.ts deleted file mode 100644 index b364f7c0a..000000000 --- a/packages/vtable/examples/debug/scroll.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* eslint-disable */ -import * as VTable from '../../src'; -import VChart from '@visactor/vchart'; -import { bindDebugTool } from '../../src/scenegraph/debug-tool'; - -const CONTAINER_ID = 'vTable'; -VTable.register.chartModule('vchart', VChart); - -function createColumn(col: number) { - const arr: any[] = []; - for (let i = 0; i < col; i++) { - const obj = { - title: i, - field: i - // width: "auto", - }; - arr.push(obj); - } - return arr; -} - -function createRecords(col: number, row: number) { - const arr: any[] = []; - for (let i = 0; i < row; i++) { - const obj = {}; - for (let j = 0; j < col; j++) { - obj[j] = `c${j}r${i}`; - } - arr.push(obj); - } - return arr; -} - -export function createTable() { - const records = createRecords(500, 500); - const columns = createColumn(500); - - const option = { - records, - columns, - // 表格列宽度的计算模式,可以是 'standard'(标准模式)、'adaptive'(自适应容器宽度模式)或 'autoWidth'(自动宽度模式),默认为 'standard'。 - widthMode: 'autoWidth', - heightMode: 'autoHeight', - defaultColWidth: 120 - // 冻结列数 - // frozenColCount: 3, - }; - - // document.getElementById(CONTAINER_ID).parentElement.style.display = 'none'; - const instance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); - window.tableInstance = instance; - - // tableInstance.onVChartEvent('mouseover', args => { - // console.log('listenChart mouseover', args); - // }); - - bindDebugTool(tableInstance.scenegraph.stage, { - customGrapicKeys: ['col', 'row'] - }); - - window.update = () => { - (option.rowTree = [ - { - dimensionKey: '20001', - value: '销售额' - } - ]), - (option.rows = [ - { - dimensionKey: '20001', - title: '销售额', - headerStyle: { - color: 'red', - cursor: 'pointer' - } - } - ]), - tableInstance.updateOption(option); - }; -} diff --git a/packages/vtable/examples/debug/site.ts b/packages/vtable/examples/debug/site.ts index 482543240..2fe908a2f 100644 --- a/packages/vtable/examples/debug/site.ts +++ b/packages/vtable/examples/debug/site.ts @@ -6,63 +6,63 @@ import { bindDebugTool } from '../../src/scenegraph/debug-tool'; const CONTAINER_ID = 'vTable'; VTable.register.chartModule('vchart', VChart); export function createTable() { - let tableInstance; - fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/company_struct.json') + fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/test-demo-data/pre-sort.json') .then(res => res.json()) .then(data => { const columns = [ { - field: 'group', - title: 'department', - width: 'auto', - tree: true, - fieldFormat(rec) { - return rec['department'] ?? rec['group'] ?? rec['name']; - } + field: 'id', + title: 'ID', + width: 80, + sort: true }, { - field: 'total_children', - title: 'memebers count', - width: 'auto', - fieldFormat(rec) { - if (rec?.['position']) { - return `position: ${rec['position']}`; - } else return rec?.['total_children']; - } + field: 'email1', + title: 'email(pre-sorted)', + width: 250, + sort: true }, { - field: 'monthly_expense', - title: 'monthly expense', - width: 'auto', - fieldFormat(rec) { - if (rec?.['salary']) { - return `salary: ${rec['salary']}`; - } else return rec?.['monthly_expense']; - } + field: 'hobbies', + title: 'hobbies(unsorted)', + width: 200, + sort: true }, { - field: 'new_hires_this_month', - title: 'new hires this month', - width: 'auto' + field: 'birthday', + title: 'birthday', + width: 120 }, { - field: 'resignations_this_month', - title: 'resignations this month', - width: 'auto' + field: 'sex', + title: 'sex', + width: 100 }, { - field: 'complaints_and_suggestions', - title: 'recived complaints counts', - width: 'auto' + field: 'tel', + title: 'telephone', + width: 150 + }, + { + field: 'work', + title: 'job', + width: 200 + }, + { + field: 'city', + title: 'city', + width: 150 } ]; - const option = { - records: data, - columns, - widthMode: 'standard' + records: data.data, + columns }; - tableInstance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); + const tableInstance = new VTable.ListTable(document.getElementById(CONTAINER_ID), option); window['tableInstance'] = tableInstance; + + data.sort.forEach(item => { + tableInstance.setSortedIndexMap(item.key, item.value); + }); }); } diff --git a/packages/vtable/examples/editor/input-editor.ts b/packages/vtable/examples/editor/input-editor.ts index 3413d2cad..a9c2aa048 100644 --- a/packages/vtable/examples/editor/input-editor.ts +++ b/packages/vtable/examples/editor/input-editor.ts @@ -134,7 +134,6 @@ export function createTable() { } ]; const option: VTable.ListTableConstructorOptions = { - emptyTip: true, container: document.getElementById(CONTAINER_ID), columns: [ { @@ -164,8 +163,7 @@ export function createTable() { widthMode: 'standard', autoFillWidth: true, allowFrozenColCount: 2, - editor: 'input', - headerEditor: 'input' + editor: 'input' }; const instance = new ListTable(option); diff --git a/packages/vtable/examples/editor/pivot-editor.ts b/packages/vtable/examples/editor/pivot-editor.ts index 3b53fd9cc..941166222 100644 --- a/packages/vtable/examples/editor/pivot-editor.ts +++ b/packages/vtable/examples/editor/pivot-editor.ts @@ -433,15 +433,14 @@ export function createTable() { } ], corner: { - // headerEditor: 'input', titleOnDimension: 'row', headerStyle: { bgColor: '#356b9c', color: '#00ffff' } - }, + } // widthMode: 'adaptive', - headerEditor: 'input' + // headerEditor: 'input' }; const tableInstance = new VTable.PivotTable(option); // 只为了方便控制太调试用,不要拷贝 diff --git a/packages/vtable/examples/header/merge-cell.ts b/packages/vtable/examples/header/merge-cell.ts index 2229d2b6e..08e701e39 100644 --- a/packages/vtable/examples/header/merge-cell.ts +++ b/packages/vtable/examples/header/merge-cell.ts @@ -1,10 +1,7 @@ import * as VTable from '../../src'; const ListTable = VTable.ListTable; const CONTAINER_ID = 'vTable'; -import { InputEditor } from '@visactor/vtable-editors'; -const input_editor = new InputEditor({}); -VTable.register.editor('input', input_editor); export function createTable() { const personsDataSource = [ { @@ -301,8 +298,7 @@ export function createTable() { } }; } - }, - editor: 'input' + } }; const instance = new ListTable(option); diff --git a/packages/vtable/examples/icon/icon-register.ts b/packages/vtable/examples/icon/icon-register.ts index 66e9344ec..e782ac19f 100644 --- a/packages/vtable/examples/icon/icon-register.ts +++ b/packages/vtable/examples/icon/icon-register.ts @@ -88,10 +88,8 @@ export function createTable() { `, tooltip: { // 气泡框,按钮的的解释信息 - title: - '更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作更多操作操作 更多操作更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作 更多操作更多操作', - style: { bgColor: 'black', arrowMark: true, color: 'white', maxHeight: 100, maxWidth: 100 }, - disappearDelay: 100 + title: '更多操作', + style: { bgColor: 'black', arrowMark: true, color: 'white' } } }); VTable.register.icon('phone', { @@ -320,8 +318,7 @@ export function createTable() { style: { arrowMark: true }, placement: VTable.TYPES.Placement.top, // 气泡框,按钮的的解释信息 - title: '对象定义形式 非注册', - disappearDelay: 100 + title: '对象定义形式 非注册' } } ], @@ -397,8 +394,7 @@ export function createTable() { return `这是第${rec.id}号`; }, title: 'ID说明', - description: `这是一个ID详细描述\n这是一个ID详细描述 -这是一个ID详细描述`, + description: '这是一个ID详细描述', sort: (v1, v2, order) => { if (order === 'desc') { return v1 === v2 ? 0 : v1 > v2 ? -1 : 1; @@ -425,18 +421,12 @@ export function createTable() { allowFrozenColCount: 8, tooltip: { renderMode: 'html', - isShowOverflowTextTooltip: true, - overflowTextTooltipDisappearDelay: 100 + isShowOverflowTextTooltip: false }, heightMode: 'autoHeight', title: { text: 'title', orient: 'top' - }, - theme: { - tooltipStyle: { - maxWidth: 200 - } } }; diff --git a/packages/vtable/examples/interactive/row-resize.ts b/packages/vtable/examples/interactive/row-resize.ts index 3650dc812..6abfafa3a 100644 --- a/packages/vtable/examples/interactive/row-resize.ts +++ b/packages/vtable/examples/interactive/row-resize.ts @@ -8,7 +8,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, dataConfig: { diff --git a/packages/vtable/examples/interactive/tooltip.ts b/packages/vtable/examples/interactive/tooltip.ts index 5c7518d7e..dad3b4334 100644 --- a/packages/vtable/examples/interactive/tooltip.ts +++ b/packages/vtable/examples/interactive/tooltip.ts @@ -39,11 +39,7 @@ export function createTable() { return `已完成${rec.progress}%`; }, title: 'progress', - description: `这是一个标题的详细描述,这是一个标题的详细描述, -这是一个标题的详细描述,这是一个标题的详细描述,这是一个标题的详细描述,这是一个标题的详细描述, -这是一个标题的详细描述,这是一个标题的详细描述, 这是一个标题的详细描述,这是一个标题的详细描述, -这是一个标题的详细描述,这是一个标题的详细描述,这是一个标题的详细描述,这是一个标题的详细描述, -这是一个标题的详细描述,这是一个标题的详细描述`, + description: '这是一个标题的详细描述', width: 150, showSort: true //显示VTable内置排序图标 }, @@ -90,8 +86,7 @@ export function createTable() { allowFrozenColCount: 2, tooltip: { renderMode: 'html', - isShowOverflowTextTooltip: true, - overflowTextTooltipDisappearDelay: 1000 + isShowOverflowTextTooltip: true } }; diff --git a/packages/vtable/examples/list-analysis/list-aggregation-edit.ts b/packages/vtable/examples/list-analysis/list-aggregation-edit.ts index 73c3195db..04e832633 100644 --- a/packages/vtable/examples/list-analysis/list-aggregation-edit.ts +++ b/packages/vtable/examples/list-analysis/list-aggregation-edit.ts @@ -2,10 +2,7 @@ import * as VTable from '../../src'; import { AggregationType } from '../../src/ts-types'; import { InputEditor } from '@visactor/vtable-editors'; const CONTAINER_ID = 'vTable'; -const input_editor = new InputEditor({ - // readonly: true, - editorType: 'textArea' -}); +const input_editor = new InputEditor({}); VTable.register.editor('input', input_editor); const generatePersons = count => { return Array.from(new Array(count)).map((_, i) => ({ @@ -174,7 +171,6 @@ export function createTable() { }), editor: 'input', headerEditor: 'input', - enableLineBreak: true, aggregation(args) { if (args.col === 1) { return [ diff --git a/packages/vtable/examples/list/list-empty-tip.ts b/packages/vtable/examples/list/list-empty-tip.ts deleted file mode 100644 index 671e75f0e..000000000 --- a/packages/vtable/examples/list/list-empty-tip.ts +++ /dev/null @@ -1,119 +0,0 @@ -import * as VTable from '../../src'; -const CONTAINER_ID = 'vTable'; - -const generatePersons = count => { - return Array.from(new Array(count)).map((_, i) => ({ - id: i + 1, - email1: `${i + 1}@xxx.com`, - name: `小明${i + 1}`, - lastName: '王', - date1: '2022年9月1日', - tel: '000-0000-0000', - sex: i % 2 === 0 ? 'boy' : 'girl', - work: i % 2 === 0 ? 'back-end engineer' : 'front-end engineer', - city: 'beijing' - })); -}; - -export function createTable() { - const columns: VTable.ColumnsDefine = [ - { - field: 'id', - title: 'ID', - width: 120, - sort: true - }, - { - field: 'email1', - title: 'email', - width: 200, - sort: true - } - ]; - const option: VTable.ListTableConstructorOptions = { - container: document.getElementById(CONTAINER_ID), - records: generatePersons(100), - // columns, - // transpose:true, - // showHeader:false, - columns: [ - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns - ], - emptyTip: { - spaceBetweenTextAndIcon: 200, - text: '无数据', - textStyle: { - color: 'red' - }, - icon: { - width: 80, - height: 80, - image: - '' - } - }, - theme: { - scrollStyle: { - barToSide: true - } - } - }; - const tableInstance = new VTable.ListTable(option); - setTimeout(() => { - tableInstance.updateOption({ - container: document.getElementById(CONTAINER_ID), - records: [], - // columns, - // transpose:true, - // showHeader:false, - columns: [ - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns - ], - emptyTip: { - spaceBetweenTextAndIcon: 20, - text: '无数据', - textStyle: { - color: 'red' - }, - icon: { - width: 80, - height: 80, - image: - '' - } - }, - theme: { - scrollStyle: { - barToSide: true - } - } - }); - }, 2000); - - setTimeout(() => { - tableInstance.setRecords(generatePersons(100)); - }, 4000); - window.tableInstance = tableInstance; -} diff --git a/packages/vtable/examples/list/list.ts b/packages/vtable/examples/list/list.ts index 06fb2e665..5133059f2 100644 --- a/packages/vtable/examples/list/list.ts +++ b/packages/vtable/examples/list/list.ts @@ -16,7 +16,7 @@ const generatePersons = count => { }; export function createTable() { - const records = generatePersons(2000); + const records = generatePersons(1000000); const columns: VTable.ColumnsDefine = [ { field: '', @@ -167,20 +167,8 @@ export function createTable() { ]; const option: VTable.ListTableConstructorOptions = { container: document.getElementById(CONTAINER_ID), - emptyTip: true, records, - columns: [ - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns, - ...columns - ], + columns, tooltip: { isShowOverflowTextTooltip: true }, @@ -199,14 +187,6 @@ export function createTable() { }, autoWrapText: true, editor: '', - // theme: VTable.themes.ARCO, - // hover: { - // highlightMode: 'cross' - // }, - // select: { - // headerSelectMode: 'cell', - // highlightMode: 'cross' - // }, excelOptions: { fillHandle: true } @@ -214,9 +194,6 @@ export function createTable() { }; const tableInstance = new VTable.ListTable(option); window.tableInstance = tableInstance; - bindDebugTool(tableInstance.scenegraph.stage, { - customGrapicKeys: ['col', 'row'] - }); tableInstance.on('change_cell_value', arg => { console.log(arg); }); diff --git a/packages/vtable/examples/menu.ts b/packages/vtable/examples/menu.ts index 47a6586e2..c88fc81cf 100644 --- a/packages/vtable/examples/menu.ts +++ b/packages/vtable/examples/menu.ts @@ -13,14 +13,6 @@ export const menus = [ { path: 'debug', name: 'site' - }, - { - path: 'debug', - name: 'animation' - }, - { - path: 'debug', - name: 'scroll' } ] }, @@ -79,10 +71,6 @@ export const menus = [ path: 'list', name: 'list-title' }, - { - path: 'list', - name: 'list-empty-tip' - }, { path: 'list', name: 'list-height-adaptive' @@ -172,14 +160,6 @@ export const menus = [ { path: 'pivot', name: 'pivot-tree-rowSeriesNumber' - }, - { - path: 'pivot', - name: 'virtual-node' - }, - { - path: 'pivot', - name: 'virtual-node-2' } ] }, @@ -266,10 +246,6 @@ export const menus = [ path: 'pivot-chart', name: 'pivotChart-legend' }, - { - path: 'pivot-chart', - name: 'pivotChart-two-legends' - }, { path: 'pivot-chart', name: 'pivotChart-hideHeader' @@ -524,18 +500,6 @@ export const menus = [ { path: 'pivot-analysis', name: 'pivot-analysis-str' - }, - { - path: 'pivot-analysis', - name: 'pivot-empty-tip' - }, - { - path: 'pivot-analysis', - name: 'pivot-analysis-calculatedField' - }, - { - path: 'pivot-analysis', - name: 'pivot-analysis-calculatedField2' } ] }, @@ -905,10 +869,6 @@ export const menus = [ { path: 'business', name: 'sales-bubble' - }, - { - path: 'business', - name: 'background-image' } ] }, @@ -946,14 +906,6 @@ export const menus = [ { path: 'unit-test-demo', name: 'pivotTable-size-legend' - }, - { - path: 'unit-test-demo', - name: 'unit-listTable-sort' - }, - { - path: 'unit-test-demo', - name: 'unit-listTable-frozen' } ] }, diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-aggregationRules.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-aggregationRules.ts index 2c8295440..448703cc2 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-aggregationRules.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-aggregationRules.ts @@ -14,7 +14,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['销售总额', '订单数', '订单均价'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, dataConfig: { diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField.ts deleted file mode 100644 index 7611d4e58..000000000 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField.ts +++ /dev/null @@ -1,169 +0,0 @@ -import * as VTable from '../../src'; -import { bindDebugTool } from '../../src/scenegraph/debug-tool'; -const PivotTable = VTable.PivotTable; -const CONTAINER_ID = 'vTable'; - -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_data.json') - .then(res => res.json()) - .then(data => { - const option: VTable.PivotTableConstructorOptions = { - records: data, - rows: [ - { - dimensionKey: 'Category', - title: 'Category', - headerStyle: { - textStick: true - }, - width: 'auto' - }, - { - dimensionKey: 'Sub-Category', - title: 'Sub-Catogery', - headerStyle: { - textStick: true - }, - width: 'auto' - } - ], - columns: [ - { - dimensionKey: 'Year', - title: 'Year', - headerStyle: { - textStick: true - } - }, - { - dimensionKey: 'Month', - title: 'Month', - headerStyle: { - textStick: true - } - } - ], - indicators: [ - { - indicatorKey: 'Quantity', - title: 'Quantity', - width: 'auto', - showSort: false, - headerStyle: { - fontWeight: 'normal' - }, - style: { - padding: [16, 28, 16, 28], - color(args) { - if (args.dataValue >= 0) { - return 'black'; - } - return 'red'; - } - } - }, - { - indicatorKey: 'Sales', - title: 'Sales', - width: 'auto', - showSort: false, - headerStyle: { - fontWeight: 'normal' - }, - format: rec => { - return '$' + Number(rec).toFixed(2); - }, - style: { - padding: [16, 28, 16, 28], - color(args) { - if (args.dataValue >= 0) { - return 'black'; - } - return 'red'; - } - } - }, - { - indicatorKey: 'Profit', - title: 'Profit', - width: 'auto', - showSort: false, - headerStyle: { - fontWeight: 'normal' - }, - format: rec => { - return '$' + Number(rec).toFixed(2); - }, - style: { - padding: [16, 28, 16, 28], - color(args) { - if (args.dataValue >= 0) { - return 'black'; - } - return 'red'; - } - } - }, - { - indicatorKey: 'calField1', - title: 'AvgPrice', - width: 'auto', - format: rec => { - return '$' + Number(rec).toFixed(2); - }, - style: { - color: 'blue' - } - } - ], - corner: { - titleOnDimension: 'row', - headerStyle: {} - }, - dataConfig: { - derivedFieldRules: [ - { - fieldName: 'Year', - derivedFunc: VTable.DataStatistics.dateFormat('Order Date', '%y', true) - }, - { - fieldName: 'Month', - derivedFunc: VTable.DataStatistics.dateFormat('Order Date', '%n', true) - } - ], - calculatedFieldRules: [ - { - key: 'calField1', - dependIndicatorKeys: ['Quantity', 'Sales'], - calculateFun: (dependValue: any) => { - return dependValue.Sales / dependValue.Quantity; - } - } - ], - totals: { - row: { - showGrandTotals: true, - showSubTotals: true, - subTotalsDimensions: ['Category'], - grandTotalLabel: '行总计', - subTotalLabel: '小计' - }, - column: { - showGrandTotals: true, - showSubTotals: true, - subTotalsDimensions: ['Year'], - grandTotalLabel: '列总计', - subTotalLabel: '小计' - } - } - }, - widthMode: 'standard' - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window.tableInstance = tableInstance; - - bindDebugTool(tableInstance.scenegraph.stage, { customGrapicKeys: ['col', 'row'] }); - }) - .catch(e => { - console.error(e); - }); diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField2.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField2.ts deleted file mode 100644 index fc89419f0..000000000 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-calculatedField2.ts +++ /dev/null @@ -1,181 +0,0 @@ -import * as VTable from '../../src'; -import { bindDebugTool } from '../../src/scenegraph/debug-tool'; -const PivotTable = VTable.PivotTable; -const CONTAINER_ID = 'vTable'; - -let tableInstance; -fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_data.json') - .then(res => res.json()) - .then(data => { - const option: VTable.PivotTableConstructorOptions = { - records: data, - rows: [ - { - dimensionKey: 'Category', - title: 'Category', - headerStyle: { - textStick: true - }, - width: 'auto' - }, - { - dimensionKey: 'Sub-Category', - title: 'Sub-Catogery', - headerStyle: { - textStick: true - }, - width: 'auto' - } - ], - columns: [ - { - dimensionKey: 'Year', - title: 'Year', - headerStyle: { - textStick: true - } - }, - { - dimensionKey: 'Month', - title: 'Month', - headerStyle: { - textStick: true - } - } - ], - indicators: [ - // { - // indicatorKey: 'Quantity', - // title: 'Quantity', - // width: 'auto', - // showSort: false, - // headerStyle: { - // fontWeight: 'normal' - // }, - // style: { - // padding: [16, 28, 16, 28], - // color(args) { - // if (args.dataValue >= 0) { - // return 'black'; - // } - // return 'red'; - // } - // } - // }, - // { - // indicatorKey: 'Sales', - // title: 'Sales', - // width: 'auto', - // showSort: false, - // headerStyle: { - // fontWeight: 'normal' - // }, - // format: rec => { - // return '$' + Number(rec).toFixed(2); - // }, - // style: { - // padding: [16, 28, 16, 28], - // color(args) { - // if (args.dataValue >= 0) { - // return 'black'; - // } - // return 'red'; - // } - // } - // }, - { - indicatorKey: 'Profit', - title: 'Profit', - width: 'auto', - showSort: false, - headerStyle: { - fontWeight: 'normal' - }, - format: rec => { - return '$' + Number(rec).toFixed(2); - }, - style: { - padding: [16, 28, 16, 28], - color(args) { - if (args.dataValue >= 0) { - return 'black'; - } - return 'red'; - } - } - }, - { - indicatorKey: 'calField1', - title: 'AvgPrice', - width: 'auto', - format: rec => { - return '$' + Number(rec).toFixed(2); - }, - style: { - color: 'blue' - } - } - ], - corner: { - titleOnDimension: 'row', - headerStyle: {} - }, - dataConfig: { - derivedFieldRules: [ - { - fieldName: 'Year', - derivedFunc: VTable.DataStatistics.dateFormat('Order Date', '%y', true) - }, - { - fieldName: 'Month', - derivedFunc: VTable.DataStatistics.dateFormat('Order Date', '%n', true) - } - ], - aggregationRules: [ - { - indicatorKey: 'QuantitySum', - field: 'Quantity', - aggregationType: VTable.TYPES.AggregationType.SUM - }, - { - indicatorKey: 'SalesSum', - field: 'Sales', - aggregationType: VTable.TYPES.AggregationType.SUM - } - ], - calculatedFieldRules: [ - { - key: 'calField1', - dependIndicatorKeys: ['QuantitySum', 'SalesSum'], - calculateFun: (dependValue: any) => { - return dependValue.SalesSum / dependValue.QuantitySum; - } - } - ], - totals: { - row: { - showGrandTotals: true, - showSubTotals: true, - subTotalsDimensions: ['Category'], - grandTotalLabel: '行总计', - subTotalLabel: '小计' - }, - column: { - showGrandTotals: true, - showSubTotals: true, - subTotalsDimensions: ['Year'], - grandTotalLabel: '列总计', - subTotalLabel: '小计' - } - } - }, - widthMode: 'standard' - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window.tableInstance = tableInstance; - - bindDebugTool(tableInstance.scenegraph.stage, { customGrapicKeys: ['col', 'row'] }); - }) - .catch(e => { - console.error(e); - }); diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-field.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-field.ts index 590ad8d89..8afa821dc 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-field.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-field.ts @@ -131,6 +131,7 @@ fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American } ] }, + enableDataAnalysis: true, widthMode: 'standard' }; tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-mapping.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-mapping.ts index 103dd29d2..06222cc5f 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-mapping.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-mapping.ts @@ -43,7 +43,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, dataConfig: { diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-more-data.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-more-data.ts index fb441f3dc..8e562d2de 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-more-data.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-more-data.ts @@ -90,7 +90,7 @@ export function createTable() { } } ], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, dataConfig: { diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-pagination.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-pagination.ts index 415d4e158..5c52b6a6a 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-pagination.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-pagination.ts @@ -90,7 +90,7 @@ export function createTable() { } } ], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, dataConfig: { diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-setRecords.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-setRecords.ts index 32c8db61a..adee31017 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-setRecords.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-setRecords.ts @@ -7,7 +7,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, corner: { titleOnDimension: 'row' }, diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-sort.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-sort.ts index 201502e9a..45b46cf25 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-sort.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-sort.ts @@ -43,7 +43,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, dataConfig: { diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-str.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-str.ts index 943d46d41..f3d36eb5f 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-str.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-str.ts @@ -15,7 +15,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['销售总额', '订单数', '订单均价'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, dataConfig: { diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-total.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-total.ts index bcbcf8d34..e47951e61 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-total.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-total.ts @@ -7,7 +7,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, dataConfig: { diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-totalData-tree.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-totalData-tree.ts index 719142a75..01499da0e 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-totalData-tree.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-totalData-tree.ts @@ -7,7 +7,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: true, rowHierarchyType: 'tree', diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-totalData.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-totalData.ts index 59fe72b62..7657c0d96 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-totalData.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-totalData.ts @@ -7,7 +7,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, dataConfig: { diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis-tree.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis-tree.ts index e7558d117..84d5ca1a7 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis-tree.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis-tree.ts @@ -7,7 +7,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: true, rowHierarchyType: 'tree', diff --git a/packages/vtable/examples/pivot-analysis/pivot-analysis.ts b/packages/vtable/examples/pivot-analysis/pivot-analysis.ts index 6b9f49cd1..82ca87e48 100644 --- a/packages/vtable/examples/pivot-analysis/pivot-analysis.ts +++ b/packages/vtable/examples/pivot-analysis/pivot-analysis.ts @@ -7,7 +7,7 @@ export function createTable() { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, corner: { titleOnDimension: 'row' }, diff --git a/packages/vtable/examples/pivot-analysis/pivot-empty-tip.ts b/packages/vtable/examples/pivot-analysis/pivot-empty-tip.ts deleted file mode 100644 index 947a0efcd..000000000 --- a/packages/vtable/examples/pivot-analysis/pivot-empty-tip.ts +++ /dev/null @@ -1,56 +0,0 @@ -import * as VTable from '../../src'; -const PivotTable = VTable.PivotTable; -const CONTAINER_ID = 'vTable'; - -export function createTable() { - const option: VTable.PivotTableConstructorOptions = { - rows: ['province', 'city'], - columns: ['category', 'sub_category'], - indicators: ['sales', 'number'], - - indicatorTitle: '指标名称', - indicatorsAsCol: false, - corner: { titleOnDimension: 'column' }, - columnResizeType: 'all', - records: [ - { - sales: 891, - number: 7789, - province: '浙江省', - city: '杭州市', - category: '家具', - sub_category: '桌子' - } - ], - emptyTip: true, - widthMode: 'autoWidth' // 宽度模式:standard 标准模式; adaptive 自动填满容器 - }; - - const instance = new PivotTable(document.getElementById(CONTAINER_ID)!, option); - window.tableInstance = instance; - - setTimeout(() => { - instance.updateOption({ - rows: ['province', 'city'], - columns: ['category', 'sub_category'], - indicators: ['sales', 'number'], - - indicatorTitle: '指标名称', - indicatorsAsCol: false, - corner: { titleOnDimension: 'column' }, - columnResizeType: 'all', - records: [ - // { - // sales: 891, - // number: 7789, - // province: '浙江省', - // city: '杭州市', - // category: '家具', - // sub_category: '桌子' - // } - ], - emptyTip: true, - widthMode: 'autoWidth' // 宽度模式:standard 标准模式; adaptive 自动填满容器 - }); - }, 1000); -} diff --git a/packages/vtable/examples/pivot-chart/noDimension-updateOption.ts b/packages/vtable/examples/pivot-chart/noDimension-updateOption.ts index b5a9b8537..2789c6139 100644 --- a/packages/vtable/examples/pivot-chart/noDimension-updateOption.ts +++ b/packages/vtable/examples/pivot-chart/noDimension-updateOption.ts @@ -86,6 +86,7 @@ export function createTable() { const tableInstance = new VTable.PivotChart(document.getElementById(CONTAINER_ID)!, option); tableInstance.updateOption({ + enableDataAnalysis: true, indicatorsAsCol: false, records: [ { diff --git a/packages/vtable/examples/pivot-chart/pivotChart-pie-legend.ts b/packages/vtable/examples/pivot-chart/pivotChart-pie-legend.ts index 6bd5b352f..215343d29 100644 --- a/packages/vtable/examples/pivot-chart/pivotChart-pie-legend.ts +++ b/packages/vtable/examples/pivot-chart/pivotChart-pie-legend.ts @@ -75,8 +75,8 @@ export function createTable() { defaultHeaderColWidth: 100, indicatorTitle: '指标', autoWrapText: true, - // widthMode: 'adaptive', - // heightMode: 'adaptive', + widthMode: 'adaptive', + heightMode: 'adaptive', corner: { titleOnDimension: 'row', headerStyle: { @@ -118,7 +118,6 @@ export function createTable() { const tableInstance = new VTable.PivotChart(document.getElementById(CONTAINER_ID), option); window.tableInstance = tableInstance; - bindDebugTool(tableInstance.scenegraph.stage, { customGrapicKeys: ['col', 'row'] }); const { LEGEND_ITEM_CLICK } = VTable.ListTable.EVENT_TYPE; tableInstance.on(LEGEND_ITEM_CLICK, args => { console.log('LEGEND_ITEM_CLICK', args); diff --git a/packages/vtable/examples/pivot-chart/pivotChart-radar.ts b/packages/vtable/examples/pivot-chart/pivotChart-radar.ts index 9387c4013..eb2e3c2b6 100644 --- a/packages/vtable/examples/pivot-chart/pivotChart-radar.ts +++ b/packages/vtable/examples/pivot-chart/pivotChart-radar.ts @@ -8,6 +8,7 @@ export function createTable() { fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') .then(res => res.json()) .then(data => { + // data=data.splice(0,260); const columns = [ { dimensionKey: 'Region', @@ -15,7 +16,8 @@ export function createTable() { headerStyle: { textStick: true } - } + }, + 'Category' ]; const rows = [ { @@ -36,45 +38,11 @@ export function createTable() { chartSpec: { type: 'radar', categoryField: 'Segment', - seriesField: 'Category', + seriesField: 'Sub-Category', valueField: 'Quantity', data: { id: 'baseData' - }, - scales: [ - { - id: 'color', - type: 'ordinal', - domain: ['Furniture', 'Office Supplies', 'Technology'], - range: ['#2E62F1', '#4DC36A', '#FF8406'] - } - ] - }, - style: { - padding: 1 - } - }, - { - indicatorKey: 'Profit', - title: 'Profit', - cellType: 'chart', - chartModule: 'vchart', - chartSpec: { - type: 'radar', - categoryField: 'Segment', - seriesField: 'Category', - valueField: 'Profit', - data: { - id: 'baseData' - }, - scales: [ - { - id: 'color', - type: 'ordinal', - domain: ['Furniture', 'Office Supplies', 'Technology'], - range: ['#2E62F1', '#4DC36A', '#FF8406'] - } - ] + } }, style: { padding: 1 @@ -82,7 +50,7 @@ export function createTable() { } ]; const option = { - hideIndicatorName: false, + hideIndicatorName: true, rows, columns, indicators, @@ -93,54 +61,26 @@ export function createTable() { defaultHeaderColWidth: 100, indicatorTitle: '指标', autoWrapText: true, + // widthMode: 'adaptive', + // heightMode: 'adaptive', corner: { titleOnDimension: 'row', headerStyle: { autoWrapText: true } }, - legends: { - orient: 'bottom', - type: 'discrete', - data: [ - { - label: 'Furniture', - shape: { - fill: '#2E62F1', - symbolType: 'circle' - } - }, - { - label: 'Office Supplies', - shape: { - fill: '#4DC36A', - symbolType: 'square' - } - }, - { - label: 'Technology', - shape: { - fill: '#FF8406', - symbolType: 'square' - } - } - ] - }, + pagination: { currentPage: 0, perPageCount: 8 } }; const tableInstance = new VTable.PivotChart(document.getElementById(CONTAINER_ID), option); - const { LEGEND_ITEM_CLICK } = VTable.ListTable.EVENT_TYPE; - tableInstance.on(LEGEND_ITEM_CLICK, args => { - console.log('LEGEND_ITEM_CLICK', args); - tableInstance.updateFilterRules([ - { - filterKey: 'Category', - filteredValues: args.value - } - ]); + tableInstance.onVChartEvent('click', args => { + console.log('onVChartEvent click', args); + }); + tableInstance.onVChartEvent('mouseover', args => { + console.log('onVChartEvent mouseover', args); }); window.tableInstance = tableInstance; diff --git a/packages/vtable/examples/pivot-chart/pivotChart-two-legends.ts b/packages/vtable/examples/pivot-chart/pivotChart-two-legends.ts deleted file mode 100644 index 398176667..000000000 --- a/packages/vtable/examples/pivot-chart/pivotChart-two-legends.ts +++ /dev/null @@ -1,10581 +0,0 @@ -/* eslint-disable */ -import * as VTable from '../../src'; -import VChart from '@visactor/vchart'; -import { bindDebugTool } from '../../src/scenegraph/debug-tool'; -const CONTAINER_ID = 'vTable'; -VTable.register.chartModule('vchart', VChart); -export function createTable() { - const rowTree = [ - { - dimensionKey: '230417170554012', - value: '一级', - children: [ - { - value: '数量', - indicatorKey: '230713183656009' - }, - { - value: '销售额', - indicatorKey: '230417171050025' - }, - { - value: '折扣', - indicatorKey: '230707112948009' - } - ] - }, - { - dimensionKey: '230417170554012', - value: '二级', - children: [ - { - value: '数量', - indicatorKey: '230713183656009' - }, - { - value: '销售额', - indicatorKey: '230417171050025' - }, - { - value: '折扣', - indicatorKey: '230707112948009' - } - ] - }, - { - dimensionKey: '230417170554012', - value: '当日', - children: [ - { - value: '数量', - indicatorKey: '230713183656009' - }, - { - value: '销售额', - indicatorKey: '230417171050025' - }, - { - value: '折扣', - indicatorKey: '230707112948009' - } - ] - }, - { - dimensionKey: '230417170554012', - value: '标准级', - children: [ - { - value: '数量', - indicatorKey: '230713183656009' - }, - { - value: '销售额', - indicatorKey: '230417171050025' - }, - { - value: '折扣', - indicatorKey: '230707112948009' - } - ] - } - ]; - const columnTree = [ - { - dimensionKey: '230417171050031', - value: '中国', - children: [ - { - dimensionKey: '230417171050028', - value: '办公用品' - }, - { - dimensionKey: '230417171050028', - value: '家具' - }, - { - dimensionKey: '230417171050028', - value: '技术' - } - ] - }, - { - dimensionKey: '230417171050031', - value: '中国', - children: [ - { - dimensionKey: '230417171050028', - value: '办公用品' - }, - { - dimensionKey: '230417171050028', - value: '家具' - }, - { - dimensionKey: '230417171050028', - value: '技术' - } - ] - } - ]; - const columns: (VTable.IDimension | string)[] = [ - { - dimensionKey: '230417171050031', - title: '国家', - headerStyle: { - color: 'red' - } - }, - '230417171050028' - // '230417170554008' - ]; - const rows = [ - { - dimensionKey: '230417170554012', - title: '邮寄方式', - headerStyle: { - color: 'red' - } - } - ]; - const indicators: VTable.TYPES.IIndicator[] = [ - { - indicatorKey: '230713183656009', - title: '数量', - width: 'auto', - cellType: 'chart', - chartModule: 'vchart', - chartSpec: { - tooltip: { - throttleInterval: 0 - }, - // type: 'common', - stack: true, - type: 'bar', - padding: { left: 0, right: 0, top: 3, bottom: 3 }, - data: { - id: 'dataId', - fields: { - //设置xField数据的顺序 - 230417170554008: { - sortIndex: 0, - domain: [ - '纸张', - '标签', - '装订机', - '系固件', - '用品', - '美术', - '器具', - '收纳具', - '信封', - '椅子', - '书架', - '用具', - '桌子', - '复印机', - '电话', - '设备', - '配件' - ] - // lockStatisticsByDomain: true - }, - 230717170834024: { - //设置seriesField数据的顺序 应该设置20001的顺序的 但是按照图例的顺序设置后堆叠效果和3.X不一致 - sortIndex: 1, - domain: ['消费者', '小型企业', '公司'] - // lockStatisticsByDomain: true - } - } - }, - axes: [{ orient: 'left', visible: true, label: { visible: true } }], - // brush: { - // brushType: 'rect', - // brushLinkSeriesIndex: [1, 2], - // inBrush: { - // colorAlpha: 1 - // }, - // outOfBrush: { - // colorAlpha: 0.2 - // } - // }, - xField: ['230417170554008'], - yField: '230713183656009', - seriesField: '20001', - bar: { - state: { - selected: { - fill: 'yellow' - }, - selected_reverse: { - // fill: '#ddd' - opacity: 0.2 - } - } - }, - scales: [ - { - id: 'color', - type: 'ordinal', - domain: [ - '公司-数量', - '小型企业-数量', - '消费者-数量', - '公司-销售额', - '小型企业-销售额', - '消费者-销售额', - '公司-利润', - '小型企业-利润', - '消费者-利润', - '公司-折扣', - '小型企业-折扣', - '消费者-折扣' - ], - range: [ - '#2E62F1', - '#4DC36A', - '#FF8406', - '#FFCC00', - '#4F44CF', - '#5AC8FA', - '#003A8C', - '#B08AE2', - '#FF6341', - '#98DD62', - '#07A199', - '#87DBDD' - ] - } - ] - }, - style: { - padding: 1 - } - }, - { - indicatorKey: '230417171050025', - title: '销售额 & 利润', - cellType: 'chart', - chartModule: 'vchart', - chartSpec: { - tooltip: { - throttleInterval: 0 - }, - type: 'common', - padding: { left: 0, right: 0, top: 3, bottom: 3 }, - // data: { - // id: 'dataId', - // fields: { - // 230417170554008: { - // sortIndex: 0, - // domain: [ - // '纸张', - // '标签', - // '装订机', - // '系固件', - // '用品', - // '美术', - // '器具', - // '收纳具', - // '信封', - // '椅子', - // '书架', - // '用具', - // '桌子', - // '复印机', - // '电话', - // '设备', - // '配件' - // ] - // // lockStatisticsByDomain: true - // }, - // 230717170834024: { - // sortIndex: 1, - // domain: ['消费者', '小型企业', '公司'] - // // lockStatisticsByDomain: true - // } - // } - // }, - series: [ - { - type: 'bar', - stack: true, - data: { - id: 'id1', - fields: { - 230417170554008: { - sortIndex: 0, - domain: [ - '纸张', - '标签', - '装订机', - '系固件', - '用品', - '美术', - '器具', - '收纳具', - '信封', - '椅子', - '书架', - '用具', - '桌子', - '复印机', - '电话', - '设备', - '配件' - ] - // lockStatisticsByDomain: true - }, - 230717170834024: { - sortIndex: 1, - domain: ['消费者', '小型企业', '公司'] - // lockStatisticsByDomain: true - } - } - }, - xField: ['230417170554008'], - yField: '230713152555009', - seriesField: '20001', - bar: { - state: { - selected: { - fill: 'yellow' - }, - selected_reverse: { - // fill: '#ddd' - opacity: 0.2 - } - } - } - }, - { - type: 'line', - stack: false, - data: { - id: 'id2', - fields: { - 230417170554008: { - sortIndex: 0, - domain: [ - '纸张', - '标签', - '装订机', - '系固件', - '用品', - '美术', - '器具', - '收纳具', - '信封', - '椅子', - '书架', - '用具', - '桌子', - '复印机', - '电话', - '设备', - '配件' - ] - // lockStatisticsByDomain: true - } - } - }, - invalidType: 'break', - xField: ['230417170554008'], - yField: '230417171050025', - seriesField: '20001', - line: { - state: { - selected: { - lineWidth: 3 - }, - selected_reverse: { - lineWidth: 1 - } - } - }, - point: { - state: { - selected: { - fill: 'yellow' - }, - selected_reverse: { - fill: '#ddd' - } - } - } - } - ], - axes: [ - { orient: 'left', visible: true, label: { visible: true } }, - { orient: 'bottom', visible: false } - ], - scales: [ - { - id: 'color', - type: 'ordinal', - domain: [ - '公司-数量', - '小型企业-数量', - '消费者-数量', - '公司-销售额', - '小型企业-销售额', - '消费者-销售额', - '公司-利润', - '小型企业-利润', - '消费者-利润', - '公司-折扣', - '小型企业-折扣', - '消费者-折扣' - ], - range: [ - '#2E62F1', - '#4DC36A', - '#FF8406', - '#FFCC00', - '#4F44CF', - '#5AC8FA', - '#003A8C', - '#B08AE2', - '#FF6341', - '#98DD62', - '#07A199', - '#87DBDD' - ] - } - ] - }, - style: { - padding: 1 - } - }, - { - indicatorKey: '230707112948009', - title: '折扣', - width: 'auto', - cellType: 'chart', - chartModule: 'vchart', - chartSpec: { - tooltip: { - throttleInterval: 0 - }, - // type: 'common', - stack: true, - type: 'area', - padding: { left: 0, right: 0, top: 3, bottom: 3 }, - data: { - id: 'dataId', - fields: { - 230417170554008: { - sortIndex: 0, - domain: [ - '纸张', - '标签', - '装订机', - '系固件', - '用品', - '美术', - '器具', - '收纳具', - '信封', - '椅子', - '书架', - '用具', - '桌子', - '复印机', - '电话', - '设备', - '配件' - ] - // lockStatisticsByDomain: true - }, - 230717170834024: { - sortIndex: 1, - domain: ['消费者', '小型企业', '公司'] - // lockStatisticsByDomain: true - } - } - }, - xField: ['230417170554008'], - yField: '230707112948009', - seriesField: '20001', - axes: [ - { orient: 'left', visible: true, label: { visible: true } }, - { orient: 'bottom', visible: false } - ], - scales: [ - { - id: 'color', - type: 'ordinal', - domain: [ - '公司-数量', - '小型企业-数量', - '消费者-数量', - '公司-销售额', - '小型企业-销售额', - '消费者-销售额', - '公司-利润', - '小型企业-利润', - '消费者-利润', - '公司-折扣', - '小型企业-折扣', - '消费者-折扣' - ], - range: [ - '#2E62F1', - '#4DC36A', - '#FF8406', - '#FFCC00', - '#4F44CF', - '#5AC8FA', - '#003A8C', - '#B08AE2', - '#FF6341', - '#98DD62', - '#07A199', - '#87DBDD' - ] - } - ], - line: { - state: { - selected: { - lineWidth: 3 - }, - selected_reverse: { - lineWidth: 1 - } - } - }, - point: { - state: { - selected: { - fill: 'yellow' - }, - selected_reverse: { - fill: '#ddd' - } - } - }, - area: { - state: { - selected: { - opacity: 1 - }, - selected_reverse: { - opacity: 0.2 - } - } - } - }, - style: { - padding: 1 - } - } - ]; - const records = [ - { - '10001': '数量', - '10002': '78', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '78', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '103', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '103', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '75', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '75', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '217', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '217', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '155', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '155', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '70', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '70', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '63', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '63', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '134', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '134', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '59', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '59', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '233', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '233', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '138', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '138', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '96', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '96', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '83', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '83', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '53', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '53', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '145', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '145', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '335', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '335', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '60', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '60', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '119', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '119', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '134', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '134', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '55', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '55', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '60', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '60', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '50', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '50', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '167', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '167', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '83', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '83', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '125', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '125', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '88', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '88', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '181', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '181', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '8778.419975280762', - '20001': '公司-销售额', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050025': '8778.419975280762', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '4544.3999671936035', - '20001': '公司-销售额', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050025': '4544.3999671936035', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '6478.471912384033', - '20001': '小型企业-销售额', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050025': '6478.471912384033', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '12578.60791015625', - '20001': '消费者-销售额', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050025': '12578.60791015625', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '8178.4079875946045', - '20001': '公司-销售额', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050025': '8178.4079875946045', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '3441.339988708496', - '20001': '小型企业-销售额', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050025': '3441.339988708496', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '6019.944019317627', - '20001': '小型企业-销售额', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050025': '6019.944019317627', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '13564.26397895813', - '20001': '消费者-销售额', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050025': '13564.26397895813', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '40415.89974975586', - '20001': '小型企业-销售额', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050025': '40415.89974975586', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '86399.31974029541', - '20001': '消费者-销售额', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050025': '86399.31974029541', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '16577.119972229004', - '20001': '消费者-销售额', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050025': '16577.119972229004', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '35870.239807128906', - '20001': '公司-销售额', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050025': '35870.239807128906', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '8749.243984222412', - '20001': '公司-销售额', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050025': '8749.243984222412', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '6880.160064697266', - '20001': '小型企业-销售额', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050025': '6880.160064697266', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '9636.08793258667', - '20001': '公司-销售额', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050025': '9636.08793258667', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '29211.251929283142', - '20001': '消费者-销售额', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050025': '29211.251929283142', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '7786.099945068359', - '20001': '公司-销售额', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050025': '7786.099945068359', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '5382.01997756958', - '20001': '消费者-销售额', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050025': '5382.01997756958', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '16882.543968200684', - '20001': '消费者-销售额', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050025': '16882.543968200684', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '3249.231948852539', - '20001': '小型企业-销售额', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050025': '3249.231948852539', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '58335.75997924805', - '20001': '公司-销售额', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050025': '58335.75997924805', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '4352.348020553589', - '20001': '小型企业-销售额', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050025': '4352.348020553589', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '177698.80960083008', - '20001': '消费者-销售额', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050025': '177698.80960083008', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '11059.999969482422', - '20001': '小型企业-销售额', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050025': '11059.999969482422', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '14968.127838134766', - '20001': '公司-销售额', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050025': '14968.127838134766', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '35897.540283203125', - '20001': '小型企业-销售额', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050025': '35897.540283203125', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '22170.82006072998', - '20001': '消费者-销售额', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050025': '22170.82006072998', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1973.5800242424011', - '20001': '公司-利润', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1973.5800242424011', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1229.6199939846992', - '20001': '公司-利润', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1229.6199939846992', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1129.772004365921', - '20001': '小型企业-利润', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1129.772004365921', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2341.3880150318146', - '20001': '消费者-利润', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '2341.3880150318146', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '541.1280030012131', - '20001': '公司-利润', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '541.1280030012131', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '947.0999919176102', - '20001': '小型企业-利润', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '947.0999919176102', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1048.1239943504333', - '20001': '小型企业-利润', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1048.1239943504333', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-1093.5960049629211', - '20001': '消费者-利润', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-1093.5960049629211', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '6390.299970626831', - '20001': '小型企业-利润', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '6390.299970626831', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '23789.77983045578', - '20001': '消费者-利润', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '23789.77983045578', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '4842.040033340454', - '20001': '消费者-利润', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '4842.040033340454', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '9227.819965362549', - '20001': '公司-利润', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '9227.819965362549', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-1142.596001625061', - '20001': '公司-利润', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-1142.596001625061', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1097.3199996948242', - '20001': '小型企业-利润', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1097.3199996948242', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1652.5879747867584', - '20001': '公司-利润', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1652.5879747867584', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '5303.452052593231', - '20001': '消费者-利润', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '5303.452052593231', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1694.4200175404549', - '20001': '公司-利润', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1694.4200175404549', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1113.8400052785873', - '20001': '消费者-利润', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1113.8400052785873', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1395.1840388700366', - '20001': '消费者-利润', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1395.1840388700366', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '729.0920102596283', - '20001': '小型企业-利润', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '729.0920102596283', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-2139.6198582798243', - '20001': '公司-利润', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-2139.6198582798243', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-628.431999206543', - '20001': '小型企业-利润', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-628.431999206543', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '14098.447641819715', - '20001': '消费者-利润', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '14098.447641819715', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2683.519994735718', - '20001': '小型企业-利润', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '2683.519994735718', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1874.628037929535', - '20001': '公司-利润', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1874.628037929535', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '8803.62003326416', - '20001': '小型企业-利润', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '8803.62003326416', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '5043.079977273941', - '20001': '消费者-利润', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '5043.079977273941', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '2.0000000298023224', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '2.0000000298023224', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '5.200000077486038', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '5.200000077486038', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '6.000000089406967', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '6.000000089406967', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '2.0000000298023224', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '2.0000000298023224', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '9.00000013411045', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '9.00000013411045', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '1.600000023841858', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '1.600000023841858', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '6.800000101327896', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '6.800000101327896', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '5.200000077486038', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '5.200000077486038', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '10.400000154972076', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '装订机', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '10.400000154972076', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '标签', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '6.000000089406967', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '6.000000089406967', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '1.600000023841858', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '系固件', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '1.600000023841858', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '3.200000047683716', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '3.200000047683716', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '7.400000110268593', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '美术', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '7.400000110268593', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '5.200000077486038', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '器具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '5.200000077486038', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '信封', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '6.800000101327896', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '用品', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '6.800000101327896', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '收纳具', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '纸张', - '230417170554012': '一级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '296', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '296', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '99', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '99', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '188', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '188', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '153', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '153', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '66', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '66', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '29', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '29', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '120', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '120', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '101', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '101', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '166', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '166', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '20', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '20', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '112', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '112', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '35', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '35', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '197995.36387634277', - '20001': '消费者-销售额', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050025': '197995.36387634277', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '101396.6240234375', - '20001': '小型企业-销售额', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050025': '101396.6240234375', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '179747.14846801758', - '20001': '消费者-销售额', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050025': '179747.14846801758', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '105944.36987304688', - '20001': '小型企业-销售额', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050025': '105944.36987304688', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '10900.540023803711', - '20001': '小型企业-销售额', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050025': '10900.540023803711', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '42906.115478515625', - '20001': '公司-销售额', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050025': '42906.115478515625', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '112905.17056274414', - '20001': '公司-销售额', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050025': '112905.17056274414', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '81048.5207824707', - '20001': '公司-销售额', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050025': '81048.5207824707', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '35407.3722076416', - '20001': '消费者-销售额', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050025': '35407.3722076416', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '23024.637939453125', - '20001': '小型企业-销售额', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050025': '23024.637939453125', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '25287.443954467773', - '20001': '公司-销售额', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050025': '25287.443954467773', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '34162.036560058594', - '20001': '消费者-销售额', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050025': '34162.036560058594', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '10992.8841714859', - '20001': '消费者-利润', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '10992.8841714859', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '16455.964065551758', - '20001': '小型企业-利润', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '16455.964065551758', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '23360.84822796285', - '20001': '消费者-利润', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '23360.84822796285', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '16143.610246658325', - '20001': '小型企业-利润', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '16143.610246658325', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2222.359998703003', - '20001': '小型企业-利润', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '2222.359998703003', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-12973.205139160156', - '20001': '公司-利润', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '-12973.205139160156', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '25661.369792938232', - '20001': '公司-利润', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '25661.369792938232', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '15978.479858398438', - '20001': '公司-利润', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '15978.479858398438', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '6079.052038028836', - '20001': '消费者-利润', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '6079.052038028836', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-13084.58203125', - '20001': '小型企业-利润', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '-13084.58203125', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3445.904010772705', - '20001': '公司-利润', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '3445.904010772705', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-9828.202814102173', - '20001': '消费者-利润', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '-9828.202814102173', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '11.700000174343586', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '11.700000174343586', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '3.200000047683716', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '3.200000047683716', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '4.000000059604645', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '4.000000059604645', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '5.500000081956387', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '5.500000081956387', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '2.0000000298023224', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '2.0000000298023224', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '2.3500000536441803', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '2.3500000536441803', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '3.400000050663948', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '椅子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '3.400000050663948', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '3.200000047683716', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '书架', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '3.200000047683716', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '6.400000095367432', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '6.400000095367432', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '2.6500000953674316', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '2.6500000953674316', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '2.8000000417232513', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '用具', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '2.8000000417232513', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '5.8500001430511475', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '桌子', - '230417170554012': '一级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '5.8500001430511475', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '88', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '88', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '41', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '41', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '122', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '122', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '65', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '65', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '91', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '91', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '84', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '84', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '24', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '24', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '111', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '111', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '98', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '98', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '185', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '185', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '86', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '86', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '43', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '43', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '75709.73181152344', - '20001': '公司-销售额', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050025': '75709.73181152344', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '38359.300354003906', - '20001': '小型企业-销售额', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050025': '38359.300354003906', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '117252.18360900879', - '20001': '消费者-销售额', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050025': '117252.18360900879', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '35585.059997558594', - '20001': '公司-销售额', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050025': '35585.059997558594', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '71932.55941772461', - '20001': '公司-销售额', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050025': '71932.55941772461', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '66796.82772827148', - '20001': '消费者-销售额', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050025': '66796.82772827148', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '19392.099578857422', - '20001': '小型企业-销售额', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050025': '19392.099578857422', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '42179.9285736084', - '20001': '公司-销售额', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050025': '42179.9285736084', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '35355.34843444824', - '20001': '消费者-销售额', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050025': '35355.34843444824', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '202830.06872558594', - '20001': '消费者-销售额', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050025': '202830.06872558594', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '77502.29187011719', - '20001': '小型企业-销售额', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050025': '77502.29187011719', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '14665.44792175293', - '20001': '小型企业-销售额', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050025': '14665.44792175293', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-3248.027666091919', - '20001': '公司-利润', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '-3248.027666091919', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-855.540153503418', - '20001': '小型企业-利润', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '-855.540153503418', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '16409.203687667847', - '20001': '消费者-利润', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '16409.203687667847', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '7314.719917297363', - '20001': '公司-利润', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '7314.719917297363', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '9457.839987754822', - '20001': '公司-利润', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '9457.839987754822', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '9913.84780740738', - '20001': '消费者-利润', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '9913.84780740738', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-3741.9199810028076', - '20001': '小型企业-利润', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '-3741.9199810028076', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-157.75183868408203', - '20001': '公司-利润', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '-157.75183868408203', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '6364.288026988506', - '20001': '消费者-利润', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '6364.288026988506', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '44028.34812831879', - '20001': '消费者-利润', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '44028.34812831879', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '9335.03183555603', - '20001': '小型企业-利润', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '9335.03183555603', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3060.988007545471', - '20001': '小型企业-利润', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '3060.988007545471', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '3.8000000566244125', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '3.8000000566244125', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '2.0000000298023224', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '2.0000000298023224', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '4.000000059604645', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '4.000000059604645', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0.4000000059604645', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '0.4000000059604645', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '5.200000077486038', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '电话', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '5.200000077486038', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '3.200000047683716', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '3.200000047683716', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '2.0000000298023224', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '设备', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '2.0000000298023224', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '3.6000000536441803', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '3.6000000536441803', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '2.8000000417232513', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '2.8000000417232513', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '3.400000050663948', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '3.400000050663948', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '2.400000035762787', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '复印机', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '2.400000035762787', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '2.0000000298023224', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '配件', - '230417170554012': '一级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '2.0000000298023224', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '417', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '417', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '263', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '263', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '293', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '293', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '176', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '176', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '83', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '83', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '148', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '148', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '86', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '86', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '217', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '217', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '50', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '50', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '83', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '83', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '335', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '335', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '156', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '156', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '240', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '240', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '128', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '128', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '92', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '92', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '83', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '83', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '179', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '179', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '105', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '105', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '169', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '169', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '165', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '165', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '212', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '212', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '224', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '224', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '176', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '176', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '49', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '49', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '71', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '71', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '369', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '369', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '128', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '128', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '43073.57579040527', - '20001': '消费者-销售额', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050025': '43073.57579040527', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '11909.659952163696', - '20001': '消费者-销售额', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050025': '11909.659952163696', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '35704.45209121704', - '20001': '消费者-销售额', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050025': '35704.45209121704', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '21331.239906311035', - '20001': '公司-销售额', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050025': '21331.239906311035', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '4695.571964263916', - '20001': '小型企业-销售额', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050025': '4695.571964263916', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '6804.840015411377', - '20001': '公司-销售额', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050025': '6804.840015411377', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '9009.503952026367', - '20001': '小型企业-销售额', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050025': '9009.503952026367', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '20872.37590789795', - '20001': '公司-销售额', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050025': '20872.37590789795', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '4738.440048217773', - '20001': '小型企业-销售额', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050025': '4738.440048217773', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '33401.6201171875', - '20001': '小型企业-销售额', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050025': '33401.6201171875', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '41139.42037963867', - '20001': '消费者-销售额', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050025': '41139.42037963867', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '16658.068145751953', - '20001': '公司-销售额', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050025': '16658.068145751953', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '242020.66117858887', - '20001': '消费者-销售额', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050025': '242020.66117858887', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '6962.283996582031', - '20001': '公司-销售额', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050025': '6962.283996582031', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '4169.62003326416', - '20001': '小型企业-销售额', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050025': '4169.62003326416', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '11624.283912658691', - '20001': '小型企业-销售额', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050025': '11624.283912658691', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '16762.956071853638', - '20001': '消费者-销售额', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050025': '16762.956071853638', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '7673.987900733948', - '20001': '小型企业-销售额', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050025': '7673.987900733948', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '149258.9285888672', - '20001': '公司-销售额', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050025': '149258.9285888672', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '17512.03998565674', - '20001': '公司-销售额', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050025': '17512.03998565674', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '11419.351974487305', - '20001': '消费者-销售额', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050025': '11419.351974487305', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '26838.559944152832', - '20001': '消费者-销售额', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050025': '26838.559944152832', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '86930.89972686768', - '20001': '公司-销售额', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050025': '86930.89972686768', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '5875.65998840332', - '20001': '小型企业-销售额', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050025': '5875.65998840332', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '84072.77294921875', - '20001': '小型企业-销售额', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050025': '84072.77294921875', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '159877.2002105713', - '20001': '消费者-销售额', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050025': '159877.2002105713', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '17843.335968017578', - '20001': '公司-销售额', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050025': '17843.335968017578', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '4541.515904426575', - '20001': '消费者-利润', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '4541.515904426575', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3427.6200039982796', - '20001': '消费者-利润', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '3427.6200039982796', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '5376.532042503357', - '20001': '消费者-利润', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '5376.532042503357', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '5056.240030765533', - '20001': '公司-利润', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '5056.240030765533', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '706.2720084190369', - '20001': '小型企业-利润', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '706.2720084190369', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1806.9799857139587', - '20001': '公司-利润', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1806.9799857139587', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '703.1639966964722', - '20001': '小型企业-利润', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '703.1639966964722', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '4718.196072459221', - '20001': '公司-利润', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '4718.196072459221', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1170.8199974298477', - '20001': '小型企业-利润', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1170.8199974298477', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '8579.199966430664', - '20001': '小型企业-利润', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '8579.199966430664', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '9876.580034255981', - '20001': '消费者-利润', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '9876.580034255981', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-805.3919949531555', - '20001': '公司-利润', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-805.3919949531555', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '10364.060329437256', - '20001': '消费者-利润', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '10364.060329437256', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '691.9640173912048', - '20001': '公司-利润', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '691.9640173912048', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '886.8999857902527', - '20001': '小型企业-利润', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '886.8999857902527', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1411.8440232276917', - '20001': '小型企业-利润', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1411.8440232276917', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-2929.724006652832', - '20001': '消费者-利润', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-2929.724006652832', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '739.9279955923557', - '20001': '小型企业-利润', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '739.9279955923557', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '10418.127985686064', - '20001': '公司-利润', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '10418.127985686064', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '4099.7600264549255', - '20001': '公司-利润', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '4099.7600264549255', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '874.4119651317596', - '20001': '消费者-利润', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '874.4119651317596', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '6648.460058093071', - '20001': '消费者-利润', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '6648.460058093071', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '26416.879835128784', - '20001': '公司-利润', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '26416.879835128784', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1195.7400109767914', - '20001': '小型企业-利润', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1195.7400109767914', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '16123.491836547852', - '20001': '小型企业-利润', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '16123.491836547852', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '44030.980217933655', - '20001': '消费者-利润', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '44030.980217933655', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3856.6360173225403', - '20001': '公司-利润', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '3856.6360173225403', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '12.400000184774399', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '12.400000184774399', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '8.400000125169754', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '8.400000125169754', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '2.8000000417232513', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '2.8000000417232513', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '3.8000000566244125', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '3.8000000566244125', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '8.00000011920929', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '8.00000011920929', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '11.800000175833702', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '11.800000175833702', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '6.400000095367432', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '6.400000095367432', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '4.400000065565109', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '4.400000065565109', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '标签', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '1.600000023841858', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '1.600000023841858', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '19.60000029206276', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '美术', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '19.60000029206276', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '4.800000071525574', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '装订机', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '4.800000071525574', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '5.200000077486038', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '5.200000077486038', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '11.200000166893005', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '系固件', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '11.200000166893005', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '信封', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '纸张', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0.800000011920929', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '器具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0.800000011920929', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '收纳具', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '2.8000000417232513', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '用品', - '230417170554012': '二级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '2.8000000417232513', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '88', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '88', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '222', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '222', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '77', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '77', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '321', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '321', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '107', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '107', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '162', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '162', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '268', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '268', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '200', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '200', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '60', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '60', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '17', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '17', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '53', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '53', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '127', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '127', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '18824.287895202637', - '20001': '小型企业-销售额', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050025': '18824.287895202637', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '40977.49607849121', - '20001': '消费者-销售额', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050025': '40977.49607849121', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '73614.63159179688', - '20001': '小型企业-销售额', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050025': '73614.63159179688', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '197062.027633667', - '20001': '消费者-销售额', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050025': '197062.027633667', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '77260.68083190918', - '20001': '小型企业-销售额', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050025': '77260.68083190918', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '162280.46755981445', - '20001': '公司-销售额', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050025': '162280.46755981445', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '263829.8865661621', - '20001': '消费者-销售额', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050025': '263829.8865661621', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '147960.97384643555', - '20001': '公司-销售额', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050025': '147960.97384643555', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '82572.02819824219', - '20001': '公司-销售额', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050025': '82572.02819824219', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '28338.303100585938', - '20001': '小型企业-销售额', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050025': '28338.303100585938', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '70506.12826538086', - '20001': '消费者-销售额', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050025': '70506.12826538086', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '27252.932106018066', - '20001': '公司-销售额', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050025': '27252.932106018066', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3390.6879682540894', - '20001': '小型企业-利润', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '3390.6879682540894', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '8553.636081695557', - '20001': '消费者-利润', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '8553.636081695557', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '4722.45210647583', - '20001': '小型企业-利润', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '4722.45210647583', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '23493.386373519897', - '20001': '消费者-利润', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '23493.386373519897', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '15420.8597240448', - '20001': '小型企业-利润', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '15420.8597240448', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '27781.627968542278', - '20001': '公司-利润', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '27781.627968542278', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '49081.507762908936', - '20001': '消费者-利润', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '49081.507762908936', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '33925.37383937836', - '20001': '公司-利润', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '33925.37383937836', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-12417.552001953125', - '20001': '公司-利润', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '-12417.552001953125', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '4524.723007202148', - '20001': '小型企业-利润', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '4524.723007202148', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-7242.17204284668', - '20001': '消费者-利润', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '-7242.17204284668', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '7276.75213766098', - '20001': '公司-利润', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '7276.75213766098', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '2.400000035762787', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '2.400000035762787', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '6.800000101327896', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '6.800000101327896', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '2.8000000417232513', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '2.8000000417232513', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '12.700000189244747', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '12.700000189244747', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '3.7000000551342964', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '3.7000000551342964', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '5.600000083446503', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '5.600000083446503', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '5.200000077486038', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '书架', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '5.200000077486038', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '8.600000128149986', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '椅子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '8.600000128149986', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '6.200000137090683', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '6.200000137090683', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '1.4000000059604645', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '1.4000000059604645', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '6.050000160932541', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '桌子', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '6.050000160932541', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '3.6000000536441803', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '用具', - '230417170554012': '二级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '3.6000000536441803', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '59', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '59', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '60', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '60', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '188', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '188', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '86', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '86', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '187', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '187', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '273', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '273', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '288', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '288', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '78', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '78', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '94', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '94', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '263', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '263', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '141', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '141', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '68', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '68', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '39280.19201660156', - '20001': '公司-销售额', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050025': '39280.19201660156', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '44899.791931152344', - '20001': '小型企业-销售额', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050025': '44899.791931152344', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '172164.10418701172', - '20001': '公司-销售额', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050025': '172164.10418701172', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '62519.015716552734', - '20001': '小型企业-销售额', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050025': '62519.015716552734', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '116980.13571166992', - '20001': '公司-销售额', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050025': '116980.13571166992', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '230886.04147338867', - '20001': '消费者-销售额', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050025': '230886.04147338867', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '87725.06452941895', - '20001': '消费者-销售额', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050025': '87725.06452941895', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '33069.8757019043', - '20001': '小型企业-销售额', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050025': '33069.8757019043', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '28236.152297973633', - '20001': '公司-销售额', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050025': '28236.152297973633', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '238193.7882080078', - '20001': '消费者-销售额', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050025': '238193.7882080078', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '113800.4001159668', - '20001': '消费者-销售额', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050025': '113800.4001159668', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '42361.983489990234', - '20001': '小型企业-销售额', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050025': '42361.983489990234', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1581.1320900917053', - '20001': '公司-利润', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '1581.1320900917053', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3464.4119186401367', - '20001': '小型企业-利润', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '3464.4119186401367', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '19382.52392578125', - '20001': '公司-利润', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '19382.52392578125', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '8931.635836213827', - '20001': '小型企业-利润', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '8931.635836213827', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-356.6640434265137', - '20001': '公司-利润', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '-356.6640434265137', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '35637.280425071716', - '20001': '消费者-利润', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '35637.280425071716', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '13350.343992233276', - '20001': '消费者-利润', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '13350.343992233276', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '7639.016065597534', - '20001': '小型企业-利润', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '7639.016065597534', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3924.5919317901134', - '20001': '公司-利润', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '3924.5919317901134', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '31144.84789276123', - '20001': '消费者-利润', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '31144.84789276123', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '13104.979837417603', - '20001': '消费者-利润', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '13104.979837417603', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '9586.584241390228', - '20001': '小型企业-利润', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '9586.584241390228', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '1.600000023841858', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '1.600000023841858', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '2.8000000417232513', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '2.8000000417232513', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '6.400000095367432', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '6.400000095367432', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '2.8000000417232513', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '2.8000000417232513', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '8.00000011920929', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '8.00000011920929', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '7.200000107288361', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '电话', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '7.200000107288361', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '8.800000131130219', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '8.800000131130219', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0.800000011920929', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '0.800000011920929', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '4.800000071525574', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '配件', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '4.800000071525574', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '7.600000113248825', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '复印机', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '7.600000113248825', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '3.200000047683716', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '3.200000047683716', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '1.600000023841858', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '设备', - '230417170554012': '二级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '1.600000023841858', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '55', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '55', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '46', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '46', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '17', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '17', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '28', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '28', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '13', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '13', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '46', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '46', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '12', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '12', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '59', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '59', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '35', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '35', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '36', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '36', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '70', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '70', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '103', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '103', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '47', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '47', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '3', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '3', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '75', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '75', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '34', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '34', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '59', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '59', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '37', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '37', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '35', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '35', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '38', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '38', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '17', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '17', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '24', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '24', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '27', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '27', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '29', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '29', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '36', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '36', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '16', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '16', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '47', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '47', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '9021.879867553711', - '20001': '消费者-销售额', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050025': '9021.879867553711', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '20378.820114135742', - '20001': '小型企业-销售额', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050025': '20378.820114135742', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '2002.2799987792969', - '20001': '公司-销售额', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050025': '2002.2799987792969', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '1350.8599853515625', - '20001': '公司-销售额', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050025': '1350.8599853515625', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '1758.3999633789062', - '20001': '小型企业-销售额', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050025': '1758.3999633789062', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '47296.4521484375', - '20001': '消费者-销售额', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050025': '47296.4521484375', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '1152.2279968261719', - '20001': '小型企业-销售额', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050025': '1152.2279968261719', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '7089.3759689331055', - '20001': '消费者-销售额', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050025': '7089.3759689331055', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '2035.5439376831055', - '20001': '小型企业-销售额', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050025': '2035.5439376831055', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '1935.0800018310547', - '20001': '消费者-销售额', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050025': '1935.0800018310547', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '6443.667964935303', - '20001': '消费者-销售额', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050025': '6443.667964935303', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '8948.267951965332', - '20001': '公司-销售额', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050025': '8948.267951965332', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '5997.180000305176', - '20001': '公司-销售额', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050025': '5997.180000305176', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '280.6999969482422', - '20001': '小型企业-销售额', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050025': '280.6999969482422', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '8398.040027618408', - '20001': '消费者-销售额', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050025': '8398.040027618408', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '10395.98013305664', - '20001': '公司-销售额', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050025': '10395.98013305664', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '17214.820014953613', - '20001': '消费者-销售额', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050025': '17214.820014953613', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '45736.20748901367', - '20001': '公司-销售额', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050025': '45736.20748901367', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '31122.839965820312', - '20001': '小型企业-销售额', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050025': '31122.839965820312', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '4758.459899902344', - '20001': '公司-销售额', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050025': '4758.459899902344', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '1278.8720092773438', - '20001': '消费者-销售额', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050025': '1278.8720092773438', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '4090.3799896240234', - '20001': '小型企业-销售额', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050025': '4090.3799896240234', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '1282.2600212097168', - '20001': '小型企业-销售额', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050025': '1282.2600212097168', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '1917.0199966430664', - '20001': '公司-销售额', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050025': '1917.0199966430664', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '2483.740026473999', - '20001': '消费者-销售额', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050025': '2483.740026473999', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '1370.0400123596191', - '20001': '小型企业-销售额', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050025': '1370.0400123596191', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '5272.7919845581055', - '20001': '公司-销售额', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050025': '5272.7919845581055', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3114.8600368499756', - '20001': '消费者-利润', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '3114.8600368499756', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3735.4799880981445', - '20001': '小型企业-利润', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '3735.4799880981445', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '548.3800106048584', - '20001': '公司-利润', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '548.3800106048584', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '228.47999501228333', - '20001': '公司-利润', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '228.47999501228333', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '306.0399932861328', - '20001': '小型企业-利润', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '306.0399932861328', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2032.4922561645508', - '20001': '消费者-利润', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '2032.4922561645508', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '100.12800216674805', - '20001': '小型企业-利润', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '100.12800216674805', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1067.8359928131104', - '20001': '消费者-利润', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1067.8359928131104', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '405.10399055480957', - '20001': '小型企业-利润', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '405.10399055480957', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '509.7399959564209', - '20001': '消费者-利润', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '509.7399959564209', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1033.9279907345772', - '20001': '消费者-利润', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1033.9279907345772', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1241.687994003296', - '20001': '公司-利润', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1241.687994003296', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '33.04001235961914', - '20001': '公司-利润', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '33.04001235961914', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '73.08000373840332', - '20001': '小型企业-利润', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '73.08000373840332', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2527.420003890991', - '20001': '消费者-利润', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '2527.420003890991', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2462.879997253418', - '20001': '公司-利润', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '2462.879997253418', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3464.9999833106995', - '20001': '消费者-利润', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '3464.9999833106995', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '6198.247783660889', - '20001': '公司-利润', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '6198.247783660889', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '7363.020133972168', - '20001': '小型企业-利润', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '7363.020133972168', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1110.7600073814392', - '20001': '公司-利润', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '1110.7600073814392', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-66.52799224853516', - '20001': '消费者-利润', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-66.52799224853516', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '972.7199816703796', - '20001': '小型企业-利润', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '972.7199816703796', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '285.4599941968918', - '20001': '小型企业-利润', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '285.4599941968918', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '669.1999979019165', - '20001': '公司-利润', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '669.1999979019165', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '621.1800022125244', - '20001': '消费者-利润', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '621.1800022125244', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '409.64000511169434', - '20001': '小型企业-利润', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '409.64000511169434', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-56.30801785737276', - '20001': '公司-利润', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-56.30801785737276', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '2.400000035762787', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '2.400000035762787', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0.800000011920929', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0.800000011920929', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '2.400000035762787', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '2.400000035762787', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '1.2000000178813934', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '1.2000000178813934', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '2.0000000298023224', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '2.0000000298023224', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '3.200000047683716', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '3.200000047683716', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '2.600000038743019', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '2.600000038743019', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '纸张', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '收纳具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '1.2000000178813934', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '1.2000000178813934', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '器具', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '信封', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '1.4000000208616257', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '美术', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '1.4000000208616257', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '标签', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0.4000000059604645', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '系固件', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0.4000000059604645', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '装订机', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '2.0000000298023224', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '用品', - '230417170554012': '当日', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '2.0000000298023224', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '7', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '7', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '5', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '5', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '38', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '38', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '48', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '48', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '12', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '12', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '29', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '29', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '69', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '69', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '11', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '11', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '32', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '32', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '121', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '121', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '13', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '13', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '50', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '50', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '7150.18505859375', - '20001': '小型企业-销售额', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050025': '7150.18505859375', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '7867.64990234375', - '20001': '消费者-销售额', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050025': '7867.64990234375', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '36149.624267578125', - '20001': '公司-销售额', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050025': '36149.624267578125', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '29512.85369873047', - '20001': '公司-销售额', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050025': '29512.85369873047', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '23194.185302734375', - '20001': '公司-销售额', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050025': '23194.185302734375', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '4982.431945800781', - '20001': '小型企业-销售额', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050025': '4982.431945800781', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '13384.28012084961', - '20001': '消费者-销售额', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050025': '13384.28012084961', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '9390.44384765625', - '20001': '小型企业-销售额', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050025': '9390.44384765625', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '8680.22396850586', - '20001': '公司-销售额', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050025': '8680.22396850586', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '66037.07626342773', - '20001': '消费者-销售额', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050025': '66037.07626342773', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '4909.93994140625', - '20001': '小型企业-销售额', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050025': '4909.93994140625', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '53496.799743652344', - '20001': '消费者-销售额', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050025': '53496.799743652344', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1801.2049560546875', - '20001': '小型企业-利润', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '1801.2049560546875', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-419.6499938964844', - '20001': '消费者-利润', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '-419.6499938964844', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '10536.90396118164', - '20001': '公司-利润', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '10536.90396118164', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3562.593894958496', - '20001': '公司-利润', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '3562.593894958496', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-2721.07499755919', - '20001': '公司-利润', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '-2721.07499755919', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '351.6520404815674', - '20001': '小型企业-利润', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '351.6520404815674', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1812.1600317955017', - '20001': '消费者-利润', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '1812.1600317955017', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1516.8440246582031', - '20001': '小型企业-利润', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '1516.8440246582031', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '776.8039779663086', - '20001': '公司-利润', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '776.8039779663086', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '7662.256109684706', - '20001': '消费者-利润', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '7662.256109684706', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '884.5199966430664', - '20001': '小型企业-利润', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '884.5199966430664', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '13153.140007019043', - '20001': '消费者-利润', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '13153.140007019043', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0.5', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '0.5', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0.25', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '0.25', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0.800000011920929', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '0.800000011920929', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '1.0000000149011612', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '1.0000000149011612', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '1.100000023841858', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '桌子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '1.100000023841858', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '1.600000023841858', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '1.600000023841858', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '2.400000035762787', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '2.400000035762787', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0.4000000059604645', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '0.4000000059604645', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '1.2000000178813934', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '用具', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '1.2000000178813934', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '4.400000065565109', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '4.400000065565109', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '椅子', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '1.600000023841858', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '书架', - '230417170554012': '当日', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '1.600000023841858', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '35', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '35', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '42', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '42', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '8', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '8', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '43', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '43', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '18', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '18', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '10', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '10', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '25', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '25', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '7', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '7', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '47', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '47', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '45', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '45', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '26', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '26', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '55', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '55', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '23162.160369873047', - '20001': '消费者-销售额', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050025': '23162.160369873047', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '35653.800231933594', - '20001': '消费者-销售额', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050025': '35653.800231933594', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '2751.4200439453125', - '20001': '小型企业-销售额', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050025': '2751.4200439453125', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '59494.98889160156', - '20001': '公司-销售额', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050025': '59494.98889160156', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '12909.62387084961', - '20001': '消费者-销售额', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050025': '12909.62387084961', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '9444.119995117188', - '20001': '小型企业-销售额', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050025': '9444.119995117188', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '20426.41943359375', - '20001': '公司-销售额', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050025': '20426.41943359375', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '4965.659912109375', - '20001': '小型企业-销售额', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050025': '4965.659912109375', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '17422.103744506836', - '20001': '公司-销售额', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050025': '17422.103744506836', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '46673.759704589844', - '20001': '公司-销售额', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050025': '46673.759704589844', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '42760.984619140625', - '20001': '小型企业-销售额', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050025': '42760.984619140625', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '36058.00817871094', - '20001': '消费者-销售额', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050025': '36058.00817871094', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3123.960006713867', - '20001': '消费者-利润', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '3123.960006713867', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '5008.080015182495', - '20001': '消费者-利润', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '5008.080015182495', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '269.3600025177002', - '20001': '小型企业-利润', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '269.3600025177002', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '19104.14761352539', - '20001': '公司-利润', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '19104.14761352539', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '1354.0241241455078', - '20001': '消费者-利润', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '1354.0241241455078', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2245.4600219726562', - '20001': '小型企业-利润', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '2245.4600219726562', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2964.919906616211', - '20001': '公司-利润', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '2964.919906616211', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-1457.5400142669678', - '20001': '小型企业-利润', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '-1457.5400142669678', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2795.7440314292908', - '20001': '公司-利润', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '2795.7440314292908', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '9753.660041809082', - '20001': '公司-利润', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '9753.660041809082', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '4369.204010009766', - '20001': '小型企业-利润', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '4369.204010009766', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '5532.967905521393', - '20001': '消费者-利润', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '5532.967905521393', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '1.600000023841858', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '1.600000023841858', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '1.2000000178813934', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '1.2000000178813934', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '1.2000000178813934', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '1.2000000178813934', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '1.2000000178813934', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '1.2000000178813934', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0.4000000059604645', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '0.4000000059604645', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0.4000000059604645', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '设备', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '0.4000000059604645', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '1.600000023841858', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '配件', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '1.600000023841858', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0.800000011920929', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '复印机', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '0.800000011920929', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0.4000000059604645', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '0.4000000059604645', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '2.0000000298023224', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '电话', - '230417170554012': '当日', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '2.0000000298023224', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '320', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '320', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '1010', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '1010', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '267', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '267', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '209', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '209', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '555', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '555', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '250', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '250', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '204', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '204', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '551', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '551', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '250', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '250', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '197', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '197', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '660', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '660', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '308', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '308', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '395', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '395', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '679', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '679', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '751', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '751', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '241', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '241', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '652', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '652', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '384', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '384', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '503', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '503', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '427', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '427', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '434', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '434', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '842', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '842', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '350', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '350', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '402', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '402', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '389', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '389', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '651', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '651', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '620', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713183656009': '620', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '42921.76001739502', - '20001': '公司-销售额', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050025': '42921.76001739502', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '84661.58401679993', - '20001': '消费者-销售额', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050025': '84661.58401679993', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '15785.643997192383', - '20001': '小型企业-销售额', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050025': '15785.643997192383', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '21581.027881622314', - '20001': '小型企业-销售额', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050025': '21581.027881622314', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '72606.23949432373', - '20001': '消费者-销售额', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050025': '72606.23949432373', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '30409.679874420166', - '20001': '小型企业-销售额', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050025': '30409.679874420166', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '27510.196060180664', - '20001': '小型企业-销售额', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050025': '27510.196060180664', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '46882.4719581604', - '20001': '公司-销售额', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050025': '46882.4719581604', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '11755.520034790039', - '20001': '小型企业-销售额', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050025': '11755.520034790039', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '193476.78018188477', - '20001': '小型企业-销售额', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050025': '193476.78018188477', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '38475.583921432495', - '20001': '消费者-销售额', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050025': '38475.583921432495', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '26525.12812614441', - '20001': '小型企业-销售额', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050025': '26525.12812614441', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '21229.740116119385', - '20001': '公司-销售额', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050025': '21229.740116119385', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '85568.64414596558', - '20001': '消费者-销售额', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050025': '85568.64414596558', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '103927.45993041992', - '20001': '消费者-销售额', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050025': '103927.45993041992', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '30325.540008544922', - '20001': '小型企业-销售额', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050025': '30325.540008544922', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '59225.235874176025', - '20001': '消费者-销售额', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050025': '59225.235874176025', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '37891.83991146088', - '20001': '公司-销售额', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050025': '37891.83991146088', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '206799.3208580017', - '20001': '公司-销售额', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050025': '206799.3208580017', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '55396.403953552246', - '20001': '公司-销售额', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050025': '55396.403953552246', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '53721.780155181885', - '20001': '公司-销售额', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050025': '53721.780155181885', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '325794.56090927124', - '20001': '消费者-销售额', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050025': '325794.56090927124', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '15698.620056152344', - '20001': '公司-销售额', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050025': '15698.620056152344', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '416654.139755249', - '20001': '公司-销售额', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050025': '416654.139755249', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '133567.42085266113', - '20001': '小型企业-销售额', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050025': '133567.42085266113', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '674093.7589492798', - '20001': '消费者-销售额', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050025': '674093.7589492798', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '28803.74006843567', - '20001': '消费者-销售额', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050025': '28803.74006843567', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '10810.37999534607', - '20001': '公司-利润', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '10810.37999534607', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '10444.92397108674', - '20001': '消费者-利润', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '10444.92397108674', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2551.584007501602', - '20001': '小型企业-利润', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '2551.584007501602', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-1599.191946864128', - '20001': '小型企业-利润', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-1599.191946864128', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '15632.399949550629', - '20001': '消费者-利润', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '15632.399949550629', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '7237.580014765263', - '20001': '小型企业-利润', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '7237.580014765263', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3538.1360330581665', - '20001': '小型企业-利润', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '3538.1360330581665', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '5785.191917344928', - '20001': '公司-利润', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '5785.191917344928', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3054.8000045120716', - '20001': '小型企业-利润', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '3054.8000045120716', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '13981.519672393799', - '20001': '小型企业-利润', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '13981.519672393799', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '6097.644009143114', - '20001': '消费者-利润', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '6097.644009143114', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '5757.667976498604', - '20001': '小型企业-利润', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '5757.667976498604', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '2400.0200235694647', - '20001': '公司-利润', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '2400.0200235694647', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '10613.904058605433', - '20001': '消费者-利润', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '10613.904058605433', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '26892.46014380455', - '20001': '消费者-利润', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '26892.46014380455', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '7200.620007514954', - '20001': '小型企业-利润', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '7200.620007514954', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-8106.503877401352', - '20001': '消费者-利润', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-8106.503877401352', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-2731.260007582605', - '20001': '公司-利润', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '-2731.260007582605', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '58109.099750995636', - '20001': '公司-利润', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '58109.099750995636', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '9477.103976607323', - '20001': '公司-利润', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '9477.103976607323', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '13291.740061283112', - '20001': '公司-利润', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '13291.740061283112', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '88785.20024251938', - '20001': '消费者-利润', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '88785.20024251938', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '3794.5600115656853', - '20001': '公司-利润', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '3794.5600115656853', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '42286.44082207978', - '20001': '公司-利润', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '42286.44082207978', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '39437.43984031677', - '20001': '小型企业-利润', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '39437.43984031677', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '71910.49672435224', - '20001': '消费者-利润', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '71910.49672435224', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '6660.640026181936', - '20001': '消费者-利润', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230713152555009': '6660.640026181936', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '32.40000048279762', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '32.40000048279762', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '6.000000089406967', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '6.000000089406967', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '16.400000244379044', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '16.400000244379044', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '5.600000083446503', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '5.600000083446503', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '20.40000030398369', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '20.40000030398369', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '6.000000089406967', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '6.000000089406967', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '21.600000321865082', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '21.600000321865082', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '11.60000017285347', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '装订机', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '11.60000017285347', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '17.200000256299973', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '系固件', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '17.200000256299973', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '22.40000033378601', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '22.40000033378601', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '纸张', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '50.20000074803829', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '50.20000074803829', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '27.000000402331352', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '美术', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '27.000000402331352', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '10.400000154972076', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '用品', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '10.400000154972076', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '信封', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '12.800000190734863', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '12.800000190734863', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '收纳具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '22.000000327825546', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '器具', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '22.000000327825546', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '0', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '标签', - '230417170554012': '标准级', - '230417171050028': '办公用品', - '230417171050031': '中国', - '230707112948009': '0', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '328', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '328', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '41', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '41', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '226', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '226', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '875', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '875', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '453', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '453', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '292', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '292', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '779', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '779', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '365', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '365', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '662', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '662', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '115', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '115', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '590', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '590', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '243', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713183656009': '243', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '186468.53421020508', - '20001': '小型企业-销售额', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050025': '186468.53421020508', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '59952.5986328125', - '20001': '小型企业-销售额', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050025': '59952.5986328125', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '308974.68658447266', - '20001': '消费者-销售额', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050025': '308974.68658447266', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '532094.8652648926', - '20001': '消费者-销售额', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050025': '532094.8652648926', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '445273.7243347168', - '20001': '公司-销售额', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050025': '445273.7243347168', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '274417.24798583984', - '20001': '小型企业-销售额', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050025': '274417.24798583984', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '160613.51583480835', - '20001': '消费者-销售额', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050025': '160613.51583480835', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '77952.50384902954', - '20001': '公司-销售额', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050025': '77952.50384902954', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '626558.0955200195', - '20001': '消费者-销售额', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050025': '626558.0955200195', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '173361.87481689453', - '20001': '公司-销售额', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050025': '173361.87481689453', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '427284.1153869629', - '20001': '公司-销售额', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050025': '427284.1153869629', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '55428.184089660645', - '20001': '小型企业-销售额', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050025': '55428.184089660645', - '230417171050028': '家具', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '30019.23391342163', - '20001': '小型企业-利润', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '30019.23391342163', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-10434.920913696289', - '20001': '小型企业-利润', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '-10434.920913696289', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-51201.35306598246', - '20001': '消费者-利润', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '-51201.35306598246', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '87338.38448595256', - '20001': '消费者-利润', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '87338.38448595256', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '64893.30401271582', - '20001': '公司-利润', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '64893.30401271582', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '38538.10804748535', - '20001': '小型企业-利润', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '38538.10804748535', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '26644.155975095928', - '20001': '消费者-利润', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '26644.155975095928', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '13682.983975410461', - '20001': '公司-利润', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '13682.983975410461', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '95117.67989848554', - '20001': '消费者-利润', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '95117.67989848554', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '-19408.886026382446', - '20001': '公司-利润', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '-19408.886026382446', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '70732.25565767288', - '20001': '公司-利润', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '70732.25565767288', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '10931.563991039991', - '20001': '小型企业-利润', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230713152555009': '10931.563991039991', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '13.90000020712614', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '13.90000020712614', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '4.500000089406967', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '4.500000089406967', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '25.70000058412552', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '25.70000058412552', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '34.00000050663948', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '34.00000050663948', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '14.000000208616257', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '14.000000208616257', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '8.00000011920929', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '8.00000011920929', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '19.200000286102295', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '19.200000286102295', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '9.600000143051147', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '9.600000143051147', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '22.40000033378601', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '书架', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '22.40000033378601', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '10.250000208616257', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '桌子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '10.250000208616257', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '23.000000342726707', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '椅子', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '23.000000342726707', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '7.200000107288361', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '用具', - '230417170554012': '标准级', - '230417171050028': '家具', - '230417171050031': '中国', - '230707112948009': '7.200000107288361', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '560', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '560', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '407', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '407', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '607', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '607', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '596', - '10003': '230713183656009', - '20001': '消费者-数量', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '596', - '230717170834024': '消费者' - }, - { - '10001': '数量', - '10002': '200', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '200', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '247', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '247', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '446', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '446', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '440', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '440', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '220', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '220', - '230717170834024': '小型企业' - }, - { - '10001': '数量', - '10002': '182', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '182', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '392', - '10003': '230713183656009', - '20001': '公司-数量', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '392', - '230717170834024': '公司' - }, - { - '10001': '数量', - '10002': '161', - '10003': '230713183656009', - '20001': '小型企业-数量', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713183656009': '161', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '505443.34341430664', - '20001': '消费者-销售额', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050025': '505443.34341430664', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '258049.79263305664', - '20001': '消费者-销售额', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050025': '258049.79263305664', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '487158.869140625', - '20001': '消费者-销售额', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050025': '487158.869140625', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '241553.1145477295', - '20001': '消费者-销售额', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050025': '241553.1145477295', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '消费者' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '159403.32949829102', - '20001': '小型企业-销售额', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050025': '159403.32949829102', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '115258.50002288818', - '20001': '小型企业-销售额', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050025': '115258.50002288818', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '376848.0517883301', - '20001': '公司-销售额', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050025': '376848.0517883301', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '162026.90100097656', - '20001': '公司-销售额', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050025': '162026.90100097656', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '211519.5308227539', - '20001': '小型企业-销售额', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050025': '211519.5308227539', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '128149.98031616211', - '20001': '公司-销售额', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050025': '128149.98031616211', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '371464.54568481445', - '20001': '公司-销售额', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050025': '371464.54568481445', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '公司' - }, - { - '10001': '销售额', - '10003': '230417171050025', - '10011': '132747.10388183594', - '20001': '小型企业-销售额', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050025': '132747.10388183594', - '230417171050028': '技术', - '230417171050031': '中国', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '72135.64385959506', - '20001': '消费者-利润', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '72135.64385959506', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '54895.65243625641', - '20001': '消费者-利润', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '54895.65243625641', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '43484.72810983658', - '20001': '消费者-利润', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '43484.72810983658', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '30725.576243638992', - '20001': '消费者-利润', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '30725.576243638992', - '230717170834024': '消费者' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '30714.348217010498', - '20001': '小型企业-利润', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '30714.348217010498', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '28825.859987705946', - '20001': '小型企业-利润', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '28825.859987705946', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '50920.491817474365', - '20001': '公司-利润', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '50920.491817474365', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '30883.43991202116', - '20001': '公司-利润', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '30883.43991202116', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '13373.331939697266', - '20001': '小型企业-利润', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '13373.331939697266', - '230717170834024': '小型企业' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '23808.679921150208', - '20001': '公司-利润', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '23808.679921150208', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '46273.94783782959', - '20001': '公司-利润', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '46273.94783782959', - '230717170834024': '公司' - }, - { - '10001': '利润', - '10003': '230713152555009', - '10012': '24785.544352531433', - '20001': '小型企业-利润', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230713152555009': '24785.544352531433', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '20.60000030696392', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '20.60000030696392', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '12.000000178813934', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '12.000000178813934', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '25.200000375509262', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '25.200000375509262', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '24.400000363588333', - '10003': '230707112948009', - '20001': '消费者-折扣', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '24.400000363588333', - '230717170834024': '消费者' - }, - { - '10001': '折扣', - '10002': '4.400000065565109', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '4.400000065565109', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '4.400000065565109', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '4.400000065565109', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '15.600000232458115', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '电话', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '15.600000232458115', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '14.400000214576721', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '配件', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '14.400000214576721', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '8.200000122189522', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '8.200000122189522', - '230717170834024': '小型企业' - }, - { - '10001': '折扣', - '10002': '6.400000095367432', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '6.400000095367432', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '10.600000157952309', - '10003': '230707112948009', - '20001': '公司-折扣', - '230417170554008': '复印机', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '10.600000157952309', - '230717170834024': '公司' - }, - { - '10001': '折扣', - '10002': '3.200000047683716', - '10003': '230707112948009', - '20001': '小型企业-折扣', - '230417170554008': '设备', - '230417170554012': '标准级', - '230417171050028': '技术', - '230417171050031': '中国', - '230707112948009': '3.200000047683716', - '230717170834024': '小型企业' - } - ]; - const option: VTable.PivotTableConstructorOptions = { - // renderChartAsync:true, - renderChartAsyncBatchCount: 50, - columnTree, - rowTree, - rows, - columns, - indicators, - indicatorsAsCol: false, - container: document.getElementById(CONTAINER_ID), - records, - defaultRowHeight: 50, - defaultHeaderRowHeight: 50, - defaultColWidth: 280, - defaultHeaderColWidth: 100, - indicatorTitle: '指标', - corner: { - titleOnDimension: 'row', - headerStyle: { - autoWrapText: true - } - }, - theme: VTable.themes.ARCO.extends({ - selectionStyle: { - cellBgColor: '' - } - }), - legends: [ - { - data: [ - { - label: '公司-数量', - shape: { - fill: '#2E62F1', - symbolType: 'circle' - } - }, - { - label: '小型企业-数量', - shape: { - fill: '#4DC36A', - symbolType: 'square' - } - }, - { - label: '消费者-数量', - shape: { - fill: '#FF8406', - symbolType: 'circle' - } - } - ], - orient: 'bottom', - position: 'start', - maxRow: 1, - padding: [50, 0, 0, 0] - }, - { - data: [ - { - label: '公司-销售额', - shape: { - fill: '#FFCC00', - symbolType: 'circle' - } - }, - { - label: '小型企业-销售额', - shape: { - fill: '#4F44CF', - symbolType: 'circle' - } - }, - { - label: '消费者-销售额', - shape: { - fill: '#5AC8FA', - symbolType: 'circle' - } - }, - { - label: '公司-利润', - shape: { - fill: '#003A8C', - symbolType: 'circle' - } - }, - { - label: '小型企业-利润', - shape: { - fill: '#B08AE2', - symbolType: 'circle' - } - }, - { - label: '消费者-利润', - shape: { - fill: '#FF6341', - symbolType: 'circle' - } - } - ], - orient: 'top', - position: 'start', - maxRow: 1, - padding: [10, 0, 0, 30] - }, - { - data: [ - { - label: '公司-折扣', - shape: { - fill: '#98DD62', - symbolType: 'circle' - } - }, - { - label: '小型企业-折扣', - shape: { - fill: '#07A199', - symbolType: 'circle' - } - }, - { - label: '消费者-折扣', - shape: { - fill: '#87DBDD', - symbolType: 'circle' - } - } - ], - orient: 'right', - position: 'start', - maxRow: 1, - padding: [50, 0, 0, 30] - } - ], - widthMode: 'adaptive', - heightMode: 'adaptive' - // hover: { - // disableHeaderHover:false, - // disableHover: true - // }, - // select: { - // disableSelect: true - // } - }; - - const tableInstance = new VTable.PivotChart(option); - tableInstance.onVChartEvent('click', args => { - console.log('onVChartEvent click', args); - }); - tableInstance.onVChartEvent('mouseover', args => { - console.log('onVChartEvent mouseover', args); - }); - const { LEGEND_ITEM_CLICK, LEGEND_ITEM_HOVER, LEGEND_ITEM_UNHOVER } = VTable.ListTable.EVENT_TYPE; - tableInstance.on(LEGEND_ITEM_CLICK, args => { - console.log('LEGEND_ITEM_CLICK', args); - tableInstance.updateFilterRules([ - { - filterKey: '20001', - filteredValues: args.value - } - ]); - }); - tableInstance.on(LEGEND_ITEM_HOVER, args => { - console.log('LEGEND_ITEM_HOVER', args); - }); - tableInstance.on(LEGEND_ITEM_UNHOVER, args => { - console.log('LEGEND_ITEM_UNHOVER', args); - }); - - // setTimeout(() => { - // const datum = { - // '10001': '数量', - // '10002': '111', - // '10003': '230713183656009', - // '20001': '公司-数量', - // '230417170554008': '配件', - // '230417170554012': '一级', - // '230417171050028': '技术', - // '230417171050031': '中国', - // '230713183656009': '111', - // '230717170834024': '公司' - // }; - // const cellAddr = { - // colHeaderPaths: [ - // { - // dimensionKey: '230417171050031', - // value: '中国' - // }, - // { - // dimensionKey: '230417171050028', - // value: '技术' - // } - // ], - // rowHeaderPaths: [ - // { - // dimensionKey: '230417170554012', - // value: '一级' - // }, - // { - // indicatorKey: '230713183656009', - // value: '数量' - // } - // ] - // }; - // const position = tableInstance.getChartDatumPosition(datum, cellAddr); - // console.log('getChartDatumPosition', position); - // }, 3000); - window.tableInstance = tableInstance; - - // bindDebugTool(tableInstance.scenegraph.stage, {}); -} diff --git a/packages/vtable/examples/pivot-chart/pivotChart.ts b/packages/vtable/examples/pivot-chart/pivotChart.ts index ede3c126f..1b100ccdd 100644 --- a/packages/vtable/examples/pivot-chart/pivotChart.ts +++ b/packages/vtable/examples/pivot-chart/pivotChart.ts @@ -9433,7 +9433,6 @@ export function createTable() { }; const option: VTable.PivotChartConstructorOptions = { columnTree, - emptyTip: true, rowTree, rows, columns, diff --git a/packages/vtable/examples/pivot/pivot-column-pref.ts b/packages/vtable/examples/pivot/pivot-column-pref.ts index 01806e047..097b66b3e 100644 --- a/packages/vtable/examples/pivot/pivot-column-pref.ts +++ b/packages/vtable/examples/pivot/pivot-column-pref.ts @@ -194,7 +194,7 @@ export function createTable() { } }, records, - + enableDataAnalysis: false, autoRowHeight: true, widthMode: 'standard', disableColumnResize: false, diff --git a/packages/vtable/examples/pivot/pivot-extension-bp.ts b/packages/vtable/examples/pivot/pivot-extension-bp.ts index 0c94b40af..02f190e59 100644 --- a/packages/vtable/examples/pivot/pivot-extension-bp.ts +++ b/packages/vtable/examples/pivot/pivot-extension-bp.ts @@ -44,7 +44,7 @@ const records = []; export function createTable() { const option: VTable.PivotTableConstructorOptions = { rowHierarchyType: 'tree', - + enableDataAnalysis: false, autoRowHeight: true, widthMode: 'standard', disableColumnResize: false, diff --git a/packages/vtable/examples/pivot/pivot-extension-row.ts b/packages/vtable/examples/pivot/pivot-extension-row.ts index bd49f43c1..f4de41f22 100644 --- a/packages/vtable/examples/pivot/pivot-extension-row.ts +++ b/packages/vtable/examples/pivot/pivot-extension-row.ts @@ -6228,7 +6228,7 @@ const records = [ export function createTable() { const option: VTable.PivotTableConstructorOptions = { rowHierarchyType: 'tree', - + enableDataAnalysis: false, autoRowHeight: true, widthMode: 'standard', disableColumnResize: false, diff --git a/packages/vtable/examples/pivot/pivot-indicator-middle.ts b/packages/vtable/examples/pivot/pivot-indicator-middle.ts index f394ff5ae..0203e1190 100644 --- a/packages/vtable/examples/pivot/pivot-indicator-middle.ts +++ b/packages/vtable/examples/pivot/pivot-indicator-middle.ts @@ -6127,7 +6127,7 @@ const records = [ export function createTable() { const option = { rowHierarchyType: 'tree', - + enableDataAnalysis: false, autoRowHeight: true, widthMode: 'standard', disableColumnResize: false, diff --git a/packages/vtable/examples/pivot/pivot.ts b/packages/vtable/examples/pivot/pivot.ts index a54cde50f..ab1fd70f7 100644 --- a/packages/vtable/examples/pivot/pivot.ts +++ b/packages/vtable/examples/pivot/pivot.ts @@ -8,7 +8,6 @@ export function createTable() { const option: VTable.PivotTableConstructorOptions = { container: document.getElementById(CONTAINER_ID), // records: data, - emptyTip: true, menu: { contextMenuItems: ['复制单元格内容', '查询详情'] }, diff --git a/packages/vtable/examples/pivot/virtual-node-2.ts b/packages/vtable/examples/pivot/virtual-node-2.ts deleted file mode 100644 index 108f04827..000000000 --- a/packages/vtable/examples/pivot/virtual-node-2.ts +++ /dev/null @@ -1,207 +0,0 @@ -import * as VTable from '../../src'; -import { bindDebugTool } from '../../src/scenegraph/debug-tool'; -const PivotTable = VTable.PivotTable; -const CONTAINER_ID = 'vTable'; - -export function createTable() { - let tableInstance; - fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option: VTable.PivotTableConstructorOptions = { - records: data, - rows: [ - { - dimensionKey: 'Category', - title: 'Category', - headerStyle: { - textStick: true, - bgColor(arg) { - if (arg.dataValue === 'Row Totals') { - return '#a5b7fc'; - } - return '#ECF1F5'; - } - }, - width: 'auto' - }, - { - dimensionKey: 'Sub-Category', - title: 'Sub-Catogery', - headerStyle: { - textStick: true, - bgColor(arg) { - if (arg.dataValue === 'Sub Totals') { - return '#d2dcff'; - } - return '#ECF1F5'; - } - }, - width: 'auto' - } - ], - columns: [ - { - dimensionKey: 'Segment-1', - title: 'Segment-custom-virtual' - } - ], - columnTree: [ - { - dimensionKey: 'Segment-1', - value: 'Segment-1 (virtual-node)', - virtual: true - // children: [ - // { - // indicatorKey: 'Quantity', - // value: 'Quantity' - // }, - // { - // indicatorKey: 'Sales', - // value: 'Sales' - // }, - // { - // indicatorKey: 'Profit', - // value: 'Profit' - // } - // ] - } - ], - indicators: [ - { - indicatorKey: 'Quantity', - title: 'Quantity', - width: 'auto', - showSort: false, - headerStyle: { - fontWeight: 'normal' - }, - style: { - padding: [16, 28, 16, 28], - color(args) { - if (args.dataValue >= 0) { - return 'black'; - } - return 'red'; - }, - bgColor(arg) { - const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; - if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { - return '#d2dcff'; - } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { - return '#a5b7fc'; - } - return undefined; - } - } - }, - { - indicatorKey: 'Sales', - title: 'Sales', - width: 'auto', - showSort: false, - headerStyle: { - fontWeight: 'normal' - }, - format: rec => { - return '$' + Number(rec).toFixed(2); - }, - style: { - padding: [16, 28, 16, 28], - color(args) { - if (args.dataValue >= 0) { - return 'black'; - } - return 'red'; - }, - bgColor(arg) { - const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; - if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { - return '#d2dcff'; - } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { - return '#a5b7fc'; - } - return undefined; - } - } - }, - { - indicatorKey: 'Profit', - title: 'Profit', - width: 'auto', - showSort: false, - headerStyle: { - fontWeight: 'normal' - }, - format: rec => { - return '$' + Number(rec).toFixed(2); - }, - style: { - padding: [16, 28, 16, 28], - color(args) { - if (args.dataValue >= 0) { - return 'black'; - } - return 'red'; - }, - bgColor(arg) { - const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; - if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { - return '#d2dcff'; - } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { - return '#a5b7fc'; - } - return undefined; - } - } - } - ], - corner: { - titleOnDimension: 'column' - }, - dataConfig: { - totals: { - row: { - showGrandTotals: true, - showSubTotals: true, - showSubTotalsOnTop: true, - showGrandTotalsOnTop: true, - subTotalsDimensions: ['Category'], - grandTotalLabel: 'Row Totals', - subTotalLabel: 'Sub Totals' - }, - column: { - showGrandTotals: true, - showSubTotals: false, - grandTotalLabel: 'Column Totals' - } - } - }, - theme: VTable.themes.DEFAULT.extends({ - headerStyle: { - bgColor: '#5071f9', - color(args) { - if ( - (args.cellHeaderPaths.colHeaderPaths?.length === 1 && args.cellHeaderPaths.colHeaderPaths[0].virtual) || - (args.cellHeaderPaths.colHeaderPaths?.length === 2 && args.cellHeaderPaths.colHeaderPaths[1].virtual) - ) { - return 'red'; - } - return '#fff'; - } - }, - cornerHeaderStyle: { - bgColor: '#5071f9', - color: '#fff' - } - }), - - widthMode: 'standard' - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window.tableInstance = tableInstance; - }) - .catch(e => { - console.log(e); - }); -} diff --git a/packages/vtable/examples/pivot/virtual-node.ts b/packages/vtable/examples/pivot/virtual-node.ts deleted file mode 100644 index fd19e6ba9..000000000 --- a/packages/vtable/examples/pivot/virtual-node.ts +++ /dev/null @@ -1,299 +0,0 @@ -import * as VTable from '../../src'; -import { bindDebugTool } from '../../src/scenegraph/debug-tool'; -const PivotTable = VTable.PivotTable; -const CONTAINER_ID = 'vTable'; - -export function createTable() { - let tableInstance; - fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/North_American_Superstore_Pivot_Chart_data.json') - .then(res => res.json()) - .then(data => { - const option: VTable.PivotTableConstructorOptions = { - supplementIndicatorNodes: false, - records: data, - rows: [ - { - dimensionKey: 'Category', - title: 'Category', - headerStyle: { - textStick: true, - bgColor(arg) { - if (arg.dataValue === 'Row Totals') { - return '#a5b7fc'; - } - return '#ECF1F5'; - } - }, - width: 'auto' - }, - { - dimensionKey: 'Sub-Category', - title: 'Sub-Catogery', - headerStyle: { - textStick: true, - bgColor(arg) { - if (arg.dataValue === 'Sub Totals') { - return '#d2dcff'; - } - return '#ECF1F5'; - } - }, - width: 'auto' - } - ], - columns: [ - { - dimensionKey: 'Segment', - title: 'Segment', - headerStyle: { - textStick: true - } - } - ], - columnTree: [ - { - dimensionKey: 'Segment-3', - value: 'Segment-3 (virtual-node)', - virtual: true - }, - { - dimensionKey: 'Segment', - value: 'Consumer' - }, - { - dimensionKey: 'Segment-1', - value: 'Segment-1 (virtual-node)', - virtual: true, - children: [ - { - dimensionKey: 'Segment', - value: 'Consumer', - children: [ - { - indicatorKey: 'Quantity', - value: 'Quantity' - }, - { - indicatorKey: 'Sales', - value: 'Sales' - }, - { - indicatorKey: 'Profit', - value: 'Profit' - } - ] - }, - { - dimensionKey: 'Segment', - value: 'Corporate', - children: [ - { - indicatorKey: 'Quantity', - value: 'Quantity' - }, - { - indicatorKey: 'Sales', - value: 'Sales' - }, - { - indicatorKey: 'Profit', - value: 'Profit' - } - ] - } - ] - }, - { - dimensionKey: 'Segment', - value: 'Home Office', - children: [ - { - dimensionKey: 'Segment-2', - value: 'Segment-2 (virtual-node)', - virtual: true, - children: [ - { - indicatorKey: 'Quantity', - value: 'Quantity' - }, - { - indicatorKey: 'Sales', - value: 'Sales' - }, - { - indicatorKey: 'Profit', - value: 'Profit' - } - ] - } - ] - }, - { - dimensionKey: 'Segment', - value: 'Column Totals', - children: [ - { - indicatorKey: 'Quantity', - value: 'Quantity' - }, - { - indicatorKey: 'Sales', - value: 'Sales' - }, - { - indicatorKey: 'Profit', - value: 'Profit' - } - ] - }, - { - dimensionKey: 'Segment-4', - value: 'Segment-4 (virtual-node)', - virtual: true - }, - { - dimensionKey: 'Segment', - value: 'Consumer' - } - ], - indicators: [ - { - indicatorKey: 'Quantity', - title: 'Quantity', - width: 'auto', - showSort: false, - headerStyle: { - fontWeight: 'normal' - }, - format: rec => { - return '$' + Number(rec).toFixed(2); - }, - style: { - padding: [16, 28, 16, 28], - color(args) { - if (args.dataValue >= 0) { - return 'black'; - } - return 'red'; - }, - bgColor(arg) { - const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; - if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { - return '#d2dcff'; - } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { - return '#a5b7fc'; - } - return undefined; - } - } - }, - { - indicatorKey: 'Sales', - title: 'Sales', - width: 'auto', - showSort: false, - headerStyle: { - fontWeight: 'normal' - }, - format: rec => { - return '$' + Number(rec).toFixed(2); - }, - style: { - padding: [16, 28, 16, 28], - color(args) { - if (args.dataValue >= 0) { - return 'black'; - } - return 'red'; - }, - bgColor(arg) { - const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; - if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { - return '#d2dcff'; - } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { - return '#a5b7fc'; - } - return undefined; - } - } - }, - { - indicatorKey: 'Profit', - title: 'Profit', - width: 'auto', - showSort: false, - headerStyle: { - fontWeight: 'normal' - }, - format: rec => { - return '$' + Number(rec).toFixed(2); - }, - style: { - padding: [16, 28, 16, 28], - color(args) { - if (args.dataValue >= 0) { - return 'black'; - } - return 'red'; - }, - bgColor(arg) { - const rowHeaderPaths = arg.cellHeaderPaths.rowHeaderPaths; - if (rowHeaderPaths?.[1]?.value === 'Sub Totals') { - return '#d2dcff'; - } else if (rowHeaderPaths?.[0]?.value === 'Row Totals') { - return '#a5b7fc'; - } - return undefined; - } - } - } - ], - corner: { - titleOnDimension: 'row' - }, - dataConfig: { - totals: { - row: { - showGrandTotals: true, - showSubTotals: true, - showSubTotalsOnTop: true, - showGrandTotalsOnTop: true, - subTotalsDimensions: ['Category'], - grandTotalLabel: 'Row Totals', - subTotalLabel: 'Sub Totals' - }, - column: { - showGrandTotals: true, - showSubTotals: false, - grandTotalLabel: 'Column Totals' - } - } - }, - theme: VTable.themes.DEFAULT.extends({ - headerStyle: { - bgColor: '#5071f9', - color(args) { - if ( - (args.cellHeaderPaths.colHeaderPaths?.length === 1 && args.cellHeaderPaths.colHeaderPaths[0].virtual) || - (args.cellHeaderPaths.colHeaderPaths?.length === 2 && args.cellHeaderPaths.colHeaderPaths[1].virtual) - ) { - return 'red'; - } - return '#fff'; - } - }, - cornerHeaderStyle: { - bgColor: '#5071f9', - color: '#fff' - } - }), - - widthMode: 'standard' - }; - tableInstance = new VTable.PivotTable(document.getElementById(CONTAINER_ID), option); - window.tableInstance = tableInstance; - }) - .catch(e => { - console.log(e); - }); -} diff --git a/packages/vtable/examples/type/checkbox.ts b/packages/vtable/examples/type/checkbox.ts index 89c388c37..4a66be9c7 100644 --- a/packages/vtable/examples/type/checkbox.ts +++ b/packages/vtable/examples/type/checkbox.ts @@ -9,7 +9,7 @@ export function createTable() { columns: [ { field: '', - headerType: 'checkbox', + // headerType: 'checkbox', cellType: 'checkbox', width: 'auto', checked(args) { @@ -72,7 +72,6 @@ export function createTable() { showFrozenIcon: true, //显示VTable内置冻结列图标 widthMode: 'standard', heightMode: 'autoHeight', - allowFrozenColCount: 3, // transpose: true theme: VTable.themes.DEFAULT.extends({ checkboxStyle: { diff --git a/packages/vtable/examples/unit-test-demo/unit-listTable-frozen.ts b/packages/vtable/examples/unit-test-demo/unit-listTable-frozen.ts deleted file mode 100644 index 3f17ff46a..000000000 --- a/packages/vtable/examples/unit-test-demo/unit-listTable-frozen.ts +++ /dev/null @@ -1,96 +0,0 @@ -import * as VTable from '../../src'; -import records from './marketsales.json'; -const ListTable = VTable.ListTable; -const CONTAINER_ID = 'vTable'; -export function createTable() { - const containerDom: HTMLElement = document.getElementById(CONTAINER_ID) as HTMLElement; - // containerDom.style.position = 'relative'; - containerDom.style.width = '1000px'; - containerDom.style.height = '800px'; - - const columns = [ - { - field: '订单 ID', - caption: '订单 ID', - sort: true, - width: 'auto', - description: '这是订单的描述信息', - style: { - fontFamily: 'Arial', - fontSize: 14 - } - }, - { - field: '订单日期', - caption: '订单日期' - }, - { - field: '发货日期', - caption: '发货日期' - }, - { - field: '客户名称', - caption: '客户名称', - style: { - padding: [10, 0, 10, 60] - } - }, - { - field: '邮寄方式', - caption: '邮寄方式' - }, - { - field: '省/自治区', - caption: '省/自治区' - }, - { - field: '产品名称', - caption: '产品名称' - }, - { - field: '类别', - caption: '类别' - }, - { - field: '子类别', - caption: '子类别' - }, - { - field: '销售额', - caption: '销售额' - }, - { - field: '数量', - caption: '数量' - }, - { - field: '折扣', - caption: '折扣' - }, - { - field: '利润', - caption: '利润' - } - ]; - const option = { - columns, - defaultColWidth: 150, - allowFrozenColCount: 5, - frozenColCount: 2 - }; - option.container = containerDom; - option.records = records; - const tableInstance = new ListTable(option); - - window.tableInstance = tableInstance; - - setTimeout(() => { - console.log(tableInstance.frozenColCount); - }, 3000); - - setTimeout(() => { - tableInstance.frozenColCount = 4; - console.log(tableInstance.frozenColCount); - tableInstance.release(); - }, 6000); -} diff --git a/packages/vtable/examples/unit-test-demo/unit-listTable-sort.ts b/packages/vtable/examples/unit-test-demo/unit-listTable-sort.ts deleted file mode 100644 index 7101cc96e..000000000 --- a/packages/vtable/examples/unit-test-demo/unit-listTable-sort.ts +++ /dev/null @@ -1,94 +0,0 @@ -import * as VTable from '../../src'; -import records from './marketsales.json'; -const ListTable = VTable.ListTable; -const CONTAINER_ID = 'vTable'; -export function createTable() { - const containerDom: HTMLElement = document.getElementById(CONTAINER_ID) as HTMLElement; - // containerDom.style.position = 'relative'; - containerDom.style.width = '1000px'; - containerDom.style.height = '800px'; - - const columns = [ - { - field: '订单 ID', - caption: '订单 ID', - sort: true, - width: 'auto', - description: '这是订单的描述信息', - style: { - fontFamily: 'Arial', - fontSize: 14 - } - }, - { - field: '订单日期', - caption: '订单日期' - }, - { - field: '发货日期', - caption: '发货日期' - }, - { - field: '客户名称', - caption: '客户名称', - style: { - padding: [10, 0, 10, 60] - } - }, - { - field: '邮寄方式', - caption: '邮寄方式' - }, - { - field: '省/自治区', - caption: '省/自治区' - }, - { - field: '产品名称', - caption: '产品名称' - }, - { - field: '类别', - caption: '类别' - }, - { - field: '子类别', - caption: '子类别' - }, - { - field: '销售额', - caption: '销售额' - }, - { - field: '数量', - caption: '数量' - }, - { - field: '折扣', - caption: '折扣' - }, - { - field: '利润', - caption: '利润' - } - ]; - const option = { - columns, - defaultColWidth: 150, - allowFrozenColCount: 5, - sortState: { - field: '订单 ID', - order: 'desc' - } - }; - - option.container = containerDom; - option.records = records; - const tableInstance = new ListTable(option); - - window.tableInstance = tableInstance; - - setTimeout(() => { - console.log(tableInstance.getCellValue(6, 3)); - }, 3000); -} diff --git a/packages/vtable/examples/unit-test-demo/unitTestPivotAnalysis.ts b/packages/vtable/examples/unit-test-demo/unitTestPivotAnalysis.ts index 251571d48..37cdedd91 100644 --- a/packages/vtable/examples/unit-test-demo/unitTestPivotAnalysis.ts +++ b/packages/vtable/examples/unit-test-demo/unitTestPivotAnalysis.ts @@ -37,7 +37,7 @@ export function createTable(el: any, v: any) { rows: ['province', 'city'], columns: ['category', 'sub_category'], indicators: ['sales', 'number'], - + enableDataAnalysis: true, indicatorTitle: '指标名称', indicatorsAsCol: false, corner: { titleOnDimension: 'row' }, diff --git a/packages/vtable/package.json b/packages/vtable/package.json index 2c84e1712..6140aa7ca 100644 --- a/packages/vtable/package.json +++ b/packages/vtable/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vtable", - "version": "1.5.0", + "version": "0.25.5", "description": "canvas table width high performance", "keywords": [ "grid", @@ -19,15 +19,7 @@ "url": "https://VisActor.io/" }, "license": "MIT", - "sideEffects": [ - "./src/ListTable-all.js", - "./src/ListTable-simple.js", - "./src/PivotTable-all.js", - "./src/PivotTable-simple.js", - "./src/PivotChart.js", - "./src/index.js", - "./src/scenegraph/scenegraph.js" - ], + "sideEffects": true, "main": "cjs/index.js", "module": "es/index.js", "types": "es/index.d.ts", @@ -58,18 +50,17 @@ }, "dependencies": { "@visactor/vtable-editors": "workspace:*", - "@visactor/vrender-core": "0.19.13-beta.0", - "@visactor/vrender-kits": "0.19.13-beta.0", - "@visactor/vrender-components": "0.19.13-beta.0", - "@visactor/vutils": "~0.18.9", + "@visactor/vrender-core": "0.18.14-alpha.0", + "@visactor/vrender-kits": "0.18.14-alpha.0", + "@visactor/vrender-components": "0.18.14-alpha.0", + "@visactor/vutils": "~0.18.1", "@visactor/vscale": "~0.18.1", "@visactor/vdataset": "~0.18.1", - "@visactor/vutils-extension": "~1.11.5", "cssfontparser": "^1.2.1" }, "devDependencies": { "luxon": "*", - "@visactor/vchart": "1.11.4", + "@visactor/vchart": "1.10.5", "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", diff --git a/packages/vtable/src/ListTable-all.ts b/packages/vtable/src/ListTable-all.ts deleted file mode 100644 index 2d497ce21..000000000 --- a/packages/vtable/src/ListTable-all.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ListTable } from './ListTable'; -import { - registerAxis, - registerEmptyTip, - registerLegend, - registerMenu, - registerTitle, - registerTooltip -} from './components'; -import { - registerChartCell, - registerCheckboxCell, - registerImageCell, - registerProgressBarCell, - registerRadioCell, - registerSparkLineCell, - registerTextCell, - registerVideoCell -} from './scenegraph/group-creater/cell-type'; - -registerAxis(); -registerEmptyTip(); -registerLegend(); -registerMenu(); -registerTitle(); -registerTooltip(); - -registerChartCell(); -registerCheckboxCell(); -registerImageCell(); -registerProgressBarCell(); -registerRadioCell(); -registerSparkLineCell(); -registerTextCell(); -registerVideoCell(); -export class ListTableAll extends ListTable {} diff --git a/packages/vtable/src/ListTable-simple.ts b/packages/vtable/src/ListTable-simple.ts deleted file mode 100644 index 77d2e735e..000000000 --- a/packages/vtable/src/ListTable-simple.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ListTable } from './ListTable'; -import { registerTextCell } from './scenegraph/group-creater/cell-type'; - -registerTextCell(); -export class ListTableSimple extends ListTable {} diff --git a/packages/vtable/src/ListTable.ts b/packages/vtable/src/ListTable.ts index b28f24b50..e498e79f6 100644 --- a/packages/vtable/src/ListTable.ts +++ b/packages/vtable/src/ListTable.ts @@ -18,13 +18,15 @@ import type { } from './ts-types'; import { HierarchyState } from './ts-types'; import { SimpleHeaderLayoutMap } from './layout'; -import { isValid } from '@visactor/vutils'; +import { isNumber, isObject, isValid } from '@visactor/vutils'; import { _setDataSource, _setRecords, sortRecords } from './core/tableHelper'; import { BaseTable } from './core'; import type { BaseTableAPI, ListTableProtected } from './ts-types/base-table'; import { TABLE_EVENT_TYPE } from './core/TABLE_EVENT_TYPE'; -import type { ITitleComponent } from './components/title/title'; +import { Title } from './components/title/title'; +import { cloneDeep } from '@visactor/vutils'; import { Env } from './tools/env'; +import { editor } from './register'; import * as editors from './edit/editors'; import { EditManeger } from './edit/edit-manager'; import { computeColWidth } from './scenegraph/layout/compute-col-width'; @@ -33,44 +35,8 @@ import { defaultOrderFn } from './tools/util'; import type { IEditor } from '@visactor/vtable-editors'; import type { ColumnData, ColumnDefine } from './ts-types/list-table/layout-map/api'; import { getCellRadioState, setCellRadioState } from './state/radio/radio'; -import { cloneDeepSpec } from '@visactor/vutils-extension'; +import { cloneDeepSpec } from '@vutils-extension'; import { setCellCheckboxState } from './state/checkbox/checkbox'; -import type { IEmptyTipComponent } from './components/empty-tip/empty-tip'; -import { Factory } from './core/factory'; -// import { -// registerAxis, -// registerEmptyTip, -// registerLegend, -// registerMenu, -// registerTitle, -// registerTooltip -// } from './components'; -// import { -// registerChartCell, -// registerCheckboxCell, -// registerImageCell, -// registerProgressBarCell, -// registerRadioCell, -// registerSparkLineCell, -// registerTextCell, -// registerVideoCell -// } from './scenegraph/group-creater/cell-type'; - -// registerAxis(); -// registerEmptyTip(); -// registerLegend(); -// registerMenu(); -// registerTitle(); -// registerTooltip(); - -// registerChartCell(); -// registerCheckboxCell(); -// registerImageCell(); -// registerProgressBarCell(); -// registerRadioCell(); -// registerSparkLineCell(); -// registerTextCell(); -// registerVideoCell(); export class ListTable extends BaseTable implements ListTableAPI { declare internalProps: ListTableProtected; @@ -103,17 +69,17 @@ export class ListTable extends BaseTable implements ListTableAPI { internalProps.sortState = options.sortState; internalProps.dataConfig = {}; //cloneDeep(options.dataConfig ?? {}); internalProps.columns = options.columns - ? cloneDeepSpec(options.columns, ['children']) // children for react + ? cloneDeepSpec(options.columns) : options.header - ? cloneDeepSpec(options.header, ['children']) + ? cloneDeepSpec(options.header) : []; - // options.columns?.forEach((colDefine, index) => { - // //如果editor 是一个IEditor的实例 需要这样重新赋值 否则clone后变质了 - // if (colDefine.editor) { - // internalProps.columns[index].editor = colDefine.editor; - // } - // }); - this.internalProps.headerHelper.setTableColumnsEditor(); + options.columns?.forEach((colDefine, index) => { + //如果editor 是一个IEditor的实例 需要这样重新赋值 否则clone后变质了 + if (colDefine.editor) { + internalProps.columns[index].editor = colDefine.editor; + } + }); + this.showHeader = options.showHeader ?? true; this.transpose = options.transpose ?? false; @@ -121,7 +87,6 @@ export class ListTable extends BaseTable implements ListTableAPI { this.editorManager = new EditManeger(this); } this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; if (options.dataSource) { _setDataSource(this, options.dataSource); @@ -131,19 +96,9 @@ export class ListTable extends BaseTable implements ListTableAPI { this.setRecords([]); } if (options.title) { - const Title = Factory.getComponent('title') as ITitleComponent; internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } - if (this.options.emptyTip) { - if (this.internalProps.emptyTip) { - this.internalProps.emptyTip.resetVisible(); - } else { - const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; - this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); - this.internalProps.emptyTip.resetVisible(); - } - } //为了确保用户监听得到这个事件 这里做了异步 确保vtable实例已经初始化完成 setTimeout(() => { this.fireListeners(TABLE_EVENT_TYPE.INITIALIZED, null); @@ -190,17 +145,14 @@ export class ListTable extends BaseTable implements ListTableAPI { */ updateColumns(columns: ColumnsDefine) { const oldHoverState = { col: this.stateManager.hover.cellPos.col, row: this.stateManager.hover.cellPos.row }; - this.internalProps.columns = cloneDeepSpec(columns, ['children']); - // columns.forEach((colDefine, index) => { - // if (colDefine.editor) { - // this.internalProps.columns[index].editor = colDefine.editor; - // } - // }); + this.internalProps.columns = cloneDeepSpec(columns); + columns.forEach((colDefine, index) => { + if (colDefine.editor) { + this.internalProps.columns[index].editor = colDefine.editor; + } + }); this.options.columns = columns; - this.internalProps.headerHelper.setTableColumnsEditor(); - this._hasAutoImageColumn = undefined; this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; this.scenegraph.clearCells(); this.headerStyleCache = new Map(); this.bodyStyleCache = new Map(); @@ -227,7 +179,6 @@ export class ListTable extends BaseTable implements ListTableAPI { this.internalProps.columns = header; this.options.header = header; this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; //需要异步等待其他事情都完成后再绘制 this.renderAsync(); } @@ -411,11 +362,8 @@ export class ListTable extends BaseTable implements ListTableAPI { if (!this.transpose) { // 列上是否配置了禁止拖拽列宽的配置项disableColumnResize const cellDefine = this.internalProps.layoutMap.getBody(col, this.columnHeaderLevelCount); - const isSeriesNumber = this.internalProps.layoutMap.isSeriesNumber(col, row); if ((cellDefine as ColumnData)?.disableColumnResize) { return false; - } else if (isSeriesNumber && this.internalProps.rowSeriesNumber.disableColumnResize === true) { - return false; } } } @@ -432,21 +380,19 @@ export class ListTable extends BaseTable implements ListTableAPI { //更新protectedSpace this.showHeader = options.showHeader ?? true; internalProps.columns = options.columns - ? cloneDeepSpec(options.columns, ['children']) + ? cloneDeepSpec(options.columns) : options.header - ? cloneDeepSpec(options.header, ['children']) + ? cloneDeepSpec(options.header) : []; - // options.columns.forEach((colDefine, index) => { - // if (colDefine.editor) { - // internalProps.columns[index].editor = colDefine.editor; - // } - // }); - this.internalProps.headerHelper.setTableColumnsEditor(); + options.columns.forEach((colDefine, index) => { + if (colDefine.editor) { + internalProps.columns[index].editor = colDefine.editor; + } + }); // 处理转置 this.transpose = options.transpose ?? false; // 更新表头 this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; // this.hasMedia = null; // 避免重复绑定 // 清空目前数据 @@ -471,19 +417,9 @@ export class ListTable extends BaseTable implements ListTableAPI { this.render(); } if (options.title) { - const Title = Factory.getComponent('title') as ITitleComponent; internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } - if (this.options.emptyTip) { - if (this.internalProps.emptyTip) { - this.internalProps.emptyTip.resetVisible(); - } else { - const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; - this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); - this.internalProps.emptyTip.resetVisible(); - } - } return new Promise(resolve => { setTimeout(resolve, 0); }); @@ -500,7 +436,6 @@ export class ListTable extends BaseTable implements ListTableAPI { pagination.perPageCount && (this.pagination.perPageCount = pagination.perPageCount || this.pagination.perPageCount); this.internalProps.layoutMap.clearCellRangeMap(); - this.internalProps.useOneRowHeightFillAll = false; // 清空单元格内容 this.scenegraph.clearCells(); //数据源缓存数据更新 @@ -540,10 +475,10 @@ export class ListTable extends BaseTable implements ListTableAPI { if (!layoutMap) { return; } - - const dataCount = table.internalProps.dataSource?.length ?? 0; layoutMap.recordsCount = - dataCount + (dataCount > 0 ? layoutMap.hasAggregationOnTopCount + layoutMap.hasAggregationOnBottomCount : 0); + (table.internalProps.dataSource?.length ?? 0) + + layoutMap.hasAggregationOnTopCount + + layoutMap.hasAggregationOnBottomCount; if (table.transpose) { table.rowCount = layoutMap.rowCount ?? 0; @@ -565,7 +500,7 @@ export class ListTable extends BaseTable implements ListTableAPI { table.rowCount = layoutMap.recordsCount * layoutMap.bodyRowSpanCount + layoutMap.headerLevelCount; // table.frozenColCount = table.options.frozenColCount ?? 0; //这里不要这样写 这个setter会检查扁头宽度 可能将frozenColCount置为0 this.internalProps.frozenColCount = this.options.frozenColCount ?? 0; - table.frozenRowCount = Math.max(layoutMap.headerLevelCount, this.options.frozenRowCount ?? 0); + table.frozenRowCount = layoutMap.headerLevelCount; if (table.bottomFrozenRowCount !== (this.options.bottomFrozenRowCount ?? 0)) { table.bottomFrozenRowCount = this.options.bottomFrozenRowCount ?? 0; @@ -838,7 +773,6 @@ export class ListTable extends BaseTable implements ListTableAPI { this.clearCellStyleCache(); this.internalProps.layoutMap.clearCellRangeMap(); - this.internalProps.useOneRowHeightFillAll = false; this.scenegraph.updateHierarchyIcon(col, row); this.scenegraph.updateRow(diffPositions.removeCellPositions, diffPositions.addCellPositions); if (checkHasChart) { @@ -905,13 +839,12 @@ export class ListTable extends BaseTable implements ListTableAPI { // 解除排序状态 if (this.internalProps.sortState) { if (Array.isArray(this.internalProps.sortState)) { - // for (let i = 0; i < (this.internalProps.sortState).length; i++) { - sortState = this.internalProps.sortState?.[0]; - sortState && (sortState.order = 'normal'); - // } + for (let i = 0; i < (this.internalProps.sortState).length; i++) { + const sortState: SortState = this.internalProps.sortState[i]; + sortState.order = 'normal'; + } } else { (this.internalProps.sortState).order = 'normal'; - sortState = this.internalProps.sortState; } } } else { @@ -922,10 +855,8 @@ export class ListTable extends BaseTable implements ListTableAPI { let order: any; let field: any; if (Array.isArray(this.internalProps.sortState)) { - if (this.internalProps.sortState?.[0]) { - ({ order, field } = this.internalProps.sortState?.[0]); - } - } else if (this.internalProps.sortState) { + ({ order, field } = this.internalProps.sortState?.[0]); + } else { ({ order, field } = this.internalProps.sortState as SortState); } if (field && executeSort) { @@ -937,13 +868,10 @@ export class ListTable extends BaseTable implements ListTableAPI { // clear cell range cache this.internalProps.layoutMap.clearCellRangeMap(); - this.internalProps.useOneRowHeightFillAll = false; this.scenegraph.sortCell(); } } - if (sortState) { - this.stateManager.updateSortState(sortState as SortState); - } + this.stateManager.updateSortState(sortState as SortState); } updateFilterRules(filterRules: FilterRules) { this.scenegraph.clearCells(); @@ -975,7 +903,7 @@ export class ListTable extends BaseTable implements ListTableAPI { const cellType = this.getCellType(col, row); if (isValid(field) && cellType === 'checkbox') { const dataIndex = this.dataSource.getIndexKey(this.getRecordShowIndexByCell(col, row)); - return this.stateManager.checkedState[dataIndex as number]?.[field as string | number]; + return this.stateManager.checkedState[dataIndex as number][field as string | number]; } return undefined; } @@ -1045,9 +973,7 @@ export class ListTable extends BaseTable implements ListTableAPI { if (order && field && order !== 'normal') { const sortFunc = this._getSortFuncFromHeaderOption(undefined, field); // 如果sort传入的信息不能生成正确的sortFunc,直接更新表格,避免首次加载无法正常显示内容 - const hd = this.internalProps.layoutMap.headerObjectsIncludeHided.find( - (col: any) => col && col.field === field - ); + const hd = this.internalProps.layoutMap.headerObjects.find((col: any) => col && col.field === field); // hd?.define?.sort && //如果这里也判断 那想要利用sortState来排序 但不显示排序图标就实现不了 if (hd.define.sort !== false) { this.dataSource.sort(hd.field, order, sortFunc ?? defaultOrderFn); @@ -1070,15 +996,6 @@ export class ListTable extends BaseTable implements ListTableAPI { this.internalProps.title.resize(); this.scenegraph.resize(); } - if (this.options.emptyTip) { - if (this.internalProps.emptyTip) { - this.internalProps.emptyTip.resetVisible(); - } else { - const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; - this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); - this.internalProps.emptyTip.resetVisible(); - } - } this.render(); if (isValid(oldHoverState.col) && isValid(oldHoverState.row) && oldHoverState.col >= 0 && oldHoverState.row >= 0) { @@ -1104,7 +1021,6 @@ export class ListTable extends BaseTable implements ListTableAPI { /** 开启单元格编辑 */ startEditCell(col?: number, row?: number) { if (isValid(col) && isValid(row)) { - this.eventManager.isDraging = false; this.selectCell(col, row); this.editorManager.startEditCell(col, row); } else if (this.stateManager.select?.cellPos) { @@ -1159,14 +1075,7 @@ export class ListTable extends BaseTable implements ListTableAPI { } return isValid(editorDefine); } - - /** - * 更改单元格数据 会触发change_cell_value事件 - * @param col - * @param row - * @param value 更改后的值 - * @param workOnEditableCell 限制只能更改配置了编辑器的单元格值。快捷键paste这里配置的true,限制只能修改可编辑单元格值 - */ + /** 更改单元格数据 会触发change_cell_value事件*/ changeCellValue(col: number, row: number, value: string | number | null, workOnEditableCell = false) { if ((workOnEditableCell && this.isHasEditorDefine(col, row)) || workOnEditableCell === false) { const recordIndex = this.getRecordShowIndexByCell(col, row); @@ -1257,29 +1166,6 @@ export class ListTable extends BaseTable implements ListTableAPI { let pasteColEnd = startCol; let pasteRowEnd = startRow; // const rowCount = values.length; - //#region 提前组织好未更改前的数据 - const beforeChangeValues: (string | number)[][] = []; - const oldValues: (string | number)[][] = []; - for (let i = 0; i < values.length; i++) { - if (startRow + i > this.rowCount - 1) { - break; - } - const rowValues = values[i]; - const rawRowValues: (string | number)[] = []; - const oldRowValues: (string | number)[] = []; - beforeChangeValues.push(rawRowValues); - oldValues.push(oldRowValues); - for (let j = 0; j < rowValues.length; j++) { - if (startCol + j > this.colCount - 1) { - break; - } - const beforeChangeValue = this.getCellRawValue(startCol + j, startRow + i); - rawRowValues.push(beforeChangeValue); - const oldValue = this.getCellOriginValue(startCol + j, startRow + i); - oldRowValues.push(oldValue); - } - } - //#endregion for (let i = 0; i < values.length; i++) { if (startRow + i > this.rowCount - 1) { break; @@ -1299,10 +1185,8 @@ export class ListTable extends BaseTable implements ListTableAPI { const value = rowValues[j]; const recordIndex = this.getRecordShowIndexByCell(startCol + j, startRow + i); const { field } = this.internalProps.layoutMap.getBody(startCol + j, startRow + i); - // const beforeChangeValue = this.getCellRawValue(startCol + j, startRow + i); - // const oldValue = this.getCellOriginValue(startCol + j, startRow + i); - const beforeChangeValue = beforeChangeValues[i][j]; - const oldValue = oldValues[i][j]; + const beforeChangeValue = this.getCellRawValue(startCol + j, startRow + i); + const oldValue = this.getCellOriginValue(startCol + j, startRow + i); if (this.isHeader(startCol + j, startRow + i)) { this.internalProps.layoutMap.updateColumnTitle(startCol + j, startRow + i, value as string); } else { @@ -1789,8 +1673,4 @@ export class ListTable extends BaseTable implements ListTableAPI { } return results; } - /** 是否为聚合值单元格 */ - isAggregation(col: number, row: number): boolean { - return this.internalProps.layoutMap.isAggregation(col, row); - } } diff --git a/packages/vtable/src/PivotChart.ts b/packages/vtable/src/PivotChart.ts index 8973569dc..617d569eb 100644 --- a/packages/vtable/src/PivotChart.ts +++ b/packages/vtable/src/PivotChart.ts @@ -23,7 +23,7 @@ import type { PivotChartAPI } from './ts-types'; import { AggregationType } from './ts-types'; -import type { HierarchyState } from './ts-types'; +import { HierarchyState } from './ts-types'; import { getField } from './data/DataSource'; import { PivotHeaderLayoutMap } from './layout/pivot-header-layout'; import { PIVOT_CHART_EVENT_TYPE } from './ts-types/pivot-table/PIVOT_TABLE_EVENT_TYPE'; @@ -38,55 +38,12 @@ import { clearChartCacheImage, updateChartData } from './scenegraph/refresh-node import type { ITableAxisOption } from './ts-types/component/axis'; import { cloneDeep, isArray } from '@visactor/vutils'; import type { DiscreteLegend } from '@visactor/vrender-components'; -import type { ITitleComponent } from './components/title/title'; +import { Title } from './components/title/title'; import { Env } from './tools/env'; import { TABLE_EVENT_TYPE } from './core/TABLE_EVENT_TYPE'; import type { IndicatorData } from './ts-types/list-table/layout-map/api'; -import { cloneDeepSpec } from '@visactor/vutils-extension'; -import type { ITreeLayoutHeadNode } from './layout/tree-helper'; -import { DimensionTree, type LayouTreeNode } from './layout/tree-helper'; -import { IndicatorDimensionKeyPlaceholder } from './tools/global'; -import { checkHasCartesianChart } from './layout/chart-helper/get-chart-spec'; -import { supplementIndicatorNodesForCustomTree } from './layout/layout-helper'; -import type { IEmptyTipComponent } from './components/empty-tip/empty-tip'; -import { Factory } from './core/factory'; -import { - registerAxis, - registerEmptyTip, - registerLegend, - registerMenu, - registerTitle, - registerTooltip -} from './components'; -import { - registerChartCell, - registerCheckboxCell, - registerImageCell, - registerProgressBarCell, - registerRadioCell, - registerSparkLineCell, - registerTextCell, - registerVideoCell -} from './scenegraph/group-creater/cell-type'; - -registerAxis(); -registerEmptyTip(); -registerLegend(); -registerMenu(); -registerTitle(); -registerTooltip(); - -registerChartCell(); -registerCheckboxCell(); -registerImageCell(); -registerProgressBarCell(); -registerRadioCell(); -registerSparkLineCell(); -registerTextCell(); -registerVideoCell(); - +import { cloneDeepSpec } from '@vutils-extension'; export class PivotChart extends BaseTable implements PivotChartAPI { - layoutNodeId: { seqId: number } = { seqId: 0 }; declare internalProps: PivotChartProtected; declare options: PivotChartConstructorOptions; pivotSortState: PivotSortState[]; @@ -131,53 +88,24 @@ export class PivotChart extends BaseTable implements PivotChartAPI { this.internalProps.rowResizeType = options.rowResizeType ?? 'row'; this.internalProps.dataConfig = { isPivotChart: true }; this._axes = isArray(options.axes) ? options.axes : []; - - let columnDimensionTree; - let rowDimensionTree; - if (options.columnTree) { - if (options.indicatorsAsCol !== false) { - this.internalProps.columnTree = supplementIndicatorNodesForCustomTree( - this.internalProps.columnTree, - options.indicators - ); - } - columnDimensionTree = new DimensionTree( - (this.internalProps.columnTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - } - if (options.rowTree) { - if (options.indicatorsAsCol === false) { - this.internalProps.rowTree = supplementIndicatorNodesForCustomTree( - this.internalProps.rowTree, - options.indicators - ); - } - rowDimensionTree = new DimensionTree( - (this.internalProps.rowTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - } - const rowKeys = rowDimensionTree?.dimensionKeys?.count - ? rowDimensionTree.dimensionKeys.valueArr() - : options.rows?.reduce((keys, rowObj) => { - if (typeof rowObj === 'string') { - keys.push(rowObj); - } else { - keys.push(rowObj.dimensionKey); - } - return keys; - }, []) ?? []; - const columnKeys = columnDimensionTree?.dimensionKeys?.count - ? columnDimensionTree.dimensionKeys.valueArr() - : options.columns?.reduce((keys, columnObj) => { - if (typeof columnObj === 'string') { - keys.push(columnObj); - } else { - keys.push(columnObj.dimensionKey); - } - return keys; - }, []) ?? []; + const rowKeys = + options.rows?.reduce((keys, rowObj) => { + if (typeof rowObj === 'string') { + keys.push(rowObj); + } else { + keys.push(rowObj.dimensionKey); + } + return keys; + }, []) ?? []; + const columnKeys = + options.columns?.reduce((keys, columnObj) => { + if (typeof columnObj === 'string') { + keys.push(columnObj); + } else { + keys.push(columnObj.dimensionKey); + } + return keys; + }, []) ?? []; const indicatorKeys = options.indicators?.reduce((keys, indicatorObj) => { if (typeof indicatorObj === 'string') { @@ -204,79 +132,15 @@ export class PivotChart extends BaseTable implements PivotChartAPI { this.internalProps.rowTree, true ); - if (this.options.indicatorsAsCol && checkHasCartesianChart(this.internalProps.indicators)) { - const supplyAxisNode = (nodes: IHeaderTreeDefine[]) => { - nodes.forEach((node: IHeaderTreeDefine) => { - if ((node.children as IHeaderTreeDefine[])?.length) { - supplyAxisNode(node.children as IHeaderTreeDefine[]); - } else { - // 在指标在列上的透视图中,主指标轴(离散轴)显示在左侧,因此需要在原先行表头的布局中最右侧加入一列,用来显示坐标轴 - // 加入的这一列dimensionKey配置为'axis',在后续行列计算维度时需要注意,这一列是为了显示坐标轴加入的,不在行列维度信息内 - node.children = [ - { - dimensionKey: 'axis', - value: '' - } - ]; - } - }); - }; - if (this.dataset.rowHeaderTree?.length) { - supplyAxisNode(this.dataset.rowHeaderTree); - } else { - this.dataset.rowHeaderTree = [ - { - dimensionKey: 'axis', - value: '' - } - ]; - } - } - if (!options.columnTree) { - if (options.indicatorsAsCol !== false) { - this.dataset.colHeaderTree = supplementIndicatorNodesForCustomTree( - this.dataset.colHeaderTree, - options.indicators - ); - } - } - if (!options.rowTree) { - if (options.indicatorsAsCol === false) { - this.dataset.rowHeaderTree = supplementIndicatorNodesForCustomTree( - this.dataset.rowHeaderTree, - options.indicators - ); - } - } - columnDimensionTree = new DimensionTree( - (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - rowDimensionTree = new DimensionTree( - (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - - this.internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset, columnDimensionTree, rowDimensionTree); + this.internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset); this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; // this.internalProps.frozenColCount = this.options.frozenColCount || this.rowHeaderLevelCount; // 生成单元格场景树 this.scenegraph.createSceneGraph(); if (options.title) { - const Title = Factory.getComponent('title') as ITitleComponent; this.internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } - if (this.options.emptyTip) { - if (this.internalProps.emptyTip) { - this.internalProps.emptyTip.resetVisible(); - } else { - const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; - this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); - this.internalProps.emptyTip.resetVisible(); - } - } //为了确保用户监听得到这个事件 这里做了异步 确保vtable实例已经初始化完成 setTimeout(() => { this.fireListeners(TABLE_EVENT_TYPE.INITIALIZED, null); @@ -319,7 +183,6 @@ export class PivotChart extends BaseTable implements PivotChartAPI { //维护选中状态 // const range = internalProps.selection.range; //保留原有单元格选中状态 super.updateOption(options); - this.layoutNodeId = { seqId: 0 }; this.internalProps.columns = cloneDeep(options.columns); this.internalProps.rows = cloneDeep(options.rows); this.internalProps.indicators = !options.indicators?.length ? [] : cloneDeepSpec(options.indicators); @@ -339,53 +202,24 @@ export class PivotChart extends BaseTable implements PivotChartAPI { //TODO 这里需要加上判断 dataConfig是否有配置变化 // if (options.rows || options.columns) { - - let columnDimensionTree; - let rowDimensionTree; - if (options.columnTree) { - if (options.indicatorsAsCol !== false) { - this.internalProps.columnTree = supplementIndicatorNodesForCustomTree( - this.internalProps.columnTree, - options.indicators - ); - } - columnDimensionTree = new DimensionTree( - (this.internalProps.columnTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - } - if (options.rowTree) { - if (options.indicatorsAsCol === false) { - this.internalProps.rowTree = supplementIndicatorNodesForCustomTree( - this.internalProps.rowTree, - options.indicators - ); - } - rowDimensionTree = new DimensionTree( - (this.internalProps.rowTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - } - const rowKeys = rowDimensionTree?.dimensionKeys?.count - ? rowDimensionTree.dimensionKeys.valueArr() - : options.rows?.reduce((keys, rowObj) => { - if (typeof rowObj === 'string') { - keys.push(rowObj); - } else { - keys.push(rowObj.dimensionKey); - } - return keys; - }, []) ?? []; - const columnKeys = columnDimensionTree?.dimensionKeys?.count - ? columnDimensionTree.dimensionKeys.valueArr() - : options.columns?.reduce((keys, columnObj) => { - if (typeof columnObj === 'string') { - keys.push(columnObj); - } else { - keys.push(columnObj.dimensionKey); - } - return keys; - }, []) ?? []; + const rowKeys = + options.rows?.reduce((keys, rowObj) => { + if (typeof rowObj === 'string') { + keys.push(rowObj); + } else { + keys.push(rowObj.dimensionKey); + } + return keys; + }, []) ?? []; + const columnKeys = + options.columns?.reduce((keys, columnObj) => { + if (typeof columnObj === 'string') { + keys.push(columnObj); + } else { + keys.push(columnObj.dimensionKey); + } + return keys; + }, []) ?? []; const indicatorKeys = options.indicators?.reduce((keys, indicatorObj) => { if (typeof indicatorObj === 'string') { @@ -413,63 +247,8 @@ export class PivotChart extends BaseTable implements PivotChartAPI { this.internalProps.rowTree, true ); - if (this.options.indicatorsAsCol && checkHasCartesianChart(this.internalProps.indicators)) { - const supplyAxisNode = (nodes: IHeaderTreeDefine[]) => { - nodes.forEach((node: IHeaderTreeDefine) => { - if ((node.children as IHeaderTreeDefine[])?.length) { - supplyAxisNode(node.children as IHeaderTreeDefine[]); - } else { - // 在指标在列上的透视图中,主指标轴(离散轴)显示在左侧,因此需要在原先行表头的布局中最右侧加入一列,用来显示坐标轴 - // 加入的这一列dimensionKey配置为'axis',在后续行列计算维度时需要注意,这一列是为了显示坐标轴加入的,不在行列维度信息内 - node.children = [ - { - dimensionKey: 'axis', - value: '' - } - ]; - } - }); - }; - if (this.dataset.rowHeaderTree?.length) { - supplyAxisNode(this.dataset.rowHeaderTree); - } else { - this.dataset.rowHeaderTree = [ - { - dimensionKey: 'axis', - value: '' - } - ]; - } - } - - if (!options.columnTree) { - if (options.indicatorsAsCol !== false) { - this.dataset.colHeaderTree = supplementIndicatorNodesForCustomTree( - this.dataset.colHeaderTree, - options.indicators - ); - } - } - - if (!options.rowTree) { - if (options.indicatorsAsCol === false) { - this.dataset.rowHeaderTree = supplementIndicatorNodesForCustomTree( - this.dataset.rowHeaderTree, - options.indicators - ); - } - } - columnDimensionTree = new DimensionTree( - (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - - rowDimensionTree = new DimensionTree( - (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - - internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset, columnDimensionTree, rowDimensionTree); + // } + internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset); // else { // console.warn('VTable Warn: your option is invalid, please check it!'); // return this; @@ -477,7 +256,6 @@ export class PivotChart extends BaseTable implements PivotChartAPI { // 更新表头 this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; // this.hasMedia = null; // 避免重复绑定 // 清空目前数据 @@ -498,19 +276,9 @@ export class PivotChart extends BaseTable implements PivotChartAPI { // 生成单元格场景树 this.scenegraph.createSceneGraph(); if (options.title) { - const Title = Factory.getComponent('title') as ITitleComponent; this.internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } - if (this.options.emptyTip) { - if (this.internalProps.emptyTip) { - this.internalProps.emptyTip.resetVisible(); - } else { - const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; - this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); - this.internalProps.emptyTip.resetVisible(); - } - } return new Promise(resolve => { setTimeout(resolve, 0); }); @@ -533,8 +301,7 @@ export class PivotChart extends BaseTable implements PivotChartAPI { table.rowCount = layoutMap.rowCount ?? 0; // table.frozenColCount = layoutMap.rowHeaderLevelCount; //这里不要这样写 这个setter会检查扁头宽度 可能将frozenColCount置为0 table.internalProps.frozenColCount = layoutMap.rowHeaderLevelCount ?? 0; - // table.frozenRowCount = layoutMap.headerLevelCount; - table.frozenRowCount = Math.max(layoutMap.headerLevelCount, this.options.frozenRowCount ?? 0); + table.frozenRowCount = layoutMap.headerLevelCount; if (table.bottomFrozenRowCount !== (layoutMap?.bottomFrozenRowCount ?? 0)) { table.bottomFrozenRowCount = layoutMap?.bottomFrozenRowCount ?? 0; } @@ -633,34 +400,17 @@ export class PivotChart extends BaseTable implements PivotChartAPI { return typeof fieldFormat === 'function' ? fieldFormat(title, col, row, this as BaseTableAPI) : title; } if (this.dataset) { - let indicatorPosition: { position: 'col' | 'row'; index?: number }; const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any, index: number) => { - if (colPath.indicatorKey) { - indicatorPosition = { - position: 'col', - index - }; - } + const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any) => { return colPath.indicatorKey ?? colPath.value; }); - const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any, index: number) => { - if (rowPath.indicatorKey) { - indicatorPosition = { - position: 'row', - index - }; - } + const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any) => { return rowPath.indicatorKey ?? rowPath.value; }); const aggregator = this.dataset.getAggregator( - // !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, - // this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, - rowKeys, - colKeys, - (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row), - true, - indicatorPosition + !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, + this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, + (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row) ); return aggregator.value ? aggregator.value() : undefined; } @@ -699,34 +449,17 @@ export class PivotChart extends BaseTable implements PivotChartAPI { return typeof title === 'function' ? title() : title; } if (this.dataset) { - let indicatorPosition: { position: 'col' | 'row'; index?: number }; const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any, index: number) => { - if (colPath.indicatorKey) { - indicatorPosition = { - position: 'col', - index - }; - } + const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any) => { return colPath.indicatorKey ?? colPath.value; }); - const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any, index: number) => { - if (rowPath.indicatorKey) { - indicatorPosition = { - position: 'row', - index - }; - } + const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any) => { return rowPath.indicatorKey ?? rowPath.value; }); const aggregator = this.dataset.getAggregator( - // !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, - // this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, - rowKeys, - colKeys, - (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row), - true, - indicatorPosition + !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, + this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, + (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row) ); return aggregator.value ? aggregator.value() : undefined; // return '' @@ -750,34 +483,17 @@ export class PivotChart extends BaseTable implements PivotChartAPI { return undefined; } if (this.dataset) { - let indicatorPosition: { position: 'col' | 'row'; index?: number }; const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any, index: number) => { - if (colPath.indicatorKey) { - indicatorPosition = { - position: 'col', - index - }; - } + const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any) => { return colPath.indicatorKey ?? colPath.value; }); - const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any, index: number) => { - if (rowPath.indicatorKey) { - indicatorPosition = { - position: 'row', - index - }; - } + const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any) => { return rowPath.indicatorKey ?? rowPath.value; }); const aggregator = this.dataset.getAggregator( - // !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, - // this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, - rowKeys, - colKeys, - (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row), - true, - indicatorPosition + !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, + this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, + (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row) ); return aggregator.records; // return '' @@ -788,6 +504,53 @@ export class PivotChart extends BaseTable implements PivotChartAPI { getCellRawRecord(col: number, row: number) { return this.getCellOriginRecord(col, row); } + /** + * 全量更新排序规则 TODO 待完善 + * @param sortRules + */ + updateSortRules(sortRules: SortRules) { + this.internalProps.dataConfig.sortRules = sortRules; + this.dataset.updateSortRules(sortRules); + this.internalProps.layoutMap.resetHeaderTree(); + // 清空单元格内容 + this.scenegraph.clearCells(); + this.refreshHeader(); + // 生成单元格场景树 + this.scenegraph.createSceneGraph(); + this.render(); + } + updatePivotSortState( + pivotSortStateConfig: { + dimensions: IDimensionInfo[]; + order: SortOrder; + }[] + ) { + // // dimensions: IDimensionInfo[], order: SortOrder + // // 清空当前 pivot sort 状态 + // const cells = this.pivotSortState.map((cell) => ({ col: cell.col, row: cell.row })); + // this.pivotSortState.length = 0; + // cells.map((cell) => { + // this.invalidateCellRange(this.getCellRange(cell.col, cell.row)); + // }); + + // 更新 pivot sort 状态 + for (let i = 0; i < pivotSortStateConfig.length; i++) { + const { dimensions, order } = pivotSortStateConfig[i]; + const cellAddress = (this.internalProps.layoutMap as PivotHeaderLayoutMap).getPivotCellAdress(dimensions); + + cellAddress && + this.pivotSortState.push({ + col: cellAddress.col, + row: cellAddress.row, + order + }); + } + + // // 更新相关单元格样式 + // this.pivotSortState.map((cell) => { + // this.invalidateCellRange(this.getCellRange(cell.col, cell.row)); + // }); + } getPivotSortState(col: number, row: number): SortOrder { if (!this.pivotSortState) { @@ -852,7 +615,31 @@ export class PivotChart extends BaseTable implements PivotChartAPI { * @param row */ toggleHierarchyState(col: number, row: number) { - //nothing + const hierarchyState = this.getHierarchyState(col, row); + if (hierarchyState === HierarchyState.expand) { + this.fireListeners(PIVOT_CHART_EVENT_TYPE.TREE_HIERARCHY_STATE_CHANGE, { + col: col, + row: row, + hierarchyState: HierarchyState.collapse + }); + } else if (hierarchyState === HierarchyState.collapse) { + this.fireListeners(PIVOT_CHART_EVENT_TYPE.TREE_HIERARCHY_STATE_CHANGE, { + col: col, + row: row, + hierarchyState: HierarchyState.expand, + originData: this.getCellOriginRecord(col, row) + }); + } + + const result = (this.internalProps.layoutMap as PivotHeaderLayoutMap).toggleHierarchyState(col, row); + //影响行数 + this.refreshRowColCount(); + // this.scenegraph.clearCells(); + // this.scenegraph.createSceneGraph(); + // this.invalidate(); + this.clearCellStyleCache(); + this.scenegraph.updateHierarchyIcon(col, row); + this.scenegraph.updateRow(result.removeCellPositions, result.addCellPositions); } /** * 通过表头的维度值路径来计算单元格位置 getCellAddressByHeaderPaths接口更强大一些 不限表头 不限参数格式 @@ -932,8 +719,6 @@ export class PivotChart extends BaseTable implements PivotChartAPI { * @returns */ private _generateCollectValuesConfig(columnKeys: string[], rowKeys: string[]): Record { - columnKeys = columnKeys.filter(key => key !== IndicatorDimensionKeyPlaceholder); - rowKeys = rowKeys.filter(key => key !== IndicatorDimensionKeyPlaceholder); const indicators = this.internalProps.indicators; const collectValuesBy: Record = {}; @@ -1194,17 +979,10 @@ export class PivotChart extends BaseTable implements PivotChartAPI { } /** 获取图例的选择状态 */ getLegendSelected() { - const selected: any[] = []; - this.internalProps.legends?.forEach(legend => { - const data = (legend.legendComponent as any)._getSelectedLegends().map((d: any) => d.label); - selected.push(...data); - }); - return selected; + return (this.internalProps.legends.legendComponent as any)._getSelectedLegends().map((d: any) => d.label); } setLegendSelected(selectedData: (string | number)[]) { - this.internalProps.legends?.forEach(legend => { - (legend.legendComponent as DiscreteLegend).setSelected(selectedData); - }); + (this.internalProps.legends.legendComponent as DiscreteLegend).setSelected(selectedData); // this.updateFilterRules([{ filterKey: '20001', filteredValues: selectedData }]); // this.invalidate(); } @@ -1389,29 +1167,10 @@ export class PivotChart extends BaseTable implements PivotChartAPI { const internalProps = this.internalProps; this.dataset.setRecords(records); - let columnDimensionTree; - let rowDimensionTree; - if (options.columnTree) { - columnDimensionTree = internalProps.layoutMap.columnDimensionTree; - } else { - columnDimensionTree = new DimensionTree( - (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - } - if (options.rowTree) { - rowDimensionTree = internalProps.layoutMap.rowDimensionTree; - } else { - rowDimensionTree = new DimensionTree( - (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - } - internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset, columnDimensionTree, rowDimensionTree); + internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset); // 更新表头 this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; // 清空单元格内容 this.scenegraph.clearCells(); @@ -1462,35 +1221,4 @@ export class PivotChart extends BaseTable implements PivotChartAPI { changeRecordOrder(source: number, target: number) { // } - /** 获取列头树结构 */ - getLayoutColumnTree(): LayouTreeNode[] { - const layoutMap = this.internalProps.layoutMap; - return layoutMap.getLayoutColumnTree(); - } - /** 获取表格列头树形结构的占位的总节点数 */ - getLayoutColumnTreeCount(): number { - const layoutMap = this.internalProps.layoutMap; - return layoutMap.getLayoutColumnTreeCount(); - } - /** 获取行头树结构 */ - getLayoutRowTree(): LayouTreeNode[] { - const layoutMap = this.internalProps.layoutMap; - return layoutMap.getLayoutRowTree(); - } - /** 获取表格行头树形结构的占位的总节点数 */ - getLayoutRowTreeCount(): number { - const layoutMap = this.internalProps.layoutMap; - return layoutMap.getLayoutRowTreeCount(); - } - /** - * 根据行列号获取表头tree节点,包含了用户在自定义树rowTree及columnTree树上的自定义属性(也是内部布局树的节点,获取后请不要随意修改) - * @param col - * @param row - * @returns - */ - getCellHeaderTreeNodes(col: number, row: number): ICellHeaderPaths { - const layoutMap = this.internalProps.layoutMap; - const headerNodes = layoutMap.getCellHeaderPathsWithTreeNode(col, row); - return headerNodes; - } } diff --git a/packages/vtable/src/PivotTable-all.ts b/packages/vtable/src/PivotTable-all.ts deleted file mode 100644 index caafdc0ed..000000000 --- a/packages/vtable/src/PivotTable-all.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { PivotTable } from './PivotTable'; -import { - registerAxis, - registerEmptyTip, - registerLegend, - registerMenu, - registerTitle, - registerTooltip -} from './components'; -import { - registerChartCell, - registerCheckboxCell, - registerImageCell, - registerProgressBarCell, - registerRadioCell, - registerSparkLineCell, - registerTextCell, - registerVideoCell -} from './scenegraph/group-creater/cell-type'; - -registerAxis(); -registerEmptyTip(); -registerLegend(); -registerMenu(); -registerTitle(); -registerTooltip(); - -registerChartCell(); -registerCheckboxCell(); -registerImageCell(); -registerProgressBarCell(); -registerRadioCell(); -registerSparkLineCell(); -registerTextCell(); -registerVideoCell(); - -export class PivotTableAll extends PivotTable {} diff --git a/packages/vtable/src/PivotTable-simple.ts b/packages/vtable/src/PivotTable-simple.ts deleted file mode 100644 index f95c2e2a1..000000000 --- a/packages/vtable/src/PivotTable-simple.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { PivotTable } from './PivotTable'; -import { registerTextCell } from './scenegraph/group-creater/cell-type'; - -registerTextCell(); - -export class PivotTableSimple extends PivotTable {} diff --git a/packages/vtable/src/PivotTable.ts b/packages/vtable/src/PivotTable.ts index 44fa6e68d..dc723256f 100644 --- a/packages/vtable/src/PivotTable.ts +++ b/packages/vtable/src/PivotTable.ts @@ -16,11 +16,9 @@ import type { IPagination, CellLocation, IIndicator, - ColumnDefine, - SortByIndicatorRule, - SortTypeRule + ColumnDefine } from './ts-types'; -import { HierarchyState, SortType } from './ts-types'; +import { HierarchyState } from './ts-types'; import { PivotHeaderLayoutMap } from './layout/pivot-header-layout'; import { FlatDataToObjects } from './dataset/flatDataToObject'; import { PIVOT_TABLE_EVENT_TYPE } from './ts-types/pivot-table/PIVOT_TABLE_EVENT_TYPE'; @@ -28,11 +26,10 @@ import { cellInRange, emptyFn } from './tools/helper'; import { Dataset } from './dataset/dataset'; import { BaseTable } from './core/BaseTable'; import type { BaseTableAPI, HeaderData, PivotTableProtected } from './ts-types/base-table'; -import type { ITitleComponent } from './components/title/title'; -import { cloneDeep, isNumber, isValid } from '@visactor/vutils'; +import { Title } from './components/title/title'; +import { cloneDeep, isValid } from '@visactor/vutils'; import { Env } from './tools/env'; -import type { ITreeLayoutHeadNode } from './layout/tree-helper'; -import { DimensionTree, type LayouTreeNode } from './layout/tree-helper'; +import type { LayouTreeNode } from './layout/tree-helper'; import { TABLE_EVENT_TYPE } from './core/TABLE_EVENT_TYPE'; import { EditManeger } from './edit/edit-manager'; import * as editors from './edit/editors'; @@ -41,19 +38,11 @@ import { computeColWidth } from './scenegraph/layout/compute-col-width'; import { computeRowHeight } from './scenegraph/layout/compute-row-height'; import { isAllDigits } from './tools/util'; import type { IndicatorData } from './ts-types/list-table/layout-map/api'; -import { cloneDeepSpec } from '@visactor/vutils-extension'; -import { parseColKeyRowKeyForPivotTable, supplementIndicatorNodesForCustomTree } from './layout/layout-helper'; -import type { IEmptyTipComponent } from './components/empty-tip/empty-tip'; -import { Factory } from './core/factory'; - +import { cloneDeepSpec } from '@vutils-extension'; export class PivotTable extends BaseTable implements PivotTableAPI { - layoutNodeId: { seqId: number } = { seqId: 0 }; declare internalProps: PivotTableProtected; declare options: PivotTableConstructorOptions; - pivotSortState: { - dimensions: IDimensionInfo[]; - order: SortOrder; - }[]; + pivotSortState: PivotSortState[]; editorManager: EditManeger; dataset?: Dataset; //数据处理对象 开启数据透视分析的表 flatDataToObjects?: FlatDataToObjects; //数据处理对象 聚合后的flat数据 转成便于查询的行列二维数组 @@ -74,159 +63,124 @@ export class PivotTable extends BaseTable implements PivotTableAPI { } } super(container as HTMLElement, options); - if (options) { - if ((options as any).layout) { - //TODO hack处理之前的demo都是定义到layout上的 所以这里直接并到options中 - Object.assign(options, (options as any).layout); + if ((options as any).layout) { + //TODO hack处理之前的demo都是定义到layout上的 所以这里直接并到options中 + Object.assign(options, (options as any).layout); + } + this.internalProps.columns = cloneDeep(options.columns); + this.internalProps.rows = cloneDeep(options.rows); + this.internalProps.indicators = cloneDeepSpec(options.indicators); + options.indicators?.forEach((indicatorDefine, index) => { + //如果editor 是一个IEditor的实例 需要这样重新赋值 否则clone后变质了 + if (typeof indicatorDefine === 'object' && indicatorDefine?.editor) { + (this.internalProps.indicators[index] as IIndicator).editor = indicatorDefine.editor; } - this.internalProps.columns = cloneDeep(options.columns); - this.internalProps.rows = cloneDeep(options.rows); - this.internalProps.indicators = cloneDeepSpec(options.indicators); - options.indicators?.forEach((indicatorDefine, index) => { - //如果editor 是一个IEditor的实例 需要这样重新赋值 否则clone后变质了 - if (typeof indicatorDefine === 'object' && indicatorDefine?.editor) { - (this.internalProps.indicators![index] as IIndicator).editor = indicatorDefine.editor; - } - }); - this.internalProps.columnTree = - options.indicatorsAsCol && !options.columns?.length && !options.columnTree ? [] : cloneDeep(options.columnTree); - this.internalProps.rowTree = - !options.indicatorsAsCol && !options.rows?.length && !options.rowTree ? [] : cloneDeep(options.rowTree); - this.internalProps.records = options.records; + }); + this.internalProps.columnTree = + options.indicatorsAsCol && !options.columns?.length && !options.columnTree ? [] : cloneDeep(options.columnTree); + this.internalProps.rowTree = + !options.indicatorsAsCol && !options.rows?.length && !options.rowTree ? [] : cloneDeep(options.rowTree); + this.internalProps.records = options.records; - //分页配置 - this.pagination = options.pagination; - this.internalProps.columnResizeType = options.columnResizeType ?? 'column'; - this.internalProps.rowResizeType = options.rowResizeType ?? 'row'; - this.internalProps.dataConfig = cloneDeep(options.dataConfig); + //分页配置 + this.pagination = options.pagination; + this.internalProps.columnResizeType = options.columnResizeType ?? 'column'; + this.internalProps.rowResizeType = options.rowResizeType ?? 'row'; + this.internalProps.dataConfig = cloneDeep(options.dataConfig); - const records = this.internalProps.records; - this.internalProps.recordsIsTwoDimensionalArray = false; - if (records?.[0]?.constructor === Array) { - this.internalProps.recordsIsTwoDimensionalArray = true; - } - if (options.customConfig?.enableDataAnalysis === false) { - // let columnDimensionTree; - // let rowDimensionTree; - // if (options.columnTree) { - const columnDimensionTree = new DimensionTree( - (this.internalProps.columnTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - // } - // if (options.rowTree) { - const rowDimensionTree = new DimensionTree( - (this.internalProps.rowTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId, - this.options.rowHierarchyType, - this.options.rowHierarchyType === 'tree' ? this.options.rowExpandLevel ?? 1 : undefined - ); - // } - this.internalProps.layoutMap = new PivotHeaderLayoutMap(this, null, columnDimensionTree, rowDimensionTree); - //判断如果数据是二维数组 则标识已经分析过 直接从二维数组挨个读取渲染即可 - //不是二维数组 对应是个object json对象 则表示flat数据,需要对应行列维度进行转成方便数据查询的行列树结构 - if (this.internalProps.recordsIsTwoDimensionalArray === false) { - this.flatDataToObjects = new FlatDataToObjects( - { - rows: this.internalProps.layoutMap.fullRowDimensionKeys, - columns: this.internalProps.layoutMap.colDimensionKeys, - indicators: this.internalProps.layoutMap.indicatorKeys, - indicatorsAsCol: this.internalProps.layoutMap.indicatorsAsCol, - indicatorDimensionKey: this.internalProps.layoutMap.indicatorDimensionKey - }, - records - ); - } - } else { - const keysResults = parseColKeyRowKeyForPivotTable(this, options); - const { rowKeys, columnKeys, indicatorKeys } = keysResults; - let { columnDimensionTree, rowDimensionTree } = keysResults; - this.dataset = new Dataset( - this.internalProps.dataConfig, - // this.pagination, - rowKeys, - columnKeys, - // options.indicatorsAsCol === false ? rowKeys.concat(IndicatorDimensionKeyPlaceholder) : rowKeys, - // options.indicatorsAsCol !== false ? columnKeys.concat(IndicatorDimensionKeyPlaceholder) : columnKeys, - indicatorKeys, - this.internalProps.indicators, - options.indicatorsAsCol ?? true, - options.records, - options.rowHierarchyType, - this.internalProps.columnTree, //传递自定义树形结构会在dataset中补充指标节点children - this.internalProps.rowTree - ); - if (!options.columnTree) { - if (options.indicatorsAsCol !== false) { - this.dataset.colHeaderTree = supplementIndicatorNodesForCustomTree( - this.dataset.colHeaderTree, - options.indicators - ); + // this.internalProps.enableDataAnalysis = options.enableDataAnalysis; + if (!options.rowTree && !options.columnTree) { + this.internalProps.enableDataAnalysis = true; + } else { + this.internalProps.enableDataAnalysis = false; + } + const records = this.internalProps.records; + if (this.internalProps.enableDataAnalysis && (options.rows || options.columns)) { + const rowKeys = + options.rows?.reduce((keys, rowObj) => { + if (typeof rowObj === 'string') { + keys.push(rowObj); + } else { + keys.push(rowObj.dimensionKey); } - columnDimensionTree = new DimensionTree( - (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - } - if (!options.rowTree) { - if (options.indicatorsAsCol === false) { - this.dataset.rowHeaderTree = supplementIndicatorNodesForCustomTree( - this.dataset.rowHeaderTree, - options.indicators - ); + return keys; + }, []) ?? []; + const columnKeys = + options.columns?.reduce((keys, columnObj) => { + if (typeof columnObj === 'string') { + keys.push(columnObj); + } else { + keys.push(columnObj.dimensionKey); } - rowDimensionTree = new DimensionTree( - (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId, - this.options.rowHierarchyType, - this.options.rowHierarchyType === 'tree' ? this.options.rowExpandLevel ?? 1 : undefined - ); - } - this.internalProps.layoutMap = new PivotHeaderLayoutMap( - this, - this.dataset, - columnDimensionTree, - rowDimensionTree + return keys; + }, []) ?? []; + const indicatorKeys = + options.indicators?.reduce((keys, indicatorObj) => { + if (typeof indicatorObj === 'string') { + keys.push(indicatorObj); + } else { + keys.push(indicatorObj.indicatorKey); + } + return keys; + }, []) ?? []; + this.dataset = new Dataset( + this.internalProps.dataConfig, + // this.pagination, + rowKeys, + columnKeys, + // options.indicatorsAsCol === false ? rowKeys.concat(IndicatorDimensionKeyPlaceholder) : rowKeys, + // options.indicatorsAsCol !== false ? columnKeys.concat(IndicatorDimensionKeyPlaceholder) : columnKeys, + indicatorKeys, + this.internalProps.indicators, + options.indicatorsAsCol ?? true, + options.records, + options.rowHierarchyType, + this.internalProps.columnTree, //传递自定义树形结构会在dataset中补充指标节点children + this.internalProps.rowTree + ); + this.internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset); + } else if (Array.isArray(this.internalProps.columnTree) || Array.isArray(this.internalProps.rowTree)) { + this.internalProps.layoutMap = new PivotHeaderLayoutMap(this, null); + //判断如果数据是二维数组 则标识已经分析过 直接从二维数组挨个读取渲染即可 + //不是二维数组 对应是个object json对象 则表示flat数据,需要对应行列维度进行转成方便数据查询的行列树结构 + if (records?.[0]?.constructor !== Array) { + this.flatDataToObjects = new FlatDataToObjects( + { + rows: this.internalProps.layoutMap.fullRowDimensionKeys, + columns: this.internalProps.layoutMap.colDimensionKeys, + indicators: this.internalProps.layoutMap.indicatorKeys, + indicatorsAsCol: this.internalProps.layoutMap.indicatorsAsCol, + indicatorDimensionKey: this.internalProps.layoutMap.indicatorDimensionKey + }, + records ); } - this._changePivotSortStateBySortRules(); - if ((options.pivotSortState?.length ?? 0) > 0) { - this.pivotSortState = []; - this.pivotSortState = options.pivotSortState; - // this.updatePivotSortState(options.pivotSortState); - } - if (Env.mode !== 'node') { - this.editorManager = new EditManeger(this); - } - - this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; - this.stateManager.initCheckedState(records); - // this.internalProps.frozenColCount = this.options.frozenColCount || this.rowHeaderLevelCount; - - // 生成单元格场景树 - this.scenegraph.createSceneGraph(); - // this.render(); + } else { + console.warn('VTable Warn: your option is invalid, please check it!'); + return; + } + this.pivotSortState = []; + if (options.pivotSortState) { + this.updatePivotSortState(options.pivotSortState); + } + if (Env.mode !== 'node') { + this.editorManager = new EditManeger(this); + } + this.refreshHeader(); + this.stateManager.initCheckedState(records); + // this.internalProps.frozenColCount = this.options.frozenColCount || this.rowHeaderLevelCount; + // 生成单元格场景树 + this.scenegraph.createSceneGraph(); + // this.render(); - if (options.title) { - const Title = Factory.getComponent('title') as ITitleComponent; - this.internalProps.title = new Title(options.title, this); - this.scenegraph.resize(); - } - if (this.options.emptyTip) { - if (this.internalProps.emptyTip) { - this.internalProps.emptyTip.resetVisible(); - } else { - const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; - this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); - this.internalProps.emptyTip.resetVisible(); - } - } - //为了确保用户监听得到这个事件 这里做了异步 确保vtable实例已经初始化完成 - setTimeout(() => { - this.fireListeners(TABLE_EVENT_TYPE.INITIALIZED, null); - }, 0); + if (options.title) { + this.internalProps.title = new Title(options.title, this); + this.scenegraph.resize(); } + //为了确保用户监听得到这个事件 这里做了异步 确保vtable实例已经初始化完成 + setTimeout(() => { + this.fireListeners(TABLE_EVENT_TYPE.INITIALIZED, null); + }, 0); } static get EVENT_TYPE(): typeof PIVOT_TABLE_EVENT_TYPE { return PIVOT_TABLE_EVENT_TYPE; @@ -246,10 +200,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { _canResizeColumn(col: number, row: number): boolean { const ifCan = super._canResizeColumn(col, row); if (ifCan) { - const isSeriesNumber = this.internalProps.layoutMap.isSeriesNumber(col, row); - if (isSeriesNumber && this.internalProps.rowSeriesNumber.disableColumnResize === true) { - return false; - } else if (!this.internalProps.layoutMap.indicatorsAsCol) { + if (!this.internalProps.layoutMap.indicatorsAsCol) { // 列上是否配置了禁止拖拽列宽的配置项disableColumnResize const cellDefine = this.internalProps.layoutMap.getBody(col, this.columnHeaderLevelCount); if ((cellDefine as IndicatorData)?.disableColumnResize) { @@ -264,7 +215,6 @@ export class PivotTable extends BaseTable implements PivotTableAPI { //维护选中状态 // const range = internalProps.selection.range; //保留原有单元格选中状态 super.updateOption(options); - this.layoutNodeId = { seqId: 0 }; this.internalProps.columns = cloneDeep(options.columns); this.internalProps.rows = cloneDeep(options.rows); this.internalProps.indicators = !options.indicators?.length ? [] : cloneDeepSpec(options.indicators); @@ -286,7 +236,12 @@ export class PivotTable extends BaseTable implements PivotTableAPI { internalProps.columnResizeType = options.columnResizeType ?? 'column'; internalProps.rowResizeType = options.rowResizeType ?? 'row'; internalProps.dataConfig = cloneDeep(options.dataConfig); - + // internalProps.enableDataAnalysis = options.enableDataAnalysis; + if (!options.rowTree && !options.columnTree) { + internalProps.enableDataAnalysis = true; + } else { + internalProps.enableDataAnalysis = false; + } //维护tree树形结构的展开状态 if ( options?.rowHierarchyType === 'tree' && @@ -304,48 +259,32 @@ export class PivotTable extends BaseTable implements PivotTableAPI { }); } const records = this.internalProps.records; - this.internalProps.recordsIsTwoDimensionalArray = false; - if (records?.[0]?.constructor === Array) { - this.internalProps.recordsIsTwoDimensionalArray = true; - } - //TODO 这里需要加上判断 dataConfig是否有配置变化 - if (options.customConfig?.enableDataAnalysis === false) { - let columnDimensionTree; - let rowDimensionTree; - if (options.columnTree) { - columnDimensionTree = new DimensionTree( - (this.internalProps.columnTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - } - if (options.rowTree) { - rowDimensionTree = new DimensionTree( - (this.internalProps.rowTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId, - this.options.rowHierarchyType, - this.options.rowHierarchyType === 'tree' ? this.options.rowExpandLevel ?? 1 : undefined - ); - } - internalProps.layoutMap = new PivotHeaderLayoutMap(this, null, columnDimensionTree, rowDimensionTree); - //判断如果数据是二维数组 则标识已经分析过 直接从二维数组挨个读取渲染即可 - //不是二维数组 对应是个object json对象 则表示flat数据,需要对应行列维度进行转成方便数据查询的行列树结构 - if (this.internalProps.recordsIsTwoDimensionalArray === false) { - this.flatDataToObjects = new FlatDataToObjects( - { - rows: internalProps.layoutMap.fullRowDimensionKeys, - columns: internalProps.layoutMap.colDimensionKeys, - indicators: internalProps.layoutMap.indicatorKeys, - indicatorsAsCol: internalProps.layoutMap.indicatorsAsCol, - indicatorDimensionKey: internalProps.layoutMap.indicatorDimensionKey - }, - records - ); - } - } else { - const keysResults = parseColKeyRowKeyForPivotTable(this, options); - const { rowKeys, columnKeys, indicatorKeys } = keysResults; - let { columnDimensionTree, rowDimensionTree } = keysResults; + if (this.internalProps.enableDataAnalysis && (options.rows || options.columns)) { + const rowKeys = options.rows?.reduce((keys, rowObj) => { + if (typeof rowObj === 'string') { + keys.push(rowObj); + } else { + keys.push(rowObj.dimensionKey); + } + return keys; + }, []); + const columnKeys = options.columns?.reduce((keys, columnObj) => { + if (typeof columnObj === 'string') { + keys.push(columnObj); + } else { + keys.push(columnObj.dimensionKey); + } + return keys; + }, []); + const indicatorKeys = options.indicators?.reduce((keys, indicatorObj) => { + if (typeof indicatorObj === 'string') { + keys.push(indicatorObj); + } else { + keys.push(indicatorObj.indicatorKey); + } + return keys; + }, []); this.dataset = new Dataset( internalProps.dataConfig, // this.pagination, @@ -354,50 +293,38 @@ export class PivotTable extends BaseTable implements PivotTableAPI { indicatorKeys, this.internalProps.indicators, options.indicatorsAsCol ?? true, - records, + options.records, options.rowHierarchyType, this.internalProps.columnTree, //传递自定义树形结构会在dataset中补充指标节点children this.internalProps.rowTree ); - if (!options.columnTree) { - if (options.indicatorsAsCol !== false) { - this.dataset.colHeaderTree = supplementIndicatorNodesForCustomTree( - this.dataset.colHeaderTree, - options.indicators - ); - } - columnDimensionTree = new DimensionTree( - (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - } - if (!options.rowTree) { - if (options.indicatorsAsCol === false) { - this.dataset.rowHeaderTree = supplementIndicatorNodesForCustomTree( - this.dataset.rowHeaderTree, - options.indicators - ); - } - rowDimensionTree = new DimensionTree( - (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId, - this.options.rowHierarchyType, - this.options.rowHierarchyType === 'tree' ? this.options.rowExpandLevel ?? 1 : undefined + internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset); + } else if (Array.isArray(this.internalProps.columnTree) || Array.isArray(this.internalProps.rowTree)) { + internalProps.layoutMap = new PivotHeaderLayoutMap(this, null); + //判断如果数据是二维数组 则标识已经分析过 直接从二维数组挨个读取渲染即可 + //不是二维数组 对应是个object json对象 则表示flat数据,需要对应行列维度进行转成方便数据查询的行列树结构 + if (records?.[0]?.constructor !== Array) { + this.flatDataToObjects = new FlatDataToObjects( + { + rows: internalProps.layoutMap.fullRowDimensionKeys, + columns: internalProps.layoutMap.colDimensionKeys, + indicators: internalProps.layoutMap.indicatorKeys, + indicatorsAsCol: internalProps.layoutMap.indicatorsAsCol, + indicatorDimensionKey: internalProps.layoutMap.indicatorDimensionKey + }, + records ); } - internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset, columnDimensionTree, rowDimensionTree); + } else { + console.warn('VTable Warn: your option is invalid, please check it!'); + return this; } - this._changePivotSortStateBySortRules(); - - if ((options.pivotSortState?.length ?? 0) > 0) { - this.pivotSortState = []; - this.pivotSortState = options.pivotSortState; - // this.updatePivotSortState(options.pivotSortState); + this.pivotSortState = []; + if (options.pivotSortState) { + this.updatePivotSortState(options.pivotSortState); } - // 更新表头 this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; // this.hasMedia = null; // 避免重复绑定 // 清空目前数据 @@ -421,19 +348,10 @@ export class PivotTable extends BaseTable implements PivotTableAPI { // this.scenegraph.resize(); // } if (options.title) { - const Title = Factory.getComponent('title') as ITitleComponent; this.internalProps.title = new Title(options.title, this); this.scenegraph.resize(); } - if (this.options.emptyTip) { - if (this.internalProps.emptyTip) { - this.internalProps.emptyTip.resetVisible(); - } else { - const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; - this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); - this.internalProps.emptyTip.resetVisible(); - } - } + // this.render(); return new Promise(resolve => { setTimeout(resolve, 0); @@ -501,8 +419,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { (layoutMap.rowHeaderLevelCount ?? 0) + layoutMap.leftRowSeriesNumberColumnCount, this.options.frozenColCount ?? 0 ); - // table.frozenRowCount = layoutMap.headerLevelCount; - table.frozenRowCount = Math.max(layoutMap.headerLevelCount, this.options.frozenRowCount ?? 0); + table.frozenRowCount = layoutMap.headerLevelCount; if (table.bottomFrozenRowCount !== (this.options.bottomFrozenRowCount ?? 0)) { table.bottomFrozenRowCount = this.options.bottomFrozenRowCount ?? 0; @@ -571,48 +488,19 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (table.internalProps.layoutMap.isHeader(col, row)) { return undefined; } - if (this.internalProps.recordsIsTwoDimensionalArray) { - const rowIndex = this.getBodyIndexByRow(row); - const colIndex = this.getBodyIndexByCol(col); - return this.records[rowIndex]?.[colIndex]; - } else if (this.dataset) { + if (this.dataset) { const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); if (cellDimensionPath) { - let indicatorPosition: { position: 'col' | 'row'; index?: number }; - const colKeys = cellDimensionPath.colHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((colPath: any, index: number) => { - if (colPath.indicatorKey) { - indicatorPosition = { - position: 'col', - index - }; - } - return colPath.indicatorKey ?? colPath.value; - }); - const rowKeys = cellDimensionPath.rowHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((rowPath: any, index: number) => { - if (rowPath.indicatorKey) { - indicatorPosition = { - position: 'row', - index - }; - } - return rowPath.indicatorKey ?? rowPath.value; - }); + const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any) => { + return colPath.indicatorKey ?? colPath.value; + }); + const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any) => { + return rowPath.indicatorKey ?? rowPath.value; + }); const aggregator = this.dataset.getAggregator( - // !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, - // this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, - rowKeys, - colKeys, - (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row), - true, - indicatorPosition + !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, + this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, + (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row) ); if (aggregator.records && aggregator.records.length >= 1) { return aggregator.records[0][field]; @@ -638,6 +526,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { return treeNode?.record[field]; } } + const rowIndex = this.getBodyIndexByRow(row); + const colIndex = this.getBodyIndexByCol(col); + return this.records[rowIndex]?.[colIndex]; } getCellValue(col: number, row: number, skipCustomMerge?: boolean): FieldData { if (!skipCustomMerge) { @@ -657,64 +548,20 @@ export class PivotTable extends BaseTable implements PivotTableAPI { const { title, fieldFormat } = this.internalProps.layoutMap.getHeader(col, row) as HeaderData; return typeof fieldFormat === 'function' ? fieldFormat(title, col, row, this as BaseTableAPI) : title; } - if (this.internalProps.recordsIsTwoDimensionalArray) { - const { fieldFormat } = this.internalProps.layoutMap.getBody(col, row) as IndicatorData; - const rowIndex = this.getBodyIndexByRow(row); - const colIndex = this.getBodyIndexByCol(col); - const dataValue = this.records[rowIndex]?.[colIndex]; - // const cellHeaderPaths = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - if (typeof fieldFormat === 'function') { - const fieldResult = fieldFormat(dataValue, col, row, this as BaseTableAPI); - return fieldResult; - } - return dataValue; - } else if (this.dataset) { + if (this.dataset) { const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - let indicatorPosition: { position: 'col' | 'row'; index?: number }; - const colKeys = cellDimensionPath.colHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - ?.map((colPath: any, index: number) => { - if (colPath.indicatorKey) { - indicatorPosition = { - position: 'col', - index - }; - } - return colPath.indicatorKey ?? colPath.value; - }); - const rowKeys = cellDimensionPath.rowHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - ?.map((rowPath: any, index: number) => { - if (rowPath.indicatorKey) { - indicatorPosition = { - position: 'row', - index - }; - } - return rowPath.indicatorKey ?? rowPath.value; - }); + const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any) => { + return colPath.indicatorKey ?? colPath.value; + }); + const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any) => { + return rowPath.indicatorKey ?? rowPath.value; + }); const aggregator = this.dataset.getAggregator( - // !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, - // this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, - rowKeys, - colKeys, - (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row), - true, - indicatorPosition + !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, + this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, + (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row) ); - const { fieldFormat } = this.internalProps.layoutMap.getBody(col, row) as IndicatorData; - // return typeof fieldFormat === 'function' - // ? fieldFormat(valueNode?.value, col, row, this as BaseTableAPI) - // : valueNode?.value ?? ''; - return aggregator.formatValue - ? aggregator.formatValue(col, row, this as BaseTableAPI) - : typeof fieldFormat === 'function' - ? fieldFormat(aggregator?.value(), col, row, this as BaseTableAPI) - : aggregator?.value() ?? ''; + return aggregator.formatValue ? aggregator.formatValue(col, row, this as BaseTableAPI) : ''; } else if (this.flatDataToObjects) { //数据为行列树结构 根据row col获取对应的维度名称 查找到对应值 const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); @@ -734,6 +581,16 @@ export class PivotTable extends BaseTable implements PivotTableAPI { ? fieldFormat(valueNode?.value, col, row, this as BaseTableAPI) : valueNode?.value ?? ''; } + const { fieldFormat } = this.internalProps.layoutMap.getBody(col, row) as IndicatorData; + const rowIndex = this.getBodyIndexByRow(row); + const colIndex = this.getBodyIndexByCol(col); + const dataValue = this.records[rowIndex]?.[colIndex]; + // const cellHeaderPaths = this.internalProps.layoutMap.getCellHeaderPaths(col, row); + if (typeof fieldFormat === 'function') { + const fieldResult = fieldFormat(dataValue, col, row, this as BaseTableAPI); + return fieldResult; + } + return dataValue; // return this.getFieldData(fieldFormat || field, col, row); } @@ -743,48 +600,18 @@ export class PivotTable extends BaseTable implements PivotTableAPI { const { title } = table.internalProps.layoutMap.getHeader(col, row); return typeof title === 'function' ? title() : title; } - if (this.internalProps.recordsIsTwoDimensionalArray) { - const rowIndex = this.getBodyIndexByRow(row); - const colIndex = this.getBodyIndexByCol(col); - const dataValue = this.records[rowIndex]?.[colIndex]; - return dataValue; - } else if (this.dataset) { - let indicatorPosition: { position: 'col' | 'row'; index?: number }; + if (this.dataset) { const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - const colKeys = cellDimensionPath.colHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((colPath: any, index: number) => { - if (colPath.indicatorKey) { - indicatorPosition = { - position: 'col', - index - }; - } - return colPath.indicatorKey ?? colPath.value; - }); - const rowKeys = cellDimensionPath.rowHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((rowPath: any, index: number) => { - if (rowPath.indicatorKey) { - indicatorPosition = { - position: 'row', - index - }; - } - return rowPath.indicatorKey ?? rowPath.value; - }); + const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any) => { + return colPath.indicatorKey ?? colPath.value; + }); + const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any) => { + return rowPath.indicatorKey ?? rowPath.value; + }); const aggregator = this.dataset.getAggregator( - // !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, - // this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, - rowKeys, - colKeys, - (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row), - true, - indicatorPosition + !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, + this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, + (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row) ); return aggregator.value ? aggregator.value() : undefined; // return '' @@ -804,7 +631,10 @@ export class PivotTable extends BaseTable implements PivotTableAPI { ); return treeNode?.value; } - + const rowIndex = this.getBodyIndexByRow(row); + const colIndex = this.getBodyIndexByCol(col); + const dataValue = this.records[rowIndex]?.[colIndex]; + return dataValue; // const { field } = table.internalProps.layoutMap.getBody(col, row); // return table.getFieldData(field, col, row); } @@ -816,48 +646,19 @@ export class PivotTable extends BaseTable implements PivotTableAPI { const { title } = table.internalProps.layoutMap.getHeader(col, row); return typeof title === 'function' ? title() : title; } - if (this.internalProps.recordsIsTwoDimensionalArray) { - const rowIndex = this.getBodyIndexByRow(row); - const colIndex = this.getBodyIndexByCol(col); - const dataValue = this.records[rowIndex]?.[colIndex]; - return dataValue; - } else if (this.dataset) { - let indicatorPosition: { position: 'col' | 'row'; index?: number }; + if (this.dataset) { const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - const colKeys = cellDimensionPath.colHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((colPath: any, index: number) => { - if (colPath.indicatorKey) { - indicatorPosition = { - position: 'col', - index - }; - } - return colPath.indicatorKey ?? colPath.value; - }); - const rowKeys = cellDimensionPath.rowHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((rowPath: any, index: number) => { - if (rowPath.indicatorKey) { - indicatorPosition = { - position: 'row', - index - }; - } - return rowPath.indicatorKey ?? rowPath.value; - }); + const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any) => { + return colPath.indicatorKey ?? colPath.value; + }); + const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any) => { + return rowPath.indicatorKey ?? rowPath.value; + }); const aggregator = this.dataset.getAggregator( - // !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, - // this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, - rowKeys, - colKeys, + !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, + this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row), - false, - indicatorPosition + false ); return aggregator.value ? aggregator.value() : undefined; } else if (this.flatDataToObjects) { @@ -877,6 +678,10 @@ export class PivotTable extends BaseTable implements PivotTableAPI { ); return treeNode?.value; } + const rowIndex = this.getBodyIndexByRow(row); + const colIndex = this.getBodyIndexByCol(col); + const dataValue = this.records[rowIndex]?.[colIndex]; + return dataValue; } // 获取原始数据 @@ -885,48 +690,18 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (table.internalProps.layoutMap.isHeader(col, row)) { return undefined; } - if (this.internalProps.recordsIsTwoDimensionalArray) { - const rowIndex = this.getBodyIndexByRow(row); - const colIndex = this.getBodyIndexByCol(col); - const dataValue = this.records[rowIndex]?.[colIndex]; - return dataValue; - } else if (this.dataset) { - let indicatorPosition: { position: 'col' | 'row'; index?: number }; + if (this.dataset) { const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - const colKeys = cellDimensionPath.colHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((colPath: any, index: number) => { - if (colPath.indicatorKey) { - indicatorPosition = { - position: 'col', - index - }; - } - return colPath.indicatorKey ?? colPath.value; - }); - const rowKeys = cellDimensionPath.rowHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((rowPath: any, index: number) => { - if (rowPath.indicatorKey) { - indicatorPosition = { - position: 'row', - index - }; - } - return rowPath.indicatorKey ?? rowPath.value; - }); + const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any) => { + return colPath.indicatorKey ?? colPath.value; + }); + const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any) => { + return rowPath.indicatorKey ?? rowPath.value; + }); const aggregator = this.dataset.getAggregator( - // !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, - // this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, - rowKeys, - colKeys, - (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row), - true, - indicatorPosition + !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, + this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, + (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row) ); return aggregator.records; // return '' @@ -946,6 +721,10 @@ export class PivotTable extends BaseTable implements PivotTableAPI { ); return treeNode?.record; } + const rowIndex = this.getBodyIndexByRow(row); + const colIndex = this.getBodyIndexByCol(col); + const dataValue = this.records[rowIndex]?.[colIndex]; + return dataValue; } getCellRawRecord(col: number, row: number) { @@ -953,48 +732,18 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (table.internalProps.layoutMap.isHeader(col, row)) { return undefined; } - if (this.internalProps.recordsIsTwoDimensionalArray) { - const rowIndex = this.getBodyIndexByRow(row); - const colIndex = this.getBodyIndexByCol(col); - const dataValue = this.records[rowIndex]?.[colIndex]; - return dataValue; - } else if (this.dataset) { - let indicatorPosition: { position: 'col' | 'row'; index?: number }; + if (this.dataset) { const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - const colKeys = cellDimensionPath.colHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((colPath: any, index: number) => { - if (colPath.indicatorKey) { - indicatorPosition = { - position: 'col', - index - }; - } - return colPath.indicatorKey ?? colPath.value; - }); - const rowKeys = cellDimensionPath.rowHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((rowPath: any, index: number) => { - if (rowPath.indicatorKey) { - indicatorPosition = { - position: 'row', - index - }; - } - return rowPath.indicatorKey ?? rowPath.value; - }); + const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any) => { + return colPath.indicatorKey ?? colPath.value; + }); + const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any) => { + return rowPath.indicatorKey ?? rowPath.value; + }); const aggregator = this.dataset.getAggregator( - // !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, - // this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, - rowKeys, - colKeys, - (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row), - false, - indicatorPosition + !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, + this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, + (this.internalProps.layoutMap as PivotHeaderLayoutMap).getIndicatorKey(col, row) ); return aggregator.records; // return '' @@ -1015,91 +764,26 @@ export class PivotTable extends BaseTable implements PivotTableAPI { ); return treeNode?.record; } + const rowIndex = this.getBodyIndexByRow(row); + const colIndex = this.getBodyIndexByCol(col); + const dataValue = this.records[rowIndex]?.[colIndex]; + return dataValue; } /** * 全量更新排序规则 * @param sortRules */ - updateSortRules(sortRules: SortRules, col?: number, row?: number) { - if (this.internalProps.dataConfig) { - this.internalProps.dataConfig.sortRules = sortRules; - } else { - this.internalProps.dataConfig = { sortRules }; - } + updateSortRules(sortRules: SortRules) { + this.internalProps.dataConfig.sortRules = sortRules; this.dataset.updateSortRules(sortRules); - this._changePivotSortStateBySortRules(); - const { layoutMap } = this.internalProps; - layoutMap.resetHeaderTree(); + this.internalProps.layoutMap.resetHeaderTree(); // 清空单元格内容 this.scenegraph.clearCells(); - if (isNumber(col) && isNumber(row)) { - if (this.isRowHeader(col, row)) { - this.setMinMaxLimitWidth(true); - this.internalProps._widthResizedColMap.clear(); - } else if (this.isCornerHeader(col, row)) { - if (layoutMap.cornerSetting.titleOnDimension === 'column') { - this.setMinMaxLimitWidth(true); - this.internalProps._widthResizedColMap.clear(); - } else if (layoutMap.cornerSetting.titleOnDimension === 'row') { - this.internalProps._heightResizedRowMap.clear(); - } - } else if (this.isColumnHeader(col, row)) { - this.internalProps._heightResizedRowMap.clear(); - } - this.refreshRowColCount(); - } else { - this.refreshHeader(); - } - this.internalProps.useOneRowHeightFillAll = false; + this.refreshHeader(); // 生成单元格场景树 - this.scenegraph.createSceneGraph(true); + this.scenegraph.createSceneGraph(); this.render(); } - _changePivotSortStateBySortRules() { - this.pivotSortState = []; - const sortRules = this.internalProps.dataConfig?.sortRules ?? []; - for (let i = 0; i < sortRules.length; i++) { - const sortRule = sortRules[i]; - if ((sortRule as SortByIndicatorRule).sortType) { - const dimensions: IDimensionInfo[] = []; - if ((sortRule as SortByIndicatorRule).sortByIndicator) { - if ( - (sortRule as SortByIndicatorRule).sortField === - (this.dataset.indicatorsAsCol - ? this.dataset.rows[this.dataset.rows.length - 1] - : this.dataset.columns[this.dataset.columns.length - 1]) - ) { - for (let j = 0; j < (sortRule as SortByIndicatorRule).query.length; j++) { - dimensions.push({ - dimensionKey: this.dataset.indicatorsAsCol ? this.dataset.columns[j] : this.dataset.rows[j], - value: (sortRule as SortByIndicatorRule).query[j] - }); - } - dimensions.push({ - indicatorKey: (sortRule as SortByIndicatorRule).sortByIndicator, - value: - this.internalProps.layoutMap.getIndicatorInfo((sortRule as SortByIndicatorRule).sortByIndicator) - ?.title ?? (sortRule as SortByIndicatorRule).sortByIndicator - }); - } - } else { - dimensions.push({ - dimensionKey: (sortRule as SortTypeRule).sortField, - isPivotCorner: true, - value: (sortRule as SortTypeRule).sortField - }); - } - this.pivotSortState.push({ - dimensions, - order: (sortRule as SortByIndicatorRule).sortType - }); - // this.changePivotSortState({ - // dimensions, - // order: (sortRule as SortByIndicatorRule).sortType - // }); - } - } - } /** * 更新排序状态 * @param pivotSortStateConfig.dimensions 排序状态维度对应关系;pivotSortStateConfig.order 排序状态 @@ -1110,120 +794,31 @@ export class PivotTable extends BaseTable implements PivotTableAPI { order: SortOrder; }[] ) { - this.pivotSortState = pivotSortStateConfig; - } - // changePivotSortState(pivotSortState: { dimensions: IDimensionInfo[]; order: SortOrder }) { - // let isExist = false; - // for (let i = 0; i < this.pivotSortState.length; i++) { - // const pivotSortStateItem = this.pivotSortState[i]; - // const dimensions = pivotSortStateItem.dimensions; - // const isEqual = dimensions.every( - // (item, index) => - // (item.dimensionKey === pivotSortState.dimensions[index].dimensionKey || - // item.indicatorKey === pivotSortState.dimensions[index].indicatorKey) && - // item.value === pivotSortState.dimensions[index].value && - // ((isValid(item.isPivotCorner ?? pivotSortState.dimensions[index].isPivotCorner) && - // item.isPivotCorner === pivotSortState.dimensions[index].isPivotCorner) || - // (!isValid(item.isPivotCorner) && !isValid(pivotSortState.dimensions[index].isPivotCorner))) - // ); - // if (isEqual) { - // isExist = true; - // pivotSortStateItem.order = pivotSortState.order; - // break; - // } - // } - // if (!isExist) { - // this.pivotSortState.push(pivotSortState); - // } - // } - /** 如果单元格所在维度或者指标配置了sort自动 可以通过该接口进行排序 */ - sort(col: number, row: number, order: SortOrder) { - let dimensions: IDimensionInfo[]; - if ((this as PivotTable).isCornerHeader(col, row)) { - const dimensionInfo = (this as PivotTable).getHeaderDefine(col, row) as any; - dimensions = []; - const dimension: IDimensionInfo = { - isPivotCorner: true, - dimensionKey: dimensionInfo.value, - value: dimensionInfo.value - }; - dimensions.push(dimension); - } else if ((this as PivotTable).isColumnHeader(col, row)) { - dimensions = (this as PivotTable).getCellHeaderPaths(col, row).colHeaderPaths as IDimensionInfo[]; - } else { - dimensions = (this as PivotTable).getCellHeaderPaths(col, row).rowHeaderPaths as IDimensionInfo[]; - } - - const sortIndicator = dimensions[dimensions.length - 1].indicatorKey; + // // dimensions: IDimensionInfo[], order: SortOrder + // // 清空当前 pivot sort 状态 + // const cells = this.pivotSortState.map((cell) => ({ col: cell.col, row: cell.row })); + // this.pivotSortState.length = 0; + // cells.map((cell) => { + // this.invalidateCellRange(this.getCellRange(cell.col, cell.row)); + // }); - const headerDefine = this.getHeaderDefine(col, row) as any; - if (headerDefine.sort) { - if ((this as PivotTable).dataset.sortRules) { - for (let i = (this as PivotTable).dataset.sortRules.length - 1; i >= 0; i--) { - const sortRule = (this as PivotTable).dataset.sortRules[i]; - if (headerDefine.dimensionKey && sortRule.sortField === headerDefine.dimensionKey) { - (this as PivotTable).dataset.sortRules.splice(i, 1); - } else if ( - sortIndicator && - // headerDefine.indicatorKey === sortIndicator && - // sortIndicator === (sortRule as SortByIndicatorRule).sortByIndicator && - sortRule.sortField === - (this.dataset.indicatorsAsCol - ? this.dataset.rows[this.dataset.rows.length - 1] - : this.dataset.columns[this.dataset.columns.length - 1]) - ) { - (this as PivotTable).dataset.sortRules.splice(i, 1); - } - } - if (sortIndicator) { - (this as PivotTable).dataset.sortRules.push({ - sortField: this.dataset.indicatorsAsCol - ? this.dataset.rows[this.dataset.rows.length - 1] - : this.dataset.columns[this.dataset.columns.length - 1], - sortType: SortType[order], - sortByIndicator: sortIndicator, - query: dimensions.reduce((arr, dimension) => { - if (dimension.dimensionKey) { - arr.push(dimension.value); - } - return arr; - }, []) - }); - } else { - (this as PivotTable).dataset.sortRules.push({ - sortField: headerDefine.dimensionKey, - sortType: SortType[order] - }); - } - } else { - if (sortIndicator) { - (this as PivotTable).dataset.sortRules = [ - { - sortField: this.dataset.indicatorsAsCol - ? this.dataset.rows[this.dataset.rows.length - 1] - : this.dataset.columns[this.dataset.columns.length - 1], - sortType: SortType[order], - sortByIndicator: sortIndicator, - query: dimensions.reduce((arr, dimension) => { - if (dimension.dimensionKey) { - arr.push(dimension.value); - } - return arr; - }, []) - } - ]; - } else { - (this as PivotTable).dataset.sortRules = [ - { - sortField: headerDefine.dimensionKey, - sortType: SortType[order] - } - ]; - } - } + // 更新 pivot sort 状态 + for (let i = 0; i < pivotSortStateConfig.length; i++) { + const { dimensions, order } = pivotSortStateConfig[i]; + const cellAddress = (this.internalProps.layoutMap as PivotHeaderLayoutMap).getPivotCellAdress(dimensions); - (this as PivotTable).updateSortRules((this as PivotTable).dataset.sortRules, col, row); + cellAddress && + this.pivotSortState.push({ + col: cellAddress.col, + row: cellAddress.row, + order + }); } + + // // 更新相关单元格样式 + // this.pivotSortState.map((cell) => { + // this.invalidateCellRange(this.getCellRange(cell.col, cell.row)); + // }); } getPivotSortState(col: number, row: number): SortOrder { @@ -1232,13 +827,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { } const cellRange = this.getCellRange(col, row); for (let i = 0; i < this.pivotSortState.length; i++) { - const pivotState = this.pivotSortState[i]; - const dimensions = pivotState.dimensions; - const cell = this.getCellAddressByHeaderPaths(dimensions); - // const { col: sortCol, row: sortRow, order } = this.pivotSortState[i]; - const order = pivotState.order; + const { col: sortCol, row: sortRow, order } = this.pivotSortState[i]; - if (cell && cellInRange(cellRange, cell.col, cell.row)) { + if (cellInRange(cellRange, sortCol, sortRow)) { return order; } } @@ -1257,7 +848,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { if (moveContext) { if (moveContext.moveType === 'column') { // 是扁平数据结构 需要将二维数组this.records进行调整 - if (this.internalProps.recordsIsTwoDimensionalArray) { + if (this.options.records?.[0]?.constructor === Array) { for (let row = 0; row < this.internalProps.records.length; row++) { const sourceColumns = (this.internalProps.records[row] as unknown as number[]).splice( moveContext.sourceIndex - this.rowHeaderLevelCount, @@ -1281,7 +872,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { this.setMinMaxLimitWidth(); } else if (moveContext.moveType === 'row') { // 是扁平数据结构 需要将二维数组this.records进行调整 - if (this.internalProps.recordsIsTwoDimensionalArray) { + if (this.options.records?.[0]?.constructor === Array) { const sourceRows = (this.internalProps.records as unknown as number[]).splice( moveContext.sourceIndex - this.columnHeaderLevelCount, moveContext.sourceSize @@ -1328,11 +919,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { hierarchyState: HierarchyState.collapse }); } else if (hierarchyState === HierarchyState.collapse) { - // const headerPaths = this.internalProps.layoutMap.getCellHeaderPaths(col, row); + const headerPaths = this.internalProps.layoutMap.getCellHeaderPaths(col, row); const headerTreeNode = this.internalProps.layoutMap.getHeadNode( - // headerPaths.rowHeaderPaths.slice(0, headerPaths.rowHeaderPaths.length), - col, - row + headerPaths.rowHeaderPaths.slice(0, headerPaths.rowHeaderPaths.length) ); if (Array.isArray(headerTreeNode.children)) { //children 是数组 表示已经有子树节点信息 @@ -1467,7 +1056,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { */ getCellHeaderTreeNodes(col: number, row: number): ICellHeaderPaths { const layoutMap = this.internalProps.layoutMap; - const headerNodes = layoutMap.getCellHeaderPathsWithTreeNode(col, row); + const headerNodes = layoutMap.getCellHeaderPathsWidthTreeNode(col, row); return headerNodes; } _hasHierarchyTreeHeader() { @@ -1494,16 +1083,19 @@ export class PivotTable extends BaseTable implements PivotTableAPI { setRecords(records: Array): void { const oldHoverState = { col: this.stateManager.hover.cellPos.col, row: this.stateManager.hover.cellPos.row }; this.options.records = this.internalProps.records = records; - this.internalProps.recordsIsTwoDimensionalArray = false; - if (records?.[0]?.constructor === Array) { - this.internalProps.recordsIsTwoDimensionalArray = true; - } const options = this.options; const internalProps = this.internalProps; - if (this.options.customConfig?.enableDataAnalysis === false) { + if (this.internalProps.enableDataAnalysis && (options.rows || options.columns)) { + this.dataset.setRecords(records); + internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset); + this.pivotSortState = []; + if (options.pivotSortState) { + this.updatePivotSortState(options.pivotSortState); + } + } else if (Array.isArray(this.internalProps.columnTree) || Array.isArray(this.internalProps.rowTree)) { //判断如果数据是二维数组 则标识已经分析过 直接从二维数组挨个读取渲染即可 //不是二维数组 对应是个object json对象 则表示flat数据,需要对应行列维度进行转成方便数据查询的行列树结构 - if (this.internalProps.recordsIsTwoDimensionalArray === false) { + if (records?.[0]?.constructor !== Array) { this.flatDataToObjects = new FlatDataToObjects( { rows: internalProps.layoutMap.fullRowDimensionKeys, @@ -1515,39 +1107,10 @@ export class PivotTable extends BaseTable implements PivotTableAPI { records ); } - } else { - this.dataset.setRecords(records); - let columnDimensionTree; - let rowDimensionTree; - if (options.columnTree) { - columnDimensionTree = internalProps.layoutMap.columnDimensionTree; - } else { - columnDimensionTree = new DimensionTree( - (this.dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId - ); - } - if (options.rowTree) { - rowDimensionTree = internalProps.layoutMap.rowDimensionTree; - } else { - rowDimensionTree = new DimensionTree( - (this.dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], - this.layoutNodeId, - this.options.rowHierarchyType, - this.options.rowHierarchyType === 'tree' ? this.options.rowExpandLevel ?? 1 : undefined - ); - } - internalProps.layoutMap = new PivotHeaderLayoutMap(this, this.dataset, columnDimensionTree, rowDimensionTree); - this.pivotSortState = []; - if (options.pivotSortState) { - this.pivotSortState = options.pivotSortState; - // this.updatePivotSortState(options.pivotSortState); - } } // 更新表头 this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; // 清空单元格内容 this.scenegraph.clearCells(); @@ -1562,20 +1125,10 @@ export class PivotTable extends BaseTable implements PivotTableAPI { this.scenegraph.resize(); } this.eventManager.updateEventBinder(); - if (this.options.emptyTip) { - if (this.internalProps.emptyTip) { - this.internalProps.emptyTip.resetVisible(); - } else { - const EmptyTip = Factory.getComponent('emptyTip') as IEmptyTipComponent; - this.internalProps.emptyTip = new EmptyTip(this.options.emptyTip, this); - this.internalProps.emptyTip.resetVisible(); - } - } } /** 开启单元格编辑 */ startEditCell(col?: number, row?: number) { if (isValid(col) && isValid(row)) { - this.eventManager.isDraging = false; this.selectCell(col, row); this.editorManager.startEditCell(col, row); } else if (this.stateManager.select?.cellPos) { @@ -1592,10 +1145,7 @@ export class PivotTable extends BaseTable implements PivotTableAPI { /** 获取单元格对应的编辑器 */ getEditor(col: number, row: number) { let editorDefine; - if (this.isCornerHeader(col, row)) { - const define = this.getHeaderDefine(col, row); - editorDefine = (define as ColumnDefine)?.headerEditor ?? this.options.headerEditor; - } else if (this.isHeader(col, row)) { + if (this.isHeader(col, row) && !this.isCornerHeader(col, row)) { const define = this.getHeaderDefine(col, row); editorDefine = (define as ColumnDefine)?.headerEditor ?? this.options.headerEditor; } else { @@ -1696,29 +1246,6 @@ export class PivotTable extends BaseTable implements PivotTableAPI { let pasteColEnd = startCol; let pasteRowEnd = startRow; // const rowCount = values.length; - //#region 提前组织好未更改前的数据 - const beforeChangeValues: (string | number)[][] = []; - const oldValues: (string | number)[][] = []; - for (let i = 0; i < values.length; i++) { - if (startRow + i > this.rowCount - 1) { - break; - } - const rowValues = values[i]; - const rawRowValues: (string | number)[] = []; - const oldRowValues: (string | number)[] = []; - beforeChangeValues.push(rawRowValues); - oldValues.push(oldRowValues); - for (let j = 0; j < rowValues.length; j++) { - if (startCol + j > this.colCount - 1) { - break; - } - const beforeChangeValue = this.getCellRawValue(startCol + j, startRow + i); - rawRowValues.push(beforeChangeValue); - const oldValue = this.getCellOriginValue(startCol + j, startRow + i); - oldRowValues.push(oldValue); - } - } - //#endregion for (let i = 0; i < values.length; i++) { if (startRow + i > this.rowCount - 1) { break; @@ -1738,8 +1265,8 @@ export class PivotTable extends BaseTable implements PivotTableAPI { ) { const value = rowValues[j]; let newValue: string | number = value; - const oldValue = oldValues[i][j]; - const rawValue = beforeChangeValues[i][j]; + const oldValue = this.getCellOriginValue(startCol + j, startRow + i); + const rawValue = this.getCellRawValue(startCol + j, startRow + i); if (typeof rawValue === 'number' && isAllDigits(value)) { newValue = parseFloat(value); } @@ -1803,15 +1330,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { } private _changeCellValueToDataSet(col: number, row: number, oldValue: string | number, newValue: string | number) { - if (this.internalProps.recordsIsTwoDimensionalArray) { - const rowIndex = this.getBodyIndexByRow(row); - const colIndex = this.getBodyIndexByCol(col); - this.records[rowIndex][colIndex] = newValue; - } else if (this.dataset) { + if (this.dataset) { const cellDimensionPath = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - if (this.isCornerHeader(col, row)) { - this.internalProps.layoutMap.changeCornerTitle(col, row, newValue as string); - } else if (this.isHeader(col, row)) { + if (this.isHeader(col, row)) { this.internalProps.layoutMap.changeTreeNodeTitle(col, row, newValue as string); !this.isCornerHeader(col, row) && @@ -1825,20 +1346,12 @@ export class PivotTable extends BaseTable implements PivotTableAPI { newValue ); } else { - const colKeys = cellDimensionPath.colHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((colPath: any) => { - return colPath.indicatorKey ?? colPath.value; - }); - const rowKeys = cellDimensionPath.rowHeaderPaths - ?.filter((path: any) => { - return !path.virtual; - }) - .map((rowPath: any) => { - return rowPath.indicatorKey ?? rowPath.value; - }); + const colKeys = cellDimensionPath.colHeaderPaths.map((colPath: any) => { + return colPath.indicatorKey ?? colPath.value; + }); + const rowKeys = cellDimensionPath.rowHeaderPaths.map((rowPath: any) => { + return rowPath.indicatorKey ?? rowPath.value; + }); this.dataset.changeTreeNodeValue( !this.internalProps.layoutMap.indicatorsAsCol ? rowKeys.slice(0, -1) : rowKeys, this.internalProps.layoutMap.indicatorsAsCol ? colKeys.slice(0, -1) : colKeys, @@ -1876,6 +1389,10 @@ export class PivotTable extends BaseTable implements PivotTableAPI { newValue ); } + } else { + const rowIndex = this.getBodyIndexByRow(row); + const colIndex = this.getBodyIndexByCol(col); + this.records[rowIndex][colIndex] = newValue; } } _hasCustomRenderOrLayout() { @@ -1923,11 +1440,9 @@ export class PivotTable extends BaseTable implements PivotTableAPI { */ setTreeNodeChildren(children: IHeaderTreeDefine[], records: any[], col: number, row: number) { if (this.flatDataToObjects) { - // const headerPaths = this.internalProps.layoutMap.getCellHeaderPaths(col, row); + const headerPaths = this.internalProps.layoutMap.getCellHeaderPaths(col, row); const headerTreeNode = this.internalProps.layoutMap.getHeadNode( - // headerPaths.rowHeaderPaths.slice(0, headerPaths.rowHeaderPaths.length), - col, - row + headerPaths.rowHeaderPaths.slice(0, headerPaths.rowHeaderPaths.length) ); headerTreeNode.children = children; this._refreshHierarchyState(col, row, () => { @@ -1940,21 +1455,6 @@ export class PivotTable extends BaseTable implements PivotTableAPI { }); this.flatDataToObjects.addRecords(records); }); - } else { - // const headerPaths = this.internalProps.layoutMap.getCellHeaderPaths(col, row); - const headerTreeNode = this.internalProps.layoutMap.getHeadNode( - // headerPaths.rowHeaderPaths.slice(0, headerPaths.rowHeaderPaths.length), - col, - row - ); - headerTreeNode.children = children; - this._refreshHierarchyState(col, row, () => { - this.dataset.changeDataConfig({ - rows: this.internalProps.layoutMap.fullRowDimensionKeys, - columns: this.internalProps.layoutMap.colDimensionKeys - }); - this.dataset.addRecords(records); - }); } } } diff --git a/packages/vtable/src/body-helper/body-helper.ts b/packages/vtable/src/body-helper/body-helper.ts index bebb94b60..3c6542929 100644 --- a/packages/vtable/src/body-helper/body-helper.ts +++ b/packages/vtable/src/body-helper/body-helper.ts @@ -30,12 +30,6 @@ export class BodyHelper { ): ColumnIconOption[] { //加入固定列图标 排序 文本中元素 const iconArr: ColumnIconOption[] = []; - - const hierarchyIcon = this.getHierarchyIcon(col, row); - if (hierarchyIcon) { - iconArr.push(hierarchyIcon); - } - const { icon: iconDefine } = this._table.getBodyColumnDefine(col, row); if (iconDefine) { @@ -72,6 +66,10 @@ export class BodyHelper { addIcon(iconResults); } } + const hierarchyIcon = this.getHierarchyIcon(col, row); + if (hierarchyIcon) { + iconArr.push(hierarchyIcon); + } context && iconArr.forEach((i, index) => { diff --git a/packages/vtable/src/body-helper/style/Style.ts b/packages/vtable/src/body-helper/style/Style.ts index 6d48253f9..10ca22e75 100644 --- a/packages/vtable/src/body-helper/style/Style.ts +++ b/packages/vtable/src/body-helper/style/Style.ts @@ -29,7 +29,6 @@ const STYLE_EVENT_TYPE = { export class Style extends EventTarget implements ColumnStyle { private _color?: ColorPropertyDefine; - private _strokeColor?: ColorPropertyDefine; private _fontSize?: FontSizePropertyDefine; private _fontFamily?: FontFamilyPropertyDefine; private _fontWeight?: FontWeightPropertyDefine; @@ -68,7 +67,6 @@ export class Style extends EventTarget implements ColumnStyle { this._textAlign = style?.textAlign ?? bodyStyle?.textAlign; //|| "left"; this._textBaseline = style?.textBaseline ?? bodyStyle?.textBaseline; //|| "middle"; this._color = style?.color ?? bodyStyle?.color; - this._strokeColor = style?.strokeColor ?? bodyStyle?.strokeColor; // icon为文字前后可添加的图表 this._fontSize = style.fontSize ?? bodyStyle?.fontSize; this._fontFamily = style.fontFamily ?? bodyStyle?.fontFamily; @@ -103,13 +101,6 @@ export class Style extends EventTarget implements ColumnStyle { this._color = color; // this.doChangeStyle(); } - get strokeColor(): ColorPropertyDefine | undefined { - return this._strokeColor; - } - set strokeColor(strokeColor: ColorPropertyDefine | undefined) { - this._strokeColor = strokeColor; - // this.doChangeStyle(); - } get fontSize(): FontSizePropertyDefine | undefined { return this._fontSize; } diff --git a/packages/vtable/src/components/axis/axis.ts b/packages/vtable/src/components/axis/axis.ts index 2cd5bd4ca..3dcf9b23e 100644 --- a/packages/vtable/src/components/axis/axis.ts +++ b/packages/vtable/src/components/axis/axis.ts @@ -2,15 +2,15 @@ import { degreeToRadian, isNil, isValidNumber, merge } from '@visactor/vutils'; import type { BaseTableAPI } from '../../ts-types/base-table'; import type { ICellAxisOption } from '../../ts-types/component/axis'; import { LineAxis, type LineAxisAttributes } from '@visactor/vrender-components'; -import { getAxisAttributes, getCommonAxis } from './get-axis-attributes'; +import { commonAxis, getAxisAttributes, getCommonAxis } from './get-axis-attributes'; import { isXAxis, isYAxis } from '../util/orient'; import type { IOrientType } from '../../ts-types/component/util'; import { BandAxisScale } from './band-scale'; import { registerDataSetInstanceParser, registerDataSetInstanceTransform } from '../util/register'; import type { Parser } from '@visactor/vdataset'; -import { DataSet, DataView } from '@visactor/vdataset'; +import { DataView } from '@visactor/vdataset'; import type { IBaseScale } from '@visactor/vscale'; -import { ticks } from '@src/vrender'; +import { ticks } from '@vutils-extension'; import { LinearAxisScale } from './linear-scale'; import { doOverlap } from './label-overlap'; import type { TableTheme } from '../../themes/theme'; @@ -21,16 +21,6 @@ const scaleParser: Parser = (scale: IBaseScale) => { return scale; }; -export interface ICartesianAxis { - new ( - option: ICellAxisOption, - width: number, - height: number, - padding: [number, number, number, number], - table: BaseTableAPI - ): CartesianAxis; -} - export class CartesianAxis { width: number; height: number; @@ -123,16 +113,11 @@ export class CartesianAxis { } initData() { - if (!this.table._vDataSet) { - this.table._vDataSet = new DataSet(); - } - registerDataSetInstanceParser(this.table._vDataSet, 'scale', scaleParser); registerDataSetInstanceTransform(this.table._vDataSet, 'ticks', ticks); const label = this.option.label || {}; const tick = this.option.tick || {}; - const tickData = new DataView(this.table._vDataSet) .parse(this.scale._scale, { type: 'scale' diff --git a/packages/vtable/src/components/axis/get-axis-component-size.ts b/packages/vtable/src/components/axis/get-axis-component-size.ts index 3c11cac29..a78f4f496 100644 --- a/packages/vtable/src/components/axis/get-axis-component-size.ts +++ b/packages/vtable/src/components/axis/get-axis-component-size.ts @@ -1,10 +1,8 @@ -import { isArray, isString, merge } from '@visactor/vutils'; +import { isArray, merge } from '@visactor/vutils'; import type { BaseTableAPI } from '../../ts-types/base-table'; import type { ICellAxisOption } from '../../ts-types/component/axis'; import { DEFAULT_TEXT_FONT_FAMILY, DEFAULT_TEXT_FONT_SIZE, commonAxis } from './get-axis-attributes'; -export type ComputeAxisComponentWidth = (config: ICellAxisOption, table: BaseTableAPI) => number; -export type ComputeAxisComponentHeight = (config: ICellAxisOption, table: BaseTableAPI) => number; /** * @description: compuational vertical axis width * @param {ICellAxisOption} config @@ -71,8 +69,7 @@ export function computeAxisComponentWidth(config: ICellAxisOption, table: BaseTa // title let titleWidth = 0; - // align with vrender-component, use isString() - if (attribute.title.visible && isString(attribute.title.text)) { + if (attribute.title.visible && attribute.title.text) { const { width, height } = table.measureText(attribute.title.text, { fontSize: attribute.title?.style?.fontSize ?? DEFAULT_TEXT_FONT_SIZE, fontWeight: attribute.title?.style?.fontWeight ?? 'normal', diff --git a/packages/vtable/src/components/empty-tip/empty-tip.ts b/packages/vtable/src/components/empty-tip/empty-tip.ts deleted file mode 100644 index f5a0a55c6..000000000 --- a/packages/vtable/src/components/empty-tip/empty-tip.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { EmptyTip as EmptyTipComponents } from '@visactor/vrender-components'; -// eslint-disable-next-line no-duplicate-imports -import type { EmptyTipAttributes } from '@visactor/vrender-components'; -import type { IEmptyTip } from '../../ts-types/component/empty-tip'; -import type { BaseTableAPI } from '../../ts-types/base-table'; -import { isEqual } from '@visactor/vutils'; -import type { ListTable } from '../../ListTable'; -import type { PivotTable } from '../../PivotTable'; -const emptyTipSvg = - ''; - -export interface IEmptyTipComponent { - new (emptyTipOption: IEmptyTip | true, table: BaseTableAPI): EmptyTip; -} - -export class EmptyTip { - table: BaseTableAPI; - _emptyTipOption: IEmptyTip = { - spaceBetweenTextAndIcon: 20, - text: 'no data', - textStyle: { - fontSize: 14, - color: '#000' - }, - icon: { - image: emptyTipSvg, - width: 100, - height: 100 - } - }; - isReleased: boolean = false; - private _emptyTipComponent: EmptyTipComponents; - private _cacheAttrs: EmptyTipAttributes; - constructor(emptyTipOption: IEmptyTip | true, table: BaseTableAPI) { - this.table = table; - this._emptyTipOption = Object.assign(this._emptyTipOption, emptyTipOption === true ? {} : emptyTipOption); - this._emptyTipComponent = this._createOrUpdateEmptyTipComponent(this._getEmptyTipAttrs()); - } - - private _createOrUpdateEmptyTipComponent(attrs: EmptyTipAttributes): EmptyTipComponents { - if (this._emptyTipComponent) { - if (!isEqual(attrs, this._cacheAttrs)) { - this._emptyTipComponent.setAttributes(attrs); - } - } else { - const emptyTip = new EmptyTipComponents(attrs); - emptyTip.name = 'emptyTip'; - this.table.scenegraph.stage.defaultLayer.appendChild(emptyTip); - this._emptyTipComponent = emptyTip; - } - // update table size - // this._adjustTableSize(this._emptyTipComponent.attribute); - return this._emptyTipComponent; - } - - resize() { - if (!this._emptyTipComponent) { - return; - } - const leftHeaderWidth = - (this.table as ListTable).transpose || (this.table as PivotTable).options.indicatorsAsCol === false - ? this.table.getFrozenColsWidth() - : 0; - const topHeaderHeight = - !(this.table as ListTable).transpose || (this.table as PivotTable).options.indicatorsAsCol - ? this.table.getFrozenRowsHeight() - : 0; - const width = - (this.table.columnHeaderLevelCount > 0 && this.table.isListTable() - ? this.table.getDrawRange().width - : this.table.tableNoFrameWidth) - leftHeaderWidth; - const height = - (this.table.rowHeaderLevelCount > 0 && this.table.isListTable() - ? this.table.getDrawRange().height - : this.table.tableNoFrameHeight) - topHeaderHeight; - this._emptyTipComponent.setAttributes({ - spaceBetweenTextAndIcon: this._emptyTipOption.spaceBetweenTextAndIcon, - x: this.table.tableX + leftHeaderWidth, - y: this.table.tableY + topHeaderHeight, - width, - height, - text: { - text: this._emptyTipOption.text, - ...this._emptyTipOption.textStyle, - fill: this._emptyTipOption.textStyle?.color - }, - icon: { - ...this._emptyTipOption.icon - } - }); - } - - release(): void { - this._emptyTipComponent && this.table.scenegraph.stage.defaultLayer.removeChild(this._emptyTipComponent); - this._emptyTipComponent = null; - this.isReleased = true; - } - resetVisible() { - if ( - ((!this.table.recordsCount || this.table.recordsCount === 0) && - this.table.internalProps.layoutMap.rowCount === this.table.internalProps.layoutMap.columnHeaderLevelCount) || - this.table.internalProps.layoutMap.colCount === this.table.internalProps.layoutMap.rowHeaderLevelCount - ) { - // this._emptyTipComponent.setAttributes({ - // visible: true - // }); - // this._emptyTipComponent.showAll(); - if (!this.table.scenegraph.stage.defaultLayer.children.includes(this._emptyTipComponent)) { - this.table.scenegraph.stage.defaultLayer.appendChild(this._emptyTipComponent); - } - } else { - // this._emptyTipComponent.setAttributes({ - // visible: false - // }); - // this._emptyTipComponent.hideAll(); - if (this.table.scenegraph.stage.defaultLayer.children.includes(this._emptyTipComponent)) { - this.table.scenegraph.stage.defaultLayer.removeChild(this._emptyTipComponent); - } - } - } - - private _getEmptyTipAttrs() { - const leftHeaderWidth = - (this.table as ListTable).transpose || (this.table as PivotTable).options.indicatorsAsCol === false - ? this.table.getFrozenColsWidth() - : 0; - const topHeaderHeight = - !(this.table as ListTable).transpose || (this.table as PivotTable).options.indicatorsAsCol - ? this.table.getFrozenRowsHeight() - : 0; - const width = - (this.table.columnHeaderLevelCount > 0 && this.table.isListTable() - ? this.table.getDrawRange().width - : this.table.tableNoFrameWidth) - leftHeaderWidth; - const height = - (this.table.rowHeaderLevelCount > 0 && this.table.isListTable() - ? this.table.getDrawRange().height - : this.table.tableNoFrameHeight) - topHeaderHeight; - - return { - spaceBetweenTextAndIcon: this._emptyTipOption.spaceBetweenTextAndIcon, - x: this.table.tableX + leftHeaderWidth, - y: this.table.tableY + topHeaderHeight, - width, - height, - text: { - text: this._emptyTipOption.text, - ...this._emptyTipOption.textStyle, - fill: this._emptyTipOption.textStyle?.color - }, - icon: { - ...this._emptyTipOption.icon - } - // visible:this.table.recordsCount === 0?true:false - } as EmptyTipAttributes; - } -} diff --git a/packages/vtable/src/components/index.ts b/packages/vtable/src/components/index.ts deleted file mode 100644 index 546696748..000000000 --- a/packages/vtable/src/components/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Factory } from '../core/factory'; -import { getAxisConfigInPivotChart } from '../layout/chart-helper/get-axis-config'; -import { CartesianAxis } from './axis/axis'; -import { computeAxisComponentHeight, computeAxisComponentWidth } from './axis/get-axis-component-size'; -import { EmptyTip } from './empty-tip/empty-tip'; -import { createLegend } from './legend/create-legend'; -import { MenuHandler } from './menu/dom/MenuHandler'; -import { Title } from './title/title'; -import { TooltipHandler } from './tooltip/TooltipHandler'; - -export const registerAxis = () => { - Factory.registerComponent('axis', CartesianAxis); - Factory.registerFunction('computeAxisComponentWidth', computeAxisComponentWidth); - Factory.registerFunction('computeAxisComponentHeight', computeAxisComponentHeight); - Factory.registerFunction('getAxisConfigInPivotChart', getAxisConfigInPivotChart); -}; - -export const registerEmptyTip = () => { - Factory.registerComponent('emptyTip', EmptyTip); -}; - -export const registerLegend = () => { - Factory.registerFunction('createLegend', createLegend); -}; - -export const registerMenu = () => { - Factory.registerComponent('menuHandler', MenuHandler); -}; - -export const registerTitle = () => { - Factory.registerComponent('title', Title); -}; - -export const registerTooltip = () => { - Factory.registerComponent('tooltipHandler', TooltipHandler); -}; diff --git a/packages/vtable/src/components/legend/create-legend.ts b/packages/vtable/src/components/legend/create-legend.ts index 4665f3aec..25bc710c6 100644 --- a/packages/vtable/src/components/legend/create-legend.ts +++ b/packages/vtable/src/components/legend/create-legend.ts @@ -3,10 +3,6 @@ import { DiscreteTableLegend } from './discrete-legend/discrete-legend'; import type { BaseTableAPI } from '../../ts-types/base-table'; import { ContinueTableLegend } from './continue-legend/continue-legend'; -export type CreateLegend = ( - option: ITableLegendOption, - table: BaseTableAPI -) => DiscreteTableLegend | ContinueTableLegend; export function createLegend(option: ITableLegendOption, table: BaseTableAPI) { if (option.type === 'color' || option.type === 'size') { return new ContinueTableLegend(option, table); diff --git a/packages/vtable/src/components/menu/dom/MenuHandler.ts b/packages/vtable/src/components/menu/dom/MenuHandler.ts index 5e4cbb349..70dafeb62 100644 --- a/packages/vtable/src/components/menu/dom/MenuHandler.ts +++ b/packages/vtable/src/components/menu/dom/MenuHandler.ts @@ -115,9 +115,6 @@ type AttachInfo = { range: CellRange; }; -export interface IMenuHandler { - new (table: BaseTableAPI): MenuHandler; -} export class MenuHandler { private _table: BaseTableAPI; private _menuInstances?: { [type: string]: BaseMenu }; diff --git a/packages/vtable/src/components/react/react-custom-layout.ts b/packages/vtable/src/components/react/react-custom-layout.ts deleted file mode 100644 index 4066d9092..000000000 --- a/packages/vtable/src/components/react/react-custom-layout.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Group } from '@src/vrender'; -import type { CustomRenderFunctionArg, ICustomLayoutFuc } from '../../ts-types'; -import type { BaseTableAPI } from '../../ts-types/base-table'; - -export function emptyCustomLayout(args: CustomRenderFunctionArg) { - const group = new Group({}); - return { - rootContainer: group, - renderDefault: true - }; -} - -export class ReactCustomLayout { - table: BaseTableAPI; - customLayoutFuncCache: Map; - reactRemoveGraphicCache: Map void>; - headerCustomLayoutFuncCache: Map; - headerReactRemoveGraphicCache: Map void>; - // reactContainerCache: Map>; - constructor(table: BaseTableAPI) { - this.table = table; - this.customLayoutFuncCache = new Map(); - // this.reactContainerCache = new Map(); - this.reactRemoveGraphicCache = new Map(); - this.headerCustomLayoutFuncCache = new Map(); - // this.headerCeactContainerCache = new Map(); - this.headerReactRemoveGraphicCache = new Map(); - } - - hasReactCreateGraphic(componentIndex: number, isHeaderCustomLayout?: boolean) { - if (isHeaderCustomLayout) { - return this.headerCustomLayoutFuncCache.has(componentIndex); - } - return this.customLayoutFuncCache.has(componentIndex); - } - - setReactCreateGraphic( - componentIndex: number, - createGraphic: ICustomLayoutFuc, - // containerCache: Map, - isHeaderCustomLayout?: boolean - ) { - if (isHeaderCustomLayout) { - this.headerCustomLayoutFuncCache.set(componentIndex, createGraphic); - } else { - this.customLayoutFuncCache.set(componentIndex, createGraphic); - } - // this.reactContainerCache.set(componentIndex, containerCache); - } - - setReactRemoveGraphic( - componentIndex: number, - removeGraphic: (col: number, row: number) => void, - isHeaderCustomLayout?: boolean - ) { - if (isHeaderCustomLayout) { - this.headerReactRemoveGraphicCache.set(componentIndex, removeGraphic); - } else { - this.reactRemoveGraphicCache.set(componentIndex, removeGraphic); - } - } - - updateCustomCell(componentIndex: number, isHeaderCustomLayout?: boolean) { - const table = this.table; - const col = componentIndex; - // to do: deal with transpose table - if (isHeaderCustomLayout) { - for (let row = 0; row < table.columnHeaderLevelCount; row++) { - table.scenegraph.updateCellContent(col, row); - } - } else { - for (let row = table.columnHeaderLevelCount; row < table.rowCount; row++) { - table.scenegraph.updateCellContent(col, row); - } - } - // table.scenegraph.updateNextFrame(); - table.scenegraph.renderSceneGraph(); // use sync render for faster update - } - - getCustomLayoutFunc(col: number, row: number) { - const { startInTotal } = this.table.getBodyColumnDefine(col, row) as any; - const isHeader = this.table.isHeader(col, row); - return ( - (isHeader ? this.headerCustomLayoutFuncCache.get(startInTotal) : this.customLayoutFuncCache.get(startInTotal)) || - emptyCustomLayout - ); - } - - removeCustomCell(col: number, row: number) { - const { startInTotal } = this.table.getBodyColumnDefine(col, row) as any; - const isHeader = this.table.isHeader(col, row); - const removeFun = isHeader - ? this.headerReactRemoveGraphicCache.get(startInTotal) - : this.reactRemoveGraphicCache.get(startInTotal); - if (removeFun) { - removeFun(col, row); - } - } -} diff --git a/packages/vtable/src/components/title/title.ts b/packages/vtable/src/components/title/title.ts index 1930a72ea..83581623f 100644 --- a/packages/vtable/src/components/title/title.ts +++ b/packages/vtable/src/components/title/title.ts @@ -5,10 +5,6 @@ import type { ITitle } from '../../ts-types/component/title'; import { getQuadProps } from '../../scenegraph/utils/padding'; import type { BaseTableAPI } from '../../ts-types/base-table'; import { isEqual } from '@visactor/vutils'; - -export interface ITitleComponent { - new (titleOption: ITitle, table: BaseTableAPI): Title; -} export class Title { table: BaseTableAPI; _titleOption: ITitle; @@ -182,9 +178,7 @@ export class Title { subtextStyle: { width: realWidth, ...this._titleOption.subtextStyle - }, - dx: this._titleOption.dx ?? 0, - dy: this._titleOption.dy ?? 0 + } } as TitleAttrs; } } diff --git a/packages/vtable/src/components/tooltip/TooltipHandler.ts b/packages/vtable/src/components/tooltip/TooltipHandler.ts index 6ba0568ca..475b47a3a 100644 --- a/packages/vtable/src/components/tooltip/TooltipHandler.ts +++ b/packages/vtable/src/components/tooltip/TooltipHandler.ts @@ -21,9 +21,6 @@ type AttachInfo = { range: CellRange; tooltipOptions: TooltipOptions; }; -export interface ITooltipHandler { - new (table: BaseTableAPI, confine: boolean): TooltipHandler; -} export class TooltipHandler { private _table: BaseTableAPI; @@ -198,8 +195,7 @@ export class TooltipHandler { placement: Placement.bottom, rect }, - disappearDelay: table.internalProps.tooltip.overflowTextTooltipDisappearDelay ?? 0, - style: table.theme.tooltipStyle + style: { arrowMark: false } }; } else if (table.internalProps.tooltip?.isShowOverflowTextTooltip) { const overflowText = table.getCellOverflowText(col, row); @@ -214,7 +210,6 @@ export class TooltipHandler { placement: Placement.bottom, rect }, - disappearDelay: table.internalProps.tooltip.overflowTextTooltipDisappearDelay ?? 0, style: table.theme.tooltipStyle }; } diff --git a/packages/vtable/src/components/tooltip/logic/BubbleTooltipElement.ts b/packages/vtable/src/components/tooltip/logic/BubbleTooltipElement.ts index 407eb7b1f..c84185ad6 100644 --- a/packages/vtable/src/components/tooltip/logic/BubbleTooltipElement.ts +++ b/packages/vtable/src/components/tooltip/logic/BubbleTooltipElement.ts @@ -3,7 +3,7 @@ import type { RectProps } from '../../../ts-types'; import { Placement } from '../../../ts-types'; import { createElement } from '../../../tools/dom'; import { importStyle } from './BubbleTooltipElementStyle'; -import { isDivSelected, isMobile } from '../../../tools/util'; +import { isMobile } from '../../../tools/util'; import type { TooltipOptions } from '../../../ts-types/tooltip'; import type { BaseTableAPI } from '../../../ts-types/base-table'; importStyle(); @@ -18,35 +18,15 @@ export class BubbleTooltipElement { private _rootElement?: HTMLElement; private _messageElement?: HTMLElement; private _triangleElement?: HTMLElement; - private _disappearDelay?: number; // 提示框延迟多久消失 - private _disappearDelayId?: any; constructor() { this._handler = new EventHandler(); const rootElement = (this._rootElement = createElement('div', [TOOLTIP_CLASS, HIDDEN_CLASS])); - const messageElement = createElement('div', [CONTENT_CLASS]); + const messageElement = createElement('span', [CONTENT_CLASS]); const triangle = createElement('span', [TRIANGLE_CLASS]); rootElement.appendChild(triangle); rootElement.appendChild(messageElement); this._messageElement = rootElement.querySelector(`.${CONTENT_CLASS}`) || undefined; this._triangleElement = rootElement.querySelector(`.${TRIANGLE_CLASS}`) || undefined; - - rootElement.addEventListener('mousemove', () => { - this._disappearDelayId && clearTimeout(this._disappearDelayId); - }); - rootElement.addEventListener('mouseleave', () => { - this._disappearDelay = undefined; - this.unbindFromCell(); - }); - - messageElement.addEventListener('wheel', e => { - e.stopPropagation(); - }); - messageElement.addEventListener('copy', e => { - const isSelected = isDivSelected(messageElement as HTMLDivElement); // 判断tooltip弹框内容是否有选中 - if (isSelected) { - e.stopPropagation(); - } - }); } bindToCell( table: BaseTableAPI, @@ -55,8 +35,6 @@ export class BubbleTooltipElement { tooltipInstanceInfo: TooltipOptions, confine: boolean ): boolean { - this._disappearDelay = tooltipInstanceInfo?.disappearDelay; - this._disappearDelayId && clearTimeout(this._disappearDelayId); const rootElement = this._rootElement; const messageElement = this._messageElement; const triangle = this._triangleElement; @@ -79,10 +57,6 @@ export class BubbleTooltipElement { tooltipInstanceInfo?.style?.color && (messageElement.style.color = tooltipInstanceInfo?.style?.color); tooltipInstanceInfo?.style?.padding && (messageElement.style.padding = `${tooltipInstanceInfo?.style?.padding.join('px ')}px`); - tooltipInstanceInfo?.style?.maxHeight && - (messageElement.style.maxHeight = `${tooltipInstanceInfo?.style?.maxHeight}px`); - tooltipInstanceInfo?.style?.maxWidth && - (messageElement.style.maxWidth = `${tooltipInstanceInfo?.style?.maxWidth}px`); messageElement && (messageElement.textContent = tooltipInstanceInfo?.content); const binded = this._bindToCell( table, @@ -126,20 +100,10 @@ export class BubbleTooltipElement { } } unbindFromCell(): void { - if (this._disappearDelay) { - this._disappearDelayId = setTimeout(() => { - const rootElement = this._rootElement; - if (rootElement?.parentElement) { - rootElement.classList.remove(SHOWN_CLASS); - rootElement.classList.add(HIDDEN_CLASS); - } - }, this._disappearDelay ?? 0); - } else { - const rootElement = this._rootElement; - if (rootElement?.parentElement) { - rootElement.classList.remove(SHOWN_CLASS); - rootElement.classList.add(HIDDEN_CLASS); - } + const rootElement = this._rootElement; + if (rootElement?.parentElement) { + rootElement.classList.remove(SHOWN_CLASS); + rootElement.classList.add(HIDDEN_CLASS); } } _canBindToCell(table: BaseTableAPI, col: number, row: number): boolean { diff --git a/packages/vtable/src/components/tooltip/logic/BubbleTooltipElementStyle.ts b/packages/vtable/src/components/tooltip/logic/BubbleTooltipElementStyle.ts index dc4f3d1a0..6c29a4166 100644 --- a/packages/vtable/src/components/tooltip/logic/BubbleTooltipElementStyle.ts +++ b/packages/vtable/src/components/tooltip/logic/BubbleTooltipElementStyle.ts @@ -18,8 +18,8 @@ export function importStyle() { .vtable__bubble-tooltip-element { position: absolute; - // pointer-events: none; - //user-select: none; + pointer-events: none; + user-select: none; max-width: 300px; z-index: 99999; @@ -33,8 +33,6 @@ export function importStyle() { } .vtable__bubble-tooltip-element--hidden { opacity: 0; - pointer-events: none; - user-select: none; /* transform: translate(-50%, -50%); */ transition: opacity 75ms linear; } @@ -53,30 +51,12 @@ export function importStyle() { white-space: pre-wrap; margin: 0; box-sizing: border-box; - overflow: auto; + overflow: hidden; word-wrap: break-word; position: relative; background-color: #FFF; z-index: 2; - border-radius: 4px; -} -/* WebKit Microsoft Edge(新版): */ -.vtable__bubble-tooltip-element__content::-webkit-scrollbar { - width: 0; - height: 0; - background-color: transparent; -} -/* Opera Firefox */ -.vtable__bubble-tooltip-element__content > scrollbar-track { - width: 0; - height: 0; - background-color: transparent; -} -/* Internet Explorer 11 和 Microsoft Edge(旧版) */ -.vtable__bubble-tooltip-element__content > scrollbar { - width: 0; - height: 0; - background-color: transparent; + border-radius: 4px } .vtable__bubble-tooltip-element__triangle { /* font-size: .75rem; */ diff --git a/packages/vtable/src/core/BaseTable.ts b/packages/vtable/src/core/BaseTable.ts index 04a5f6fc9..4b43e73d6 100644 --- a/packages/vtable/src/core/BaseTable.ts +++ b/packages/vtable/src/core/BaseTable.ts @@ -49,9 +49,7 @@ import type { TableEventOptions, WidthAdaptiveModeDef, HeightAdaptiveModeDef, - ListTableAPI, - ColumnInfo, - RowInfo + ListTableAPI } from '../ts-types'; import { event, style as utilStyle } from '../tools/helper'; @@ -70,7 +68,7 @@ import { EventManager } from '../event/event'; import { BodyHelper } from '../body-helper/body-helper'; import { HeaderHelper } from '../header-helper/header-helper'; import type { PivotHeaderLayoutMap } from '../layout/pivot-header-layout'; -import type { ITooltipHandler } from '../components/tooltip/TooltipHandler'; +import { TooltipHandler } from '../components/tooltip/TooltipHandler'; import type { CachedDataSource, DataSource } from '../data'; import { AABBBounds, @@ -97,6 +95,8 @@ import { IconCache } from '../plugins/icons'; import { _applyColWidthLimits, _getScrollableVisibleRect, + _getTargetFrozenColAt, + _getTargetFrozenRowAt, _setDataSource, _setRecords, _toPxWidth, @@ -104,7 +104,7 @@ import { getStyleTheme, updateRootElementPadding } from './tableHelper'; -import type { IMenuHandler } from '../components/menu/dom/MenuHandler'; +import { MenuHandler } from '../components/menu/dom/MenuHandler'; import type { BaseTableAPI, BaseTableConstructorOptions, @@ -113,8 +113,8 @@ import type { } from '../ts-types/base-table'; import { FocusInput } from './FouseInput'; import { defaultPixelRatio } from '../tools/pixel-ratio'; -import type { CreateLegend } from '../components/legend/create-legend'; -import type { DataSet } from '@visactor/vdataset'; +import { createLegend } from '../components/legend/create-legend'; +import { DataSet } from '@visactor/vdataset'; import { Title } from '../components/title/title'; import type { Chart } from '../scenegraph/graphic/chart'; import { setBatchRenderChartCount } from '../scenegraph/graphic/contributions/chart-render-helper'; @@ -126,20 +126,7 @@ import { RowSeriesNumberHelper } from './row-series-number-helper'; import { CustomCellStylePlugin, mergeStyle } from '../plugins/custom-cell-style'; import { hideCellSelectBorder, restoreCellSelectBorder } from '../scenegraph/select/update-select-border'; import type { ITextGraphicAttribute } from '@src/vrender'; -import { ReactCustomLayout } from '../components/react/react-custom-layout'; import type { ISortedMapItem } from '../data/DataSource'; -import { hasAutoImageColumn } from '../layout/layout-helper'; -import { Factory } from './factory'; -import { - getCellAt, - getCellAtRelativePosition, - getColAt, - getRowAt, - getTargetColAt, - getTargetColAtConsiderRightFrozen, - getTargetRowAt, - getTargetRowAtConsiderBottomFrozen -} from './utils/get-cell-position'; const { toBoxArray } = utilStyle; const { isTouchEvent } = event; @@ -168,7 +155,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { canvasWidth?: number; canvasHeight?: number; - _vDataSet?: DataSet; + _vDataSet: DataSet; scenegraph: Scenegraph; stateManager: StateManager; eventManager: EventManager; @@ -209,9 +196,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { columnWidthComputeMode?: 'normal' | 'only-header' | 'only-body'; - reactCustomLayout?: ReactCustomLayout; - _hasAutoImageColumn?: boolean; - constructor(container: HTMLElement, options: BaseTableConstructorOptions = {}) { super(); if (!container && options.mode !== 'node') { @@ -221,7 +205,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { // rowCount = 0, // colCount = 0, frozenColCount = 0, - frozenRowCount, + // frozenRowCount = 0, defaultRowHeight = 40, defaultHeaderRowHeight, defaultColWidth = 80, @@ -310,15 +294,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { internalProps.canvas = document.createElement('canvas'); internalProps.element.appendChild(internalProps.canvas); internalProps.context = internalProps.canvas.getContext('2d')!; - - if (options.customConfig?.createReactContainer) { - internalProps.bodyDomContainer = document.createElement('div'); - internalProps.bodyDomContainer.classList.add('table-component-container'); - internalProps.element.appendChild(internalProps.bodyDomContainer); - internalProps.headerDomContainer = document.createElement('div'); - internalProps.headerDomContainer.classList.add('table-component-container'); - internalProps.element.appendChild(internalProps.headerDomContainer); - } } internalProps.handler = new EventHandler(); @@ -328,7 +303,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { internalProps.pixelRatio = pixelRatio; internalProps.frozenColCount = frozenColCount; - internalProps.frozenRowCount = frozenRowCount; internalProps.defaultRowHeight = defaultRowHeight; internalProps.defaultHeaderRowHeight = defaultHeaderRowHeight ?? defaultRowHeight; // defaultHeaderRowHeight没有设置取defaultRowHeight @@ -343,7 +317,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { internalProps.columnResizeMode = columnResizeMode; internalProps.rowResizeMode = rowResizeMode; - internalProps.dragHeaderMode = dragHeaderMode ?? 'none'; + internalProps.dragHeaderMode = dragHeaderMode; internalProps.renderChartAsync = renderChartAsync; setBatchRenderChartCount(renderChartAsyncBatchCount); internalProps.overscrollBehavior = overscrollBehavior ?? 'auto'; @@ -415,29 +389,17 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { : 0 : 10; // 生成scenegraph - // this._vDataSet = new DataSet(); + this._vDataSet = new DataSet(); this.scenegraph = new Scenegraph(this); this.stateManager = new StateManager(this); this.eventManager = new EventManager(this); if (options.legends) { - internalProps.legends = []; - const createLegend = Factory.getFunction('createLegend') as CreateLegend; - if (Array.isArray(options.legends)) { - for (let i = 0; i < options.legends.length; i++) { - internalProps.legends.push(createLegend(options.legends[i], this)); - } - this.scenegraph.tableGroup.setAttributes({ - x: this.tableX, - y: this.tableY - }); - } else { - internalProps.legends.push(createLegend(options.legends, this)); - this.scenegraph.tableGroup.setAttributes({ - x: this.tableX, - y: this.tableY - }); - } + internalProps.legends = createLegend(options.legends, this); + this.scenegraph.tableGroup.setAttributes({ + x: this.tableX, + y: this.tableY + }); } //原有的toolTip提示框处理,主要在文字绘制不全的时候 出来全文本提示信息 需要加个字段设置是否有效 @@ -450,7 +412,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { options.tooltip ); if (internalProps.tooltip.renderMode === 'html') { - const TooltipHandler = Factory.getComponent('tooltipHandler') as ITooltipHandler; internalProps.tooltipHandler = new TooltipHandler(this, internalProps.tooltip.confine); } internalProps.menu = Object.assign( @@ -467,7 +428,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { (this.globalDropDownMenu = options.menu.defaultHeaderMenuItems); if (internalProps.menu.renderMode === 'html') { - const MenuHandler = Factory.getComponent('menuHandler') as IMenuHandler; internalProps.menuHandler = new MenuHandler(this); } @@ -509,15 +469,12 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { resize() { this._updateSize(); - this.internalProps.legends?.forEach(legend => { - legend?.resize(); - }); + if (this.internalProps.legends) { + this.internalProps.legends.resize(); + } if (this.internalProps.title) { this.internalProps.title.resize(); } - if (this.internalProps.emptyTip) { - this.internalProps.emptyTip.resize(); - } // this.stateManager.checkFrozen(); this.scenegraph.resize(); } @@ -550,7 +507,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * 注意 这个值和options.frozenColCount 不一样!options.frozenColCount是用户实际设置的; 这里获取的值是调整过:frozen的列过宽时 frozeCount为0 */ get frozenColCount(): number { - return this.internalProps?.layoutMap?.frozenColCount ?? this.internalProps?.frozenColCount ?? 0; + return this.internalProps.layoutMap?.frozenColCount ?? this.internalProps.frozenColCount ?? 0; } /** * Set the number of frozen columns. @@ -610,7 +567,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * Get the number of frozen rows. */ get frozenRowCount(): number { - return this.internalProps?.layoutMap?.frozenRowCount ?? this.internalProps?.frozenRowCount ?? 0; + return this.internalProps.layoutMap?.frozenRowCount ?? this.internalProps.frozenRowCount ?? 0; } /** * Set the number of frozen rows. @@ -621,7 +578,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } get rightFrozenColCount(): number { - return this.internalProps?.layoutMap?.rightFrozenColCount ?? this.internalProps?.rightFrozenColCount ?? 0; + return this.internalProps.layoutMap?.rightFrozenColCount ?? this.internalProps.rightFrozenColCount ?? 0; } set rightFrozenColCount(rightFrozenColCount: number) { @@ -629,7 +586,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } get bottomFrozenRowCount(): number { - return this.internalProps?.layoutMap?.bottomFrozenRowCount ?? this.internalProps?.bottomFrozenRowCount ?? 0; + return this.internalProps.layoutMap?.bottomFrozenRowCount ?? this.internalProps.bottomFrozenRowCount ?? 0; } set bottomFrozenRowCount(bottomFrozenRowCount: number) { @@ -895,20 +852,8 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @param pixelRatio */ setPixelRatio(pixelRatio: number) { - if (pixelRatio !== this.internalProps.pixelRatio) { - this.internalProps.pixelRatio = pixelRatio; - const canvasWidth = this.options.canvasWidth; - this.internalProps.calcWidthContext = { - _: this.internalProps, - get full(): number { - if (Env.mode === 'node') { - return canvasWidth / (pixelRatio ?? 1); - } - return this._.canvas.width / ((this._.context as any).pixelRatio ?? window.devicePixelRatio); - } - }; - this.scenegraph.setPixelRatio(pixelRatio); - } + this.internalProps.pixelRatio = pixelRatio; + this.scenegraph.setPixelRatio(pixelRatio); } /** * 窗口尺寸发生变化 或者像数比变化 @@ -923,21 +868,9 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { if (Env.mode === 'browser') { const element = this.getElement(); - let widthWithoutPadding = 0; - let heightWithoutPadding = 0; - if (element.parentElement) { - const computedStyle = element.parentElement.style || window.getComputedStyle(element.parentElement); // 兼容性处理 - widthWithoutPadding = - element.parentElement.offsetWidth - - parseInt(computedStyle.paddingLeft || '0px', 10) - - parseInt(computedStyle.paddingRight || '0px', 10); - heightWithoutPadding = - element.parentElement.offsetHeight - - parseInt(computedStyle.paddingTop || '0px', 10) - - parseInt(computedStyle.paddingBottom || '0px', 20); - } - const width1 = widthWithoutPadding ?? 1 - 1; - const height1 = heightWithoutPadding ?? 1 - 1; + + const width1 = element.parentElement?.offsetWidth ?? 1 - 1; + const height1 = element.parentElement?.offsetHeight ?? 1 - 1; element.style.width = (width1 && `${width1 - padding.left - padding.right}px`) || '0px'; element.style.height = (height1 && `${height1 - padding.top - padding.bottom}px`) || '0px'; @@ -958,15 +891,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { canvas.style.width = `${widthP}px`; canvas.style.height = `${heightP}px`; } - - if (this.internalProps.bodyDomContainer) { - this.internalProps.bodyDomContainer.style.width = `${widthP}px`; - this.internalProps.bodyDomContainer.style.height = `${heightP}px`; - } - if (this.internalProps.headerDomContainer) { - this.internalProps.headerDomContainer.style.width = `${widthP}px`; - this.internalProps.headerDomContainer.style.height = `${heightP}px`; - } } else if (Env.mode === 'node') { widthP = this.canvasWidth - 1; heightP = this.canvasHeight - 1; @@ -1090,23 +1014,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { // : this.internalProps.defaultRowHeight) // ); if (isValid(this.rowHeightsMap.get(row))) { - if (this.options.customConfig?._disableColumnAndRowSizeRound) { - const height = this.rowHeightsMap.get(row); - let heightRange; - if (row < this.frozenRowCount) { - heightRange = this.rowHeightsMap.getSumInRange(0, row); - } else if (row >= this.rowCount - this.bottomFrozenRowCount) { - heightRange = this.rowHeightsMap.getSumInRange(row, this.rowCount - 1); - } else { - heightRange = this.rowHeightsMap.getSumInRange(this.frozenRowCount, row); - } - heightRange = Number(heightRange.toFixed(2)); // avoid precision problem - // if heightRange number is int - if (Number.isInteger(heightRange)) { - return Math.ceil(height); - } - return Math.floor(height); - } return this.rowHeightsMap.get(row); } const defaultHeight = this.getDefaultRowHeight(row); @@ -1160,18 +1067,12 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { */ _setRowHeight(row: number, height: number, clearCache?: boolean): void { // this.rowHeightsMap.put(row, Math.round(height)); - this.rowHeightsMap.put(row, this.options.customConfig?._disableColumnAndRowSizeRound ? height : Math.round(height)); + this.rowHeightsMap.put(row, Math.round(height)); // 清楚影响缓存 if (clearCache) { this._clearRowRangeHeightsMap(row); } } - - setRowHeight(row: number, height: number) { - this.scenegraph.setRowHeight(row, height); - this.internalProps._heightResizedRowMap.add(row); // add resize tag - } - /** * 获取指定行范围的总高度 * @param startCol @@ -1214,33 +1115,8 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { h += this.getRowHeight(i); } } else { - if (this.options.customConfig?._disableColumnAndRowSizeRound) { - // for (let i = startRow; i <= endRow; i++) { - // h += this.getRowHeight(i); - // } - const tempH = this.rowHeightsMap.getSumInRange(startRow, endRow); - let heightRange; - if (endRow < this.frozenRowCount) { - heightRange = this.rowHeightsMap.getSumInRange(0, endRow); - } else if (endRow >= this.rowCount - this.bottomFrozenRowCount) { - heightRange = this.rowHeightsMap.getSumInRange(endRow, this.rowCount - 1); - } else { - heightRange = this.rowHeightsMap.getSumInRange(this.frozenRowCount, endRow); - } - heightRange = Number(heightRange.toFixed(2)); // avoid precision problem - // if heightRange number is int - if (Number.isInteger(heightRange)) { - return Math.ceil(tempH); - } - return Math.floor(tempH); - } h = this.rowHeightsMap.getSumInRange(startRow, endRow); } - // if (this.options._disableColumnAndRowSizeRound) { - // // console.log(startRow, endRow, Number(h.toFixed(2))); - // // return Number(h.toFixed(2)); - // return h; - // } return Math.round(h); } /** @@ -1346,11 +1222,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @returns */ _setColWidth(col: number, width: string | number, clearCache?: boolean, skipCheckFrozen?: boolean): void { - this.colWidthsMap.put( - col, - // typeof width === 'number' ? (this.options.customConfig?._disableColumnAndRowSizeRound ? width : Math.round(width)) : width - typeof width === 'number' ? Math.round(width) : width - ); + this.colWidthsMap.put(col, typeof width === 'number' ? Math.round(width) : width); // 清楚影响缓存 if (clearCache) { this._clearColRangeWidthsMap(col); @@ -1362,11 +1234,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } } - setColWidth(col: number, width: number) { - this.scenegraph.setColWidth(col, width); - this.internalProps._widthResizedColMap.add(col); // add resize tag - } - /** * 清空含有指定col的缓存 * @param col @@ -1503,11 +1370,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { const width = this.getColWidth(col); if (isFrozenCell && isFrozenCell.col) { if (this.isRightFrozenColumn(col, row)) { - if (this.getAllColsWidth() <= this.tableNoFrameWidth) { - absoluteLeft = this.getColsWidth(0, col - 1) || 0; - } else { - absoluteLeft = this.tableNoFrameWidth - (this.getColsWidth(col, this.colCount - 1) ?? 0); - } + absoluteLeft = this.tableNoFrameWidth - (this.getColsWidth(col, this.colCount - 1) ?? 0); } else { absoluteLeft = this.getColsWidth(0, col - 1) || 0; // absoluteLeft += this.scrollLeft; @@ -1520,11 +1383,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { const height = this.getRowHeight(row); if (isFrozenCell && isFrozenCell.row) { if (this.isBottomFrozenRow(col, row)) { - if (this.getAllRowsHeight() <= this.tableNoFrameHeight) { - absoluteTop = this.getRowsHeight(0, row - 1); - } else { - absoluteTop = this.tableNoFrameHeight - (this.getRowsHeight(row, this.rowCount - 1) ?? 0); - } + absoluteTop = this.tableNoFrameHeight - (this.getRowsHeight(row, this.rowCount - 1) ?? 0); } else { absoluteTop = this.getRowsHeight(0, row - 1); // absoluteTop += this.scrollTop; @@ -1668,10 +1527,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { const scrollLeft = this.scrollLeft; if (this.isLeftFrozenColumn(startCol) && this.isRightFrozenColumn(endCol)) { width = this.tableNoFrameWidth - (this.getColsWidth(startCol + 1, this.colCount - 1) ?? 0) - absoluteLeft; - // width = - // this.tableNoFrameWidth - - // (this.getColsWidth(0, startCol - 1) ?? 0) - - // (this.getColsWidth(endCol + 1, this.colCount - 1) ?? 0); } else if (this.isLeftFrozenColumn(startCol) && !this.isLeftFrozenColumn(endCol)) { width = Math.max(width - scrollLeft, this.getColsWidth(startCol, this.frozenColCount - 1)); } else if (!this.isRightFrozenColumn(startCol) && this.isRightFrozenColumn(endCol)) { @@ -1689,10 +1544,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { const scrollTop = this.scrollTop; if (this.isTopFrozenRow(startRow) && this.isBottomFrozenRow(endRow)) { height = this.tableNoFrameHeight - (this.getRowsHeight(startRow + 1, this.rowCount - 1) ?? 0) - absoluteTop; - // height = - // this.tableNoFrameHeight - - // (this.getRowsHeight(0, startRow - 1) ?? 0) - - // (this.getRowsHeight(endRow + 1, this.rowCount - 1) ?? 0); } else if (this.isTopFrozenRow(startRow) && !this.isTopFrozenRow(endRow)) { height = Math.max(height - scrollTop, this.getRowsHeight(startRow, this.frozenRowCount - 1)); } else if (!this.isBottomFrozenRow(startRow) && this.isBottomFrozenRow(endRow)) { @@ -1785,7 +1636,20 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @returns */ getRowAt(absoluteY: number): { top: number; row: number; bottom: number; height: number } { - return getRowAt(absoluteY, this); + const frozen = _getTargetFrozenRowAt(this, absoluteY); + if (frozen) { + return frozen; + } + let row = this.getTargetRowAt(absoluteY); + if (!row) { + row = { + top: -1, + row: -1, + bottom: -1, + height: -1 + }; + } + return row; } /** * 根据x值计算所在列 @@ -1793,7 +1657,20 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @returns */ getColAt(absoluteX: number): { left: number; col: number; right: number; width: number } { - return getColAt(absoluteX, this); + const frozen = _getTargetFrozenColAt(this, absoluteX); + if (frozen) { + return frozen; + } + let col = this.getTargetColAt(absoluteX); + if (!col) { + col = { + left: -1, + col: -1, + right: -1, + width: 1 + }; + } + return col; } /** * 根据坐标值获取行列位置,index和rect范围 @@ -1802,18 +1679,23 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @returns */ getCellAt(absoluteX: number, absoluteY: number): CellAddressWithBound { - return getCellAt(absoluteX, absoluteY, this); - } - - /** - * 获取屏幕坐标对应的单元格信息,考虑滚动 - * @param this - * @param relativeX 左边x值,相对于容器左上角,已考虑格滚动情况 - * @param relativeY 左边y值,相对于容器左上角,已考虑格滚动情况 - * @returns - */ - getCellAtRelativePosition(relativeX: number, relativeY: number): CellAddressWithBound { - return getCellAtRelativePosition(relativeX, relativeY, this); + const rowInfo = this.getRowAt(absoluteY); + const { row, top, bottom, height } = rowInfo; + const colInfo = this.getColAt(absoluteX); + const { col, left, right, width } = colInfo; + const rect = { + left, + right, + top, + bottom, + width, + height + }; + return { + row, + col, + rect + }; } /** * 检查行列号是否正确 @@ -2086,15 +1968,9 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { super.release?.(); internalProps.handler?.release?.(); // internalProps.scrollable?.release?.(); - this.eventManager.release(); internalProps.focusControl?.release?.(); - internalProps.legends?.forEach(legend => { - legend?.release(); - }); + internalProps.legends?.release(); internalProps.title?.release(); - internalProps.title = null; - internalProps.emptyTip?.release(); - internalProps.emptyTip = null; internalProps.layoutMap.release(); if (internalProps.releaseList) { internalProps.releaseList.forEach(releaseObj => releaseObj?.release?.()); @@ -2110,8 +1986,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } (this as any).editorManager?.editingEditor?.onEnd?.(); this.isReleased = true; - this.scenegraph = null; - this.internalProps = null; } fireListeners( @@ -2127,7 +2001,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { */ updateOption(options: BaseTableConstructorOptions) { (this.options as BaseTable['options']) = options; - this._hasAutoImageColumn = undefined; const { // rowCount = 0, // colCount = 0, @@ -2219,7 +2092,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { internalProps.columnResizeMode = columnResizeMode; internalProps.rowResizeMode = rowResizeMode; - internalProps.dragHeaderMode = dragHeaderMode ?? 'none'; + internalProps.dragHeaderMode = dragHeaderMode; internalProps.renderChartAsync = renderChartAsync; setBatchRenderChartCount(renderChartAsyncBatchCount); internalProps.overscrollBehavior = overscrollBehavior ?? 'auto'; @@ -2265,14 +2138,9 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { : 0 : 10; // 生成scenegraph - // this._vDataSet = new DataSet(); - internalProps.legends?.forEach(legend => { - legend?.release(); - }); + this._vDataSet = new DataSet(); + internalProps.legends?.release(); internalProps.title?.release(); - internalProps.title = null; - internalProps.emptyTip?.release(); - internalProps.emptyTip = null; internalProps.layoutMap.release(); this.scenegraph.clearCells(); this.scenegraph.updateComponent(); @@ -2283,23 +2151,11 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { // this.eventManager = new EventManager(this); this.eventManager.updateEventBinder(); if (options.legends) { - internalProps.legends = []; - const createLegend = Factory.getFunction('createLegend') as CreateLegend; - if (Array.isArray(options.legends)) { - for (let i = 0; i < options.legends.length; i++) { - internalProps.legends.push(createLegend(options.legends[i], this)); - } - this.scenegraph.tableGroup.setAttributes({ - x: this.tableX, - y: this.tableY - }); - } else { - internalProps.legends.push(createLegend(options.legends, this)); - this.scenegraph.tableGroup.setAttributes({ - x: this.tableX, - y: this.tableY - }); - } + internalProps.legends = createLegend(options.legends, this); + this.scenegraph.tableGroup.setAttributes({ + x: this.tableX, + y: this.tableY + }); } // if (options.title) { // internalProps.title = new Title(options.title, this); @@ -2317,7 +2173,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { options.tooltip ); if (internalProps.tooltip.renderMode === 'html' && !internalProps.tooltipHandler) { - const TooltipHandler = Factory.getComponent('tooltipHandler') as ITooltipHandler; internalProps.tooltipHandler = new TooltipHandler(this, internalProps.tooltip.confine); } @@ -2336,7 +2191,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { (this.globalDropDownMenu = options.menu.defaultHeaderMenuItems); if (internalProps.menu.renderMode === 'html' && !internalProps.menuHandler) { - const MenuHandler = Factory.getComponent('menuHandler') as IMenuHandler; internalProps.menuHandler = new MenuHandler(this); } this.clearCellStyleCache(); @@ -2356,7 +2210,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { renderWithRecreateCells() { const oldHoverState = { col: this.stateManager.hover.cellPos.col, row: this.stateManager.hover.cellPos.row }; this.refreshHeader(); - this.internalProps.useOneRowHeightFillAll = false; this.scenegraph.clearCells(); this.clearCellStyleCache(); this.scenegraph.createSceneGraph(); @@ -2475,9 +2328,68 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @param absoluteX * @returns */ - - getTargetColAt(absoluteX: number): ColumnInfo | null { - return getTargetColAt(absoluteX, this); + getTargetColAt(absoluteX: number): { col: number; left: number; right: number; width: number } | null { + if (absoluteX === 0) { + return { left: 0, col: 0, right: 0, width: 0 }; + } + const findBefore = ( + startCol: number, + startRight: number + ): { + left: number; + col: number; + right: number; + width: number; + } | null => { + let right = startRight; + for (let col = startCol; col >= 0; col--) { + const width = this.getColWidth(col); + const left = right - width; + if (Math.round(left) <= Math.round(absoluteX) && Math.round(absoluteX) < Math.round(right)) { + return { + left, + col, + right, + width + }; + } + right = left; + } + return null; + }; + const findAfter = ( + startCol: number, + startRight: number + ): { + left: number; + col: number; + right: number; + width: number; + } | null => { + let left = startRight - this.getColWidth(startCol); + const { colCount } = this.internalProps; + for (let col = startCol; col < colCount; col++) { + const width = this.getColWidth(col); + const right = left + width; + if (Math.round(left) <= Math.round(absoluteX) && Math.round(absoluteX) < Math.round(right)) { + return { + left, + col, + right, + width + }; + } + left = right; + } + return null; + }; + //计算这个位置处是第几行 + const candCol = this.computeTargetColByX(absoluteX); + const right = this.getColsWidth(0, candCol); + if (absoluteX >= right) { + return findAfter(candCol, right); + } + return findBefore(candCol, right); } /** * 根据y获取该位置所处行值 @@ -2485,9 +2397,73 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @param absoluteX * @returns */ - - getTargetRowAt(absoluteY: number): RowInfo | null { - return getTargetRowAt(absoluteY, this); + getTargetRowAt(absoluteY: number): { row: number; top: number; bottom: number; height: number } | null { + if (absoluteY === 0) { + return { top: 0, row: 0, bottom: 0, height: 0 }; + } + + const findBefore = ( + startRow: number, + startBottom: number + ): { + top: number; + row: number; + bottom: number; + height: number; + } | null => { + let bottom = startBottom; + for (let row = startRow; row >= 0; row--) { + const height = this.getRowHeight(row); + const top = bottom - height; + if (Math.round(top) <= Math.round(absoluteY) && Math.round(absoluteY) < Math.round(bottom)) { + return { + top, + row, + bottom, + height + }; + } + bottom = top; + } + return null; + }; + const findAfter = ( + startRow: number, + startBottom: number + ): { + top: number; + row: number; + bottom: number; + height: number; + } | null => { + let top = startBottom - this.getRowHeight(startRow); + const { rowCount } = this.internalProps; + for (let row = startRow; row < rowCount; row++) { + const height = this.getRowHeight(row); + const bottom = top + height; + if (Math.round(top) <= Math.round(absoluteY) && Math.round(absoluteY) < Math.round(bottom)) { + return { + top, + row, + bottom, + height + }; + } + top = bottom; + } + return null; + }; + // const candRow = Math.min( + // Math.ceil(absoluteY / this.internalProps.defaultRowHeight), + // this.rowCount - 1 + // ); + //计算这个位置处是第几行 + const candRow = this.computeTargetRowByY(absoluteY); + const bottom = this.getRowsHeight(0, candRow); + if (absoluteY >= bottom) { + return findAfter(candRow, bottom); + } + return findBefore(candRow, bottom); } /** @@ -2496,9 +2472,30 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @param absoluteX * @returns */ - - getTargetColAtConsiderRightFrozen(absoluteX: number, isConsider: boolean): ColumnInfo | null { - return getTargetColAtConsiderRightFrozen(absoluteX, isConsider, this); + getTargetColAtConsiderRightFrozen( + absoluteX: number, + isConsider: boolean + ): { col: number; left: number; right: number; width: number } | null { + if (absoluteX === 0) { + return { left: 0, col: 0, right: 0, width: 0 }; + } + if ( + isConsider && + absoluteX > this.tableNoFrameWidth - this.getRightFrozenColsWidth() && + absoluteX < this.tableNoFrameWidth + ) { + for (let i = 0; i < this.rightFrozenColCount; i++) { + if (absoluteX > this.tableNoFrameWidth - this.getColsWidth(this.colCount - i - 1, this.colCount - 1)) { + return { + col: this.colCount - i - 1, + left: undefined, + right: undefined, + width: undefined + }; + } + } + } + return this.getTargetColAt(absoluteX); } /** @@ -2507,11 +2504,87 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @param absoluteX * @returns */ - - getTargetRowAtConsiderBottomFrozen(absoluteY: number, isConsider: boolean): RowInfo | null { - return getTargetRowAtConsiderBottomFrozen(absoluteY, isConsider, this); + getTargetRowAtConsiderBottomFrozen( + absoluteY: number, + isConsider: boolean + ): { row: number; top: number; bottom: number; height: number } | null { + if (absoluteY === 0) { + return { top: 0, row: 0, bottom: 0, height: 0 }; + } + if ( + isConsider && + absoluteY > this.tableNoFrameHeight - this.getBottomFrozenRowsHeight() && + absoluteY < this.tableNoFrameHeight + ) { + for (let i = 0; i < this.rightFrozenColCount; i++) { + if (absoluteY > this.tableNoFrameHeight - this.getRowsHeight(this.rowCount - i - 1, this.rowCount - 1)) { + return { + row: this.rowCount - i - 1, + top: undefined, + bottom: undefined, + height: undefined + }; + } + } + } + return this.getTargetRowAt(absoluteY); } + /** + * 根据y值(包括了scroll的)计算所在行 + * @param this + * @param absoluteY 左边y值,包含了scroll滚动距离 + * @returns + */ + private computeTargetRowByY(absoluteY: number): number { + let defaultRowHeight = this.internalProps.defaultRowHeight; + + //使用二分法计算出row + if (this._rowRangeHeightsMap.get(`$0$${this.rowCount - 1}`)) { + defaultRowHeight = this._rowRangeHeightsMap.get(`$0$${this.rowCount - 1}`) / this.rowCount; + // let startRow = 0; + // let endRow = this.rowCount - 1; + // while (endRow - startRow > 1) { + // const midRow = Math.floor((startRow + endRow) / 2); + // if (absoluteY < this._rowRangeHeightsMap.get(`$0$${midRow}`)) { + // endRow = midRow; + // } else if (absoluteY > this._rowRangeHeightsMap.get(`$0$${midRow}`)) { + // startRow = midRow; + // } else { + // return midRow; + // } + // } + // return endRow; + } + //否则使用defaultRowHeight大约计算一个row + return Math.min(Math.ceil(absoluteY / defaultRowHeight), this.rowCount - 1); + } + /** + * 根据x值(包括了scroll的)计算所在列 主要借助colRangeWidthsMap缓存来提高计算效率 + * @param this + * @param absoluteX 左边x值,包含了scroll滚动距离 + * @returns + */ + private computeTargetColByX(absoluteX: number): number { + //使用二分法计算出col + if (this._colRangeWidthsMap.get(`$0$${this.colCount - 1}`)) { + let startCol = 0; + let endCol = this.colCount - 1; + while (endCol - startCol > 1) { + const midCol = Math.floor((startCol + endCol) / 2); + if (absoluteX < this._colRangeWidthsMap.get(`$0$${midCol}`)) { + endCol = midCol; + } else if (absoluteX > this._colRangeWidthsMap.get(`$0$${midCol}`)) { + startCol = midCol; + } else { + return midCol; + } + } + return endCol; + } + //否则使用defaultColWidth大约计算一个col + return Math.min(Math.ceil(absoluteX / this.internalProps.defaultColWidth), this.colCount - 1); + } /** * 清除选中单元格 */ @@ -2523,10 +2596,9 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @param col * @param row */ - selectCell(col: number, row: number, isShift?: boolean, isCtrl?: boolean) { - const isHasSelected = !!this.stateManager.select.ranges?.length; - this.stateManager.updateSelectPos(col, row, isShift, isCtrl); - this.stateManager.endSelectCells(true, isHasSelected); + selectCell(col: number, row: number) { + this.stateManager.updateSelectPos(col, row); + this.stateManager.endSelectCells(); } /** * 选中单元格区域,可设置多个区域同时选中 @@ -2536,29 +2608,13 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { const { scrollLeft, scrollTop } = this; cellRanges.forEach((cellRange: CellRange, index: number) => { if (cellRange.start.col === cellRange.end.col && cellRange.start.row === cellRange.end.row) { - this.stateManager.updateSelectPos( - cellRange.start.col, - cellRange.start.row, - false, - index >= 1, - false, - false, - true - ); + this.stateManager.updateSelectPos(cellRange.start.col, cellRange.start.row, false, index >= 1); } else { - this.stateManager.updateSelectPos( - cellRange.start.col, - cellRange.start.row, - false, - index >= 1, - false, - false, - true - ); + this.stateManager.updateSelectPos(cellRange.start.col, cellRange.start.row, false, index >= 1); this.stateManager.updateInteractionState(InteractionState.grabing); - this.stateManager.updateSelectPos(cellRange.end.col, cellRange.end.row, false, index >= 1, false, false, true); + this.stateManager.updateSelectPos(cellRange.end.col, cellRange.end.row, false, index >= 1); } - this.stateManager.endSelectCells(false, false); + this.stateManager.endSelectCells(false); this.stateManager.updateInteractionState(InteractionState.default); }); // 选择后 会自动滚动到所选区域最后一行一列的位置 这里再设置回滚动前位置 @@ -2834,7 +2890,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { if (this.internalProps.layoutMap.isHeader(col, row)) { return undefined; } - return this.getCellOriginRecord(col, row); + return this.internalProps.dataSource?.get(this.getRecordShowIndexByCell(col, row)); } /** @deprecated 请使用getRecordByCell */ getRecordByRowCol(col: number, row: number) { @@ -2869,11 +2925,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { getCellRange(col: number, row: number): CellRange { if (this.internalProps.customMergeCell) { const customMerge = this.internalProps.customMergeCell(col, row, this); - if ( - customMerge && - customMerge.range && - (isValid(customMerge.text) || customMerge.customLayout || customMerge.customRender) - ) { + if (customMerge && customMerge.range && customMerge.text) { return customMerge.range; } } @@ -2887,11 +2939,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { getCustomMerge(col: number, row: number) { if (this.internalProps.customMergeCell) { const customMerge = this.internalProps.customMergeCell(col, row, this); - if ( - customMerge && - customMerge.range && - (isValid(customMerge.text) || customMerge.customLayout || this.customRender) - ) { + if (customMerge && customMerge.range && (customMerge.text || customMerge.customLayout || this.customRender)) { if (customMerge.style) { const styleClass = this.internalProps.bodyHelper.getStyleClass('text'); const style = customMerge.style; @@ -3100,11 +3148,8 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { if (this.isPivotTable() && !this.isBottomFrozenRow(row) && !this.isRightFrozenColumn(col)) { // use dimensionKey&indicatorKey to cache style object in pivot table const define = this.getHeaderDefine(col, row) as any; - const isCorner = this.isCornerHeader(col, row); cacheKey = define?.dimensionKey - ? isCorner - ? `dim-cor-${define.dimensionKey}` - : `dim-${define.dimensionKey}` + ? `dim-${define.dimensionKey}` : define?.indicatorKey ? `ind-${define.indicatorKey}` : `${col}-${row}`; @@ -3411,29 +3456,22 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * @returns */ _canDragHeaderPosition(col: number, row: number): boolean { - if ( - this.isHeader(col, row) && - (this.stateManager.isSelected(col, row) || - this.options.select?.disableHeaderSelect || - this.options.select?.disableSelect) - ) { + if (this.isHeader(col, row) && this.stateManager.isSelected(col, row)) { if (this.internalProps.frozenColDragHeaderMode === 'disabled' && this.isFrozenColumn(col)) { return false; } - if (this.stateManager.isSelected(col, row)) { - const selectRange = this.stateManager.select.ranges[0]; - //判断是否整行或者整列选中 - if (this.isColumnHeader(col, row)) { - if (selectRange.end.row !== this.rowCount - 1) { - return false; - } - } else if (this.isRowHeader(col, row)) { - if (selectRange.end.col !== this.colCount - 1) { - return false; - } - } else { + const selectRange = this.stateManager.select.ranges[0]; + //判断是否整行或者整列选中 + if (this.isColumnHeader(col, row)) { + if (selectRange.end.row !== this.rowCount - 1) { return false; } + } else if (this.isRowHeader(col, row)) { + if (selectRange.end.col !== this.colCount - 1) { + return false; + } + } else { + return false; } const define = this.getHeaderDefine(col, row); if (!define) { @@ -3527,9 +3565,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { ? getProp('bgColor', actStyle, col, row, this) : (theme.group.fill as string), color: isBoolean(theme.text.fill) ? getProp('color', actStyle, col, row, this) : (theme.text.fill as string), - strokeColor: isBoolean(theme.text.stroke) - ? getProp('strokeColor', actStyle, col, row, this) - : (theme.text.stroke as string), fontFamily: theme.text.fontFamily, fontSize: theme.text.fontSize, fontWeight: theme.text.fontWeight, @@ -3873,12 +3908,28 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } hasAutoImageColumn() { - if (this._hasAutoImageColumn === undefined) { - this._hasAutoImageColumn = hasAutoImageColumn(this); - } - return this._hasAutoImageColumn; + const bodyColumn = (this.internalProps.layoutMap.columnObjects as ColumnData[]).find((column: ColumnData) => { + if ( + (column.cellType === 'image' || column.cellType === 'video' || typeof column.cellType === 'function') && + (column.define as ImageColumnDefine).imageAutoSizing + ) { + return true; + } + return false; + }); + const headerObj = (this.internalProps.layoutMap.headerObjects as HeaderData[]).find((column: HeaderData) => { + if (column) { + if ( + (column.headerType === 'image' || column.headerType === 'video' || typeof column.headerType === 'function') && + (column.define as ImageColumnDefine).imageAutoSizing + ) { + return true; + } + } + return false; + }); + return bodyColumn || headerObj; } - /** 获取当前hover单元格的图表实例。这个方法hover实时获取有点缺陷:鼠标hover到单元格上触发了 chart.ts中的activate方法 但此时this.stateManager.hover?.cellPos?.col还是-1 */ _getActiveChartInstance() { // 根据hover的单元格位置 获取单元格实例 拿到chart图元 @@ -3903,58 +3954,28 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { if (col < this.frozenColCount && row < this.frozenRowCount) { return true; } - let colHeaderRangeRect; - if (this.frozenRowCount >= 1) { - colHeaderRangeRect = this.getCellRangeRelativeRect({ - start: { - col: 0, - row: 0 - }, - end: { - col: this.colCount - 1, - row: this.frozenRowCount - 1 - } - }); - } - let rowHeaderRangeRect; - if (this.frozenColCount >= 1) { - rowHeaderRangeRect = this.getCellRangeRelativeRect({ - start: { - col: 0, - row: 0 - }, - end: { - col: this.frozenColCount - 1, - row: this.rowCount - 1 - } - }); - } - let bottomFrozenRangeRect; - if (this.bottomFrozenRowCount >= 1) { - bottomFrozenRangeRect = this.getCellRangeRelativeRect({ - start: { - col: 0, - row: this.rowCount - this.bottomFrozenRowCount - }, - end: { - col: this.colCount - 1, - row: this.rowCount - 1 - } - }); - } - let rightFrozenRangeRect; - if (this.rightFrozenColCount >= 1) { - rightFrozenRangeRect = this.getCellRangeRelativeRect({ - start: { - col: this.colCount - this.rightFrozenColCount, - row: 0 - }, - end: { - col: this.colCount - 1, - row: this.rowCount - 1 - } - }); - } + + const colHeaderRangeRect = this.getCellRangeRelativeRect({ + start: { + col: 0, + row: 0 + }, + end: { + col: this.colCount - 1, + row: this.columnHeaderLevelCount + } + }); + const rowHeaderRangeRect = this.getCellRangeRelativeRect({ + start: { + col: 0, + row: 0 + }, + end: { + col: this.rowHeaderLevelCount, + row: this.rowCount - 1 + } + }); + if ( rect.top >= drawRange.top && rect.bottom <= drawRange.bottom && @@ -3962,14 +3983,12 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { rect.right <= drawRange.right ) { // return true; - if (this.isFrozenCell(col, row)) { + if (this.isHeader(col, row)) { return true; } else if ( // body cell drawRange do not intersect colHeaderRangeRect&rowHeaderRangeRect - rect.top >= (colHeaderRangeRect?.bottom ?? rect.top) && - rect.left >= (rowHeaderRangeRect?.right ?? rect.left) && - rect.bottom <= (bottomFrozenRangeRect?.top ?? rect.bottom) && - rect.right <= (rightFrozenRangeRect?.left ?? rect.right) + drawRange.top >= colHeaderRangeRect.bottom && + drawRange.left >= rowHeaderRangeRect.right ) { return true; } @@ -4001,7 +4020,7 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { * 导出某个单元格图片 * @returns base64图片 */ - exportCellImg(col: number, row: number, options?: { disableBackground?: boolean; disableBorder?: boolean }) { + exportCellImg(col: number, row: number) { const isInView = this.cellIsInVisualView(col, row); const { scrollTop, scrollLeft } = this; if (!isInView) { @@ -4019,35 +4038,15 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { this.scenegraph.component.hideVerticalScrollBar(); this.scenegraph.component.hideHorizontalScrollBar(); - // hide border - this.scenegraph.tableGroup.border.setAttribute('visible', false); - - // deal with options - let oldFill; - if (options?.disableBackground) { - const cellGroup = this.scenegraph.getCell(col, row); - oldFill = cellGroup.attribute.fill; - cellGroup.setAttribute('fill', 'transparent'); - } - let oldStroke; - if (options?.disableBorder) { - const cellGroup = this.scenegraph.getCell(col, row); - oldStroke = cellGroup.attribute.stroke; - cellGroup.setAttribute('stroke', false); - } - this.scenegraph.renderSceneGraph(); - let sizeOffset = 0; - if (this.theme.cellBorderClipDirection === 'bottom-right') { - sizeOffset = 1; - } + const c = this.scenegraph.stage.toCanvas( false, new AABBBounds().set( cellRect.left + this.tableX + 1, cellRect.top + this.tableY + 1, - cellRect.right + this.tableX - sizeOffset, - cellRect.bottom + this.tableY - sizeOffset + cellRect.right + this.tableX, + cellRect.bottom + this.tableY ) ); if (!isInView) { @@ -4056,27 +4055,12 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { } // return c.toDataURL('image/jpeg', 0.5); - // restore border - this.scenegraph.tableGroup.border.setAttribute('visible', true); - - // restore options - if (oldFill) { - const cellGroup = this.scenegraph.getCell(col, row); - cellGroup.setAttribute('fill', oldFill); - } - if (oldStroke) { - const cellGroup = this.scenegraph.getCell(col, row); - cellGroup.setAttribute('stroke', oldStroke); - } - // restore hover&select style if (this.stateManager.select?.ranges?.length > 0) { restoreCellSelectBorder(this.scenegraph); } this.stateManager.updateHoverPos(hoverCol, hoverRow); - this.scenegraph.updateNextFrame(); - return c.toDataURL(); } @@ -4234,9 +4218,6 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { changeRecordOrder(source: number, target: number) { // } - hasCustomCellStyle(customStyleId: string): boolean { - return this.customCellStylePlugin.hasCustomCellStyle(customStyleId); - } registerCustomCellStyle(customStyleId: string, customStyle: ColumnStyleOption | undefined | null) { this.customCellStylePlugin.registerCustomCellStyle(customStyleId, customStyle); } @@ -4280,35 +4261,4 @@ export abstract class BaseTable extends EventTarget implements BaseTableAPI { // startInertia() { // startInertia(0, -1, 1, this.stateManager); // } - - checkReactCustomLayout() { - if (!this.reactCustomLayout) { - this.reactCustomLayout = new ReactCustomLayout(this); - } - } - - get bodyDomContainer() { - return this.internalProps.bodyDomContainer; - } - get headerDomContainer() { - return this.internalProps.headerDomContainer; - } - /** - * 显示移动列或移动行的高亮线 如果(col,row)单元格是列头 则显示高亮列线; 如果(col,row)单元格是行头 则显示高亮行线 - * @param col 在表头哪一列后显示高亮线 - * @param row 在表头哪一行后显示高亮线 - */ - showMoverLine(col: number, row: number) { - this.scenegraph.component.showMoveCol(col, row, 0); - this.scenegraph.renderSceneGraph(); - } - /** - * 隐藏掉移动列或移动行的高亮线 - * @param col - * @param row - */ - hideMoverLine(col: number, row: number) { - this.scenegraph.component.hideMoveCol(); - this.scenegraph.renderSceneGraph(); - } } diff --git a/packages/vtable/src/core/TABLE_EVENT_TYPE.ts b/packages/vtable/src/core/TABLE_EVENT_TYPE.ts index dbdf2a3a3..847fe8c9d 100644 --- a/packages/vtable/src/core/TABLE_EVENT_TYPE.ts +++ b/packages/vtable/src/core/TABLE_EVENT_TYPE.ts @@ -20,11 +20,6 @@ export interface TableEvents { * 单元格选中状态改变事件 */ SELECTED_CELL: 'selected_cell'; - - /** - * 单元格选中状态改变事件 - */ - SELECTED_CLEAR: 'selected_clear'; /** * 键盘按下事件 */ @@ -175,7 +170,6 @@ export const TABLE_EVENT_TYPE: TableEvents = { MOUSEDOWN_CELL: 'mousedown_cell', MOUSEUP_CELL: 'mouseup_cell', SELECTED_CELL: 'selected_cell', - SELECTED_CLEAR: 'selected_clear', KEYDOWN: 'keydown', MOUSEENTER_TABLE: 'mouseenter_table', MOUSELEAVE_TABLE: 'mouseleave_table', diff --git a/packages/vtable/src/core/factory.ts b/packages/vtable/src/core/factory.ts deleted file mode 100644 index 91fa95eb7..000000000 --- a/packages/vtable/src/core/factory.ts +++ /dev/null @@ -1,29 +0,0 @@ -export class Factory { - private static _components: { [key: string]: any } = {}; - private static _functions: { [key: string]: any } = {}; - private static _cellTypes: { [key: string]: any } = {}; - - static registerComponent(key: string, component: any) { - Factory._components[key] = component; - } - - static getComponent(key: string) { - return Factory._components[key]; - } - - static registerFunction(key: string, func: any) { - Factory._functions[key] = func; - } - - static getFunction(key: string) { - return Factory._functions[key]; - } - - static registerCellType(key: string, cellType: any) { - Factory._cellTypes[key] = cellType; - } - - static getCellType(key: string) { - return Factory._cellTypes[key]; - } -} diff --git a/packages/vtable/src/core/style.ts b/packages/vtable/src/core/style.ts index 545ef0e5e..ac546e901 100644 --- a/packages/vtable/src/core/style.ts +++ b/packages/vtable/src/core/style.ts @@ -41,15 +41,6 @@ export function importStyle() { height: 100%; text-align: left; -webkit-font-smoothing:auto; - - overflow: hidden; // for react-vtable dom custom element -} -.vtable .table-component-container { - pointer-events: none; - overflow: hidden; - position: absolute; - top: 0px; - left: 0px; } .vtable > canvas { position: absolute; diff --git a/packages/vtable/src/core/tableHelper.ts b/packages/vtable/src/core/tableHelper.ts index ecbaae88a..833de32e0 100644 --- a/packages/vtable/src/core/tableHelper.ts +++ b/packages/vtable/src/core/tableHelper.ts @@ -248,7 +248,6 @@ export function getStyleTheme( const textAlign = getProp('textAlign', headerStyle, col, row, table); const textBaseline = getProp('textBaseline', headerStyle, col, row, table); const color = getProp('color', headerStyle, col, row, table); - const strokeColor = getProp('strokeColor', headerStyle, col, row, table); const lineHeight = getProp('lineHeight', headerStyle, col, row, table); const underline = getProp('underline', headerStyle, col, row, table); // boolean @@ -293,7 +292,6 @@ export function getStyleTheme( fontStyle, fontVariant, fill: color, - stroke: strokeColor ?? false, textAlign, textBaseline, lineHeight: lineHeight ?? fontSize, diff --git a/packages/vtable/src/core/utils/get-cell-position.ts b/packages/vtable/src/core/utils/get-cell-position.ts deleted file mode 100644 index fa60f924e..000000000 --- a/packages/vtable/src/core/utils/get-cell-position.ts +++ /dev/null @@ -1,426 +0,0 @@ -import type { CellAddressWithBound } from '../../ts-types'; -import type { BaseTableAPI } from '../../ts-types/base-table'; -import { _getTargetFrozenColAt, _getTargetFrozenRowAt } from '../tableHelper'; - -/** - * 根据y值计算所在行 - * @param absoluteY 相对于表格左上角的y坐标(无滚动) - * @returns - */ -export function getRowAt( - absoluteY: number, - _this: BaseTableAPI -): { top: number; row: number; bottom: number; height: number } { - const frozen = _getTargetFrozenRowAt(_this as any, absoluteY); - if (frozen) { - return frozen; - } - let row = getTargetRowAt(absoluteY, _this); - if (!row) { - row = { - top: -1, - row: -1, - bottom: -1, - height: -1 - }; - } - return row; -} - -/** - * 根据x值计算所在列 - * @param absoluteX 相对于表格左上角的x坐标(无滚动) - * @returns - */ -export function getColAt( - absoluteX: number, - _this: BaseTableAPI -): { left: number; col: number; right: number; width: number } { - const frozen = _getTargetFrozenColAt(_this as any, absoluteX); - if (frozen) { - return frozen; - } - let col = getTargetColAt(absoluteX, _this); - if (!col) { - col = { - left: -1, - col: -1, - right: -1, - width: 1 - }; - } - return col; -} -/** - * 根据坐标值获取行列位置,index和rect范围 - * @param absoluteX 表格左上角的x坐标(无滚动) - * @param absoluteY 表格左上角的y坐标(无滚动) - * @returns - */ -export function getCellAt(absoluteX: number, absoluteY: number, _this: BaseTableAPI): CellAddressWithBound { - const rowInfo = getRowAt(absoluteY, _this); - const { row, top, bottom, height } = rowInfo; - const colInfo = getColAt(absoluteX, _this); - const { col, left, right, width } = colInfo; - const rect = { - left, - right, - top, - bottom, - width, - height - }; - return { - row, - col, - rect - }; -} - -/** - * 根据x获取该位置所处列值 - * @param table - * @param absoluteX 表格左上角的x坐标(无滚动) - * @returns - */ -export function getTargetColAt( - absoluteX: number, - _this: BaseTableAPI -): { col: number; left: number; right: number; width: number } | null { - if (absoluteX === 0) { - return { left: 0, col: 0, right: 0, width: 0 }; - } - const findBefore = ( - startCol: number, - startRight: number - ): { - left: number; - col: number; - right: number; - width: number; - } | null => { - let right = startRight; - for (let col = startCol; col >= 0; col--) { - const width = _this.getColWidth(col); - const left = right - width; - if (Math.round(left) <= Math.round(absoluteX) && Math.round(absoluteX) < Math.round(right)) { - return { - left, - col, - right, - width - }; - } - right = left; - } - return null; - }; - const findAfter = ( - startCol: number, - startRight: number - ): { - left: number; - col: number; - right: number; - width: number; - } | null => { - let left = startRight - _this.getColWidth(startCol); - const { colCount } = _this.internalProps; - for (let col = startCol; col < colCount; col++) { - const width = _this.getColWidth(col); - const right = left + width; - if (Math.round(left) <= Math.round(absoluteX) && Math.round(absoluteX) < Math.round(right)) { - return { - left, - col, - right, - width - }; - } - left = right; - } - return null; - }; - //计算这个位置处是第几行 - const candCol = computeTargetColByX(absoluteX, _this); - const right = _this.getColsWidth(0, candCol); - if (absoluteX >= right) { - return findAfter(candCol, right); - } - return findBefore(candCol, right); -} - -/** - * 根据y获取该位置所处行值 - * @param table - * @param absoluteX 表格左上角的y坐标(无滚动) - * @returns - */ -export function getTargetRowAt( - absoluteY: number, - _this: BaseTableAPI -): { row: number; top: number; bottom: number; height: number } | null { - if (absoluteY === 0) { - return { top: 0, row: 0, bottom: 0, height: 0 }; - } - - const findBefore = ( - startRow: number, - startBottom: number - ): { - top: number; - row: number; - bottom: number; - height: number; - } | null => { - let bottom = startBottom; - for (let row = startRow; row >= 0; row--) { - const height = _this.getRowHeight(row); - const top = bottom - height; - if (Math.round(top) <= Math.round(absoluteY) && Math.round(absoluteY) < Math.round(bottom)) { - return { - top, - row, - bottom, - height - }; - } - bottom = top; - } - return null; - }; - const findAfter = ( - startRow: number, - startBottom: number - ): { - top: number; - row: number; - bottom: number; - height: number; - } | null => { - let top = startBottom - _this.getRowHeight(startRow); - const { rowCount } = _this.internalProps; - for (let row = startRow; row < rowCount; row++) { - const height = _this.getRowHeight(row); - const bottom = top + height; - if (Math.round(top) <= Math.round(absoluteY) && Math.round(absoluteY) < Math.round(bottom)) { - return { - top, - row, - bottom, - height - }; - } - top = bottom; - } - return null; - }; - // const candRow = Math.min( - // Math.ceil(absoluteY / this.internalProps.defaultRowHeight), - // this.rowCount - 1 - // ); - //计算这个位置处是第几行 - const candRow = computeTargetRowByY(absoluteY, _this); - const bottom = _this.getRowsHeight(0, candRow); - if (absoluteY >= bottom) { - return findAfter(candRow, bottom); - } - return findBefore(candRow, bottom); -} - -/** - * 根据x获取右侧冻结中该位置所处列值 - * @param table - * @param absoluteX 屏幕坐标x值 - * @returns - */ -export function getTargetColAtConsiderRightFrozen( - absoluteX: number, - isConsider: boolean, - _this: BaseTableAPI -): { col: number; left: number; right: number; width: number } | null { - if (absoluteX === 0) { - return { left: 0, col: 0, right: 0, width: 0 }; - } - if ( - isConsider && - absoluteX > _this.tableNoFrameWidth - _this.getRightFrozenColsWidth() && - absoluteX < _this.tableNoFrameWidth && - absoluteX <= _this.getAllColsWidth() - ) { - for (let i = 0; i < _this.rightFrozenColCount; i++) { - if (absoluteX > _this.tableNoFrameWidth - _this.getColsWidth(_this.colCount - i - 1, _this.colCount - 1)) { - return { - col: _this.colCount - i - 1, - left: undefined, - right: undefined, - width: undefined - }; - } - } - } - return getTargetColAt(absoluteX, _this); -} - -/** - * 根据y获取底部冻结该位置所处行值 - * @param table - * @param absoluteX 屏幕坐标y值 - * @returns - */ -export function getTargetRowAtConsiderBottomFrozen( - absoluteY: number, - isConsider: boolean, - _this: BaseTableAPI -): { row: number; top: number; bottom: number; height: number } | null { - if (absoluteY === 0) { - return { top: 0, row: 0, bottom: 0, height: 0 }; - } - if ( - isConsider && - absoluteY > _this.tableNoFrameHeight - _this.getBottomFrozenRowsHeight() && - absoluteY < _this.tableNoFrameHeight - ) { - for (let i = 0; i < _this.rightFrozenColCount; i++) { - if (absoluteY > _this.tableNoFrameHeight - _this.getRowsHeight(_this.rowCount - i - 1, _this.rowCount - 1)) { - return { - row: _this.rowCount - i - 1, - top: undefined, - bottom: undefined, - height: undefined - }; - } - } - } - return getTargetRowAt(absoluteY, _this); -} - -/** - * 根据y值(包括了scroll的)计算所在行 - * @param this - * @param absoluteY 左边y值,包含了scroll滚动距离 - * @returns - */ -export function computeTargetRowByY(absoluteY: number, _this: BaseTableAPI): number { - let defaultRowHeight = _this.internalProps.defaultRowHeight; - - //使用二分法计算出row - if (_this._rowRangeHeightsMap.get(`$0$${_this.rowCount - 1}`)) { - defaultRowHeight = _this._rowRangeHeightsMap.get(`$0$${_this.rowCount - 1}`) / _this.rowCount; - // let startRow = 0; - // let endRow = this.rowCount - 1; - // while (endRow - startRow > 1) { - // const midRow = Math.floor((startRow + endRow) / 2); - // if (absoluteY < this._rowRangeHeightsMap.get(`$0$${midRow}`)) { - // endRow = midRow; - // } else if (absoluteY > this._rowRangeHeightsMap.get(`$0$${midRow}`)) { - // startRow = midRow; - // } else { - // return midRow; - // } - // } - // return endRow; - } - //否则使用defaultRowHeight大约计算一个row - return Math.min(Math.ceil(absoluteY / defaultRowHeight), _this.rowCount - 1); -} - -/** - * 根据x值(包括了scroll的)计算所在列 主要借助colRangeWidthsMap缓存来提高计算效率 - * @param this - * @param absoluteX 左边x值,包含了scroll滚动距离 - * @returns - */ -export function computeTargetColByX(absoluteX: number, _this: BaseTableAPI): number { - //使用二分法计算出col - if (_this._colRangeWidthsMap.get(`$0$${_this.colCount - 1}`)) { - let startCol = 0; - let endCol = _this.colCount - 1; - while (endCol - startCol > 1) { - const midCol = Math.floor((startCol + endCol) / 2); - if (absoluteX < _this._colRangeWidthsMap.get(`$0$${midCol}`)) { - endCol = midCol; - } else if (absoluteX > _this._colRangeWidthsMap.get(`$0$${midCol}`)) { - startCol = midCol; - } else { - return midCol; - } - } - return endCol; - } - //否则使用defaultColWidth大约计算一个col - return Math.min(Math.ceil(absoluteX / _this.internalProps.defaultColWidth), _this.colCount - 1); -} - -/** - * 获取屏幕坐标对应的单元格信息,考虑滚动 - * @param this - * @param relativeX 左边x值,相对于容器左上角,考虑表格滚动 - * @param relativeY 左边y值,相对于容器左上角,考虑表格滚动 - * @returns - */ -export function getCellAtRelativePosition(x: number, y: number, _this: BaseTableAPI): CellAddressWithBound { - // table border and outer component - x -= _this.tableX; - y -= _this.tableY; - - // top frozen - let topFrozen = false; - if (y > 0 && y < _this.getFrozenRowsHeight()) { - topFrozen = true; - } - - // left frozen - let leftFrozen = false; - if (x > 0 && x < _this.getFrozenColsWidth()) { - leftFrozen = true; - } - - // bottom frozen - let bottomFrozen = false; - if ( - y > _this.tableNoFrameHeight - _this.getBottomFrozenRowsHeight() && - y < _this.tableNoFrameHeight && - y <= _this.getAllRowsHeight() - ) { - bottomFrozen = true; - } - // right frozen - let rightFrozen = false; - if ( - x > _this.tableNoFrameWidth - _this.getRightFrozenColsWidth() && - x < _this.tableNoFrameWidth && - x <= _this.getAllColsWidth() - ) { - rightFrozen = true; - } - - const colInfo = getTargetColAtConsiderRightFrozen( - leftFrozen || rightFrozen ? x : x + _this.scrollLeft, - rightFrozen, - _this - ); - const rowInfo = getTargetRowAtConsiderBottomFrozen( - topFrozen || bottomFrozen ? y : y + _this.scrollTop, - bottomFrozen, - _this - ); - if (colInfo && rowInfo) { - const { row, top, bottom, height } = rowInfo; - const { col, left, right, width } = colInfo; - const rect = { - left, - right, - top, - bottom, - width, - height - }; - return { - row, - col, - rect - }; - } - return { col: -1, row: -1 }; -} diff --git a/packages/vtable/src/data/DataSource.ts b/packages/vtable/src/data/DataSource.ts index b8170a57e..48437b047 100644 --- a/packages/vtable/src/data/DataSource.ts +++ b/packages/vtable/src/data/DataSource.ts @@ -178,12 +178,7 @@ export class DataSource extends EventTarget implements DataSourceAPI { // 注册聚合类型 registedAggregators: { [key: string]: { - new (config: { - dimension: string | string[]; - formatFun?: any; - isRecord?: boolean; - aggregationFun?: Function; - }): Aggregator; + new (dimension: string | string[], formatFun?: any, isRecord?: boolean, aggregationFun?: Function): Aggregator; }; } = {}; rowHierarchyType: 'grid' | 'tree'; @@ -284,12 +279,12 @@ export class DataSource extends EventTarget implements DataSourceAPI { if (Array.isArray(aggragation)) { for (let j = 0; j < aggragation.length; j++) { const item = aggragation[j]; - const aggregator = new this.registedAggregators[item.aggregationType]({ - dimension: field as string, - formatFun: item.formatFun, - isRecord: true, - aggregationFun: (item as CustomAggregation).aggregationFun - }); + const aggregator = new this.registedAggregators[item.aggregationType]( + field as string, + item.formatFun, + true, + (item as CustomAggregation).aggregationFun + ); this.fieldAggregators.push(aggregator); if (!columnObjs[i].aggregator) { columnObjs[i].aggregator = []; @@ -297,12 +292,12 @@ export class DataSource extends EventTarget implements DataSourceAPI { columnObjs[i].aggregator.push(aggregator); } } else { - const aggregator = new this.registedAggregators[aggragation.aggregationType]({ - dimension: field as string, - formatFun: aggragation.formatFun, - isRecord: true, - aggregationFun: (aggragation as CustomAggregation).aggregationFun - }); + const aggregator = new this.registedAggregators[aggragation.aggregationType]( + field as string, + aggragation.formatFun, + true, + (aggragation as CustomAggregation).aggregationFun + ); this.fieldAggregators.push(aggregator); columnObjs[i].aggregator = aggregator; } @@ -738,7 +733,6 @@ export class DataSource extends EventTarget implements DataSourceAPI { addRecord(record: any, index: number) { if (Array.isArray(this.records)) { this.records.splice(index, 0, record); - this.adjustBeforeChangedRecordsMap(index, 1); this.currentIndexedData.push(this.currentIndexedData.length); this._sourceLength += 1; if (this.rowHierarchyType === 'tree') { @@ -773,7 +767,6 @@ export class DataSource extends EventTarget implements DataSourceAPI { if (Array.isArray(this.records)) { if (Array.isArray(recordArr)) { this.records.splice(index, 0, ...recordArr); - this.adjustBeforeChangedRecordsMap(index, recordArr.length); for (let i = 0; i < recordArr.length; i++) { this.currentIndexedData.push(this.currentIndexedData.length); } @@ -808,7 +801,6 @@ export class DataSource extends EventTarget implements DataSourceAPI { */ addRecordForSorted(record: any) { if (Array.isArray(this.records)) { - this.beforeChangedRecordsMap = []; // 排序情况下插入数据,很难将原index和插入新增再次排序后的新index做对应,所以这里之前先清除掉beforeChangedRecordsMap 不做维护 this.records.push(record); this.currentIndexedData.push(this.currentIndexedData.length); this._sourceLength += 1; @@ -826,7 +818,6 @@ export class DataSource extends EventTarget implements DataSourceAPI { */ addRecordsForSorted(recordArr: any) { if (Array.isArray(this.records)) { - this.beforeChangedRecordsMap = []; // 排序情况下插入数据,很难将原index和插入新增再次排序后的新index做对应,所以这里之前先清除掉beforeChangedRecordsMap 不做维护 if (Array.isArray(recordArr)) { this.records.push(...recordArr); for (let i = 0; i < recordArr.length; i++) { @@ -842,14 +833,6 @@ export class DataSource extends EventTarget implements DataSourceAPI { } } - adjustBeforeChangedRecordsMap(insertIndex: number, insertCount: number) { - const length = this.beforeChangedRecordsMap.length; - for (let key = length - 1; key >= insertIndex; key--) { - const record = this.beforeChangedRecordsMap[key]; - delete this.beforeChangedRecordsMap[key]; - this.beforeChangedRecordsMap[key + insertCount] = record; - } - } /** * 删除多条数据recordIndexs */ @@ -862,7 +845,6 @@ export class DataSource extends EventTarget implements DataSourceAPI { if (recordIndex >= this._sourceLength || recordIndex < 0) { continue; } - delete this.beforeChangedRecordsMap[recordIndex]; realDeletedRecordIndexs.push(recordIndex); this.records.splice(recordIndex, 1); this.currentIndexedData.pop(); @@ -895,7 +877,6 @@ export class DataSource extends EventTarget implements DataSourceAPI { continue; } const rawIndex = this.currentIndexedData[recordIndex] as number; - delete this.beforeChangedRecordsMap[rawIndex]; this.records.splice(rawIndex, 1); this._sourceLength -= 1; } @@ -917,7 +898,6 @@ export class DataSource extends EventTarget implements DataSourceAPI { if (recordIndex >= this._sourceLength || recordIndex < 0) { continue; } - delete this.beforeChangedRecordsMap[recordIndex]; realDeletedRecordIndexs.push(recordIndex); this.records[recordIndex] = records[index]; } @@ -942,7 +922,6 @@ export class DataSource extends EventTarget implements DataSourceAPI { if (typeof rawIndex !== 'number') { return; } - delete this.beforeChangedRecordsMap[rawIndex]; realDeletedRecordIndexs.push(recordIndex); this.records[rawIndex] = records[index]; } diff --git a/packages/vtable/src/dataset/dataset.ts b/packages/vtable/src/dataset/dataset.ts index af0981291..70e14a47b 100644 --- a/packages/vtable/src/dataset/dataset.ts +++ b/packages/vtable/src/dataset/dataset.ts @@ -19,25 +19,22 @@ import type { CollectValueBy, CollectedValue, IIndicator, - IPivotChartDataConfig, - CalculateddFieldRules + IPivotChartDataConfig } from '../ts-types'; import { AggregationType, SortType } from '../ts-types'; -import type { Aggregator, IAggregator } from './statistics-helper'; +import type { Aggregator } from './statistics-helper'; import { AvgAggregator, CountAggregator, MaxAggregator, MinAggregator, NoneAggregator, - RecalculateAggregator, RecordAggregator, SumAggregator, naturalSort, sortBy, typeSort } from './statistics-helper'; -import { IndicatorDimensionKeyPlaceholder } from '../tools/global'; /** * 数据处理模块 */ @@ -45,7 +42,7 @@ export class Dataset { /** * 用户配置 */ - dataConfig?: IPivotTableDataConfig | IPivotChartDataConfig; + dataConfig: IPivotTableDataConfig | IPivotChartDataConfig; // /** // * 分页配置 // */ @@ -53,7 +50,7 @@ export class Dataset { /** * 明细数据 */ - records?: any[] | Record; + records: any[] | Record; /** * 树形节点,最后的子节点对应到body部分的每个单元格 树结构: 行-列-单元格 */ @@ -80,34 +77,27 @@ export class Dataset { //是否已排序 sorted = false; //排序规则 - sortRules?: SortRules; + sortRules: SortRules; //过滤规则 - filterRules?: FilterRules; + filterRules: FilterRules; //聚合规则 - aggregationRules?: AggregationRules; + aggregationRules: AggregationRules; //派生字段规则 - derivedFieldRules?: DerivedFieldRules; - mappingRules?: MappingRules; - calculatedFieldRules?: CalculateddFieldRules; - calculatedFiledKeys?: string[]; - calculatedFieldDependIndicatorKeys?: string[]; + derivedFieldRules: DerivedFieldRules; + mappingRules: MappingRules; //汇总配置 - totals?: Totals; + totals: Totals; //全局统计各指标的极值 indicatorStatistics: { max: Aggregator; min: Aggregator; total: Aggregator }[] = []; aggregators: { [key: string]: { - new (args: { - key: string; - dimension: string | string[]; - formatFun?: any; - isRecord?: boolean; - needSplitPositiveAndNegative?: boolean; - calculateFun?: any; - dependAggregators?: any; - dependIndicatorKeys?: string[]; - }): Aggregator; + new ( + dimension: string | string[], + formatFun?: any, + isRecord?: boolean, + needSplitPositiveAndNegative?: boolean + ): Aggregator; }; } = {}; @@ -120,35 +110,32 @@ export class Dataset { private rowGrandTotalLabel: string; private rowSubTotalLabel: string; private needSplitPositiveAndNegative?: boolean; - collectValuesBy?: Record; //收集维度值,field收集维度,by按什么进行分组收集 + collectValuesBy: Record; //收集维度值,field收集维度,by按什么进行分组收集 collectedValues: Record> = {}; cacheCollectedValues: Record> = {}; rows: string[]; - rowsHasValue: boolean[]; //rows中的key是否有在records中体现 columns: string[]; - columnsHasValue: boolean[]; //columns中的key是否有在records中体现 indicatorKeys: string[]; - indicatorKeysIncludeCalculatedFieldDependIndicatorKeys: string[]; - customRowTree?: IHeaderTreeDefine[]; - customColTree?: IHeaderTreeDefine[]; + customRowTree: IHeaderTreeDefine[]; + customColTree: IHeaderTreeDefine[]; // // 存储行表头path 这个是全量的 对比于分页截取的rowKeysPath; // private rowKeysPath_FULL: string[][]; colHeaderTree: any[]; rowHeaderTree: any[]; rowHierarchyType: 'grid' | 'tree'; - indicators?: (string | IIndicator)[]; + indicators: (string | IIndicator)[]; indicatorsAsCol: boolean; // 记录用户传入的汇总数据 totalRecordsTree: Record> = {}; constructor( - dataConfig: IPivotTableDataConfig | IPivotChartDataConfig | undefined, + dataConfig: IPivotTableDataConfig | IPivotChartDataConfig, // pagination: IPagination, rows: string[], columns: string[], indicatorKeys: string[], - indicators: (string | IIndicator)[] | undefined, + indicators: (string | IIndicator)[], indicatorsAsCol: boolean, - records: any[] | Record | undefined, + records: any[] | Record, rowHierarchyType?: 'grid' | 'tree', customColTree?: IHeaderTreeDefine[], customRowTree?: IHeaderTreeDefine[], @@ -162,32 +149,10 @@ export class Dataset { this.aggregationRules = this.dataConfig?.aggregationRules; this.derivedFieldRules = this.dataConfig?.derivedFieldRules; this.mappingRules = this.dataConfig?.mappingRules; - this.calculatedFieldRules = this.dataConfig?.calculatedFieldRules; - this.calculatedFiledKeys = this.calculatedFieldRules?.map(rule => rule.key) ?? []; - this.calculatedFieldDependIndicatorKeys = - this.calculatedFieldRules?.reduce((arr: string[], rule) => { - for (let i = 0; i < rule.dependIndicatorKeys.length; i++) { - if (arr.indexOf(rule.dependIndicatorKeys[i]) === -1) { - arr.push(rule.dependIndicatorKeys[i]); - } - } - return arr; - }, []) ?? []; this.totals = this.dataConfig?.totals; this.rows = rows; this.columns = columns; this.indicatorKeys = indicatorKeys; - this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys = [...indicatorKeys]; - - for (let m = 0; m < this.calculatedFieldDependIndicatorKeys.length; m++) { - if ( - this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys.indexOf( - this.calculatedFieldDependIndicatorKeys[m] - ) === -1 - ) { - this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys.push(this.calculatedFieldDependIndicatorKeys[m]); - } - } this.indicatorsAsCol = indicatorsAsCol; this.indicators = indicators; this.customColTree = customColTree; @@ -201,15 +166,15 @@ export class Dataset { this.rowsIsTotal = new Array(this.rows?.length ?? 0).fill(false); this.colsIsTotal = new Array(this.columns?.length ?? 0).fill(false); - if (this.totals?.row && this.totals.row.showSubTotals !== false && this.totals.row.subTotalsDimensions) { - for (let i = 0, len = this.totals?.row?.subTotalsDimensions?.length ?? 0; i < len; i++) { + if (this.totals?.row && this.totals.row.showSubTotals !== false) { + for (let i = 0, len = this.totals?.row?.subTotalsDimensions?.length; i < len; i++) { const dimension = this.totals.row.subTotalsDimensions[i]; const dimensionIndex = this.rows.indexOf(dimension); this.rowsIsTotal[dimensionIndex] = true; } } - if (this.totals?.column && this.totals.column.showSubTotals !== false && this.totals.column.subTotalsDimensions) { - for (let i = 0, len = this.totals?.column?.subTotalsDimensions?.length ?? 0; i < len; i++) { + if (this.totals?.column && this.totals.column.showSubTotals !== false) { + for (let i = 0, len = this.totals?.column?.subTotalsDimensions?.length; i < len; i++) { const dimension = this.totals.column.subTotalsDimensions[i]; const dimensionIndex = this.columns.indexOf(dimension); this.colsIsTotal[dimensionIndex] = true; @@ -232,29 +197,11 @@ export class Dataset { this.rowFlatKeys = {}; this.colKeys = []; this.rowKeys = []; - this.rowsHasValue = []; - this.columnsHasValue = []; if (records) { //处理数据 this.records = records; const t0 = typeof window !== 'undefined' ? window.performance.now() : 0; - // if (records?.[0]?.constructor !== Array) { - // 不能加这个判断来提升性能了, - // PivotChart 会有这种设置情况 - // records: { - // "0": [ - // { - // "10001": "数量", - // "10002": "37534", - // "10003": "sum_1700027602758", - // "30001": "数量", - // "1700046734980": "", - // sum_1700027602758: "37534", - // }, - // ], - // }, this.processRecords(); - // } //processRecord中按照collectValuesBy 收集了维度值。现在需要对有聚合需求的sumby 处理收集维度值范围 this.processCollectedValuesWithSumBy(); @@ -283,18 +230,16 @@ export class Dataset { const t7 = typeof window !== 'undefined' ? window.performance.now() : 0; if (this.customRowTree) { - // if (!this.indicatorsAsCol) { - // this.customRowTree = this._adjustCustomTree(this.customRowTree); - // } + if (!this.indicatorsAsCol) { + this.customRowTree = this._adjustCustomTree(this.customRowTree); + } this.rowHeaderTree = this.customRowTree; } else { if (this.rowHierarchyType === 'tree') { this.rowHeaderTree = this.ArrToTree1( this.rowKeys, - this.rows.filter((key, index) => { - return this.rowsHasValue[index]; - }), + this.rows, this.indicatorsAsCol ? undefined : this.indicators, this.totals?.row?.showGrandTotals || (!this.indicatorsAsCol && this.columns.length === 0) || @@ -304,9 +249,7 @@ export class Dataset { } else { this.rowHeaderTree = this.ArrToTree( this.rowKeys, - this.rows.filter((key, index) => { - return this.rowsHasValue[index]; - }), + this.rows, this.indicatorsAsCol ? undefined : this.indicators, this.rowsIsTotal, this.totals?.row?.showGrandTotals || (this.indicatorsAsCol && this.rows.length === 0), @@ -318,16 +261,14 @@ export class Dataset { } } if (this.customColTree) { - // if (this.indicatorsAsCol) { - // this.customColTree = this._adjustCustomTree(this.customColTree); - // } + if (this.indicatorsAsCol) { + this.customColTree = this._adjustCustomTree(this.customColTree); + } this.colHeaderTree = this.customColTree; } else { this.colHeaderTree = this.ArrToTree( this.colKeys, - this.columns.filter((key, index) => { - return this.columnsHasValue[index]; - }), + this.columns, this.indicatorsAsCol ? this.indicators : undefined, this.colsIsTotal, this.totals?.column?.showGrandTotals || (!this.indicatorsAsCol && this.columns.length === 0), // || this.rows.length === 0,//todo 这里原有逻辑暂时注释掉 @@ -362,12 +303,11 @@ export class Dataset { this.registerAggregator(AggregationType.MIN, MinAggregator); this.registerAggregator(AggregationType.AVG, AvgAggregator); this.registerAggregator(AggregationType.NONE, NoneAggregator); - this.registerAggregator(AggregationType.RECALCULATE, RecalculateAggregator); } /**processRecord中按照collectValuesBy 收集了维度值。现在需要对有聚合需求的 处理收集维度值范围 */ private processCollectedValuesWithSumBy() { for (const field in this.collectedValues) { - if (this.collectValuesBy?.[field]?.sumBy) { + if (this.collectValuesBy[field]?.sumBy) { for (const byKeys in this.collectedValues[field]) { let max; @@ -444,16 +384,14 @@ export class Dataset { } /**processRecord中按照collectValuesBy 收集了维度值。现在需要对有排序需求的处理 */ private processCollectedValuesWithSortBy() { - const that = this; for (const field in this.collectedValues) { - if (this.collectValuesBy?.[field]?.sortBy) { + if (this.collectValuesBy[field]?.sortBy) { for (const byKeys in this.collectedValues[field]) { this.collectedValues[field][byKeys] = (this.collectedValues[field][byKeys] as Array).sort( - (a, b) => - (that.collectValuesBy![field].sortBy?.indexOf(a) ?? -1) - - (that.collectValuesBy![field].sortBy?.indexOf(b) ?? -1) + (a, b) => this.collectValuesBy[field]?.sortBy.indexOf(a) - this.collectValuesBy[field]?.sortBy.indexOf(b) ); } + } else { } } } @@ -462,7 +400,7 @@ export class Dataset { */ private generateCollectedValuesSortRule() { for (const field in this.collectedValues) { - if (this.collectValuesBy && this.collectValuesBy[field] && !this.collectValuesBy[field].sortBy) { + if (this.collectValuesBy[field] && !this.collectValuesBy[field].sortBy) { let sortByRule: string[] = []; for (const byKeys in this.collectedValues[field]) { if (Array.isArray(this.collectedValues[field][byKeys])) { @@ -483,7 +421,7 @@ export class Dataset { */ private processRecords() { let isNeedFilter = false; - if ((this.dataConfig?.filterRules?.length ?? 0) >= 1) { + if (this.dataConfig?.filterRules?.length >= 1) { isNeedFilter = true; } //常规records是数组的情况 @@ -510,19 +448,17 @@ export class Dataset { } private filterRecord(record: any) { let isReserved = true; - if (this.dataConfig?.filterRules) { - for (let i = 0; i < this.dataConfig.filterRules.length; i++) { - const filterRule = this.dataConfig?.filterRules[i]; - if (filterRule.filterKey) { - const filterValue = record[filterRule.filterKey]; - if (filterRule.filteredValues?.indexOf(filterValue) === -1) { - isReserved = false; - break; - } - } else if (!filterRule.filterFunc?.(record)) { + for (let i = 0; i < this.dataConfig.filterRules.length; i++) { + const filterRule = this.dataConfig?.filterRules[i]; + if (filterRule.filterKey) { + const filterValue = record[filterRule.filterKey]; + if (filterRule.filteredValues.indexOf(filterValue) === -1) { isReserved = false; break; } + } else if (!filterRule.filterFunc?.(record)) { + isReserved = false; + break; } } return isReserved; @@ -535,9 +471,7 @@ export class Dataset { private processRecord(record: any, assignedIndicatorKey?: string) { //这个派生字段的计算位置有待确定,是否应该放到filter之前 this.derivedFieldRules?.forEach((derivedFieldRule: DerivedFieldRule, i: number) => { - if (derivedFieldRule.fieldName && derivedFieldRule.derivedFunc) { - record[derivedFieldRule.fieldName] = derivedFieldRule.derivedFunc(record); - } + record[derivedFieldRule.fieldName] = derivedFieldRule.derivedFunc(record); }); //#region 按照collectValuesBy 收集维度值 for (const field in this.collectValuesBy) { @@ -560,16 +494,14 @@ export class Dataset { } if (this.collectValuesBy[field].sumBy) { - const sumByKeys = this.collectValuesBy[field] - .sumBy!.map(byField => record[byField]) - .join(this.stringJoinChar); + const sumByKeys = this.collectValuesBy[field].sumBy.map(byField => record[byField]).join(this.stringJoinChar); if (!this.collectedValues[field][collectKeys][sumByKeys]) { - this.collectedValues[field][collectKeys][sumByKeys] = new this.aggregators[AggregationType.SUM]({ - key: field, - dimension: field, - isRecord: undefined, - needSplitPositiveAndNegative: this.needSplitPositiveAndNegative - }); + this.collectedValues[field][collectKeys][sumByKeys] = new this.aggregators[AggregationType.SUM]( + field, + undefined, + undefined, + this.needSplitPositiveAndNegative + ); } this.collectedValues[field][collectKeys][sumByKeys].push(record); } else if (this.collectValuesBy[field].range) { @@ -594,16 +526,15 @@ export class Dataset { //#endregion //#region 收集rowKey colKey - const colKey: string[] = []; - const rowKey: string[] = []; + const colKey = []; + const rowKey = []; let isToTalRecord = false; for (let l = 0, len1 = this.rows.length; l < len1; l++) { const rowAttr = this.rows[l]; if (rowAttr in record) { - this.rowsHasValue[l] = true; rowKey.push(record[rowAttr]); - } else if (rowAttr !== IndicatorDimensionKeyPlaceholder) { + } else { //如果数据中缺失某个维度的值 可以认为是用户传入的汇总数据 if ( this.dataConfig?.totals?.row?.showGrandTotals && @@ -618,7 +549,6 @@ export class Dataset { break; } else if ( // this.dataConfig?.totals?.row?.showSubTotals && - this.dataConfig?.totals?.row?.subTotalsDimensions && this.dataConfig?.totals?.row?.subTotalsDimensions.indexOf(this.rows[l - 1]) >= 0 ) { if (this.rowHierarchyType === 'grid') { @@ -633,9 +563,8 @@ export class Dataset { for (let n = 0, len2 = this.columns.length; n < len2; n++) { const colAttr = this.columns[n]; if (colAttr in record) { - this.columnsHasValue[n] = true; colKey.push(record[colAttr]); - } else if (colAttr !== IndicatorDimensionKeyPlaceholder) { + } else { //如果数据中缺失某个维度的值 可以认为是用户传入的汇总数据 if ( this.dataConfig?.totals?.column?.showGrandTotals && @@ -650,7 +579,6 @@ export class Dataset { break; } else if ( // this.dataConfig?.totals?.column?.showSubTotals && - this.dataConfig?.totals?.column?.subTotalsDimensions && this.dataConfig?.totals?.column?.subTotalsDimensions.indexOf(this.columns[n - 1]) >= 0 ) { colKey.push(this.colSubTotalLabel); @@ -675,53 +603,28 @@ export class Dataset { if (!this.totalRecordsTree[flatRowKey][flatColKey]) { this.totalRecordsTree[flatRowKey][flatColKey] = []; } - const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; - for (let i = 0; i < toComputeIndicatorKeys.length; i++) { - if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { - const calculatedFieldRule = this.calculatedFieldRules?.find(rule => rule.key === toComputeIndicatorKeys[i]); - if (!this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i]) { - this.totalRecordsTree[flatRowKey][flatColKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ - key: toComputeIndicatorKeys[i], - dimension: toComputeIndicatorKeys[i], - isRecord: true, - formatFun: ( + + for (let i = 0; i < this.indicatorKeys.length; i++) { + const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); + if (!this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i]) { + this.totalRecordsTree[flatRowKey][flatColKey][i] = new this.aggregators[ + aggRule?.aggregationType ?? AggregationType.SUM + ]( + aggRule?.field ?? this.indicatorKeys[i], + aggRule?.formatFun ?? + ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; + return indicator.indicatorKey === this.indicatorKeys[i]; } return false; }) as IIndicator - )?.format, - calculateFun: calculatedFieldRule?.calculateFun, - dependAggregators: this.totalRecordsTree[flatRowKey][flatColKey], - dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys - }); - } - toComputeIndicatorKeys[i] in record && this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i].push(record); - } else { - const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); - if (!this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i]) { - this.totalRecordsTree[flatRowKey][flatColKey][i] = new this.aggregators[ - aggRule?.aggregationType ?? AggregationType.SUM - ]({ - key: toComputeIndicatorKeys[i], - dimension: aggRule?.field ?? toComputeIndicatorKeys[i], - formatFun: - aggRule?.formatFun ?? - ( - this.indicators?.find((indicator: string | IIndicator) => { - if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; - } - return false; - }) as IIndicator - )?.format - }); - } - - //push融合了计算过程 - toComputeIndicatorKeys[i] in record && this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i].push(record); + )?.format + ); } + + //push融合了计算过程 + this.indicatorKeys[i] in record && this.totalRecordsTree[flatRowKey]?.[flatColKey]?.[i].push(record); } return; } @@ -745,99 +648,61 @@ export class Dataset { } //组织树结构: 行-列-单元格 行key为flatRowKey如’山东青岛‘ 列key为flatColKey如’家具椅子‘ - if (!this.tree[flatRowKey]) { - this.tree[flatRowKey] = {}; - } - //这里改成数组 因为可能是多个指标值 遍历indicators 生成对应类型的聚合对象 - if (!this.tree[flatRowKey]?.[flatColKey]) { - this.tree[flatRowKey][flatColKey] = []; - } - - const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; - for (let i = 0; i < toComputeIndicatorKeys.length; i++) { - if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { - const calculatedFieldRule = this.calculatedFieldRules?.find(rule => rule.key === toComputeIndicatorKeys[i]); + // TODO 原先pivotTable是必须有行或列维度的 pivotChart这里强制进入 + if (true || colKey.length !== 0 || rowKey.length !== 0) { + if (!this.tree[flatRowKey]) { + this.tree[flatRowKey] = {}; + } + //这里改成数组 因为可能是多个指标值 遍历indicators 生成对应类型的聚合对象 + if (!this.tree[flatRowKey]?.[flatColKey]) { + this.tree[flatRowKey][flatColKey] = []; + } + for (let i = 0; i < this.indicatorKeys.length; i++) { + const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); if (!this.tree[flatRowKey]?.[flatColKey]?.[i]) { - this.tree[flatRowKey][flatColKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ - key: toComputeIndicatorKeys[i], - dimension: toComputeIndicatorKeys[i], - isRecord: true, - formatFun: ( - this.indicators?.find((indicator: string | IIndicator) => { - if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; - } - return false; - }) as IIndicator - )?.format, - calculateFun: calculatedFieldRule?.calculateFun, - dependAggregators: this.tree[flatRowKey][flatColKey], - dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys - }); + this.tree[flatRowKey][flatColKey][i] = new this.aggregators[aggRule?.aggregationType ?? AggregationType.SUM]( + aggRule?.field ?? this.indicatorKeys[i], + aggRule?.formatFun ?? + ( + this.indicators?.find((indicator: string | IIndicator) => { + if (typeof indicator !== 'string') { + return indicator.indicatorKey === this.indicatorKeys[i]; + } + return false; + }) as IIndicator + )?.format + ); } - this.tree[flatRowKey]?.[flatColKey]?.[i].push(record); - } else { - const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); - let needAddToAggregator = false; if (assignedIndicatorKey) { - toComputeIndicatorKeys[i] === assignedIndicatorKey && (needAddToAggregator = true); + this.indicatorKeys[i] === assignedIndicatorKey && this.tree[flatRowKey]?.[flatColKey]?.[i].push(record); } //加入聚合结果 考虑field为数组的情况 else if (aggRule?.field) { if (typeof aggRule?.field === 'string') { - aggRule?.field in record && (needAddToAggregator = true); + aggRule?.field in record && this.tree[flatRowKey]?.[flatColKey]?.[i].push(record); } else { const isPush = aggRule?.field.find((field: string) => { return field in record; }); - isPush && (needAddToAggregator = true); + isPush && this.tree[flatRowKey]?.[flatColKey]?.[i].push(record); } } else { //push融合了计算过程 - toComputeIndicatorKeys[i] in record && (needAddToAggregator = true); - } - if (!this.tree[flatRowKey]?.[flatColKey]?.[i] && needAddToAggregator) { - this.tree[flatRowKey][flatColKey][i] = new this.aggregators[aggRule?.aggregationType ?? AggregationType.SUM]({ - key: toComputeIndicatorKeys[i], - dimension: aggRule?.field ?? toComputeIndicatorKeys[i], - formatFun: - aggRule?.formatFun ?? - ( - this.indicators?.find((indicator: string | IIndicator) => { - if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; - } - return false; - }) as IIndicator - )?.format - }); - } - - if (needAddToAggregator) { - this.tree[flatRowKey]?.[flatColKey]?.[i].push(record); + this.indicatorKeys[i] in record && this.tree[flatRowKey]?.[flatColKey]?.[i].push(record); } } } - //统计整体的最大最小值和总计值 共mapping使用 if (this.mappingRules) { for (let i = 0; i < this.indicatorKeys.length; i++) { if (!this.indicatorStatistics[i]) { const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); this.indicatorStatistics[i] = { - max: new this.aggregators[AggregationType.MAX]({ - key: this.indicatorKeys[i], - dimension: this.indicatorKeys[i] - }), - min: new this.aggregators[AggregationType.MIN]({ - key: this.indicatorKeys[i], - dimension: this.indicatorKeys[i] - }), - total: new this.aggregators[aggRule?.aggregationType ?? AggregationType.SUM]({ - key: this.indicatorKeys[i], - dimension: aggRule?.field ?? this.indicatorKeys[i], - formatFun: - aggRule?.formatFun ?? + max: new this.aggregators[AggregationType.MAX](this.indicatorKeys[i]), + min: new this.aggregators[AggregationType.MIN](this.indicatorKeys[i]), + total: new this.aggregators[aggRule?.aggregationType ?? AggregationType.SUM]( + aggRule?.field ?? this.indicatorKeys[i], + aggRule?.formatFun ?? ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { @@ -846,7 +711,7 @@ export class Dataset { return false; }) as IIndicator )?.format - }) + ) }; } //push融合了计算过程 @@ -870,9 +735,7 @@ export class Dataset { if (this.rowHierarchyType === 'tree') { this.rowHeaderTree = this.ArrToTree1( this.rowKeys, - this.rows.filter((key, index) => { - return this.rowsHasValue[index]; - }), + this.rows, this.indicatorsAsCol ? undefined : this.indicators, this.totals?.row?.showGrandTotals || (!this.indicatorsAsCol && this.columns.length === 0) || @@ -882,9 +745,7 @@ export class Dataset { } else { this.rowHeaderTree = this.ArrToTree( this.rowKeys, - this.rows.filter((key, index) => { - return this.rowsHasValue[index]; - }), + this.rows, this.indicatorsAsCol ? undefined : this.indicators, this.rowsIsTotal, this.totals?.row?.showGrandTotals || (this.indicatorsAsCol && this.rows.length === 0), @@ -899,9 +760,7 @@ export class Dataset { if (!this.customColTree) { this.colHeaderTree = this.ArrToTree( this.colKeys, - this.columns.filter((key, index) => { - return this.columnsHasValue[index]; - }), + this.columns, this.indicatorsAsCol ? this.indicators : undefined, this.colsIsTotal, this.totals?.column?.showGrandTotals || (!this.indicatorsAsCol && this.columns.length === 0), // || this.rows.length === 0,//todo 这里原有逻辑暂时注释掉 @@ -976,9 +835,8 @@ export class Dataset { rowKey: string[] | string = [], colKey: string[] | string = [], indicator: string, - considerChangedValue: boolean = true, - indicatorPosition?: { position: 'col' | 'row'; index?: number } - ): IAggregator { + considerChangedValue: boolean = true + ): Aggregator { const indicatorIndex = this.indicatorKeys.indexOf(indicator); // let agg; let flatRowKey; @@ -986,28 +844,12 @@ export class Dataset { if (typeof rowKey === 'string') { flatRowKey = rowKey; } else { - //考虑 指标key有可能在数组中间位置或者前面的可能 将其删除再添加到尾部 - if (!indicatorPosition || indicatorPosition.position === 'row') { - rowKey.map((key, i) => { - if (key === indicator && (!isValid(indicatorPosition?.index) || i === indicatorPosition.index)) { - rowKey.splice(i, 1); - } - }); - } flatRowKey = rowKey.join(this.stringJoinChar); } if (typeof colKey === 'string') { flatColKey = colKey; } else { - //考虑 指标key有可能在数组中间位置或者前面的可能 将其删除再添加到尾部 - if (!indicatorPosition || indicatorPosition.position === 'col') { - colKey.map((key, i) => { - if (key === indicator && (!isValid(indicatorPosition?.index) || i === indicatorPosition.index)) { - colKey.splice(i, 1); - } - }); - } flatColKey = colKey.join(this.stringJoinChar); } //TODO 原有逻辑 但这里先强制跳过 @@ -1087,6 +929,9 @@ export class Dataset { value(): any { return null; }, + formatValue() { + return ''; + }, clearCacheValue() { // do nothing }, @@ -1146,7 +991,7 @@ export class Dataset { let field; const that = this; const sortersArr: any[] = function (_this: any) { - const results: any = []; + const results = []; for (let l = 0, len1 = fieldArr.length; l < len1; l++) { field = fieldArr[l]; let isHasSortRule = false; @@ -1237,7 +1082,7 @@ export class Dataset { ) { colKey.push(that.colSubTotalLabel); } - return that.getAggregator(rowKey, colKey, (sortRule).sortByIndicator!).value(); + return that.getAggregator(rowKey, colKey, (sortRule).sortByIndicator).value(); }; if (isSortRow) { return naturalSort( @@ -1251,7 +1096,7 @@ export class Dataset { ); }; } else if ((sortRule).sortBy) { - return sortBy((sortRule).sortBy!); + return sortBy((sortRule).sortBy); } if ((sortRule).sortType) { return typeSort; @@ -1267,8 +1112,8 @@ export class Dataset { totalStatistics() { const that = this; if ( - (that?.totals?.column?.subTotalsDimensions && that?.totals?.column?.subTotalsDimensions?.length >= 1) || - (that?.totals?.row?.subTotalsDimensions && that?.totals?.row?.subTotalsDimensions?.length >= 1) || + that?.totals?.column?.subTotalsDimensions?.length >= 1 || + that?.totals?.row?.subTotalsDimensions?.length >= 1 || that?.totals?.column?.showGrandTotals || that?.totals?.row?.showGrandTotals // || @@ -1282,83 +1127,49 @@ export class Dataset { * @param flatColKey */ const colCompute = (flatRowKey: string, flatColKey: string) => { + console.log('totalStatistics', flatRowKey); if (this.totalRecordsTree?.[flatRowKey]?.[flatColKey]) { // 利用汇总数据替换 this.tree[flatRowKey][flatColKey] = this.totalRecordsTree?.[flatRowKey]?.[flatColKey]; return; } const colKey = flatColKey.split(this.stringJoinChar); - if ( - that.totals?.column?.subTotalsDimensions && - that.totals?.column?.subTotalsDimensions?.length > 0 && - that.totals.column.showSubTotals !== false - ) { - for (let i = 0, len = that.totals?.column?.subTotalsDimensions?.length; i < len; i++) { - const dimension = that.totals.column.subTotalsDimensions[i]; - const dimensionIndex = that.columns.indexOf(dimension); - if (dimensionIndex >= 0) { - const colTotalKey = colKey.slice(0, dimensionIndex + 1); - // if (this.rowHierarchyType === 'grid') { - colTotalKey.push(that.colSubTotalLabel); - // } - const flatColTotalKey = colTotalKey.join(this.stringJoinChar); - if (this.totalRecordsTree?.[flatRowKey]?.[flatColTotalKey]) { - // 利用汇总数据替换 - this.tree[flatRowKey][flatColTotalKey] = this.totalRecordsTree?.[flatRowKey]?.[flatColTotalKey]; - return; - } - if (!this.tree[flatRowKey][flatColTotalKey]) { - this.tree[flatRowKey][flatColTotalKey] = []; - } - const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; - - for (let i = 0; i < toComputeIndicatorKeys.length; i++) { - if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { - const calculatedFieldRule = this.calculatedFieldRules?.find( - rule => rule.key === toComputeIndicatorKeys[i] - ); - if (!this.tree[flatRowKey]?.[flatColTotalKey]?.[i]) { - this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ - key: toComputeIndicatorKeys[i], - dimension: toComputeIndicatorKeys[i], - isRecord: true, - formatFun: ( - this.indicators?.find((indicator: string | IIndicator) => { - if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; - } - return false; - }) as IIndicator - )?.format, - calculateFun: calculatedFieldRule?.calculateFun, - dependAggregators: this.tree[flatRowKey][flatColTotalKey], - dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys - }); - } - this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); - } else { - if (!this.tree[flatRowKey][flatColTotalKey][i]) { - const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); - this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[ - aggRule?.aggregationType ?? AggregationType.SUM - ]({ - key: toComputeIndicatorKeys[i], - dimension: aggRule?.field ?? toComputeIndicatorKeys[i], - formatFun: - aggRule?.formatFun ?? - ( - this.indicators?.find((indicator: string | IIndicator) => { - if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; - } - return false; - }) as IIndicator - )?.format - }); - } - this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); - } + for (let i = 0, len = that.totals?.column?.subTotalsDimensions?.length; i < len; i++) { + const dimension = that.totals.column.subTotalsDimensions[i]; + const dimensionIndex = that.columns.indexOf(dimension); + if (dimensionIndex >= 0) { + const colTotalKey = colKey.slice(0, dimensionIndex + 1); + // if (this.rowHierarchyType === 'grid') { + colTotalKey.push(that.colSubTotalLabel); + // } + const flatColTotalKey = colTotalKey.join(this.stringJoinChar); + if (this.totalRecordsTree?.[flatRowKey]?.[flatColTotalKey]) { + // 利用汇总数据替换 + this.tree[flatRowKey][flatColTotalKey] = this.totalRecordsTree?.[flatRowKey]?.[flatColTotalKey]; + return; + } + if (!this.tree[flatRowKey][flatColTotalKey]) { + this.tree[flatRowKey][flatColTotalKey] = []; + } + for (let i = 0; i < this.indicatorKeys.length; i++) { + if (!this.tree[flatRowKey][flatColTotalKey][i]) { + const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); + this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[ + aggRule?.aggregationType ?? AggregationType.SUM + ]( + aggRule?.field ?? this.indicatorKeys[i], + aggRule?.formatFun ?? + ( + this.indicators?.find((indicator: string | IIndicator) => { + if (typeof indicator !== 'string') { + return indicator.indicatorKey === this.indicatorKeys[i]; + } + return false; + }) as IIndicator + )?.format + ); } + this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); } } } @@ -1372,126 +1183,67 @@ export class Dataset { if (!this.tree[flatRowKey][flatColTotalKey]) { this.tree[flatRowKey][flatColTotalKey] = []; } - const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; - for (let i = 0; i < toComputeIndicatorKeys.length; i++) { - if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { - const calculatedFieldRule = this.calculatedFieldRules?.find( - rule => rule.key === toComputeIndicatorKeys[i] - ); - if (!this.tree[flatRowKey]?.[flatColTotalKey]?.[i]) { - this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ - key: toComputeIndicatorKeys[i], - dimension: toComputeIndicatorKeys[i], - isRecord: true, - formatFun: ( + for (let i = 0; i < this.indicatorKeys.length; i++) { + if (!this.tree[flatRowKey][flatColTotalKey][i]) { + const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); + this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[ + aggRule?.aggregationType ?? AggregationType.SUM + ]( + aggRule?.field ?? this.indicatorKeys[i], + aggRule?.formatFun ?? + ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; + return indicator.indicatorKey === this.indicatorKeys[i]; } return false; }) as IIndicator - )?.format, - calculateFun: calculatedFieldRule?.calculateFun, - dependAggregators: this.tree[flatRowKey][flatColTotalKey], - dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys - }); - } - this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); - } else { - if (!this.tree[flatRowKey][flatColTotalKey][i]) { - const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); - this.tree[flatRowKey][flatColTotalKey][i] = new this.aggregators[ - aggRule?.aggregationType ?? AggregationType.SUM - ]({ - key: toComputeIndicatorKeys[i], - dimension: aggRule?.field ?? toComputeIndicatorKeys[i], - formatFun: - aggRule?.formatFun ?? - ( - this.indicators?.find((indicator: string | IIndicator) => { - if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; - } - return false; - }) as IIndicator - )?.format - }); - } - this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); + )?.format + ); } + this.tree[flatRowKey][flatColTotalKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); } } }; Object.keys(that.tree).forEach(flatRowKey => { const rowKey = flatRowKey.split(this.stringJoinChar); Object.keys(that.tree[flatRowKey]).forEach(flatColKey => { - if ( - that.totals?.row?.subTotalsDimensions && - that.totals?.row?.subTotalsDimensions?.length > 0 && - that.totals.row.showSubTotals !== false - ) { - for (let i = 0, len = that.totals?.row?.subTotalsDimensions?.length; i < len; i++) { - const dimension = that.totals.row.subTotalsDimensions[i]; - const dimensionIndex = that.rows.indexOf(dimension); - if (dimensionIndex >= 0 && dimensionIndex < that.rows.length - 1) { - const rowTotalKey = rowKey.slice(0, dimensionIndex + 1); - if (this.rowHierarchyType === 'grid') { - // 如果是tree的情况则不追加小计单元格值 - rowTotalKey.push(that.rowSubTotalLabel); - } - const flatRowTotalKey = rowTotalKey.join(this.stringJoinChar); - if (!this.tree[flatRowTotalKey]) { - this.tree[flatRowTotalKey] = {}; - rowTotalKeys.push(flatRowTotalKey); - } - if (!this.tree[flatRowTotalKey][flatColKey]) { - this.tree[flatRowTotalKey][flatColKey] = []; - } - const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; - for (let i = 0; i < toComputeIndicatorKeys.length; i++) { - if (!this.tree[flatRowTotalKey][flatColKey][i]) { - if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { - const calculatedFieldRule = this.calculatedFieldRules?.find( - rule => rule.key === toComputeIndicatorKeys[i] - ); - this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ - key: toComputeIndicatorKeys[i], - dimension: toComputeIndicatorKeys[i], - isRecord: true, - formatFun: ( - this.indicators?.find((indicator: string | IIndicator) => { - if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; - } - return false; - }) as IIndicator - )?.format, - calculateFun: calculatedFieldRule?.calculateFun, - dependAggregators: this.tree[flatRowTotalKey][flatColKey], - dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys - }); - } else { - const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); - this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[ - aggRule?.aggregationType ?? AggregationType.SUM - ]({ - key: toComputeIndicatorKeys[i], - dimension: aggRule?.field ?? toComputeIndicatorKeys[i], - formatFun: - aggRule?.formatFun ?? - ( - this.indicators?.find((indicator: string | IIndicator) => { - if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; - } - return false; - }) as IIndicator - )?.format - }); - } - } - this.tree[flatRowTotalKey][flatColKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); + for (let i = 0, len = that.totals?.row?.subTotalsDimensions?.length; i < len; i++) { + const dimension = that.totals.row.subTotalsDimensions[i]; + const dimensionIndex = that.rows.indexOf(dimension); + if (dimensionIndex >= 0 && dimensionIndex < that.rows.length - 1) { + const rowTotalKey = rowKey.slice(0, dimensionIndex + 1); + if (this.rowHierarchyType === 'grid') { + // 如果是tree的情况则不追加小计单元格值 + rowTotalKey.push(that.rowSubTotalLabel); + } + const flatRowTotalKey = rowTotalKey.join(this.stringJoinChar); + if (!this.tree[flatRowTotalKey]) { + this.tree[flatRowTotalKey] = {}; + rowTotalKeys.push(flatRowTotalKey); + } + if (!this.tree[flatRowTotalKey][flatColKey]) { + this.tree[flatRowTotalKey][flatColKey] = []; + } + for (let i = 0; i < this.indicatorKeys.length; i++) { + if (!this.tree[flatRowTotalKey][flatColKey][i]) { + const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); + this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[ + aggRule?.aggregationType ?? AggregationType.SUM + ]( + aggRule?.field ?? this.indicatorKeys[i], + aggRule?.formatFun ?? + ( + this.indicators?.find((indicator: string | IIndicator) => { + if (typeof indicator !== 'string') { + return indicator.indicatorKey === this.indicatorKeys[i]; + } + return false; + }) as IIndicator + )?.format + ); } + this.tree[flatRowTotalKey][flatColKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); } } } @@ -1505,48 +1257,23 @@ export class Dataset { if (!this.tree[flatRowTotalKey][flatColKey]) { this.tree[flatRowTotalKey][flatColKey] = []; } - const toComputeIndicatorKeys = this.indicatorKeysIncludeCalculatedFieldDependIndicatorKeys; - for (let i = 0; i < toComputeIndicatorKeys.length; i++) { + for (let i = 0; i < this.indicatorKeys.length; i++) { if (!this.tree[flatRowTotalKey][flatColKey][i]) { - if (this.calculatedFiledKeys.indexOf(toComputeIndicatorKeys[i]) >= 0) { - const calculatedFieldRule = this.calculatedFieldRules?.find( - rule => rule.key === toComputeIndicatorKeys[i] - ); - this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[AggregationType.RECALCULATE]({ - key: toComputeIndicatorKeys[i], - dimension: toComputeIndicatorKeys[i], - isRecord: true, - formatFun: ( + const aggRule = this.getAggregatorRule(this.indicatorKeys[i]); + this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[ + aggRule?.aggregationType ?? AggregationType.SUM + ]( + aggRule?.field ?? this.indicatorKeys[i], + aggRule?.formatFun ?? + ( this.indicators?.find((indicator: string | IIndicator) => { if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; + return indicator.indicatorKey === this.indicatorKeys[i]; } return false; }) as IIndicator - )?.format, - calculateFun: calculatedFieldRule?.calculateFun, - dependAggregators: this.tree[flatRowTotalKey][flatColKey], - dependIndicatorKeys: calculatedFieldRule?.dependIndicatorKeys - }); - } else { - const aggRule = this.getAggregatorRule(toComputeIndicatorKeys[i]); - this.tree[flatRowTotalKey][flatColKey][i] = new this.aggregators[ - aggRule?.aggregationType ?? AggregationType.SUM - ]({ - key: toComputeIndicatorKeys[i], - dimension: aggRule?.field ?? toComputeIndicatorKeys[i], - formatFun: - aggRule?.formatFun ?? - ( - this.indicators?.find((indicator: string | IIndicator) => { - if (typeof indicator !== 'string') { - return indicator.indicatorKey === toComputeIndicatorKeys[i]; - } - return false; - }) as IIndicator - )?.format - }); - } + )?.format + ); } this.tree[flatRowTotalKey][flatColKey][i].push(that.tree[flatRowKey]?.[flatColKey]?.[i]); } @@ -1570,7 +1297,7 @@ export class Dataset { private ArrToTree1( arr: string[][], rows: string[], - indicators: (string | IIndicator)[] | undefined, + indicators: (string | IIndicator)[], isGrandTotal: boolean, grandTotalLabel: string ) { @@ -1590,7 +1317,7 @@ export class Dataset { path.push(value); const flatKey = path.join(concatStr); //id的值可以每次生成一个新的 这里用的path作为id 方便layout对象获取 - let item: { value: string; dimensionKey: string; children: any[] | undefined } = map.get(flatKey); // 当前节点 + let item: { value: string; dimensionKey: string; children: any[] } = map.get(flatKey); // 当前节点 if (!item) { item = { value, @@ -1598,7 +1325,7 @@ export class Dataset { dimensionKey: rows[index], //树的叶子节点补充指标 children: - index === list.length - 1 && (indicators?.length ?? 0) >= 1 + index === list.length - 1 && indicators?.length >= 1 ? indicators?.map(indicator => { if (typeof indicator === 'string') { return { @@ -1640,7 +1367,7 @@ export class Dataset { private ArrToTree( arr: string[][], rows: string[], - indicators: (string | IIndicator)[] | undefined, + indicators: (string | IIndicator)[], subTotalFlags: boolean[], isGrandTotal: boolean, grandTotalLabel: string, @@ -1664,7 +1391,7 @@ export class Dataset { path.push(value); const flatKey = path.join(concatStr); //id的值可以每次生成一个新的 这里用的path作为id 方便layout对象获取 - let item: { value: string; dimensionKey: string; children: any[] | undefined } = map.get(flatKey); // 当前节点 + let item: { value: string; dimensionKey: string; children: any[] } = map.get(flatKey); // 当前节点 if (!item) { item = { value, @@ -1672,7 +1399,7 @@ export class Dataset { // id: flatKey, //getId(node?.id ?? '', (node?.children?.length ?? result.length) + 1), //树的叶子节点补充指标 children: - index === list.length - 1 && (indicators?.length ?? 0) >= 1 + index === list.length - 1 && indicators?.length >= 1 ? indicators?.map(indicator => { if (typeof indicator === 'string') { return { @@ -1688,36 +1415,35 @@ export class Dataset { : [] }; if (subTotalFlags[index]) { - let curChild = item.children ?? []; + let curChild = item.children; // for (let i = index; i < list.length - 1; i++) { - const totalChild: { value: string; dimensionKey: string; children: any[] | undefined; levelSpan: number } = - { - value: subTotalLabel, - dimensionKey: rows[index + 1], - levelSpan: subTotalFlags.length - index - 1, - // id: `${flatKey}${concatStr}${subTotalLabel}`, // getId(item?.id, 1), - //树的叶子节点补充指标 - children: - // i + 1 === list.length - 1 && - (indicators?.length ?? 0) >= 1 - ? indicators?.map(indicator => { - if (typeof indicator === 'string') { - return { - indicatorKey: indicator, - value: indicator - }; - } + const totalChild: { value: string; dimensionKey: string; children: any[]; levelSpan: number } = { + value: subTotalLabel, + dimensionKey: rows[index + 1], + levelSpan: subTotalFlags.length - index - 1, + // id: `${flatKey}${concatStr}${subTotalLabel}`, // getId(item?.id, 1), + //树的叶子节点补充指标 + children: + // i + 1 === list.length - 1 && + indicators?.length >= 1 + ? indicators?.map(indicator => { + if (typeof indicator === 'string') { return { - indicatorKey: indicator.indicatorKey, - value: indicator.title + indicatorKey: indicator, + value: indicator }; - }) - : [] - }; + } + return { + indicatorKey: indicator.indicatorKey, + value: indicator.title + }; + }) + : [] + }; curChild.push(totalChild); - curChild = totalChild.children ?? []; + curChild = totalChild.children; // } } @@ -1739,10 +1465,7 @@ export class Dataset { if (arr?.length) { arr.forEach(item => addList(item)); } else if (indicators) { - result = indicators?.map((indicator: IIndicator | string): { indicatorKey: string; value: string } => { - if (typeof indicator === 'string') { - return { indicatorKey: indicator, value: indicator }; - } + result = indicators?.map((indicator: IIndicator): { indicatorKey: string; value: string } => { return { indicatorKey: indicator.indicatorKey, value: indicator.title ?? indicator.indicatorKey }; }); } @@ -1796,7 +1519,7 @@ export class Dataset { if ((this.dataConfig as IPivotChartDataConfig).dimensionSortArray) { this.cacheCollectedValues[key] = arraySortByAnotherArray( this.collectedValues[key] as unknown as string[], - (this.dataConfig as IPivotChartDataConfig).dimensionSortArray! + (this.dataConfig as IPivotChartDataConfig).dimensionSortArray ) as unknown as Record; } else { this.cacheCollectedValues[key] = this.collectedValues[key]; @@ -1805,6 +1528,32 @@ export class Dataset { } } + private _adjustCustomTree(customTree: IHeaderTreeDefine[]) { + const checkNode = (nodes: IHeaderTreeDefine[], isHasIndicator: boolean) => { + nodes.forEach((node: IHeaderTreeDefine) => { + if ( + !node.indicatorKey && + !isHasIndicator && + (!(node.children as IHeaderTreeDefine[])?.length || !node.children) + ) { + node.children = this.indicators?.map((indicator: IIndicator): { indicatorKey: string; value: string } => { + return { indicatorKey: indicator.indicatorKey, value: indicator.title ?? indicator.indicatorKey }; + }); + } else if (node.children && Array.isArray(node.children)) { + checkNode(node.children, isHasIndicator || !!node.indicatorKey); + } + }); + }; + if (customTree?.length) { + checkNode(customTree, false); + } else { + customTree = this.indicators?.map((indicator: IIndicator): { indicatorKey: string; value: string } => { + return { indicatorKey: indicator.indicatorKey, value: indicator.title ?? indicator.indicatorKey }; + }); + } + return customTree; + } + changeTreeNodeValue( rowKey: string[] | string = [], colKey: string[] | string = [], @@ -1875,22 +1624,6 @@ export class Dataset { this.processRecords(); } } - changeDataConfig(dataConfig: { - rows: string[]; //行维度字段数组; - columns: string[]; //列维度字段数组; - }) { - this.rows = dataConfig.rows; - this.columns = dataConfig.columns; - } - addRecords(records: any[]) { - for (let i = 0, len = records.length; i < len; i++) { - const record = records[i]; - this.processRecord(record); - } - if (Array.isArray(this.records)) { - this.records.push(records); - } - } } function arraySortByAnotherArray(array: string[], sortArray: string[]) { diff --git a/packages/vtable/src/dataset/statistics-helper.ts b/packages/vtable/src/dataset/statistics-helper.ts index 72e5d4f42..1a718aed8 100644 --- a/packages/vtable/src/dataset/statistics-helper.ts +++ b/packages/vtable/src/dataset/statistics-helper.ts @@ -2,32 +2,19 @@ import type { SortOrder } from '../ts-types'; import { AggregationType } from '../ts-types'; import type { BaseTableAPI } from '../ts-types/base-table'; -export interface IAggregator { - records?: any[]; - value: () => any; - className: string; - push: (record: any) => void; - recalculate: () => any; - formatValue?: (col?: number, row?: number, table?: BaseTableAPI) => any; - formatFun?: () => any; - clearCacheValue: () => any; - reset: () => void; -} -export abstract class Aggregator implements IAggregator { +export abstract class Aggregator { className = 'Aggregator'; isRecord?: boolean = true; //是否需要维护records 将数据源都记录下来 records?: any[] = []; type?: string; - key: string; field?: string | string[]; formatFun?: any; _formatedValue?: any; - constructor(config: { key: string; dimension: string; formatFun?: any; isRecord?: boolean }) { - this.key = config.key; - this.field = config.dimension; - this.formatFun = config.formatFun; - this.isRecord = config.isRecord ?? this.isRecord; + constructor(dimension: string, formatFun?: any, isRecord?: boolean) { + this.field = dimension; + this.formatFun = formatFun; + this.isRecord = isRecord ?? this.isRecord; } abstract push(record: any): void; abstract value(): any; @@ -53,7 +40,7 @@ export class RecordAggregator extends Aggregator { type: string = AggregationType.RECORD; isRecord?: boolean = true; push(record: any): void { - if (record && this.isRecord && this.records) { + if (this.isRecord) { if (record.className === 'Aggregator') { this.records.push(...record.records); } else { @@ -78,14 +65,10 @@ export class NoneAggregator extends Aggregator { declare field?: string; fieldValue?: any; push(record: any): void { - if (record) { - if (this.isRecord) { - this.records = [record]; - } - if (this.field) { - this.fieldValue = record[this.field]; - } + if (this.isRecord) { + this.records = [record]; } + this.fieldValue = record[this.field]; } value() { return this.fieldValue; @@ -102,82 +85,26 @@ export class CustomAggregator extends Aggregator { type: string = AggregationType.CUSTOM; //仅获取其中一条数据 不做聚合 其fieldValue可以是number或者string类型 isRecord?: boolean = true; declare field?: string; - aggregationFun?: Function; + aggregationFun: Function; values: (string | number)[] = []; fieldValue?: any; - constructor(config: { - key: string; - dimension: string; - formatFun?: any; - isRecord?: boolean; - aggregationFun?: Function; - }) { - super(config); - this.aggregationFun = config.aggregationFun; - } - push(record: any): void { - if (record) { - if (this.isRecord && this.records) { - if (record.className === 'Aggregator') { - this.records.push(...record.records); - } else { - this.records.push(record); - } - } - if (this.field) { - this.values.push(record[this.field]); - } - } - } - value() { - if (!this.fieldValue) { - this.fieldValue = this.aggregationFun?.(this.values, this.records, this.field); - } - return this.fieldValue; - } - reset() { - this.records = []; - this.fieldValue = undefined; - } - recalculate() { - // do nothing - } -} -export class RecalculateAggregator extends Aggregator { - type: string = AggregationType.RECALCULATE; //仅获取其中一条数据 不做聚合 其fieldValue可以是number或者string类型 - isRecord?: boolean = true; - declare field?: string; - calculateFun: Function; - fieldValue?: any; - dependAggregators: Aggregator[]; - dependIndicatorKeys: string[]; - constructor(config: { - key: string; - dimension: string; - formatFun: any; - isRecord: boolean; - calculateFun: Function; - dependAggregators: Aggregator[]; - dependIndicatorKeys: string[]; - }) { - super(config); - this.calculateFun = config.calculateFun; - this.dependAggregators = config.dependAggregators; - this.dependIndicatorKeys = config.dependIndicatorKeys; + constructor(dimension: string, formatFun?: any, isRecord?: boolean, aggregationFun?: Function) { + super(dimension, formatFun, isRecord); + this.aggregationFun = aggregationFun; } push(record: any): void { - if (record && this.isRecord && this.records) { + if (this.isRecord) { if (record.className === 'Aggregator') { this.records.push(...record.records); } else { this.records.push(record); } } + this.values.push(record[this.field]); } value() { if (!this.fieldValue) { - const aggregatorValue = _getDependAggregatorValues(this.dependAggregators, this.dependIndicatorKeys); - this.fieldValue = this.calculateFun?.(aggregatorValue, this.records, this.field); + this.fieldValue = this.aggregationFun?.(this.values, this.records, this.field); } return this.fieldValue; } @@ -196,44 +123,36 @@ export class SumAggregator extends Aggregator { nagetiveSum = 0; declare field?: string; needSplitPositiveAndNegativeForSum?: boolean = false; - constructor(config: { - key: string; - dimension: string; - formatFun?: any; - isRecord?: boolean; - needSplitPositiveAndNegative?: boolean; - }) { - super(config); - this.needSplitPositiveAndNegativeForSum = config.needSplitPositiveAndNegative ?? false; + constructor(dimension: string, formatFun?: any, isRecord?: boolean, needSplitPositiveAndNegative?: boolean) { + super(dimension, formatFun, isRecord); + this.needSplitPositiveAndNegativeForSum = needSplitPositiveAndNegative ?? false; } push(record: any): void { - if (record) { - if (this.isRecord && this.records) { - if (record.className === 'Aggregator') { - this.records.push(...record.records); - } else { - this.records.push(record); - } - } + if (this.isRecord) { if (record.className === 'Aggregator') { - const value = record.value(); - this.sum += value; - if (this.needSplitPositiveAndNegativeForSum) { - if (value > 0) { - this.positiveSum += value; - } else if (value < 0) { - this.nagetiveSum += value; - } + this.records.push(...record.records); + } else { + this.records.push(record); + } + } + if (record.className === 'Aggregator') { + const value = record.value(); + this.sum += value; + if (this.needSplitPositiveAndNegativeForSum) { + if (value > 0) { + this.positiveSum += value; + } else if (value < 0) { + this.nagetiveSum += value; } - } else if (this.field && !isNaN(parseFloat(record[this.field]))) { - const value = parseFloat(record[this.field]); - this.sum += value; - if (this.needSplitPositiveAndNegativeForSum) { - if (value > 0) { - this.positiveSum += value; - } else if (value < 0) { - this.nagetiveSum += value; - } + } + } else if (!isNaN(parseFloat(record[this.field]))) { + const value = parseFloat(record[this.field]); + this.sum += value; + if (this.needSplitPositiveAndNegativeForSum) { + if (value > 0) { + this.positiveSum += value; + } else if (value < 0) { + this.nagetiveSum += value; } } } @@ -254,28 +173,26 @@ export class SumAggregator extends Aggregator { recalculate() { this.sum = 0; this._formatedValue = undefined; - if (this.records) { - for (let i = 0; i < this.records.length; i++) { - const record = this.records[i]; - if (record.className === 'Aggregator') { - const value = record.value(); - this.sum += value; - if (this.needSplitPositiveAndNegativeForSum) { - if (value > 0) { - this.positiveSum += value; - } else if (value < 0) { - this.nagetiveSum += value; - } + for (let i = 0; i < this.records.length; i++) { + const record = this.records[i]; + if (record.className === 'Aggregator') { + const value = record.value(); + this.sum += value; + if (this.needSplitPositiveAndNegativeForSum) { + if (value > 0) { + this.positiveSum += value; + } else if (value < 0) { + this.nagetiveSum += value; } - } else if (this.field && !isNaN(parseFloat(record[this.field]))) { - const value = parseFloat(record[this.field]); - this.sum += value; - if (this.needSplitPositiveAndNegativeForSum) { - if (value > 0) { - this.positiveSum += value; - } else if (value < 0) { - this.nagetiveSum += value; - } + } + } else if (!isNaN(parseFloat(record[this.field]))) { + const value = parseFloat(record[this.field]); + this.sum += value; + if (this.needSplitPositiveAndNegativeForSum) { + if (value > 0) { + this.positiveSum += value; + } else if (value < 0) { + this.nagetiveSum += value; } } } @@ -288,20 +205,18 @@ export class CountAggregator extends Aggregator { count = 0; declare field?: string; push(record: any): void { - if (record) { - if (this.isRecord && this.records) { - if (record.className === 'Aggregator') { - this.records.push(...record.records); - } else { - this.records.push(record); - } - } + if (this.isRecord) { if (record.className === 'Aggregator') { - this.count += record.value(); + this.records.push(...record.records); } else { - this.count++; + this.records.push(record); } } + if (record.className === 'Aggregator') { + this.count += record.value(); + } else { + this.count++; + } } value() { return this.count; @@ -313,14 +228,12 @@ export class CountAggregator extends Aggregator { recalculate() { this.count = 0; this._formatedValue = undefined; - if (this.records) { - for (let i = 0; i < this.records.length; i++) { - const record = this.records[i]; - if (record.className === 'Aggregator') { - this.count += record.value(); - } else { - this.count++; - } + for (let i = 0; i < this.records.length; i++) { + const record = this.records[i]; + if (record.className === 'Aggregator') { + this.count += record.value(); + } else { + this.count++; } } } @@ -331,22 +244,20 @@ export class AvgAggregator extends Aggregator { count = 0; declare field?: string; push(record: any): void { - if (record) { - if (this.isRecord && this.records) { - if (record.className === 'Aggregator') { - this.records.push(...record.records); - } else { - this.records.push(record); - } - } - if (record.className === 'Aggregator' && record.type === AggregationType.AVG) { - this.sum += record.sum; - this.count += record.count; - } else if (this.field && !isNaN(parseFloat(record[this.field]))) { - this.sum += parseFloat(record[this.field]); - this.count++; + if (this.isRecord) { + if (record.className === 'Aggregator') { + this.records.push(...record.records); + } else { + this.records.push(record); } } + if (record.className === 'Aggregator' && record.type === AggregationType.AVG) { + this.sum += record.sum; + this.count += record.count; + } else if (!isNaN(parseFloat(record[this.field]))) { + this.sum += parseFloat(record[this.field]); + this.count++; + } } value() { return this.sum / this.count; @@ -360,16 +271,14 @@ export class AvgAggregator extends Aggregator { this.sum = 0; this.count = 0; this._formatedValue = undefined; - if (this.records) { - for (let i = 0; i < this.records.length; i++) { - const record = this.records[i]; - if (record.className === 'Aggregator' && record.type === AggregationType.AVG) { - this.sum += record.sum; - this.count += record.count; - } else if (this.field && !isNaN(parseFloat(record[this.field]))) { - this.sum += parseFloat(record[this.field]); - this.count++; - } + for (let i = 0; i < this.records.length; i++) { + const record = this.records[i]; + if (record.className === 'Aggregator' && record.type === AggregationType.AVG) { + this.sum += record.sum; + this.count += record.count; + } else if (!isNaN(parseFloat(record[this.field]))) { + this.sum += parseFloat(record[this.field]); + this.count++; } } } @@ -379,24 +288,22 @@ export class MaxAggregator extends Aggregator { max: number = Number.MIN_SAFE_INTEGER; declare field?: string; push(record: any): void { - if (record) { - if (this.isRecord && this.records) { - if (record.className === 'Aggregator') { - this.records.push(...record.records); - } else { - this.records.push(record); - } - } + if (this.isRecord) { if (record.className === 'Aggregator') { - this.max = record.max > this.max ? record.max : this.max; - } else if (typeof record === 'number') { - this.max = record > this.max ? record : this.max; - } else if (this.field && typeof record[this.field] === 'number') { - this.max = record[this.field] > this.max ? record[this.field] : this.max; - } else if (this.field && !isNaN(record[this.field])) { - this.max = parseFloat(record[this.field]) > this.max ? parseFloat(record[this.field]) : this.max; + this.records.push(...record.records); + } else { + this.records.push(record); } } + if (record.className === 'Aggregator') { + this.max = record.max > this.max ? record.max : this.max; + } else if (typeof record === 'number') { + this.max = record > this.max ? record : this.max; + } else if (typeof record[this.field] === 'number') { + this.max = record[this.field] > this.max ? record[this.field] : this.max; + } else if (!isNaN(record[this.field])) { + this.max = parseFloat(record[this.field]) > this.max ? parseFloat(record[this.field]) : this.max; + } } value() { return this.max; @@ -408,18 +315,16 @@ export class MaxAggregator extends Aggregator { recalculate() { this.max = Number.MIN_SAFE_INTEGER; this._formatedValue = undefined; - if (this.records) { - for (let i = 0; i < this.records.length; i++) { - const record = this.records[i]; - if (record.className === 'Aggregator') { - this.max = record.max > this.max ? record.max : this.max; - } else if (typeof record === 'number') { - this.max = record > this.max ? record : this.max; - } else if (this.field && typeof record[this.field] === 'number') { - this.max = record[this.field] > this.max ? record[this.field] : this.max; - } else if (this.field && !isNaN(record[this.field])) { - this.max = parseFloat(record[this.field]) > this.max ? parseFloat(record[this.field]) : this.max; - } + for (let i = 0; i < this.records.length; i++) { + const record = this.records[i]; + if (record.className === 'Aggregator') { + this.max = record.max > this.max ? record.max : this.max; + } else if (typeof record === 'number') { + this.max = record > this.max ? record : this.max; + } else if (typeof record[this.field] === 'number') { + this.max = record[this.field] > this.max ? record[this.field] : this.max; + } else if (!isNaN(record[this.field])) { + this.max = parseFloat(record[this.field]) > this.max ? parseFloat(record[this.field]) : this.max; } } } @@ -429,22 +334,20 @@ export class MinAggregator extends Aggregator { min: number = Number.MAX_SAFE_INTEGER; declare field?: string; push(record: any): void { - if (record) { - if (this.isRecord && this.records) { - if (record.className === 'Aggregator') { - this.records.push(...record.records); - } else { - this.records.push(record); - } - } + if (this.isRecord) { if (record.className === 'Aggregator') { - this.min = record.min < this.min ? record.min : this.min; - } else if (typeof record === 'number') { - this.min = record < this.min ? record : this.min; - } else if (this.field && typeof record[this.field] === 'number') { - this.min = record[this.field] < this.min ? record[this.field] : this.min; + this.records.push(...record.records); + } else { + this.records.push(record); } } + if (record.className === 'Aggregator') { + this.min = record.min < this.min ? record.min : this.min; + } else if (typeof record === 'number') { + this.min = record < this.min ? record : this.min; + } else if (typeof record[this.field] === 'number') { + this.min = record[this.field] < this.min ? record[this.field] : this.min; + } } value() { return this.min; @@ -456,16 +359,14 @@ export class MinAggregator extends Aggregator { recalculate() { this.min = Number.MAX_SAFE_INTEGER; this._formatedValue = undefined; - if (this.records) { - for (let i = 0; i < this.records.length; i++) { - const record = this.records[i]; - if (record.className === 'Aggregator') { - this.min = record.min < this.min ? record.min : this.min; - } else if (typeof record === 'number') { - this.min = record < this.min ? record : this.min; - } else if (this.field && typeof record[this.field] === 'number') { - this.min = record[this.field] < this.min ? record[this.field] : this.min; - } + for (let i = 0; i < this.records.length; i++) { + const record = this.records[i]; + if (record.className === 'Aggregator') { + this.min = record.min < this.min ? record.min : this.min; + } else if (typeof record === 'number') { + this.min = record < this.min ? record : this.min; + } else if (typeof record[this.field] === 'number') { + this.min = record[this.field] < this.min ? record[this.field] : this.min; } } } @@ -599,14 +500,3 @@ export function sortBy(order: string[]) { return naturalSort(a, b); }; } - -function _getDependAggregatorValues(aggregators: Aggregator[], dependIndicatorKeys: string[]) { - const dependAggregatorValues: any = {}; - for (let m = 0; m < dependIndicatorKeys?.length; m++) { - const aggrator = aggregators.find(aggrator => aggrator.key === dependIndicatorKeys[m]); - if (aggrator) { - dependAggregatorValues[aggrator.key] = aggrator?.value(); - } - } - return dependAggregatorValues; -} diff --git a/packages/vtable/src/edit/edit-manager.ts b/packages/vtable/src/edit/edit-manager.ts index 28574712e..4def11ad7 100644 --- a/packages/vtable/src/edit/edit-manager.ts +++ b/packages/vtable/src/edit/edit-manager.ts @@ -65,14 +65,14 @@ export class EditManeger { // console.warn("VTable Warn: cell has config custom render or layout, can't be edited"); // return; // } - // if (!this.table.isHeader(col, row)) { - // const range = this.table.getCellRange(col, row); - // const isMerge = range.start.col !== range.end.col || range.start.row !== range.end.row; - // if (isMerge) { - // console.warn("VTable Warn: this is merge cell, can't be edited"); - // return; - // } - // } + if (!this.table.isHeader(col, row)) { + const range = this.table.getCellRange(col, row); + const isMerge = range.start.col !== range.end.col || range.start.row !== range.end.row; + if (isMerge) { + console.warn("VTable Warn: this is merge cell, can't be edited"); + return; + } + } if ((this.table.internalProps.layoutMap as SimpleHeaderLayoutMap)?.isAggregation?.(col, row)) { console.warn("VTable Warn: this is aggregation value, can't be edited"); return; @@ -108,10 +108,10 @@ export class EditManeger { } } - /** 如果是事件触发调用该接口 请传入原始事件对象 将判断事件对象是否在编辑器本身上面 来处理是否结束编辑 返回值如果为false说明没有退出编辑状态*/ - completeEdit(e?: Event): boolean { + /** 如果是事件触发调用该接口 请传入原始事件对象 将判断事件对象是否在编辑器本身上面 来处理是否结束编辑 */ + completeEdit(e?: Event) { if (!this.editingEditor) { - return true; + return; } const target = e?.target as HTMLElement | undefined; @@ -122,10 +122,10 @@ export class EditManeger { console.warn('VTable Warn: `targetIsOnEditor` is deprecated, please use `isEditorElement` instead.'); if (editor.targetIsOnEditor(target)) { - return false; + return; } } else if (!editor.isEditorElement || editor.isEditorElement(target)) { - return false; + return; } } @@ -134,23 +134,13 @@ export class EditManeger { } if (!this.editingEditor.validateValue || this.editingEditor.validateValue?.()) { const changedValue = this.editingEditor.getValue?.(); - const range = this.table.getCellRange(this.editCell.col, this.editCell.row); - const changedValues: any[] = []; - for (let row = range.start.row; row <= range.end.row; row++) { - const rowChangedValues = []; - for (let col = range.start.col; col <= range.end.col; col++) { - rowChangedValues.push(changedValue); - } - changedValues.push(rowChangedValues); - } - (this.table as ListTableAPI).changeCellValues(range.start.col, range.start.row, changedValues); + (this.table as ListTableAPI).changeCellValue(this.editCell.col, this.editCell.row, changedValue); + this.editingEditor.exit && console.warn('VTable Warn: `exit` is deprecated, please use `onEnd` instead.'); this.editingEditor.exit?.(); this.editingEditor.onEnd?.(); this.editingEditor = null; - return true; } - return false; } cancelEdit() { diff --git a/packages/vtable/src/event/EventHandler.ts b/packages/vtable/src/event/EventHandler.ts index f59b6e4e6..c7fd2ce62 100644 --- a/packages/vtable/src/event/EventHandler.ts +++ b/packages/vtable/src/event/EventHandler.ts @@ -13,15 +13,7 @@ type EventListenerObject = { options: any[]; }; -export type ResizeObserverCallBack = ({ - width, - height, - windowSizeNotChange -}: { - width: number; - height: number; - windowSizeNotChange: boolean; -}) => void; +export type ResizeObserverCallBack = ({ width, height }: { width: number; height: number }) => void; export class ResizeObserver { resizeTime = 100; @@ -77,12 +69,11 @@ export class ResizeObserver { callBack = () => { const newSize = this.getSize(); - let windowSizeNotChange = false; if (newSize.width === this.lastSize.width && newSize.height === this.lastSize.height) { - windowSizeNotChange = true; + return; } this.lastSize = newSize; - this.cb && this.cb({ ...this.lastSize, windowSizeNotChange }); + this.cb && this.cb({ ...this.lastSize }); }; setSize(size: { width: number; height: number }) { @@ -90,9 +81,9 @@ export class ResizeObserver { } private onResize = () => { - // if (this.checkSize()) { - this.callBackDebounce(); - // } + if (this.checkSize()) { + this.callBackDebounce(); + } }; private checkSize() { diff --git a/packages/vtable/src/event/event.ts b/packages/vtable/src/event/event.ts index 1c356f652..0535d2f2c 100644 --- a/packages/vtable/src/event/event.ts +++ b/packages/vtable/src/event/event.ts @@ -55,8 +55,6 @@ export class EventManager { //报错已绑定过的事件 后续清除绑定 globalEventListeners: { name: string; env: 'document' | 'body' | 'window'; callback: (e?: any) => void }[] = []; inertiaScroll: InertiaScroll; - - bindSparklineHoverEvent: boolean; constructor(table: BaseTableAPI) { this.table = table; this.handleTextStickBindId = []; @@ -104,9 +102,6 @@ export class EventManager { }); this.handleTextStickBindId = []; } - - // chart hover - bindSparklineHoverEvent(this.table); }, 0); } bindSelfEvent() { @@ -129,9 +124,7 @@ export class EventManager { } else if (funcType === IconFuncTypeEnum.drillDown) { drillClick(this.table); } else if (funcType === IconFuncTypeEnum.collapse || funcType === IconFuncTypeEnum.expand) { - const isHasSelected = !!stateManager.select.ranges?.length; - stateManager.updateSelectPos(-1, -1); - stateManager.endSelectCells(true, isHasSelected); + this.table.stateManager.updateSelectPos(-1, -1); this.table.toggleHierarchyState(col, row); } }); @@ -580,12 +573,11 @@ export class EventManager { chechColumnMover(eventArgsSet: SceneEvent): boolean { // return false; const { eventArgs } = eventArgsSet; + if ( eventArgs && this.table.isHeader(eventArgs.col, eventArgs.row) && - (checkCellInSelect(eventArgs.col, eventArgs.row, this.table.stateManager.select.ranges) || - this.table.options.select?.disableHeaderSelect || - this.table.options.select?.disableSelect) && + checkCellInSelect(eventArgs.col, eventArgs.row, this.table.stateManager.select.ranges) && // this.table.stateManager.select.cellPosStart.col === eventArgs.col && // this.table.stateManager.select.cellPosStart.row === eventArgs.row && this.table._canDragHeaderPosition(eventArgs.col, eventArgs.row) diff --git a/packages/vtable/src/event/listener/container-dom.ts b/packages/vtable/src/event/listener/container-dom.ts index 136ce607f..d1c15dff8 100644 --- a/packages/vtable/src/event/listener/container-dom.ts +++ b/packages/vtable/src/event/listener/container-dom.ts @@ -5,8 +5,7 @@ import { TABLE_EVENT_TYPE } from '../../core/TABLE_EVENT_TYPE'; import { handleWhell } from '../scroll'; import { browser } from '../../tools/helper'; import type { EventManager } from '../event'; -import { getPixelRatio } from '../../tools/pixel-ratio'; -import { endResizeCol, endResizeRow } from './table-group'; +import { BaseTableAPI } from '../../ts-types/base-table'; export function bindContainerDomListener(eventManager: EventManager) { const table = eventManager.table; @@ -44,7 +43,7 @@ export function bindContainerDomListener(eventManager: EventManager) { ) { if ( !(table.options.keyboardOptions?.moveEditCellOnArrowKeys ?? false) && - (table as ListTableAPI).editorManager?.editingEditor + (table as ListTableAPI).editorManager.editingEditor ) { // 编辑单元格状态下 如果没有开启方向键切换cell 则退出 。方向键可以在编辑input内移动光标 return; @@ -58,57 +57,25 @@ export function bindContainerDomListener(eventManager: EventManager) { // 处理向上箭头键 if (e.key === 'ArrowUp') { - if (e.ctrlKey || e.metaKey) { - targetCol = stateManager.select.cellPos.col; - targetRow = 0; - } else if (e.shiftKey) { - targetCol = stateManager.select.cellPos.col; - targetRow = Math.min(table.rowCount - 1, Math.max(0, stateManager.select.cellPos.row - 1)); - } else { - targetCol = stateManager.select.cellPos.col; - targetRow = Math.min(table.rowCount - 1, Math.max(0, stateManager.select.cellPos.row - 1)); - } + targetCol = stateManager.select.cellPos.col; + targetRow = Math.min(table.rowCount - 1, Math.max(0, stateManager.select.cellPos.row - 1)); } else if (e.key === 'ArrowDown') { // 处理向下箭头键 - if (e.ctrlKey || e.metaKey) { - targetCol = stateManager.select.cellPos.col; - targetRow = table.rowCount - 1; - } else if (e.shiftKey) { - targetCol = stateManager.select.cellPos.col; - targetRow = Math.min(table.rowCount - 1, Math.max(0, stateManager.select.cellPos.row + 1)); - } else { - targetCol = stateManager.select.cellPos.col; - targetRow = Math.min(table.rowCount - 1, Math.max(0, stateManager.select.cellPos.row + 1)); - } + targetCol = stateManager.select.cellPos.col; + targetRow = Math.min(table.rowCount - 1, Math.max(0, stateManager.select.cellPos.row + 1)); } else if (e.key === 'ArrowLeft') { // 处理向左箭头键 - if (e.ctrlKey || e.metaKey) { - targetCol = 0; - targetRow = stateManager.select.cellPos.row; - } else if (e.shiftKey) { - targetRow = stateManager.select.cellPos.row; - targetCol = Math.min(table.colCount - 1, Math.max(0, stateManager.select.cellPos.col - 1)); - } else { - targetRow = stateManager.select.cellPos.row; - targetCol = Math.min(table.colCount - 1, Math.max(0, stateManager.select.cellPos.col - 1)); - } + targetRow = stateManager.select.cellPos.row; + targetCol = Math.min(table.colCount - 1, Math.max(0, stateManager.select.cellPos.col - 1)); } else if (e.key === 'ArrowRight') { // 处理向右箭头键 - if (e.ctrlKey || e.metaKey) { - targetCol = table.colCount - 1; - targetRow = stateManager.select.cellPos.row; - } else if (e.shiftKey) { - targetRow = stateManager.select.cellPos.row; - targetCol = Math.min(table.colCount - 1, Math.max(0, stateManager.select.cellPos.col + 1)); - } else { - targetRow = stateManager.select.cellPos.row; - targetCol = Math.min(table.colCount - 1, Math.max(0, stateManager.select.cellPos.col + 1)); - } + targetRow = stateManager.select.cellPos.row; + targetCol = Math.min(table.colCount - 1, Math.max(0, stateManager.select.cellPos.col + 1)); } - table.selectCell(targetCol, targetRow, e.shiftKey); + table.selectCell(targetCol, targetRow); if ( (table.options.keyboardOptions?.moveEditCellOnArrowKeys ?? false) && - (table as ListTableAPI).editorManager?.editingEditor + (table as ListTableAPI).editorManager.editingEditor ) { // 开启了方向键切换编辑单元格 并且当前已经在编辑状态下 切换到下一个需先退出再进入下个单元格的编辑 (table as ListTableAPI).editorManager.completeEdit(); @@ -122,25 +89,22 @@ export function bindContainerDomListener(eventManager: EventManager) { } else if (e.key === 'Enter') { // 如果按enter键 可以结束当前的编辑 或开启编辑选中的单元格(仅限单选) if ((table as ListTableAPI).editorManager.editingEditor) { - // 如果是结束当前编辑,且有主动监听keydown事件,则先触发keydown事件,之后再结束编辑 - handleKeydownListener(e); (table as ListTableAPI).editorManager.completeEdit(); table.getElement().focus(); - // 直接返回,不再触发最后的keydown监听事件相关代码 - return; - } - if ( - (table.options.keyboardOptions?.editCellOnEnter ?? true) && - (table.stateManager.select.ranges?.length ?? 0) === 1 - ) { - // 如果开启按enter键进入编辑的配置 且当前有选中的单元格 则进入编辑(仅限单选) - const startCol = table.stateManager.select.ranges[0].start.col; - const startRow = table.stateManager.select.ranges[0].start.row; - const endCol = table.stateManager.select.ranges[0].end.col; - const endRow = table.stateManager.select.ranges[0].end.row; - if (startCol === endCol && startRow === endRow) { - if ((table as ListTableAPI).getEditor(startCol, startRow)) { - (table as ListTableAPI).editorManager.startEditCell(startCol, startRow); + } else { + if ( + (table.options.keyboardOptions?.editCellOnEnter ?? true) && + (table.stateManager.select.ranges?.length ?? 0) === 1 + ) { + // 如果开启按enter键进入编辑的配置 且当前有选中的单元格 则进入编辑 + const startCol = table.stateManager.select.ranges[0].start.col; + const startRow = table.stateManager.select.ranges[0].start.row; + const endCol = table.stateManager.select.ranges[0].end.col; + const endRow = table.stateManager.select.ranges[0].end.row; + if (startCol === endCol && startRow === endRow) { + if ((table as ListTableAPI).getEditor(startCol, startRow)) { + (table as ListTableAPI).editorManager.startEditCell(startCol, startRow); + } } } } @@ -161,7 +125,7 @@ export function bindContainerDomListener(eventManager: EventManager) { targetCol = stateManager.select.cellPos.col + 1; } table.selectCell(targetCol, targetRow); - if ((table as ListTableAPI).editorManager?.editingEditor) { + if ((table as ListTableAPI).editorManager.editingEditor) { (table as ListTableAPI).editorManager.completeEdit(); table.getElement().focus(); if ((table as ListTableAPI).getEditor(targetCol, targetRow)) { @@ -172,13 +136,6 @@ export function bindContainerDomListener(eventManager: EventManager) { } } - handleKeydownListener(e); - }); - /** - * 处理主动注册的keydown事件 - * @param e - */ - function handleKeydownListener(e: KeyboardEvent) { if ((table as any).hasListeners(TABLE_EVENT_TYPE.KEYDOWN)) { const cellsEvent: KeydownEvent = { keyCode: e.keyCode ?? e.which, @@ -189,7 +146,7 @@ export function bindContainerDomListener(eventManager: EventManager) { }; table.fireListeners(TABLE_EVENT_TYPE.KEYDOWN, cellsEvent); } - } + }); handler.on(table.getElement(), 'copy', (e: KeyboardEvent) => { if (table.keyboardOptions?.copySelected) { @@ -321,19 +278,8 @@ export function bindContainerDomListener(eventManager: EventManager) { // 临时绕行解决因为display设置为none产生的问题 return; } - if (!isValid(table.options.pixelRatio)) { - table.setPixelRatio(getPixelRatio()); - } - if (!e.windowSizeNotChange) { - table.resize(); - } + table.resize(); }); - - // const regex = /]*>(.*?)<\/tr>/gs; // 匹配标签及其内容 - const regex = /]*>([\s\S]*?)<\/tr>/g; // for webpack3 - // const cellRegex = /]*>(.*?)<\/td>/gs; // 匹配标签及其内容 - const cellRegex = /]*>([\s\S]*?)<\/td>/g; // for webpack3 - function pasteHtmlToTable(item: ClipboardItem) { const ranges = table.stateManager.select.ranges; const selectRangeLength = ranges.length; @@ -348,10 +294,12 @@ export function bindContainerDomListener(eventManager: EventManager) { blob.text().then((pastedData: any) => { // 解析html数据 if (pastedData && /(]*>(.*?)<\/tr>/gs; // 匹配标签及其内容 // const matches = pastedData.matchAll(regex); const matches = Array.from(pastedData.matchAll(regex)); for (const match of matches) { const rowContent = match[1]; // 获取标签中的内容 + const cellRegex = /]*>(.*?)<\/td>/gs; // 匹配标签及其内容 const cellMatches: RegExpMatchArray[] = Array.from(rowContent.matchAll(cellRegex)); // 获取标签中的内容 const rowValues = cellMatches.map(cellMatch => { return ( @@ -513,11 +461,6 @@ export function bindContainerDomListener(eventManager: EventManager) { table.eventManager.isDown = false; table.eventManager.isDraging = false; table.eventManager.inertiaScroll.endInertia(); - if (stateManager.isResizeCol()) { - endResizeCol(table); - } else if (stateManager.isResizeRow()) { - endResizeRow(table); - } }; eventManager.globalEventListeners.push({ name: 'pointerup', @@ -669,11 +612,14 @@ export function bindContainerDomListener(eventManager: EventManager) { } } table.stateManager.updateInteractionState(InteractionState.grabing); - const targetCol = table.getTargetColAtConsiderRightFrozen(selectX, considerFrozenX); - const targetRow = table.getTargetRowAtConsiderBottomFrozen(selectY, considerFrozenY); - if (isValid(targetCol) && isValid(targetRow)) { - table.stateManager.updateSelectPos(targetCol.col, targetRow.row, false, false, false, true); - } + table.stateManager.updateSelectPos( + table.getTargetColAtConsiderRightFrozen(selectX, considerFrozenX).col, + table.getTargetRowAtConsiderBottomFrozen(selectY, considerFrozenY).row, + false, + false, + false, + true + ); }); } else if (table.eventManager.inertiaScroll.isInertiaScrolling()) { table.eventManager.inertiaScroll.endInertia(); diff --git a/packages/vtable/src/event/listener/scroll-bar.ts b/packages/vtable/src/event/listener/scroll-bar.ts index c2f461035..92d6eec18 100644 --- a/packages/vtable/src/event/listener/scroll-bar.ts +++ b/packages/vtable/src/event/listener/scroll-bar.ts @@ -37,11 +37,6 @@ export function bindScrollBarListener(eventManager: EventManager) { }); scenegraph.component.vScrollBar.addEventListener('pointerdown', (e: FederatedPointerEvent) => { e.stopPropagation(); //防止冒泡到stage上 检测到挨着列间隔线判断成拖拽状态 - if ((scenegraph.table as any).hasListeners(TABLE_EVENT_TYPE.MOUSEDOWN_TABLE)) { - scenegraph.table.fireListeners(TABLE_EVENT_TYPE.MOUSEDOWN_TABLE, { - event: e.nativeEvent - }); - } }); scenegraph.component.vScrollBar.addEventListener('scrollDown', (e: FederatedPointerEvent) => { scenegraph.table.eventManager.LastBodyPointerXY = { x: e.x, y: e.y }; @@ -80,11 +75,6 @@ export function bindScrollBarListener(eventManager: EventManager) { }); scenegraph.component.hScrollBar.addEventListener('pointerdown', (e: FederatedPointerEvent) => { e.stopPropagation(); //防止冒泡到stage上 检测到挨着列间隔线判断成拖拽状态 - if ((scenegraph.table as any).hasListeners(TABLE_EVENT_TYPE.MOUSEDOWN_TABLE)) { - scenegraph.table.fireListeners(TABLE_EVENT_TYPE.MOUSEDOWN_TABLE, { - event: e.nativeEvent - }); - } }); scenegraph.component.hScrollBar.addEventListener('scrollDown', (e: FederatedPointerEvent) => { scenegraph.table.eventManager.LastBodyPointerXY = { x: e.x, y: e.y }; diff --git a/packages/vtable/src/event/listener/table-group.ts b/packages/vtable/src/event/listener/table-group.ts index b60b4023f..598bf428f 100644 --- a/packages/vtable/src/event/listener/table-group.ts +++ b/packages/vtable/src/event/listener/table-group.ts @@ -12,7 +12,7 @@ import type { SceneEvent } from '../util'; import { getCellEventArgsSet, regIndexReg } from '../util'; import { TABLE_EVENT_TYPE } from '../../core/TABLE_EVENT_TYPE'; import type { Group } from '../../scenegraph/graphic/group'; -import { isValid } from '@visactor/vutils'; +import { isValid, last } from '@visactor/vutils'; import { getIconAndPositionFromTarget } from '../../scenegraph/utils/icon'; import { cellInRanges } from '../../tools/helper'; import { Rect } from '../../tools/Rect'; @@ -40,10 +40,7 @@ export function bindTableGroupListener(eventManager: EventManager) { // if (stateManager.interactionState === InteractionState.scrolling) { // return; // } - if ( - stateManager.interactionState === InteractionState.grabing && - !(table as ListTableAPI).editorManager?.editingEditor - ) { + if (stateManager.interactionState === InteractionState.grabing) { if (Math.abs(lastX - e.x) + Math.abs(lastY - e.y) >= 1) { if (stateManager.isResizeCol()) { /* do nothing */ @@ -56,11 +53,7 @@ export function bindTableGroupListener(eventManager: EventManager) { } } return; - } else if ( - table.eventManager.isDraging && - stateManager.isSelecting() && - !(table as ListTableAPI).editorManager?.editingEditor - ) { + } else if (table.eventManager.isDraging && stateManager.isSelecting()) { eventManager.dealTableSelect(eventArgsSet, true); } // 更新列宽调整pointer @@ -118,8 +111,7 @@ export function bindTableGroupListener(eventManager: EventManager) { }), scaleRatio: table.canvas.getBoundingClientRect().width / table.canvas.offsetWidth, event: e.nativeEvent, - target: eventArgsSet?.eventArgs?.target, - mergeCellInfo: eventArgsSet.eventArgs?.mergeInfo + target: eventArgsSet?.eventArgs?.target }); } } @@ -151,8 +143,7 @@ export function bindTableGroupListener(eventManager: EventManager) { funcType: (icon as any).attribute.funcType } : undefined, - target: eventArgsSet?.eventArgs?.target, - mergeCellInfo: eventArgsSet.eventArgs?.mergeInfo + target: eventArgsSet?.eventArgs?.target }); } }); @@ -341,19 +332,11 @@ export function bindTableGroupListener(eventManager: EventManager) { } } } - const isCompleteEdit = (table as ListTableAPI).editorManager?.completeEdit(e.nativeEvent); - if (isCompleteEdit === false) { - // 如果没有正常退出编辑状态 则不执行下面的逻辑 如选择其他单元格的逻辑 - return; - } + (table as ListTableAPI).editorManager?.completeEdit(e.nativeEvent); stateManager.updateInteractionState(InteractionState.default); eventManager.dealTableHover(); //点击到表格外部不需要取消选中状态 - if (table.options.select?.outsideClickDeselect) { - const isHasSelected = !!stateManager.select.ranges?.length; - eventManager.dealTableSelect(); - stateManager.endSelectCells(true, isHasSelected); - } + // eventManager.dealTableSelect(); }); table.scenegraph.tableGroup.addEventListener('pointerdown', (e: FederatedPointerEvent) => { @@ -392,15 +375,10 @@ export function bindTableGroupListener(eventManager: EventManager) { // 点击在menu外,且不是下拉菜单的icon,移除menu stateManager.hideMenu(); } - const isCompleteEdit = (table as ListTableAPI).editorManager?.completeEdit(e.nativeEvent); - if (isCompleteEdit === false) { - // 如果没有正常退出编辑状态 则不执行下面的逻辑 如选择其他单元格的逻辑 - return; - } + (table as ListTableAPI).editorManager?.completeEdit(e.nativeEvent); + const hitIcon = (eventArgsSet?.eventArgs?.target as any)?.role?.startsWith('icon') ? eventArgsSet.eventArgs.target - : (e.target as any).role?.startsWith('icon') - ? e.target : undefined; eventManager.downIcon = hitIcon; if (!hitIcon || (hitIcon.attribute as IIconGraphicAttribute).interactive === false) { @@ -493,8 +471,7 @@ export function bindTableGroupListener(eventManager: EventManager) { col: eventArgsSet.eventArgs.col, row: eventArgsSet.eventArgs.row, event: e.nativeEvent, - target: eventArgsSet?.eventArgs?.target, - mergeCellInfo: eventArgsSet.eventArgs.mergeInfo + target: eventArgsSet?.eventArgs?.target }); } } @@ -543,8 +520,7 @@ export function bindTableGroupListener(eventManager: EventManager) { col: (eventArgsSet.eventArgs.target as unknown as Group).col, row: (eventArgsSet.eventArgs.target as unknown as Group).row, scaleRatio: table.canvas.getBoundingClientRect().width / table.canvas.offsetWidth, - target: eventArgsSet?.eventArgs?.target, - mergeCellInfo: eventArgsSet.eventArgs?.mergeInfo + target: eventArgsSet?.eventArgs?.target }; cellsEvent.cells = table.getSelectedCellInfos(); @@ -564,8 +540,7 @@ export function bindTableGroupListener(eventManager: EventManager) { col: eventArgsSet.eventArgs.col, row: eventArgsSet.eventArgs.row, event: e.nativeEvent, - target: eventArgsSet?.eventArgs?.target, - mergeCellInfo: eventArgsSet.eventArgs?.mergeInfo + target: eventArgsSet?.eventArgs?.target }); } } @@ -606,8 +581,7 @@ export function bindTableGroupListener(eventManager: EventManager) { funcType: (icon as any).attribute.funcType } : undefined, - target: eventArgsSet?.eventArgs?.target, - mergeCellInfo: eventArgsSet.eventArgs?.mergeInfo + target: eventArgsSet?.eventArgs?.target }; if (cellInRanges(table.stateManager.select.ranges, col, row)) { // 用户右键点击已经选中的区域 @@ -644,9 +618,8 @@ export function bindTableGroupListener(eventManager: EventManager) { const eventArgsSet: SceneEvent = getCellEventArgsSet(e); if (eventManager.touchSetTimeout) { clearTimeout(eventManager.touchSetTimeout); - const isHasSelected = !!stateManager.select.ranges?.length; eventManager.dealTableSelect(eventArgsSet); - stateManager.endSelectCells(true, isHasSelected); + stateManager.endSelectCells(); eventManager.touchSetTimeout = undefined; } } @@ -676,8 +649,7 @@ export function bindTableGroupListener(eventManager: EventManager) { funcType: (icon as any).attribute.funcType } : undefined, - target: eventArgsSet?.eventArgs?.target, - mergeCellInfo: eventArgsSet.eventArgs?.mergeInfo + target: eventArgsSet?.eventArgs?.target }; table.fireListeners(TABLE_EVENT_TYPE.CLICK_CELL, cellsEvent); @@ -689,21 +661,9 @@ export function bindTableGroupListener(eventManager: EventManager) { if ((eventArgsSet.eventArgs?.target as any) !== stateManager.residentHoverIcon?.icon) { stateManager.hideMenu(); } - const isCompleteEdit = (table as ListTableAPI).editorManager?.completeEdit(e.nativeEvent); - if (isCompleteEdit === false) { - // 如果没有正常退出编辑状态 则不执行下面的逻辑 如选择其他单元格的逻辑 - return; - } - - const hitIcon = (e.target as any).role?.startsWith('icon') ? e.target : undefined; - eventManager.downIcon = hitIcon; + (table as ListTableAPI).editorManager?.completeEdit(e.nativeEvent); // 处理列宽调整 这里和tableGroup.addEventListener('pointerdown' 逻辑一样 - if ( - !hitIcon && - !eventManager.checkCellFillhandle(eventArgsSet) && - !stateManager.columnResize.resizing && - eventManager.checkColumnResize(eventArgsSet, true) - ) { + if (!eventManager.checkCellFillhandle(eventArgsSet) && eventManager.checkColumnResize(eventArgsSet, true)) { // eventManager.startColumnResize(e); // eventManager._resizing = true; table.scenegraph.updateChartState(null); @@ -753,13 +713,7 @@ export function bindTableGroupListener(eventManager: EventManager) { ) { stateManager.updateInteractionState(InteractionState.default); eventManager.dealTableHover(); - const isHasSelected = !!stateManager.select.ranges?.length; - // 点击空白区域取消选中 - if (table.options.select?.blankAreaClickDeselect ?? true) { - eventManager.dealTableSelect(); - } - stateManager.endSelectCells(true, isHasSelected); - + eventManager.dealTableSelect(); stateManager.updateCursor(); table.scenegraph.updateChartState(null); } else if (table.eventManager.isDraging && stateManager.isSelecting()) { @@ -823,7 +777,6 @@ export function bindTableGroupListener(eventManager: EventManager) { ...cellInfo, event: e.nativeEvent, target: eventArgsSet?.eventArgs?.target, - mergeCellInfo: eventArgsSet?.eventArgs?.mergeInfo, checked: (e.detail as unknown as { checked: boolean }).checked }; @@ -936,7 +889,6 @@ export function bindTableGroupListener(eventManager: EventManager) { ...cellInfo, event: e.nativeEvent, target: eventArgsSet?.eventArgs?.target, - mergeCellInfo: eventArgsSet?.eventArgs?.mergeInfo, radioIndexInCell }; table.fireListeners(TABLE_EVENT_TYPE.RADIO_STATE_CHANGE, cellsEvent); @@ -957,7 +909,7 @@ export function bindGesture(eventManager: EventManager) { dblclickHandler(e, table); }); } -export function endResizeCol(table: BaseTableAPI) { +function endResizeCol(table: BaseTableAPI) { table.stateManager.endResizeCol(); // textStick 依赖了这个事件 所以一定要触发RESIZE_COLUMN_END // if ((table as any).hasListeners(TABLE_EVENT_TYPE.RESIZE_COLUMN_END)) { @@ -974,7 +926,7 @@ export function endResizeCol(table: BaseTableAPI) { // } } -export function endResizeRow(table: BaseTableAPI) { +function endResizeRow(table: BaseTableAPI) { table.stateManager.endResizeRow(); table.fireListeners(TABLE_EVENT_TYPE.RESIZE_ROW_END, { @@ -1022,8 +974,7 @@ function dblclickHandler(e: FederatedPointerEvent, table: BaseTableAPI) { funcType: (icon as any).attribute.funcType } : undefined, - target: eventArgsSet?.eventArgs?.target, - mergeCellInfo: eventArgsSet?.eventArgs?.mergeInfo + target: eventArgsSet?.eventArgs?.target }; table.fireListeners(TABLE_EVENT_TYPE.DBLCLICK_CELL, cellsEvent); } diff --git a/packages/vtable/src/event/media-click.ts b/packages/vtable/src/event/media-click.ts index 4a5c498eb..334796e5b 100644 --- a/packages/vtable/src/event/media-click.ts +++ b/packages/vtable/src/event/media-click.ts @@ -12,11 +12,6 @@ export function bindMediaClick(table: BaseTableAPI): void { table.on(TABLE_EVENT_TYPE.CLICK_CELL, (e: MousePointerCellEvent) => { //如果目前是在某个icon上,如收起展开按钮 则不进行其他点击逻辑 const { col, row } = e; - - if (e.target.type === 'image' && (e.target as any).role && (e.target as any).role.startsWith('icon')) { - // click icon - return; - } let cellType; if (table.internalProps.layoutMap.isHeader(col, row)) { cellType = table.isPivotTable() diff --git a/packages/vtable/src/event/sparkline-event.ts b/packages/vtable/src/event/sparkline-event.ts index a6f849e44..2e4f81d41 100644 --- a/packages/vtable/src/event/sparkline-event.ts +++ b/packages/vtable/src/event/sparkline-event.ts @@ -5,10 +5,6 @@ import type { MousePointerCellEvent } from '../ts-types'; import type { BaseTableAPI } from '../ts-types/base-table'; export function bindSparklineHoverEvent(table: BaseTableAPI) { - if (table.eventManager.bindSparklineHoverEvent) { - return; - } - // 判断是否有sparkline 类型 let hasSparkLine = false; if (table.isPivotTable()) { @@ -27,8 +23,6 @@ export function bindSparklineHoverEvent(table: BaseTableAPI) { return; } - table.eventManager.bindSparklineHoverEvent = true; - table.on(TABLE_EVENT_TYPE.MOUSEMOVE_CELL, (e: MousePointerCellEvent) => { const { col, row, x, y } = e; const type = table.getBodyColumnType(col, row); diff --git a/packages/vtable/src/event/util.ts b/packages/vtable/src/event/util.ts index 1763beaee..fe8db38f1 100644 --- a/packages/vtable/src/event/util.ts +++ b/packages/vtable/src/event/util.ts @@ -1,7 +1,5 @@ import type { FederatedPointerEvent, IEventTarget } from '@src/vrender'; import type { Group } from '../scenegraph/graphic/group'; -import type { MergeCellInfo } from '../ts-types'; -import { isValid } from '@visactor/vutils'; export interface SceneEvent { abstractPos: { @@ -13,7 +11,6 @@ export interface SceneEvent { row: number; event: FederatedPointerEvent; targetCell: Group; - mergeInfo?: MergeCellInfo; target: IEventTarget; }; } @@ -37,14 +34,13 @@ export function getCellEventArgsSet(e: FederatedPointerEvent): SceneEvent { row: targetCell.row, event: e, targetCell, - mergeInfo: getMergeCellInfo(targetCell), target: e.target }; } return tableEvent; } -export function getTargetCell(target: any) { +function getTargetCell(target: any) { while (target && target.parent) { if (target.role === 'cell') { return target; @@ -54,21 +50,4 @@ export function getTargetCell(target: any) { return null; } -function getMergeCellInfo(cellGroup: Group): MergeCellInfo | undefined { - if ( - isValid(cellGroup.mergeStartCol) && - isValid(cellGroup.mergeStartRow) && - isValid(cellGroup.mergeEndCol) && - isValid(cellGroup.mergeEndRow) - ) { - return { - colStart: cellGroup.mergeStartCol, - colEnd: cellGroup.mergeEndCol, - rowStart: cellGroup.mergeStartRow, - rowEnd: cellGroup.mergeEndRow - }; - } - return undefined; -} - export const regIndexReg = /radio-\d+-\d+-(\d+)/; diff --git a/packages/vtable/src/header-helper/header-helper.ts b/packages/vtable/src/header-helper/header-helper.ts index ffb15e64c..4f266b786 100644 --- a/packages/vtable/src/header-helper/header-helper.ts +++ b/packages/vtable/src/header-helper/header-helper.ts @@ -1,12 +1,4 @@ -import type { - ColumnIconOption, - ColumnsDefine, - ListTableAPI, - PivotTableAPI, - RectProps, - SortOrder, - SvgIcon -} from '../ts-types'; +import type { ColumnIconOption, ListTableAPI, PivotTableAPI, RectProps, SortOrder, SvgIcon } from '../ts-types'; import { HierarchyState, IconFuncTypeEnum, IconPosition, InternalIconName } from '../ts-types'; import * as registerIcons from '../icons'; import { cellInRange } from '../tools/helper'; @@ -59,25 +51,11 @@ export class HeaderHelper { const icons: ColumnIconOption[] = []; if (this._table.isPivotTable()) { // 透视表显示排序按钮 - const { showSort, sort } = this._table.internalProps.layoutMap.getHeader(col, row) as HeaderData; + const { showSort } = this._table.internalProps.layoutMap.getHeader(col, row) as HeaderData; if (showSort) { - let order = (this._table as PivotTableAPI).getPivotSortState(col, row) as string; - if (order) { - order = order.toUpperCase(); - } - const sortIcon = order === 'ASC' ? this.downIcon : order === 'DESC' ? this.upIcon : this.normalIcon; + const order = (this._table as PivotTableAPI).getPivotSortState(col, row); + const sortIcon = order === 'asc' ? this.downIcon : order === 'desc' ? this.upIcon : this.normalIcon; - if (sortIcon) { - icons.push(sortIcon); - } - } else if (sort) { - // 处理配置了sort的情况 - const sortIcon = this.getSortIconForPivotTable( - (this._table as PivotTableAPI).getPivotSortState(col, row), - this._table, - col, - row - ); if (sortIcon) { icons.push(sortIcon); } @@ -216,26 +194,6 @@ export class HeaderHelper { return icon; } - getSortIconForPivotTable( - order: SortOrder | undefined, - _table: BaseTableAPI, - col: number, - row: number - ): ColumnIconOption | null { - const headerC = _table.getHeaderDefine(col, row) as any; - if ( - !headerC || - headerC.showSort === false || - (!isValid(headerC.showSort) && !headerC.sort) || - (headerC.columns && headerC.columns.length > 0) - ) { - return null; - } - const icon = order === 'ASC' ? this.downIcon : order === 'DESC' ? this.upIcon : this.normalIcon; - // const icon = order === 'ASC' ? this.downIcon : this.upIcon; - return icon; - } - private getDropDownStateIcons(_table: BaseTableAPI, col: number, row: number): ColumnIconOption[] { const headerC = _table.getHeaderDefine(col, row) as any; const headerL = _table._getHeaderLayoutMap(col, row); @@ -427,18 +385,4 @@ export class HeaderHelper { return CheckboxStyle; } } - - setTableColumnsEditor() { - const setEditor = (colDefines: ColumnsDefine, setColumns: ColumnsDefine) => { - colDefines?.forEach((colDefine, index) => { - if (colDefine.editor) { - setColumns[index].editor = colDefine.editor; - } - if (colDefine.columns) { - setEditor(colDefine.columns, setColumns[index].columns); - } - }); - }; - setEditor((this._table as ListTable).options.columns, (this._table as ListTable).internalProps.columns); - } } diff --git a/packages/vtable/src/header-helper/style/Style.ts b/packages/vtable/src/header-helper/style/Style.ts index 52cef9f31..1c49d268b 100644 --- a/packages/vtable/src/header-helper/style/Style.ts +++ b/packages/vtable/src/header-helper/style/Style.ts @@ -27,7 +27,6 @@ const EVENT_TYPE = { }; export class Style extends EventTarget implements ColumnStyle { private _color?: ColorPropertyDefine; - private _strokeColor?: ColorPropertyDefine; private _fontSize?: FontSizePropertyDefine; private _fontFamily?: FontFamilyPropertyDefine; private _fontWeight?: FontWeightPropertyDefine; @@ -73,7 +72,6 @@ export class Style extends EventTarget implements ColumnStyle { constructor(style: IStyleOption = {}, headerStyle: IStyleOption = {}) { super(); this._color = style.color ?? headerStyle?.color; - this._strokeColor = style?.strokeColor ?? headerStyle?.strokeColor; // icon为文字前后可添加的图标 // this._icon = style.icon; this._fontSize = style.fontSize ?? headerStyle?.fontSize; @@ -123,13 +121,6 @@ export class Style extends EventTarget implements ColumnStyle { this._color = color; //this.doChangeStyle(); } - get strokeColor(): ColorPropertyDefine | undefined { - return this._strokeColor; - } - set strokeColor(strokeColor: ColorPropertyDefine | undefined) { - this._strokeColor = strokeColor; - // this.doChangeStyle(); - } get fontSize(): FontSizePropertyDefine | undefined { return this._fontSize; } diff --git a/packages/vtable/src/index.ts b/packages/vtable/src/index.ts index 2928eca9e..5bf04dd23 100644 --- a/packages/vtable/src/index.ts +++ b/packages/vtable/src/index.ts @@ -30,11 +30,8 @@ import type { TextAlignType, TextBaselineType } from './ts-types'; -import { ListTableAll as ListTable } from './ListTable-all'; -import { ListTableSimple } from './ListTable-simple'; -// import { PivotTable } from './PivotTable'; -import { PivotTableAll as PivotTable } from './PivotTable-all'; -import { PivotTableSimple } from './PivotTable-simple'; +import { ListTable } from './ListTable'; +import { PivotTable } from './PivotTable'; import { PivotChart } from './PivotChart'; import type { MousePointerCellEvent } from './ts-types/events'; import * as CustomLayout from './render/layout'; @@ -48,10 +45,6 @@ import { restoreMeasureText, setCustomAlphabetCharSet } from './scenegraph/utils export { getDataCellPath } from './tools/get-data-path'; export * from './render/jsx'; -export { getTargetCell } from './event/util'; - -// export * as VRender from './vrender'; -import * as VRender from './vrender'; export const version = __VERSION__; /** @@ -65,10 +58,8 @@ export { TYPES, core, ListTable, - ListTableSimple, ListTableConstructorOptions, PivotTable, - PivotTableSimple, PivotTableConstructorOptions, PivotChartConstructorOptions, PivotChart, @@ -104,8 +95,7 @@ export { renderChart, graphicUtil, setCustomAlphabetCharSet, - restoreMeasureText, - VRender + restoreMeasureText }; /** @private */ @@ -121,6 +111,3 @@ function clearGlobal() { // columns.type.clearGlobal(); } TYPES.AggregationType; - -export * from './components'; -export * from './scenegraph/group-creater/cell-type'; diff --git a/packages/vtable/src/layout/chart-helper/get-axis-config.ts b/packages/vtable/src/layout/chart-helper/get-axis-config.ts index d3d5439c4..20130f297 100644 --- a/packages/vtable/src/layout/chart-helper/get-axis-config.ts +++ b/packages/vtable/src/layout/chart-helper/get-axis-config.ts @@ -2,12 +2,10 @@ import { isArray, isNumber, isValid, merge } from '@visactor/vutils'; import type { PivotHeaderLayoutMap } from '../pivot-header-layout'; import type { ITableAxisOption } from '../../ts-types/component/axis'; import type { PivotChart } from '../../PivotChart'; +import { getAxisDomainRangeAndLabels } from './get-axis-domain'; import type { CollectedValue } from '../../ts-types'; import { getNewRangeToAlign } from './zero-align'; -import { Factory } from '../../core/factory'; -import type { GetAxisDomainRangeAndLabels } from './get-axis-domain'; -export type GetAxisConfigInPivotChart = (col: number, row: number, layout: PivotHeaderLayoutMap) => any; export function getAxisConfigInPivotChart(col: number, row: number, layout: PivotHeaderLayoutMap): any { if (!layout._table.isPivotChart()) { return undefined; @@ -174,13 +172,12 @@ export function getAxisConfigInPivotChart(col: number, row: number, layout: Pivo // 左侧维度轴 return merge( { - domain: chartType === 'scatter' ? undefined : Array.from(domain), - // domain: - // chartType === 'scatter' - // ? undefined - // : spec?.series?.length >= 1 //chartType === 'common' 原来这样判断的 - // ? Array.from(domain) - // : Array.from(domain).reverse(), + domain: + chartType === 'scatter' + ? undefined + : spec?.series?.length >= 1 //chartType === 'common' 原来这样判断的 + ? Array.from(domain) + : Array.from(domain).reverse(), range: chartType === 'scatter' ? domain : undefined, title: { autoRotate: true @@ -190,13 +187,7 @@ export function getAxisConfigInPivotChart(col: number, row: number, layout: Pivo { orient: 'left', type: chartType === 'scatter' ? axisOption?.type ?? 'linear' : 'band', - __vtableChartTheme: theme, - // 默认左侧维度轴对应的图表direction 为 horizontal - // 散点图特殊处理 - inverse: transformInverse( - axisOption, - (spec?.direction ?? (chartType === 'scatter' ? 'vertical' : 'horizontal')) === Direction.horizontal - ) + __vtableChartTheme: theme } ); } @@ -424,7 +415,7 @@ export function getAxisOption(col: number, row: number, orient: string, layout: }; } -function checkZeroAlign(spec: any, orient: string, layout: PivotHeaderLayoutMap) { +export function checkZeroAlign(spec: any, orient: string, layout: PivotHeaderLayoutMap) { // check condition: // 1. two axes and one set sync // 2. axisId in sync is another @@ -560,7 +551,6 @@ function getRange( range.min = range.min < 0 ? -1 : 0; range.max = range.max > 0 ? 1 : 0; } - const getAxisDomainRangeAndLabels = Factory.getFunction('getAxisDomainRangeAndLabels') as GetAxisDomainRangeAndLabels; const { range: niceRange, ticks } = getAxisDomainRangeAndLabels( range.min, range.max, @@ -662,25 +652,3 @@ export function isLeftOrRightAxis(col: number, row: number, layout: PivotHeaderL } return false; } - -const enum Direction { - vertical = 'vertical', - horizontal = 'horizontal' -} - -// align with vchart (packages/vchart/src/component/axis/cartesian/util/common.ts) -function transformInverse(spec: any, isHorizontal: boolean) { - // 这里处理下 direction === 'horizontal' 下的 Y 轴 - // 因为 Y 轴绘制的时候默认是从下至上绘制的,但是在 direction === 'horizontal' 场景下,图表应该是按照从上至下阅读的 - // 所以这里在这种场景下坐标轴会默认 inverse 已达到效果 - let inverse = spec?.inverse; - if (isHorizontal && !isXAxis(spec?.orient)) { - inverse = isValid(spec?.inverse) ? !spec?.inverse : true; - } - return inverse; -} - -type IOrientType = 'left' | 'top' | 'right' | 'bottom' | 'z'; -function isXAxis(orient: IOrientType) { - return orient === 'bottom' || orient === 'top'; -} diff --git a/packages/vtable/src/layout/chart-helper/get-axis-domain.ts b/packages/vtable/src/layout/chart-helper/get-axis-domain.ts index 2e5e6cf23..0dbe96002 100644 --- a/packages/vtable/src/layout/chart-helper/get-axis-domain.ts +++ b/packages/vtable/src/layout/chart-helper/get-axis-domain.ts @@ -89,5 +89,3 @@ export function getAxisDomainRangeAndLabels( ticks: scaleTicks }; } - -export type GetAxisDomainRangeAndLabels = typeof getAxisDomainRangeAndLabels; diff --git a/packages/vtable/src/layout/chart-helper/get-chart-spec.ts b/packages/vtable/src/layout/chart-helper/get-chart-spec.ts index 91c012394..67c2801b0 100644 --- a/packages/vtable/src/layout/chart-helper/get-chart-spec.ts +++ b/packages/vtable/src/layout/chart-helper/get-chart-spec.ts @@ -2,12 +2,10 @@ import { cloneDeep, isArray, isNumber, merge } from '@visactor/vutils'; import type { PivotHeaderLayoutMap } from '../pivot-header-layout'; import type { SimpleHeaderLayoutMap } from '../simple-header-layout'; import { getAxisOption, getAxisRange } from './get-axis-config'; +import { getAxisDomainRangeAndLabels } from './get-axis-domain'; import { getNewRangeToAlign } from './zero-align'; -import type { IChartIndicator, IIndicator } from '../../ts-types'; -import { cloneDeepSpec } from '@visactor/vutils-extension'; -import { Factory } from '../../core/factory'; -import type { GetAxisDomainRangeAndLabels } from './get-axis-domain'; -import { DEFAULT_TEXT_FONT_SIZE } from '../../components/axis/get-axis-attributes'; +import type { IChartIndicator } from '../../ts-types'; +import { cloneDeepSpec } from '@vutils-extension'; const NO_AXISID_FRO_VTABLE = 'NO_AXISID_FRO_VTABLE'; @@ -55,11 +53,11 @@ export function isShareChartSpec(col: number, row: number, layout: PivotHeaderLa return true; } /** 检查是否有直角坐标系的图表 */ -export function checkHasCartesianChart(indicatorsDefine: (IIndicator | IChartIndicator | string)[]) { +export function checkHasCartesianChart(layout: PivotHeaderLayoutMap) { let isHasCartesianChart = false; - for (let i = 0; i < indicatorsDefine.length; i++) { + for (let i = 0; i < layout.indicatorsDefine.length; i++) { //columnObjects数量和指标数量一样 并不是每个列都有 所有会快一些 - const columnObj = indicatorsDefine[i] as IChartIndicator; + const columnObj = layout.indicatorsDefine[i] as IChartIndicator; if (columnObj.chartSpec) { if ( columnObj.chartSpec.type !== 'wordCloud' && @@ -213,15 +211,14 @@ export function getChartAxes(col: number, row: number, layout: PivotHeaderLayout axes.push( merge( { - range, - label: { style: { fontSize: DEFAULT_TEXT_FONT_SIZE } } + range }, axisOption, { type: axisOption?.type || 'linear', orient: index === 0 ? 'bottom' : 'top', // visible: true, - label: { visible: false, flush: true }, + label: { visible: false }, // label: { flush: true }, title: { visible: false }, domainLine: { visible: false }, @@ -249,8 +246,7 @@ export function getChartAxes(col: number, row: number, layout: PivotHeaderLayout merge( { domain: chartType === 'scatter' && !Array.isArray(domain) ? undefined : Array.from(domain ?? []), - range: chartType === 'scatter' && !Array.isArray(domain) ? domain : undefined, - label: { style: { fontSize: DEFAULT_TEXT_FONT_SIZE } } + range: chartType === 'scatter' && !Array.isArray(domain) ? domain : undefined }, axisOption, { @@ -312,15 +308,14 @@ export function getChartAxes(col: number, row: number, layout: PivotHeaderLayout axes.push( merge( { - range, - label: { style: { fontSize: DEFAULT_TEXT_FONT_SIZE } } + range }, axisOption, { type: axisOption?.type || 'linear', orient: index === 0 ? 'left' : 'right', // visible: true, - label: { visible: false, flush: true }, + label: { visible: false }, // label: { flush: true }, title: { visible: false }, domainLine: { visible: false }, @@ -350,8 +345,7 @@ export function getChartAxes(col: number, row: number, layout: PivotHeaderLayout merge( { domain: chartType === 'scatter' && !Array.isArray(domain) ? undefined : Array.from(domain ?? []), - range: chartType === 'scatter' && !Array.isArray(domain) ? domain : undefined, - label: { style: { fontSize: DEFAULT_TEXT_FONT_SIZE } } + range: chartType === 'scatter' && !Array.isArray(domain) ? domain : undefined }, axisOption, { @@ -430,9 +424,6 @@ function getRange( range.max = Math.max(range.max, 0); } if (axisOption?.nice) { - const getAxisDomainRangeAndLabels = Factory.getFunction( - 'getAxisDomainRangeAndLabels' - ) as GetAxisDomainRangeAndLabels; const { range: axisRange } = getAxisDomainRangeAndLabels( range.min, range.max, diff --git a/packages/vtable/src/layout/layout-helper.ts b/packages/vtable/src/layout/layout-helper.ts index 4a655d3a8..63a1b15ec 100644 --- a/packages/vtable/src/layout/layout-helper.ts +++ b/packages/vtable/src/layout/layout-helper.ts @@ -1,23 +1,6 @@ -import { isArray, isString } from '@visactor/vutils'; -import type { PivotTable } from '../PivotTable'; -import { AggregationType } from '../ts-types'; -import type { BaseTableAPI } from '../ts-types/base-table'; -import type { - Aggregation, - IHeaderTreeDefine, - IIndicator, - ListTableConstructorOptions, - PivotTableConstructorOptions -} from '../ts-types'; +import type { Aggregation } from '../ts-types'; import type { ColumnData } from '../ts-types/list-table/layout-map/api'; -import type { IChartColumnIndicator } from '../ts-types/pivot-table/indicator/chart-indicator'; import type { SimpleHeaderLayoutMap } from './simple-header-layout'; -import type { IImageDimension } from '../ts-types/pivot-table/dimension/image-dimension'; -import type { IImageColumnIndicator, IImageHeaderIndicator } from '../ts-types/pivot-table/indicator/image-indicator'; -import type { IImageColumnBodyDefine, IImageHeaderDefine } from '../ts-types/list-table/define/image-define'; -import type { ITreeLayoutHeadNode } from './tree-helper'; -import { DimensionTree } from './tree-helper'; -import type { ISparklineColumnIndicator } from '../ts-types/pivot-table/indicator/sparkline-indicator'; export function checkHasAggregation(layoutMap: SimpleHeaderLayoutMap) { const columnObjects = layoutMap.columnObjects; @@ -69,274 +52,12 @@ export function checkHasAggregationOnBottom(layoutMap: SimpleHeaderLayoutMap) { } export function checkHasTreeDefine(layoutMap: SimpleHeaderLayoutMap) { - const { columns } = layoutMap._table.options as ListTableConstructorOptions; - if (isArray(columns) && columns.length > 0) { - for (let i = 0; i < columns.length; i++) { - const column = columns[i]; - if (isString(column)) { - continue; - } - if (column.tree) { - return true; - } - } - } - return false; -} - -export function hasAutoImageColumn(table: BaseTableAPI) { - const { columns, rows, indicators } = table.options as PivotTableConstructorOptions; - if (table.isPivotTable()) { - // pivot table - if (isArray(columns) && columns.length > 0) { - for (let i = 0; i < columns.length; i++) { - const column = columns[i]; - if (isString(column)) { - continue; - } - if ( - (column.headerType === 'image' || column.headerType === 'video' || typeof column.headerType === 'function') && - (column as IImageDimension).imageAutoSizing - ) { - return true; - } - } - } - if (isArray(rows) && rows.length > 0) { - for (let i = 0; i < rows.length; i++) { - const row = rows[i]; - if (isString(row)) { - continue; - } - if ( - (row.headerType === 'image' || row.headerType === 'video' || typeof row.headerType === 'function') && - (row as IImageDimension).imageAutoSizing - ) { - return true; - } - } - } - if (isArray(indicators) && indicators.length > 0) { - for (let i = 0; i < indicators.length; i++) { - const indicator = indicators[i]; - if (isString(indicator)) { - continue; - } - if ( - ((indicator.cellType === 'image' || - indicator.cellType === 'video' || - typeof indicator.cellType === 'function') && - (indicator as IImageColumnIndicator).imageAutoSizing) || - ((indicator.headerType === 'image' || - indicator.headerType === 'video' || - typeof indicator.headerType === 'function') && - (indicator as IImageHeaderIndicator).imageAutoSizing) - ) { - return true; - } - } - } - } else { - // list table - if (isArray(columns) && columns.length > 0) { - for (let i = 0; i < columns.length; i++) { - const column = columns[i] as unknown as ListTableConstructorOptions['columns'][0]; - if ( - ((column.cellType === 'image' || column.cellType === 'video' || typeof column.cellType === 'function') && - (column as IImageColumnBodyDefine).imageAutoSizing) || - ((column.headerType === 'image' || - column.headerType === 'video' || - typeof column.headerType === 'function') && - (column as IImageHeaderDefine).imageAutoSizing) - ) { - return true; - } - } + const columnObjects = layoutMap.columnObjects; + for (let i = 0; i < columnObjects.length; i++) { + const column = columnObjects[i]; + if ((column as ColumnData)?.define?.tree) { + return true; } } return false; } - -export function parseColKeyRowKeyForPivotTable(table: PivotTable, options: PivotTableConstructorOptions) { - let columnDimensionTree; - let rowDimensionTree; - // let isNeedResetColumnDimensionTree = true; - // let isNeedResetRowDimensionTree = true; - if (options.columnTree) { - if (table.options.indicatorsAsCol !== false && table.options.supplementIndicatorNodes !== false) { - table.internalProps.columnTree = supplementIndicatorNodesForCustomTree( - table.internalProps.columnTree, - options.indicators - ); - } - columnDimensionTree = new DimensionTree( - (table.internalProps.columnTree as ITreeLayoutHeadNode[]) ?? [], - table.layoutNodeId - ); - - // if ( - // table.options.supplementIndicatorNodes !== false && - // table.options.indicatorsAsCol !== false && - // !columnDimensionTree.dimensionKeys.contain(IndicatorDimensionKeyPlaceholder) && - // options.indicators?.length >= 1 - // ) { - // isNeedResetColumnDimensionTree = true; - // } else { - // isNeedResetColumnDimensionTree = false; - // } - // } else { - // if (options.indicatorsAsCol !== false) { - // table.internalProps.columnTree = supplementIndicatorNodesForCustomTree([], options.indicators); - // } - } - if (options.rowTree) { - if (table.options.indicatorsAsCol === false && table.options.supplementIndicatorNodes !== false) { - table.internalProps.rowTree = supplementIndicatorNodesForCustomTree( - table.internalProps.rowTree, - options.indicators - ); - } - rowDimensionTree = new DimensionTree( - (table.internalProps.rowTree as ITreeLayoutHeadNode[]) ?? [], - table.layoutNodeId, - table.options.rowHierarchyType, - table.options.rowHierarchyType === 'tree' ? table.options.rowExpandLevel ?? 1 : undefined - ); - // if ( - // table.options.supplementIndicatorNodes !== false && - // table.options.indicatorsAsCol === false && - // !rowDimensionTree.dimensionKeys.contain(IndicatorDimensionKeyPlaceholder) && - // options.indicators?.length >= 1 - // ) { - // isNeedResetRowDimensionTree = true; - // } else { - // isNeedResetRowDimensionTree = false; - // } - // } else { - // if (options.indicatorsAsCol === false) { - // table.internalProps.rowTree = supplementIndicatorNodesForCustomTree([], options.indicators); - // } - } - const rowKeys = rowDimensionTree?.dimensionKeys?.count - ? rowDimensionTree.dimensionKeys.valueArr() - : options.rows?.reduce((keys: string[], rowObj) => { - if (typeof rowObj === 'string') { - keys.push(rowObj); - } else { - keys.push(rowObj.dimensionKey); - } - return keys; - }, []) ?? []; - const columnKeys = columnDimensionTree?.dimensionKeys?.count - ? columnDimensionTree.dimensionKeys.valueArr() - : options.columns?.reduce((keys: string[], columnObj) => { - if (typeof columnObj === 'string') { - keys.push(columnObj); - } else { - keys.push(columnObj.dimensionKey); - } - return keys; - }, []) ?? []; - const indicatorKeys = - options.indicators?.reduce((keys: string[], indicatorObj) => { - if (typeof indicatorObj === 'string') { - keys.push(indicatorObj); - } else { - keys.push(indicatorObj.indicatorKey); - if ( - (indicatorObj as IChartColumnIndicator).chartSpec || - (indicatorObj as ISparklineColumnIndicator).sparklineSpec - ) { - if (table.internalProps.dataConfig?.aggregationRules) { - if ( - !table.internalProps.dataConfig.aggregationRules.find(aggregation => { - return aggregation.indicatorKey === indicatorObj.indicatorKey; - }) - ) { - table.internalProps.dataConfig.aggregationRules.push({ - field: indicatorObj.indicatorKey, - indicatorKey: indicatorObj.indicatorKey, - aggregationType: AggregationType.NONE - }); - } - } else if (table.internalProps.dataConfig) { - table.internalProps.dataConfig.aggregationRules = [ - { - field: indicatorObj.indicatorKey, - indicatorKey: indicatorObj.indicatorKey, - aggregationType: AggregationType.NONE - } - ]; - } else { - table.internalProps.dataConfig = { - aggregationRules: [ - { - field: indicatorObj.indicatorKey, - indicatorKey: indicatorObj.indicatorKey, - aggregationType: AggregationType.NONE - } - ] - }; - } - } - } - return keys; - }, []) ?? []; - if (options.rowHierarchyType === 'tree' && (options.extensionRows?.length ?? 0) >= 1) { - options.extensionRows?.forEach(extensionRow => { - const extension_rowKeys: string[] = []; - extensionRow.rows.forEach(row => { - if (typeof row === 'string') { - extension_rowKeys.push(row); - } else { - extension_rowKeys.push(row.dimensionKey); - } - }); - rowKeys.push(...extension_rowKeys); - }); - } - return { - rowKeys, - columnKeys, - indicatorKeys, - // isNeedResetColumnDimensionTree, - // isNeedResetRowDimensionTree, - columnDimensionTree, - rowDimensionTree - }; -} - -export function supplementIndicatorNodesForCustomTree( - customTree: IHeaderTreeDefine[], - indicators: (string | IIndicator)[] -) { - const checkNode = (nodes: IHeaderTreeDefine[], isHasIndicator: boolean) => { - nodes.forEach((node: IHeaderTreeDefine) => { - if ( - !node.indicatorKey && - !isHasIndicator && - (!(node.children as IHeaderTreeDefine[])?.length || !node.children) - ) { - node.children = indicators?.map((indicator: IIndicator | string): { indicatorKey: string; value: string } => { - if (typeof indicator === 'string') { - return { indicatorKey: indicator, value: indicator }; - } - return { indicatorKey: indicator.indicatorKey, value: indicator.title ?? indicator.indicatorKey }; - }); - } else if (node.children && Array.isArray(node.children)) { - checkNode(node.children, isHasIndicator || !!node.indicatorKey); - } - }); - }; - if (customTree?.length) { - checkNode(customTree, false); - } else { - customTree = indicators?.map((indicator: IIndicator | string): { indicatorKey: string; value: string } => { - if (typeof indicator === 'string') { - return { indicatorKey: indicator, value: indicator }; - } - return { indicatorKey: indicator.indicatorKey, value: indicator.title ?? indicator.indicatorKey }; - }); - } - return customTree; -} diff --git a/packages/vtable/src/layout/pivot-header-layout.ts b/packages/vtable/src/layout/pivot-header-layout.ts index 1def71326..d093a1400 100644 --- a/packages/vtable/src/layout/pivot-header-layout.ts +++ b/packages/vtable/src/layout/pivot-header-layout.ts @@ -34,6 +34,8 @@ import type { PivotTable } from '../PivotTable'; import type { PivotChart } from '../PivotChart'; import { IndicatorDimensionKeyPlaceholder } from '../tools/global'; import { diffCellAddress } from '../tools/diff-cell'; +import type { ILinkDimension } from '../ts-types/pivot-table/dimension/link-dimension'; +import type { IImageDimension } from '../ts-types/pivot-table/dimension/image-dimension'; import { checkHasCartesianChart, checkHasChart, @@ -52,8 +54,7 @@ import { cloneDeep, isArray, isValid } from '@visactor/vutils'; import type { TextStyle } from '../body-helper/style'; import type { ITableAxisOption } from '../ts-types/component/axis'; import { getQuadProps } from '../scenegraph/utils/padding'; -import type { GetAxisConfigInPivotChart } from './chart-helper/get-axis-config'; -import { Factory } from '../core/factory'; +import { getAxisConfigInPivotChart } from './chart-helper/get-axis-config'; // export const sharedVar = { seqId: 0 }; // let colIndex = 0; @@ -70,18 +71,10 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { cornerHeaderObjs: HeaderData[]; columnHeaderObjs: HeaderData[] = []; rowHeaderObjs: HeaderData[] = []; - - private _cornerHeaderCellFullPathIds: number[][] = []; - private _columnHeaderCellFullPathIds: number[][] = []; - private _rowHeaderCellFullPathIds: number[][] = []; - private _rowHeaderCellFullPathIds_FULL: number[][] = []; //分页需求新增 为了保存全量的id 当页的是_rowHeaderCellIds - - /**下面四份代表实际展示的 如果隐藏了某部分表头 那这里就会相比上面的数组少了隐藏掉的id */ private _cornerHeaderCellIds: number[][] = []; private _columnHeaderCellIds: number[][] = []; private _rowHeaderCellIds: number[][] = []; private _rowHeaderCellIds_FULL: number[][] = []; //分页需求新增 为了保存全量的id 当页的是_rowHeaderCellIds - private _columnWidths: WidthData[] = []; private _columnHeaderLevelCount: number; private _rowHeaderLevelCount: number; @@ -159,13 +152,8 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { rightRowSeriesNumberColumn: SeriesNumberColumnData[]; rightRowSeriesNumberColumnCount: number = 0; //#endregion - constructor( - table: PivotTable | PivotChart, - dataset: Dataset, - columnDimensionTree: DimensionTree, - rowDimensionTree: DimensionTree - ) { - this.sharedVar = table.layoutNodeId; + constructor(table: PivotTable | PivotChart, dataset: Dataset) { + this.sharedVar = { seqId: 0 }; this._table = table; if ((table as PivotTable).options.rowHierarchyType === 'tree') { this.extensionRows = (table as PivotTable).options.extensionRows; @@ -197,6 +185,34 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (dataset) { this.rowTree = dataset.rowHeaderTree; this.columnTree = dataset.colHeaderTree; + if (this.indicatorsAsCol && this._table.isPivotChart() && checkHasCartesianChart(this)) { + const supplyAxisNode = (nodes: IHeaderTreeDefine[]) => { + nodes.forEach((node: IHeaderTreeDefine) => { + if ((node.children as IHeaderTreeDefine[])?.length) { + supplyAxisNode(node.children as IHeaderTreeDefine[]); + } else { + // 在指标在列上的透视图中,主指标轴(离散轴)显示在左侧,因此需要在原先行表头的布局中最右侧加入一列,用来显示坐标轴 + // 加入的这一列dimensionKey配置为'axis',在后续行列计算维度时需要注意,这一列是为了显示坐标轴加入的,不在行列维度信息内 + node.children = [ + { + dimensionKey: 'axis', + value: '' + } + ]; + } + }); + }; + if (this.rowTree?.length) { + supplyAxisNode(this.rowTree); + } else { + this.rowTree = [ + { + dimensionKey: 'axis', + value: '' + } + ]; + } + } } // 收集指标所有key this.indicatorsDefine?.forEach(indicator => { @@ -207,22 +223,28 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.indicatorKeys.push(indicator.indicatorKey); } }); - this.columnDimensionTree = columnDimensionTree; // new DimensionTree((this.columnTree as ITreeLayoutHeadNode[]) ?? [], this.sharedVar); - this.rowDimensionTree = rowDimensionTree; - // new DimensionTree( - // (this.rowTree as ITreeLayoutHeadNode[]) ?? [], - // this.sharedVar, - // this.rowHierarchyType, - // this.rowHierarchyType === 'tree' ? this.rowExpandLevel : undefined - // ); + this.columnDimensionTree = new DimensionTree((this.columnTree as ITreeLayoutHeadNode[]) ?? [], this.sharedVar); + this.rowDimensionTree = new DimensionTree( + (this.rowTree as ITreeLayoutHeadNode[]) ?? [], + this.sharedVar, + this.rowHierarchyType, + this.rowHierarchyType === 'tree' ? this.rowExpandLevel : undefined + ); this.colDimensionKeys = this.columnDimensionTree.dimensionKeys.valueArr(); this.rowDimensionKeys = this.rowDimensionTree.dimensionKeys.valueArr(); this.fullRowDimensionKeys = this.fullRowDimensionKeys.concat(this.rowDimensionKeys); this.resetRowHeaderLevelCount(); + //生成列表头单元格 + this._generateColHeaderIds(); + + this.colIndex = 0; + //生成行表头单元格 + this._generateRowHeaderIds(); + if (this._table.isPivotChart()) { - this.hasTwoIndicatorAxes = this.indicatorsDefine.some((indicatorObject: any) => { + this.hasTwoIndicatorAxes = this._indicators.some(indicatorObject => { if ( indicatorObject.chartSpec && indicatorObject.chartSpec.series && @@ -250,14 +272,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { // this.colAttrs[this.colAttrs.length-1]===this.indicatorDimensionKey&&this.colAttrs.pop(); // this.rowAttrs[this.rowAttrs.length-1]===this.indicatorDimensionKey&&this.rowAttrs.pop(); - //生成列表头单元格 - this._generateColHeaderIds(); - - this.colIndex = 0; - //生成行表头单元格 - this._generateRowHeaderIds(); - - this._rowHeaderCellFullPathIds_FULL = transpose(this._rowHeaderCellFullPathIds_FULL); + this._rowHeaderCellIds_FULL = transpose(this._rowHeaderCellIds_FULL); if ((table as PivotTable).options.rowHierarchyType === 'tree' && this.extensionRows?.length >= 1) { this.generateExtensionRowTree(); @@ -276,73 +291,36 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } this.sharedVar.seqId = Math.max(this.sharedVar.seqId, this._headerObjects.length); - //#region 生成cornerHeaderObjs及_cornerHeaderCellIds - // if (this.cornerSetting.titleOnDimension === 'all') { - let colDimensionKeys = this.columnDimensionTree.dimensionKeysIncludeVirtual.valueArr(); - //#region 处理需求 当没有数据时仍然显示角头维度名称 - if ( - this.dataset && - (this.dataset.records?.length ?? 0) === 0 && - !this.dataset.customColTree && - !this.dataset.customRowTree - ) { - colDimensionKeys = this.columnsDefine.map(define => { - if (typeof define === 'string') { - return define; - } - return define.dimensionKey; - }); - if (this.indicatorsAsCol) { - colDimensionKeys.push(this.indicatorDimensionKey); - } - } - //#endregion - - colDimensionKeys = this.columnHeaderTitle ? [''].concat(colDimensionKeys) : colDimensionKeys; - - let rowDimensionKeys: string[]; - let extensionRowDimensions = []; - if (this.rowHierarchyType === 'tree' && this.extensionRows?.length >= 1) { - // 如果是有扩展行维度 - const rowTreeFirstKey = []; - rowTreeFirstKey.push(this.rowDimensionKeys[0]); - this._extensionRowDimensionKeys.forEach(extensionRowKeys => { - rowTreeFirstKey.push(extensionRowKeys[0]); - }); - extensionRowDimensions = this.extensionRows.reduce((dimensions, cur) => { - return dimensions.concat(cur.rows); - }, []); - - rowDimensionKeys = this.rowHeaderTitle ? [''].concat(rowTreeFirstKey as any) : rowTreeFirstKey; - } else { - //#region 处理需求 当没有数据时仍然显示角头维度名称 - rowDimensionKeys = this.rowDimensionTree.dimensionKeysIncludeVirtual.valueArr(); - if ( - this.dataset && - (this.dataset.records?.length ?? 0) === 0 && - !this.dataset.customColTree && - !this.dataset.customRowTree - ) { - rowDimensionKeys = this.rowsDefine.map(define => { - if (typeof define === 'string') { - return define; - } - return define.dimensionKey; + //生成cornerHeaderObjs及_cornerHeaderCellIds + if (this.cornerSetting.titleOnDimension === 'column') { + this.cornerHeaderObjs = this._addCornerHeaders( + this.columnHeaderTitle ? [''].concat(this.colDimensionKeys as any) : this.colDimensionKeys, + this.columnsDefine + ); + } else if (this.cornerSetting.titleOnDimension === 'row') { + if (this.rowHierarchyType === 'tree' && this.extensionRows?.length >= 1) { + // 如果是有扩展行维度 + const rowTreeFirstKey = []; + rowTreeFirstKey.push(this.rowDimensionKeys[0]); + this._extensionRowDimensionKeys.forEach(extensionRowKeys => { + rowTreeFirstKey.push(extensionRowKeys[0]); }); - if (!this.indicatorsAsCol) { - rowDimensionKeys.push(this.indicatorDimensionKey); - } + const extensionRowDimensions = this.extensionRows.reduce((dimensions, cur) => { + return dimensions.concat(cur.rows); + }, []); + this.cornerHeaderObjs = this._addCornerHeaders( + this.rowHeaderTitle ? [''].concat(rowTreeFirstKey as any) : rowTreeFirstKey, + this.rowsDefine.concat(extensionRowDimensions) + ); + } else { + this.cornerHeaderObjs = this._addCornerHeaders( + this.rowHeaderTitle ? [''].concat(this.rowDimensionKeys as any) : this.rowDimensionKeys, + this.rowsDefine + ); } - //#endregion - rowDimensionKeys = this.rowHeaderTitle ? [''].concat(rowDimensionKeys) : rowDimensionKeys; + } else { + this.cornerHeaderObjs = this._addCornerHeaders(null, undefined); } - - this.cornerHeaderObjs = this._addCornerHeaders( - colDimensionKeys, - rowDimensionKeys, - this.columnsDefine.concat(...this.rowsDefine, ...extensionRowDimensions) - ); - //#endregion this.colIndex = 0; this._headerObjectMap = this._headerObjects.reduce((o, e) => { o[e.id as number] = e; @@ -356,8 +334,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } else { this._indicatorShowType = 'none'; } - - this.generateCellIdsConsiderHideHeader(); this.setPagination((table as PivotTable).options.pagination); if (this._table.isPivotChart()) { @@ -398,9 +374,37 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { // } return false; }); + + // if (this.indicatorsAsCol) { + // const cell_id = 'rowHeaderEmpty'; + // this._headerObjectMap[cell_id] = { + // id: cell_id, + // title: '', + // field: cell_id, + // headerType: this.cornerSetting.headerType ?? 'text', + // style: this.cornerSetting.headerStyle, + // define: { + // // id: + // } + // }; + // this._headerObjects.push(this._headerObjectMap[cell_id]); + // // this.rowShowAttrs.push(cell_id); + + // // deal with sub indicator axis + + // if (!this.hasTwoIndicatorAxes) { + // // this.colShowAttrs.pop(); + // } + // } else { + // const axisOption = ((this._table as PivotChart).pivotChartAxes as ITableAxisOption[]).find(axisOption => { + // return axisOption.orient === 'left'; + // }); + // if (axisOption?.visible === false) { + // // this.rowShowAttrs.pop(); + // } + // } } this.handleRowSeriesNumber(table.internalProps.rowSeriesNumber); - this.setColumnWidths(); } handleRowSeriesNumber(rowSeriesNumber: IRowSeriesNumber) { @@ -453,36 +457,14 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } _generateColHeaderIds() { if (this.columnDimensionTree.tree.children?.length >= 1) { - //#region 处理需求 当没有数据时仍然显示角头维度名称 - let startRow = 0; - if ( - this.dataset && - (this.dataset.records?.length ?? 0) === 0 && - !this.dataset.customColTree && - !this.dataset.customRowTree && - this.indicatorsAsCol && - this.columnDimensionTree.totalLevel < this.columnHeaderLevelCount - ) { - startRow = this.columnHeaderLevelCount - this.columnDimensionTree.totalLevel; - for (let i = 0; i < startRow; i++) { - this._columnHeaderCellFullPathIds.unshift([]); - } - } - //#endregion - this._addHeaders( - this._columnHeaderCellFullPathIds, - startRow, - this.columnDimensionTree.tree.children, - [], - this.columnHeaderObjs - ); + this._addHeaders(this._columnHeaderCellIds, 0, this.columnDimensionTree.tree.children, [], this.columnHeaderObjs); } // if (typeof this.showColumnHeader !== 'boolean') { if (this.columnHeaderTitle) { this.sharedVar.seqId = Math.max(this.sharedVar.seqId, this._headerObjects.length); const id = ++this.sharedVar.seqId; - const firstRowIds = Array(this.colCount - this.rowHeaderLevelCount - this.rightFrozenColCount).fill(id); - this._columnHeaderCellFullPathIds.unshift(firstRowIds); + const firstRowIds = Array(this.colCount - this.rowHeaderLevelCount).fill(id); + this._columnHeaderCellIds.unshift(firstRowIds); const cell: HeaderData = { id, title: @@ -511,7 +493,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (this.rowDimensionTree.tree.children?.length >= 1) { if (this.rowHierarchyType === 'tree') { this._addHeadersForTreeMode( - this._rowHeaderCellFullPathIds_FULL, + this._rowHeaderCellIds_FULL, 0, this.rowDimensionTree.tree.children, [], @@ -521,39 +503,15 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.rowHeaderObjs ); } else { - //#region 处理需求 当没有数据时仍然显示角头维度名称 - let startRow = 0; - if ( - this.dataset && - (this.dataset.records?.length ?? 0) === 0 && - !this.dataset.customColTree && - !this.dataset.customRowTree && - !this.indicatorsAsCol && - this.rowDimensionTree.totalLevel < this.rowHeaderLevelCount - ) { - startRow = this.rowHeaderLevelCount - this.rowDimensionTree.totalLevel; - for (let i = 0; i < startRow; i++) { - this._rowHeaderCellFullPathIds_FULL.unshift([]); - } - } - //#endregion - this._addHeaders( - this._rowHeaderCellFullPathIds_FULL, - startRow, - this.rowDimensionTree.tree.children, - [], - this.rowHeaderObjs - ); + this._addHeaders(this._rowHeaderCellIds_FULL, 0, this.rowDimensionTree.tree.children, [], this.rowHeaderObjs); } } // if (typeof this.showRowHeader !== 'boolean') { if (this.rowHeaderTitle) { this.sharedVar.seqId = Math.max(this.sharedVar.seqId, this._headerObjects.length); const id = ++this.sharedVar.seqId; - const firstColIds = Array(this._rowHeaderCellFullPathIds_FULL[0]?.length ?? this.rowDimensionTree.tree.size).fill( - id - ); - this._rowHeaderCellFullPathIds_FULL.unshift(firstColIds); + const firstColIds = Array(this._rowHeaderCellIds_FULL[0]?.length ?? this.rowDimensionTree.tree.size).fill(id); + this._rowHeaderCellIds_FULL.unshift(firstColIds); const cell: HeaderData = { id, title: @@ -637,290 +595,68 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { dealHeaderForTreeMode(hd, _headerCellIds, results, roots, row, totalLevel, show, dimensions, this); } } - private _addCornerHeaders( - colDimensionKeys: string[] | null, - rowDimensionKeys: string[] | null, - dimensions: (string | IDimension)[] - ) { + private _addCornerHeaders(dimensionKeys: (string | number)[] | null, dimensions: (string | IDimension)[]) { const results: HeaderData[] = []; - if (this.cornerSetting.titleOnDimension === 'all') { - if (this.indicatorsAsCol) { - let indicatorAtIndex = -1; - if (colDimensionKeys) { - colDimensionKeys.forEach((dimensionKey: string, key: number) => { - if (dimensionKey === this.indicatorDimensionKey) { - indicatorAtIndex = key; - } - const id = ++this.sharedVar.seqId; - const dimensionInfo: IDimension = dimensions.find(dimension => - typeof dimension === 'string' ? false : dimension.dimensionKey === dimensionKey - ) as IDimension; - const cell: HeaderData = { - id, - title: - dimensionKey === this.indicatorDimensionKey - ? this.indicatorTitle - : dimensionInfo - ? dimensionInfo.title - : dimensionKey === 'axis' - ? '' - : (dimensionKey as string), - field: dimensionKey, //'维度名称', - style: this.cornerSetting.headerStyle, - headerType: this.cornerSetting.headerType ?? 'text', - showSort: dimensionInfo?.showSortInCorner, - sort: dimensionInfo?.sort, - define: { - showSort: dimensionInfo?.showSortInCorner, - sort: dimensionInfo?.sort, - dimensionKey: dimensionKey, // '维度名称', - id, - value: dimensionKey, - headerEditor: this.cornerSetting.headerEditor, - disableHeaderHover: !!this.cornerSetting.disableHeaderHover, - disableHeaderSelect: !!this.cornerSetting.disableHeaderSelect - }, - dropDownMenu: dimensionInfo?.cornerDropDownMenu, - pivotInfo: { - value: dimensionInfo?.title ?? '', - dimensionKey, - isPivotCorner: true - // customInfo: dimensionInfo?.customInfo - }, - description: dimensionInfo?.cornerDescription - }; - results[id] = cell; - this._headerObjects[id] = cell; - - if (!this._cornerHeaderCellFullPathIds[key]) { - this._cornerHeaderCellFullPathIds[key] = []; - } - for (let r = 0; r < this.rowHeaderLevelCount; r++) { - this._cornerHeaderCellFullPathIds[key][r] = id; - } - }); - } - if (rowDimensionKeys) { - rowDimensionKeys.forEach((dimensionKey: string, key: number) => { - const id = ++this.sharedVar.seqId; - const dimensionInfo: IDimension = dimensions.find(dimension => - typeof dimension === 'string' ? false : dimension.dimensionKey === dimensionKey - ) as IDimension; - const cell: HeaderData = { - id, - title: - dimensionKey === this.indicatorDimensionKey - ? this.indicatorTitle - : dimensionInfo - ? dimensionInfo.title - : dimensionKey === 'axis' - ? '' - : (dimensionKey as string), - field: dimensionKey, //'维度名称', - style: this.cornerSetting.headerStyle, - headerType: this.cornerSetting.headerType ?? 'text', - showSort: dimensionInfo?.showSortInCorner, - sort: dimensionInfo?.sort, - define: { - showSort: dimensionInfo?.showSortInCorner, - sort: dimensionInfo?.sort, - dimensionKey: dimensionKey, // '维度名称', - id, - value: dimensionKey, - headerEditor: this.cornerSetting.headerEditor, - disableHeaderHover: !!this.cornerSetting.disableHeaderHover, - disableHeaderSelect: !!this.cornerSetting.disableHeaderSelect - }, - dropDownMenu: dimensionInfo?.cornerDropDownMenu, - pivotInfo: { - value: dimensionInfo?.title ?? '', - dimensionKey, - isPivotCorner: true - // customInfo: dimensionInfo?.customInfo - }, - description: dimensionInfo?.cornerDescription - }; - results[id] = cell; - this._headerObjects[id] = cell; - if (!this._cornerHeaderCellFullPathIds[indicatorAtIndex]) { - this._cornerHeaderCellFullPathIds[indicatorAtIndex] = []; - } - this._cornerHeaderCellFullPathIds[indicatorAtIndex][key] = id; - }); - } - } else { - let indicatorAtIndex = -1; - if (rowDimensionKeys) { - rowDimensionKeys.forEach((dimensionKey: string, key: number) => { - if (dimensionKey === this.indicatorDimensionKey) { - indicatorAtIndex = key; - } - const id = ++this.sharedVar.seqId; - const dimensionInfo: IDimension = dimensions.find(dimension => - typeof dimension === 'string' ? false : dimension.dimensionKey === dimensionKey - ) as IDimension; - const cell: HeaderData = { - id, - title: - dimensionKey === this.indicatorDimensionKey - ? this.indicatorTitle - : dimensionInfo - ? dimensionInfo.title - : dimensionKey === 'axis' - ? '' - : (dimensionKey as string), - field: dimensionKey, //'维度名称', - style: this.cornerSetting.headerStyle, - headerType: this.cornerSetting.headerType ?? 'text', - showSort: dimensionInfo?.showSortInCorner, - sort: dimensionInfo?.sort, - define: { - showSort: dimensionInfo?.showSortInCorner, - sort: dimensionInfo?.sort, - dimensionKey: dimensionKey, // '维度名称', - id, - value: dimensionKey, - headerEditor: this.cornerSetting.headerEditor, - disableHeaderHover: !!this.cornerSetting.disableHeaderHover, - disableHeaderSelect: !!this.cornerSetting.disableHeaderSelect - }, - dropDownMenu: dimensionInfo?.cornerDropDownMenu, - pivotInfo: { - value: dimensionInfo?.title ?? '', - dimensionKey, - isPivotCorner: true - // customInfo: dimensionInfo?.customInfo - }, - description: dimensionInfo?.cornerDescription - }; - results[id] = cell; - this._headerObjects[id] = cell; - - for (let r = 0; r < this.columnHeaderLevelCount; r++) { - if (!this._cornerHeaderCellFullPathIds[r]) { - this._cornerHeaderCellFullPathIds[r] = []; - } - this._cornerHeaderCellFullPathIds[r][key] = id; - } - }); - } - if (colDimensionKeys) { - colDimensionKeys.forEach((dimensionKey: string, key: number) => { - const id = ++this.sharedVar.seqId; - const dimensionInfo: IDimension = dimensions.find(dimension => - typeof dimension === 'string' ? false : dimension.dimensionKey === dimensionKey - ) as IDimension; - const cell: HeaderData = { - id, - title: - dimensionKey === this.indicatorDimensionKey - ? this.indicatorTitle - : dimensionInfo - ? dimensionInfo.title - : dimensionKey === 'axis' - ? '' - : (dimensionKey as string), - field: dimensionKey, //'维度名称', - style: this.cornerSetting.headerStyle, - headerType: this.cornerSetting.headerType ?? 'text', - showSort: dimensionInfo?.showSortInCorner, - sort: dimensionInfo?.sort, - define: { - showSort: dimensionInfo?.showSortInCorner, - sort: dimensionInfo?.sort, - dimensionKey: dimensionKey, // '维度名称', - id, - value: dimensionKey, - headerEditor: this.cornerSetting.headerEditor, - disableHeaderHover: !!this.cornerSetting.disableHeaderHover, - disableHeaderSelect: !!this.cornerSetting.disableHeaderSelect - }, - dropDownMenu: dimensionInfo?.cornerDropDownMenu, - pivotInfo: { - value: dimensionInfo?.title ?? '', - dimensionKey, - isPivotCorner: true - // customInfo: dimensionInfo?.customInfo - }, - description: dimensionInfo?.cornerDescription - }; - results[id] = cell; - this._headerObjects[id] = cell; - // if (!this._cornerHeaderCellFullPathIds[indicatorAtIndex]) { - // this._cornerHeaderCellFullPathIds[indicatorAtIndex] = []; - // } - this._cornerHeaderCellFullPathIds[key][indicatorAtIndex] = id; - }); - } - } - } else if (this.cornerSetting.titleOnDimension === 'row' || this.cornerSetting.titleOnDimension === 'column') { - const dimensionKeys = this.cornerSetting?.titleOnDimension === 'row' ? rowDimensionKeys : colDimensionKeys; - if (dimensionKeys) { - dimensionKeys.forEach((dimensionKey: string, key: number) => { - const id = ++this.sharedVar.seqId; - // const dimensionInfo: IDimension = - // (this.rowsDefine?.find(dimension => - // typeof dimension === 'string' ? false : dimension.dimensionKey === dimensionKey - // ) as IDimension) ?? - // (this.columnsDefine?.find(dimension => - // typeof dimension === 'string' ? false : dimension.dimensionKey === dimensionKey - // ) as IDimension); - const dimensionInfo: IDimension = dimensions.find(dimension => - typeof dimension === 'string' ? false : dimension.dimensionKey === dimensionKey - ) as IDimension; - const cell: HeaderData = { + if (dimensionKeys) { + dimensionKeys.forEach((dimensionKey: string | number, key: number) => { + const id = ++this.sharedVar.seqId; + // const dimensionInfo: IDimension = + // (this.rowsDefine?.find(dimension => + // typeof dimension === 'string' ? false : dimension.dimensionKey === dimensionKey + // ) as IDimension) ?? + // (this.columnsDefine?.find(dimension => + // typeof dimension === 'string' ? false : dimension.dimensionKey === dimensionKey + // ) as IDimension); + const dimensionInfo: IDimension = dimensions.find(dimension => + typeof dimension === 'string' ? false : dimension.dimensionKey === dimensionKey + ) as IDimension; + const cell: HeaderData = { + id, + title: + dimensionKey === this.indicatorDimensionKey + ? this.indicatorTitle + : dimensionInfo + ? dimensionInfo.title + : dimensionKey === 'axis' + ? '' + : (dimensionKey as string), + field: '维度名称', + style: this.cornerSetting.headerStyle, + headerType: this.cornerSetting.headerType ?? 'text', + define: { + dimensionKey: '维度名称', id, - title: - dimensionKey === this.indicatorDimensionKey - ? this.indicatorTitle - : dimensionInfo - ? dimensionInfo.title - : dimensionKey === 'axis' - ? '' - : (dimensionKey as string), - field: dimensionKey, //'维度名称', - style: this.cornerSetting.headerStyle, - headerType: this.cornerSetting.headerType ?? 'text', - showSort: dimensionInfo?.showSortInCorner, - sort: dimensionInfo?.sort, - define: { - showSort: dimensionInfo?.showSortInCorner, - sort: dimensionInfo?.sort, - dimensionKey: dimensionKey, // '维度名称', - id, - value: dimensionKey, - headerEditor: this.cornerSetting.headerEditor, - disableHeaderHover: !!this.cornerSetting.disableHeaderHover, - disableHeaderSelect: !!this.cornerSetting.disableHeaderSelect - }, - dropDownMenu: dimensionInfo?.cornerDropDownMenu, - pivotInfo: { - value: dimensionInfo?.title ?? '', - dimensionKey, - isPivotCorner: true - // customInfo: dimensionInfo?.customInfo - }, - description: dimensionInfo?.cornerDescription - }; - results[id] = cell; - this._headerObjects[id] = cell; - if (this.cornerSetting.titleOnDimension === 'column') { - if (!this._cornerHeaderCellFullPathIds[key]) { - this._cornerHeaderCellFullPathIds[key] = []; - } - for (let r = 0; r < this.rowHeaderLevelCount; r++) { - this._cornerHeaderCellFullPathIds[key][r] = id; - } - } else if (this.cornerSetting.titleOnDimension === 'row') { - for (let r = 0; r < this.columnHeaderLevelCount; r++) { - if (!this._cornerHeaderCellFullPathIds[r]) { - this._cornerHeaderCellFullPathIds[r] = []; - } - this._cornerHeaderCellFullPathIds[r][key] = id; + value: dimensionKey, + disableHeaderHover: !!this.cornerSetting.disableHeaderHover, + disableHeaderSelect: !!this.cornerSetting.disableHeaderSelect + }, + dropDownMenu: dimensionInfo?.cornerDropDownMenu, + pivotInfo: { + value: dimensionInfo?.title ?? '', + dimensionKey, + isPivotCorner: true + // customInfo: dimensionInfo?.customInfo + }, + description: dimensionInfo?.cornerDescription + }; + results[id] = cell; + this._headerObjects[id] = cell; + if (this.cornerSetting.titleOnDimension === 'column') { + if (!this._cornerHeaderCellIds[key]) { + this._cornerHeaderCellIds[key] = []; + } + for (let r = 0; r < this.rowHeaderLevelCount; r++) { + this._cornerHeaderCellIds[key][r] = id; + } + } else if (this.cornerSetting.titleOnDimension === 'row') { + for (let r = 0; r < this.columnHeaderLevelCount; r++) { + if (!this._cornerHeaderCellIds[r]) { + this._cornerHeaderCellIds[r] = []; } + this._cornerHeaderCellIds[r][key] = id; } - }); - } + } + }); } else { const id = ++this.sharedVar.seqId; const cell: HeaderData = { @@ -941,20 +677,19 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this._headerObjects[id] = cell; for (let r = 0; r < this.columnHeaderLevelCount; r++) { for (let j = 0; j < this.rowHeaderLevelCount; j++) { - if (!this._cornerHeaderCellFullPathIds[r]) { - this._cornerHeaderCellFullPathIds[r] = []; + if (!this._cornerHeaderCellIds[r]) { + this._cornerHeaderCellIds[r] = []; } - this._cornerHeaderCellFullPathIds[r][j] = id; + this._cornerHeaderCellIds[r][j] = id; } } } - return results; } private generateExtensionRowTree() { this.extensionRows.forEach((extensionRow, indexP) => { - const old_rowHeaderCellIds = this._rowHeaderCellFullPathIds_FULL; - this._rowHeaderCellFullPathIds_FULL = []; + const old_rowHeaderCellIds = this._rowHeaderCellIds_FULL; + this._rowHeaderCellIds_FULL = []; old_rowHeaderCellIds.forEach((row_ids: number[], index) => { const key = row_ids[row_ids.length - 1]; this.colIndex = 0; @@ -991,7 +726,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.rowHeaderObjs ); for (let i = 0; i < extensionRowTreeHeaderIds[0].length; i++) { - this._rowHeaderCellFullPathIds_FULL.push(row_ids.concat(extensionRowTreeHeaderIds[0][i])); + this._rowHeaderCellIds_FULL.push(row_ids.concat(extensionRowTreeHeaderIds[0][i])); } }); }); @@ -1387,7 +1122,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { : this.columnDimensionTree.totalLevel : this.columnDimensionTree.totalLevel : this.columnDimensionTree.totalLevel; - if (this.columnHeaderTitle) { count += 1; } @@ -1395,39 +1129,14 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this._table.isPivotChart() && this.indicatorsAsCol && !this.hasTwoIndicatorAxes && - checkHasCartesianChart(this.indicatorsDefine) + checkHasCartesianChart(this) ) { count -= 1; } - //#region 处理需求 当没有数据时仍然显示角头维度名称 - if (count === 0 && this.dataset && !this.dataset.customColTree && !this.dataset.customRowTree) { - if (this.cornerSetting.titleOnDimension === 'row') { - count = 1; - } else if ( - (this.dataset.records?.length ?? 0) === 0 && - (this.cornerSetting.titleOnDimension === 'column' || this.cornerSetting.titleOnDimension === 'all') - ) { - count = this.columnsDefine.length ?? 0; - } - } else if ( - this.dataset && - (this.dataset.records?.length ?? 0) === 0 && - !this.dataset.customColTree && - !this.dataset.customRowTree - ) { - if (this.cornerSetting.titleOnDimension === 'column' || this.cornerSetting.titleOnDimension === 'all') { - count = this.columnsDefine.length ?? 0; - if (!this.hideIndicatorName && this.indicatorsAsCol) { - count++; - } - } - } - //#endregion this.columnHeaderLevelCount = count; return; } - // this.columnHeaderLevelCount = 0; - this.columnHeaderLevelCount = !this.indicatorsAsCol ? 0 : this.hideIndicatorName ? 0 : 1; + this.columnHeaderLevelCount = 0; return; } resetRowHeaderLevelCount() { @@ -1441,7 +1150,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.rowHeaderLevelCount = 1 + extensionRowCount; return; } - const rowLevelCount = this.rowDimensionTree.totalLevel; + const rowLevelCount = this.rowDimensionKeys.length; // let count = this.indicatorsAsCol // ? rowLevelCount // : this.hideIndicatorName //设置隐藏表头,且表头最下面一级就是指标维度 则-1 @@ -1466,30 +1175,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { // if (this._table.isPivotChart()&&this.indicatorsAsCol) { // count+=1; // } - //#region 处理需求 当没有数据时仍然显示角头维度名称 - if (count === 0 && this.dataset && !this.dataset.customColTree && !this.dataset.customRowTree) { - if (this.cornerSetting.titleOnDimension === 'column') { - count = 1; - } else if ( - (this.dataset.records?.length ?? 0) === 0 && - (this.cornerSetting.titleOnDimension === 'row' || this.cornerSetting.titleOnDimension === 'all') - ) { - count = this.rowsDefine.length ?? 0; - } - } else if ( - this.dataset && - (this.dataset.records?.length ?? 0) === 0 && - !this.dataset.customColTree && - !this.dataset.customRowTree - ) { - if (this.cornerSetting.titleOnDimension === 'row' || this.cornerSetting.titleOnDimension === 'all') { - count = this.rowsDefine.length; - if (!this.hideIndicatorName && !this.indicatorsAsCol) { - count++; - } - } - } - //#endregion this.rowHeaderLevelCount = count; return; } @@ -1511,24 +1196,15 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } get colCount(): number { return ( - (this.columnDimensionTree.totalLevel > 0 || - this._table.isPivotChart() || - (this.dataset.records as Array)?.length > 0 || - (this.dataset.records && !Array.isArray(this.dataset.records)) - ? this.columnDimensionTree.tree.size - : 0) + + this.columnDimensionTree.tree.size + this.rowHeaderLevelCount + this.rightHeaderColCount + - this.leftRowSeriesNumberColumnCount - ); // 小心rightFrozenColCount和colCount的循环引用 造成调用栈溢出 + this.leftRowSeriesNumberColumnCount // 小心rightFrozenColCount和colCount的循环引用 造成调用栈溢出 + ); } get rowCount(): number { return ( - ((this._table.records || this.dataset.records - ? Array.isArray(this._table.records) - ? this._table.records.length > 0 - : true - : false) && + ((Array.isArray(this._table.records) ? this._table.records.length > 0 : true) && this._indicators?.length > 0 && // 前两个判断条件来判断 有展示的body值的情况 需要展示body row !this._rowHeaderCellIds?.length // 需要展示body值 但 _rowHeaderCellIds的长度维度为0 无rows 行表头为空 ? 1 //兼容bugserver: https://bugserver.cn.goofy.app/case?product=VTable&fileid=65364a57173c354c242a7c4f @@ -1552,7 +1228,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } return 0; } - if (this.indicatorKeys.length >= 1 && checkHasCartesianChart(this.indicatorsDefine)) { + if (this.indicatorKeys.length >= 1 && checkHasCartesianChart(this)) { const axisOption = ((this._table as PivotChart).pivotChartAxes as ITableAxisOption[]).find(axisOption => { return axisOption.orient === 'bottom'; }); @@ -1626,13 +1302,13 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (this.isSeriesNumber(col, row)) { return ''; } else if (this.isCornerHeader(col, row)) { - return this._cornerHeaderCellIds[row]?.[col - this.leftRowSeriesNumberColumnCount]; + return this._cornerHeaderCellIds[row][col - this.leftRowSeriesNumberColumnCount]; } else if (this.isColumnHeader(col, row)) { - return this._columnHeaderCellIds[row]?.[col - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount]; + return this._columnHeaderCellIds[row][col - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount]; } else if (this.isRowHeader(col, row)) { return this._rowHeaderCellIds[row - this.columnHeaderLevelCount]?.[col - this.leftRowSeriesNumberColumnCount]; } else if (this.isRightFrozenColumn(col, row)) { - return this._rowHeaderCellIds[row - this.columnHeaderLevelCount]?.[this.rowHeaderLevelCount - 1]; + return this._rowHeaderCellIds[row - this.columnHeaderLevelCount][this.rowHeaderLevelCount - 1]; } else if (this.isBottomFrozenRow(col, row)) { return this._columnHeaderCellIds[this.columnHeaderLevelCount - 1]?.[ col - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount @@ -1711,40 +1387,28 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { const paths = this.getCellHeaderPaths(_col, _row); if (this.indicatorsAsCol) { const indicatorKey = paths.colHeaderPaths?.find(colPath => colPath.indicatorKey)?.indicatorKey; - return isValid(indicatorKey) - ? this._indicators?.find(indicator => indicator.indicatorKey === indicatorKey) ?? - this._indicators[0] ?? { - id: '', - field: undefined, - indicatorKey: undefined, - cellType: 'text', - define: undefined - } - : { - id: '', - field: undefined, - indicatorKey: undefined, - cellType: 'text', - define: undefined - }; - } - const indicatorKey = paths.rowHeaderPaths?.find(rowPath => rowPath.indicatorKey)?.indicatorKey; - return isValid(indicatorKey) - ? this._indicators?.find(indicator => indicator.indicatorKey === indicatorKey) ?? - this._indicators[0] ?? { - id: '', - field: undefined, - indicatorKey: undefined, - cellType: 'text', - define: undefined - } - : { + return ( + this._indicators?.find(indicator => indicator.indicatorKey === indicatorKey) ?? + this._indicators[0] ?? { id: '', field: undefined, indicatorKey: undefined, cellType: 'text', define: undefined - }; + } + ); + } + const indicatorKey = paths.rowHeaderPaths?.find(rowPath => rowPath.indicatorKey)?.indicatorKey; + return ( + this._indicators?.find(indicator => indicator.indicatorKey === indicatorKey) ?? + this._indicators[0] ?? { + id: '', + field: undefined, + indicatorKey: undefined, + cellType: 'text', + define: undefined + } + ); } // getBodyLayoutRangeById(id: LayoutObjectId): CellRange { // for (let col = 0; col < (this.colCount ?? 0); col++) { @@ -1912,7 +1576,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { // return { start: { col: 0, row: 0 }, end: { col: 0, row: 0 } }; // } - getCellHeaderPathsWithTreeNode(col: number, row: number): IPivotTableCellHeaderPaths { + getCellHeaderPathsWidthTreeNode(col: number, row: number): IPivotTableCellHeaderPaths { // if (this._CellHeaderPathMap.has(`$${col}$${row}`)) // if (this._CellHeaderPathMap.has(`${col}-${row}`)) { // return this._CellHeaderPathMap.get(`${col}-${row}`); @@ -1959,7 +1623,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { // rowPath = this.rowDimensionTree.getTreePath(recordRow, col + hd.hierarchyLevel); // } // 考虑多层级的ExtensionRowTree - const row_pathIds = this._rowHeaderCellFullPathIds[recordRow]; //获取当前行的cellId 但这个cellId不是各级维度都有的 下面逻辑就是找全路径然后再去各个树找path的过程 + const row_pathIds = this._rowHeaderCellIds[recordRow]; //获取当前行的cellId 但这个cellId不是各级维度都有的 下面逻辑就是找全路径然后再去各个树找path的过程 let findTree = this.rowDimensionTree; //第一棵寻找的树是第一列的维度树 主树 let level = 0; //level和col对应,代表一层层树找的过程 while (findTree) { @@ -1999,7 +1663,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { return p; } getCellHeaderPaths(col: number, row: number): IPivotTableCellHeaderPaths { - const headerPathsWidthNode = this.getCellHeaderPathsWithTreeNode(col, row); + const headerPathsWidthNode = this.getCellHeaderPathsWidthTreeNode(col, row); const headerPaths: IPivotTableCellHeaderPaths = { colHeaderPaths: [], rowHeaderPaths: [], @@ -2010,13 +1674,11 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { dimensionKey?: string; indicatorKey?: string; value?: string; - virtual?: boolean; } = {}; colHeaderPath.dimensionKey = colHeader.dimensionKey; colHeaderPath.indicatorKey = colHeader.indicatorKey; colHeaderPath.value = colHeader.value ?? this.getIndicatorInfoByIndicatorKey(colHeader.indicatorKey)?.title ?? ''; - colHeaderPath.virtual = colHeader.virtual; - headerPaths.colHeaderPaths!.push(colHeaderPath); + headerPaths.colHeaderPaths.push(colHeaderPath); }); headerPathsWidthNode.rowHeaderPaths?.forEach((rowHeader: any) => { @@ -2025,14 +1687,12 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { dimensionKey?: string; indicatorKey?: string; value?: string; - virtual?: boolean; } = {}; rowHeaderPath.dimensionKey = rowHeader.dimensionKey; rowHeaderPath.indicatorKey = rowHeader.indicatorKey; rowHeaderPath.value = rowHeader.value ?? this.getIndicatorInfoByIndicatorKey(rowHeader.indicatorKey)?.title ?? ''; - rowHeaderPath.virtual = rowHeader.virtual; - headerPaths.rowHeaderPaths!.push(rowHeaderPath); + headerPaths.rowHeaderPaths.push(rowHeaderPath); } }); return headerPaths; @@ -2139,7 +1799,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { * @param row */ toggleHierarchyState(col: number, row: number) { - const oldRowHeaderCellIds = this._rowHeaderCellFullPathIds_FULL.slice(0); + const oldRowHeaderCellIds = this._rowHeaderCellIds_FULL.slice(0); const oldRowHeaderCellPositons = oldRowHeaderCellIds.map((id, row) => { return { col, row: row + this.columnHeaderLevelCount }; }); @@ -2148,12 +1808,12 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { (hd.define).hierarchyState === HierarchyState.collapse ? HierarchyState.expand : HierarchyState.collapse; //过程类似构造函数处理过程 this.rowDimensionTree.reset(this.rowDimensionTree.tree.children, true); - this._rowHeaderCellFullPathIds_FULL = []; + this._rowHeaderCellIds_FULL = []; this.rowDimensionKeys = this.rowDimensionTree.dimensionKeys.valueArr(); this.fullRowDimensionKeys = []; this.fullRowDimensionKeys = this.fullRowDimensionKeys.concat(this.rowDimensionKeys); this._addHeadersForTreeMode( - this._rowHeaderCellFullPathIds_FULL, + this._rowHeaderCellIds_FULL, 0, this.rowDimensionTree.tree.children, [], @@ -2166,7 +1826,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (this.rowHeaderTitle) { const id = ++this.sharedVar.seqId; const firstColIds = Array(this.rowCount - this.columnHeaderLevelCount).fill(id); - this._rowHeaderCellFullPathIds_FULL.unshift(firstColIds); + this._rowHeaderCellIds_FULL.unshift(firstColIds); const cell: HeaderData = { id, title: @@ -2192,7 +1852,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.rowHeaderObjs.push(cell); this._headerObjects[id] = cell; } - this._rowHeaderCellFullPathIds_FULL = transpose(this._rowHeaderCellFullPathIds_FULL); + this._rowHeaderCellIds_FULL = transpose(this._rowHeaderCellIds_FULL); if (this.rowHierarchyType === 'tree' && this.extensionRows?.length >= 1) { this.generateExtensionRowTree(); } @@ -2212,13 +1872,12 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { col, row, oldRowHeaderCellIds.map(oldCellId => oldCellId[col - this.leftRowSeriesNumberColumnCount]), - this._rowHeaderCellFullPathIds_FULL.map(newCellId => newCellId[col - this.leftRowSeriesNumberColumnCount]), + this._rowHeaderCellIds_FULL.map(newCellId => newCellId[col - this.leftRowSeriesNumberColumnCount]), oldRowHeaderCellPositons, this ); - // this._rowHeaderCellIds = this._rowHeaderCellIds_FULL.slice(); - this.generateCellIdsConsiderHideHeader(); - this.setPagination(this.pagination); + this._rowHeaderCellIds = this._rowHeaderCellIds_FULL.slice(); + return diffCell; } // 为列宽计算专用,兼容列表 @@ -2450,10 +2109,10 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } else if (this.isRowHeader(source.col, source.row)) { if (this.rowHierarchyType === 'tree') { const sourceRowHeaderPaths = cloneDeep( - this.getCellHeaderPathsWithTreeNode(source.col, source.row).rowHeaderPaths + this.getCellHeaderPathsWidthTreeNode(source.col, source.row).rowHeaderPaths ); const targetRowHeaderPaths = cloneDeep( - this.getCellHeaderPathsWithTreeNode(target.col, target.row).rowHeaderPaths + this.getCellHeaderPathsWidthTreeNode(target.col, target.row).rowHeaderPaths ); sourceRowHeaderPaths.pop(); // 如果用了缓存_CellHeaderPathMap的话 这里pop会影响缓存的值 所以上面使用clone targetRowHeaderPaths.pop(); @@ -2523,30 +2182,17 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (targetIndex === sourceCellRange.start.col) { return null; } - // // _columnHeaderCellIds 逐行将每一行的source id 移动到目标地址targetCol处 - // for (let row = 0; row < this._columnHeaderCellIds.length; row++) { - // // 从header id的二维数组中取出需要操作的source ids - // const sourceIds = this._columnHeaderCellIds[row].splice( - // sourceCellRange.start.col - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount, - // sourceSize - // ); - // // 将source ids插入到目标地址targetCol处 - // // 把sourceIds变成一个适合splice的数组(包含splice前2个参数的数组) 以通过splice来插入sourceIds数组 - // sourceIds.unshift(targetIndex - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount, 0); - // Array.prototype.splice.apply(this._columnHeaderCellIds[row], sourceIds); - // } - // _columnHeaderCellFullPathIds 调整了 _columnHeaderCellIds就不需要调整了 因为他们的第二层数组对象是引用关系 - // _columnHeaderCellFullPathIds 逐行将每一行的source id 移动到目标地址targetCol处 - for (let row = 0; row < this._columnHeaderCellFullPathIds.length; row++) { + // 逐行将每一行的source id 移动到目标地址targetCol处 + for (let row = 0; row < this._columnHeaderCellIds.length; row++) { // 从header id的二维数组中取出需要操作的source ids - const sourceIds = this._columnHeaderCellFullPathIds[row].splice( + const sourceIds = this._columnHeaderCellIds[row].splice( sourceCellRange.start.col - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount, sourceSize ); // 将source ids插入到目标地址targetCol处 // 把sourceIds变成一个适合splice的数组(包含splice前2个参数的数组) 以通过splice来插入sourceIds数组 sourceIds.unshift(targetIndex - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount, 0); - Array.prototype.splice.apply(this._columnHeaderCellFullPathIds[row], sourceIds); + Array.prototype.splice.apply(this._columnHeaderCellIds[row], sourceIds); } //将_columns的列定义调整位置 同调整_headerCellIds逻辑 @@ -2559,7 +2205,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { // 对维度树结构调整节点位置 this.columnDimensionTree.movePosition( - this.getCellHeaderPathsWithTreeNode(source.col, source.row).colHeaderPaths.length - 1, + this.getCellHeaderPathsWidthTreeNode(source.col, source.row).colHeaderPaths.length - 1, sourceCellRange.start.col - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount, targetCellRange.start.col - this.rowHeaderLevelCount - this.leftRowSeriesNumberColumnCount ); @@ -2577,8 +2223,8 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } else if (this.isRowHeader(source.col, source.row)) { // 插入目标地址的列index let targetIndex; - const sourceRowHeaderPaths = this.getCellHeaderPathsWithTreeNode(source.col, source.row).rowHeaderPaths as any; - const targetRowHeaderPaths = this.getCellHeaderPathsWithTreeNode(target.col, target.row).rowHeaderPaths as any; + const sourceRowHeaderPaths = this.getCellHeaderPathsWidthTreeNode(source.col, source.row).rowHeaderPaths as any; + const targetRowHeaderPaths = this.getCellHeaderPathsWidthTreeNode(target.col, target.row).rowHeaderPaths as any; const sourceRowHeaderNode = sourceRowHeaderPaths[sourceRowHeaderPaths.length - 1]; const targetRowHeaderNode = targetRowHeaderPaths[sourceRowHeaderPaths.length - 1]; //整体移动的列数 @@ -2608,14 +2254,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { ); sourceIds.unshift((targetIndex - this.currentPageStartIndex) as any, 0 as any); Array.prototype.splice.apply(this._rowHeaderCellIds, sourceIds); - - // 表头id _rowHeaderCellFullPathIds - const sourceIds0 = this._rowHeaderCellFullPathIds.splice( - sourceCellRange.start.row - this.columnHeaderLevelCount, - sourceSize - ); - sourceIds0.unshift((targetIndex - this.currentPageStartIndex) as any, 0 as any); - Array.prototype.splice.apply(this._rowHeaderCellFullPathIds, sourceIds0); // 表头id _rowHeaderCellIds_FULL进行调整 // 从header id的二维数组中取出需要操作的source ids const sourceIds_FULL = this._rowHeaderCellIds_FULL.splice( @@ -2624,13 +2262,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { ); sourceIds_FULL.unshift(targetIndex as any, 0 as any); Array.prototype.splice.apply(this._rowHeaderCellIds_FULL, sourceIds_FULL); - // 表头id _rowHeaderCellFullPathIds_FULL进行调整 - const sourceIds_FULL0 = this._rowHeaderCellFullPathIds_FULL.splice( - sourceCellRange.start.row - this.columnHeaderLevelCount + this.currentPageStartIndex, - sourceSize - ); - sourceIds_FULL0.unshift(targetIndex as any, 0 as any); - Array.prototype.splice.apply(this._rowHeaderCellFullPathIds_FULL, sourceIds_FULL0); // 对维度树结构调整节点位置 this.rowDimensionTree.movePosition( sourceRowHeaderPaths.length - 1, @@ -2666,9 +2297,12 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { // } IPivotTableCellHeaderPaths | IDimensionInfo[] ): CellAddress | undefined { - let colHeaderPaths: IDimensionInfo[]; - let rowHeaderPaths: IDimensionInfo[]; - let isCornerCell = false; + let colHeaderPaths; + let rowHeaderPaths: { + dimensionKey?: string; + indicatorKey?: string; + value?: string; + }[]; let forceBody = false; if (Array.isArray(dimensionPaths)) { if (dimensionPaths.length > this.rowDimensionKeys.length + this.colDimensionKeys.length) { @@ -2710,32 +2344,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.fullRowDimensionKeys.indexOf(b.dimensionKey ?? this.indicatorDimensionKey) ); }); - - colHeaderPaths?.forEach(a => { - if (a.isPivotCorner) { - isCornerCell = true; - } - }); - rowHeaderPaths?.forEach(a => { - if (a.isPivotCorner) { - isCornerCell = true; - } - }); - if (isCornerCell) { - if (this.cornerSetting.titleOnDimension === 'row') { - for (let i = 0; i < this.rowDimensionKeys.length; i++) { - if (rowHeaderPaths[0].dimensionKey === this.rowDimensionKeys[i]) { - return { col: i + this.leftRowSeriesNumberColumnCount, row: 0 }; - } - } - } else { - for (let i = 0; i < this.colDimensionKeys.length; i++) { - if (colHeaderPaths[0].dimensionKey === this.colDimensionKeys[i]) { - return { col: 0, row: i }; - } - } - } - } let needLowestLevel = false; // needLowestLevel来标记是否需要 提供到最底层的维度层级信息 // 如果行列维度都有值 说明是匹配body单元格 那这个时候 维度层级应该是满的 if (colHeaderPaths?.length >= 1 && rowHeaderPaths?.length >= 1) { @@ -2850,7 +2458,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } //树形展示的情况下 肯定是在第0列 } if (colDimensionFinded || forceBody) { - col = this.rowHeaderLevelCount + this.leftRowSeriesNumberColumnCount; + col = this.rowHeaderLevelCount; const { startInTotal, level } = (colDimensionFinded as ITreeLayoutHeadNode) ?? defaultDimension; col += startInTotal ?? 0; defaultRow = this.columnHeaderTitle ? level + 1 : level; @@ -2912,7 +2520,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { ((this.isFrozenRow(col, row) || this.isBottomFrozenRow(col, row)) && isHasCartesianChartInline(col, row, 'col', this)) ) { - const getAxisConfigInPivotChart = Factory.getFunction('getAxisConfigInPivotChart') as GetAxisConfigInPivotChart; return getAxisConfigInPivotChart(col, row, this); } return undefined; @@ -2936,7 +2543,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (!this._table.isPivotChart()) { return false; } - if (this.indicatorKeys.length >= 1 && checkHasCartesianChart(this.indicatorsDefine)) { + if (this.indicatorKeys.length >= 1 && checkHasCartesianChart(this)) { if ( (this.isBottomFrozenRow(col, row) && isHasCartesianChartInline(col, row, 'col', this)) || (this.isRightFrozenColumn(col, row) && isHasCartesianChartInline(col, row, 'row', this)) @@ -2983,7 +2590,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { setPagination(pagination: IPagination): void { this.clearCellRangeMap(); - this._table.internalProps.useOneRowHeightFillAll = false; this.pagination = pagination; if ( @@ -3002,18 +2608,10 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.currentPageStartIndex = perPageCount * (currentPage || 0); this.currentPageEndIndex = this.currentPageStartIndex + perPageCount; this._rowHeaderCellIds = this._rowHeaderCellIds_FULL?.slice(this.currentPageStartIndex, this.currentPageEndIndex); - this._rowHeaderCellFullPathIds = this._rowHeaderCellFullPathIds_FULL?.slice( - this.currentPageStartIndex, - this.currentPageEndIndex - ); } else { this.currentPageStartIndex = 0; this.currentPageEndIndex = this._rowHeaderCellIds_FULL.length; this._rowHeaderCellIds = this._rowHeaderCellIds_FULL?.slice(this.currentPageStartIndex, this.currentPageEndIndex); - this._rowHeaderCellFullPathIds = this._rowHeaderCellFullPathIds_FULL?.slice( - this.currentPageStartIndex, - this.currentPageEndIndex - ); } this.pagination && (this.pagination.totalCount = this._rowHeaderCellIds_FULL?.length); } @@ -3025,17 +2623,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { }); } - getHeadNode(col: number, row: number) { - let dimensions: IDimensionInfo[]; - const headerPaths = this.getCellHeaderPaths(col, row); - if (headerPaths.rowHeaderPaths && (headerPaths.rowHeaderPaths?.length ?? 0) > 0) { - dimensions = headerPaths.rowHeaderPaths?.slice(0, headerPaths.rowHeaderPaths.length); - } else if (headerPaths.colHeaderPaths && headerPaths.colHeaderPaths.length > 0) { - dimensions = headerPaths.colHeaderPaths.slice(0, headerPaths.colHeaderPaths.length); - } - return this.getHeadNodeByRowOrColDimensions(dimensions, col, row); - } - getHeadNodeByRowOrColDimensions(dimensions: IDimensionInfo[], col?: number, row?: number) { + getHeadNode(dimensions: IDimensionInfo[]) { if (!Array.isArray(dimensions)) { return undefined; } @@ -3043,18 +2631,6 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { let rowDimension; let colArr = this.columnTree; let colDimension; - - // 处理带有扩展row时 获取node错误问题 rowArr需要变更为有相应扩展后的tree - if ( - isValid(row) && - isValid(col) && - this.rowHierarchyType === 'tree' && - this.extensionRows && - col >= 1 + this.leftRowSeriesNumberColumnCount - ) { - const hdId = this.getCellId(col - 1, row); - rowArr = this._rowHeaderExtensionTree[hdId].tree.children; - } for (let i = 0; i < dimensions.length; i++) { const highlightDimension = dimensions[i]; if ( @@ -3087,7 +2663,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if (isCol) { continue; } - for (let k = 0; k < rowArr?.length ?? 0; k++) { + for (let k = 0; k < rowArr.length; k++) { const dimension = rowArr[k]; if ( (isValid(highlightDimension.dimensionKey) && @@ -3114,6 +2690,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } return undefined; } + clearCellRangeMap() { // this._cellRangeMap.clear(); this._largeCellRangeCache.length = 0; @@ -3159,7 +2736,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if ((this._table as PivotChart)._selectedDataItemsInChart.length >= 1) { const match = (this._table as PivotChart)._selectedDataItemsInChart.find(item => { for (const itemKey in item) { - if (typeof item[itemKey] !== 'object' && item[itemKey] !== datum[itemKey]) { + if (item[itemKey] !== datum[itemKey]) { return false; } } @@ -3169,7 +2746,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } else if ((this._table as PivotChart)._selectedDimensionInChart?.length) { // 判断维度点击 const match = (this._table as PivotChart)._selectedDimensionInChart.every(item => { - if (typeof item.value !== 'object' && datum[item.key] !== item.value) { + if (datum[item.key] !== item.value) { return false; } return true; @@ -3184,7 +2761,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { if ((this._table as PivotChart)._selectedDataItemsInChart.length >= 1) { const match = (this._table as PivotChart)._selectedDataItemsInChart.find(item => { for (const itemKey in item) { - if (typeof item[itemKey] !== 'object' && item[itemKey] !== datum[itemKey]) { + if (item[itemKey] !== datum[itemKey]) { return false; } } @@ -3194,7 +2771,7 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { } else if ((this._table as PivotChart)._selectedDimensionInChart?.length) { // 判断维度点击 const match = (this._table as PivotChart)._selectedDimensionInChart.every(item => { - if (typeof item.value !== 'object' && datum[item.key] !== item.value) { + if (datum[item.key] !== item.value) { return false; } return true; @@ -3460,10 +3037,8 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { return totalCount; } resetHeaderTree() { - this.colIndex = 0; //和初始化代码逻辑一致 但未考虑透视图类型 - this._rowHeaderCellFullPathIds_FULL = []; - this._columnHeaderCellFullPathIds = []; + this._rowHeaderCellIds_FULL = []; this._columnHeaderCellIds = []; const dataset = this.dataset; // if (dataset) { @@ -3477,25 +3052,20 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { this.rowHierarchyType, this.rowHierarchyType === 'tree' ? this.rowExpandLevel : undefined ); - - this.resetColumnHeaderLevelCount(); - //生成列表头单元格 this._generateColHeaderIds(); this.colIndex = 0; //生成行表头单元格 this._generateRowHeaderIds(); - this._rowHeaderCellFullPathIds_FULL = transpose(this._rowHeaderCellFullPathIds_FULL); + + this.resetColumnHeaderLevelCount(); + this._rowHeaderCellIds_FULL = transpose(this._rowHeaderCellIds_FULL); this._headerObjectMap = this._headerObjects.reduce((o, e) => { o[e.id as number] = e; return o; }, {} as { [key: LayoutObjectId]: HeaderData }); - - this._CellHeaderPathMap = new Map(); - this._largeCellRangeCache.length = 0; - this.generateCellIdsConsiderHideHeader(); this.setPagination(this.pagination); } isSeriesNumberInHeader(col: number, row: number): boolean { @@ -3577,93 +3147,17 @@ export class PivotHeaderLayoutMap implements LayoutMapAPI { /** 修改表头值 */ changeTreeNodeTitle(col: number, row: number, value: string) { - // const headerPaths = this.getCellHeaderPaths(col, row); - // if (headerPaths.rowHeaderPaths.length > 0) { - // const headerTreeNode = this.getHeadNode(headerPaths.rowHeaderPaths.slice(0, headerPaths.rowHeaderPaths.length)); - // headerTreeNode.value = value; - // } else if (headerPaths.colHeaderPaths.length > 0) { - // const headerTreeNode = this.getHeadNode(headerPaths.colHeaderPaths.slice(0, headerPaths.colHeaderPaths.length)); - // headerTreeNode.value = value; - // } - const headerTreeNode = this.getHeadNode(col, row); - headerTreeNode.value = value; + const headerPaths = this.getCellHeaderPaths(col, row); + if (headerPaths.rowHeaderPaths.length > 0) { + const headerTreeNode = this.getHeadNode(headerPaths.rowHeaderPaths.slice(0, headerPaths.rowHeaderPaths.length)); + headerTreeNode.value = value; + } else if (headerPaths.colHeaderPaths.length > 0) { + const headerTreeNode = this.getHeadNode(headerPaths.colHeaderPaths.slice(0, headerPaths.colHeaderPaths.length)); + headerTreeNode.value = value; + } const id = this.getCellId(col, row); this._headerObjectMap[id as number].title = value; } - changeCornerTitle(col: number, row: number, value: string) { - if (this.isCornerHeader(col, row)) { - const id = this.getCellId(col, row); - this._headerObjectMap[id as number].title = value; - } - } - generateCellIdsConsiderHideHeader() { - // deal with hide header - // 创建原数组的副本 - this._columnHeaderCellIds = this._columnHeaderCellFullPathIds.slice(); - if (!this.showColumnHeader) { - if (this.indicatorsAsCol && !this.hideIndicatorName) { - const indicatorIndex = this.colDimensionKeys.indexOf(IndicatorDimensionKeyPlaceholder); - const indicatorIds: number[][] = this._columnHeaderCellIds.splice(indicatorIndex, 1); - this._columnHeaderCellIds.splice(0, this._columnHeaderCellIds.length); - this._columnHeaderCellIds.push(indicatorIds[0]); - } else { - this._columnHeaderCellIds.splice(0, this._columnHeaderCellIds.length); - } - } - // 创建原数组的副本 - this._rowHeaderCellIds_FULL = this._rowHeaderCellFullPathIds_FULL.slice(); - if (!this.showRowHeader) { - if (!this.indicatorsAsCol && !this.hideIndicatorName) { - const indicatorIndex = this.rowDimensionKeys.indexOf(IndicatorDimensionKeyPlaceholder); - this._rowHeaderCellIds_FULL.forEach((cellIds: number[], index: number) => { - const _cellIds = cellIds.slice(); - const indicator = _cellIds.splice(indicatorIndex, 1); - _cellIds.splice(0, _cellIds.length); - _cellIds.push(indicator[0]); - this._rowHeaderCellIds_FULL[index] = _cellIds; - }); - } else { - this._rowHeaderCellIds_FULL.forEach((cellIds: number[], index: number) => { - const _cellIds = cellIds.slice(); - _cellIds.splice(0, _cellIds.length); - this._rowHeaderCellIds_FULL[index] = _cellIds; - }); - } - } - this._rowHeaderCellIds = this._rowHeaderCellIds_FULL.slice(); - - // 创建原数组的副本 - this._cornerHeaderCellIds = this._cornerHeaderCellFullPathIds.slice(); - if (this.rowHeaderLevelCount === 0 || this.columnHeaderLevelCount === 0) { - this._cornerHeaderCellIds = []; - } else if (this.cornerSetting.titleOnDimension === 'row' && !this.showRowHeader) { - if (!this.indicatorsAsCol && !this.hideIndicatorName) { - const indicatorIndex = this.rowDimensionKeys.indexOf(IndicatorDimensionKeyPlaceholder); - this._cornerHeaderCellIds.forEach((cellIds: number[], index: number) => { - const _cellIds = cellIds.slice(); - const indicator = _cellIds.splice(indicatorIndex, 1); - _cellIds.splice(0, _cellIds.length); - _cellIds.push(indicator[0]); - this._cornerHeaderCellIds[index] = _cellIds; - }); - } else { - this._cornerHeaderCellIds.forEach((cellIds: number[], index: number) => { - const _cellIds = cellIds.slice(); - _cellIds.splice(0, _cellIds.length); - this._cornerHeaderCellIds[index] = _cellIds; - }); - } - } else if (this.cornerSetting.titleOnDimension === 'column' && !this.showColumnHeader) { - if (this.indicatorsAsCol && !this.hideIndicatorName) { - const indicatorIndex = this.colDimensionKeys.indexOf(IndicatorDimensionKeyPlaceholder); - const indicatorIds: number[][] = this._cornerHeaderCellIds.splice(indicatorIndex, 1); - this._cornerHeaderCellIds.splice(0, this._cornerHeaderCellIds.length); - this._cornerHeaderCellIds.push(indicatorIds[0]); - } else { - this._cornerHeaderCellIds.splice(0, this._cornerHeaderCellIds.length); - } - } - } } /** 计算 scale 的实际 range 长度 */ function scaleWholeRangeSize(count: number, bandwidth: number, paddingInner: number, paddingOuter: number) { diff --git a/packages/vtable/src/layout/row-height-map.ts b/packages/vtable/src/layout/row-height-map.ts index ff8fe142a..9b5fb03c9 100644 --- a/packages/vtable/src/layout/row-height-map.ts +++ b/packages/vtable/src/layout/row-height-map.ts @@ -67,10 +67,6 @@ export class NumberRangeMap { put(position: number, newValue: number) { if (this.data.has(position)) { const oldValue = this.data.get(position); - - if (oldValue === newValue) { - return; - } this.data.set(position, newValue); const difference = newValue - oldValue; this.totalSum += difference; diff --git a/packages/vtable/src/layout/simple-header-layout.ts b/packages/vtable/src/layout/simple-header-layout.ts index 5df2a9d98..744a08d66 100644 --- a/packages/vtable/src/layout/simple-header-layout.ts +++ b/packages/vtable/src/layout/simple-header-layout.ts @@ -37,12 +37,9 @@ export class SimpleHeaderLayoutMap implements LayoutMapAPI { private seqId: number = 0; private _headerObjects: HeaderData[]; private _headerObjectMap: { [key in LayoutObjectId]: HeaderData }; - private _headerObjectsIncludeHided: HeaderData[]; - // private _headerObjectMapIncludeHided: { [key in LayoutObjectId]: HeaderData }; // private _headerObjectFieldKey: { [key in string]: HeaderData }; private _headerCellIds: number[][]; private _columns: ColumnData[]; - private _columnsIncludeHided: ColumnData[]; rowSeriesNumberColumn: SeriesNumberColumnData[]; leftRowSeriesNumberColumn: SeriesNumberColumnData[]; rightRowSeriesNumberColumn: SeriesNumberColumnData[]; @@ -72,20 +69,11 @@ export class SimpleHeaderLayoutMap implements LayoutMapAPI { this._showHeader = showHeader; this._table = table; this._columns = []; - this._columnsIncludeHided = []; this._headerCellIds = []; this.hierarchyIndent = hierarchyIndent ?? 20; this.hierarchyTextStartAlignment = table.options.hierarchyTextStartAlignment; this.columnTree = new DimensionTree(columns as any, { seqId: 0 }); //seqId这里没有利用上 所有顺便传了0 - this._headerObjectsIncludeHided = this._addHeaders(0, columns, []); - // this._headerObjectMapIncludeHided = this._headerObjectsIncludeHided.reduce((o, e) => { - // o[e.id as number] = e; - // return o; - // }, {} as { [key in LayoutObjectId]: HeaderData }); - - this._headerObjects = this._headerObjectsIncludeHided.filter(col => { - return col.define.hide !== true; - }); + this._headerObjects = this._addHeaders(0, columns, []); this._headerObjectMap = this._headerObjects.reduce((o, e) => { o[e.id as number] = e; return o; @@ -741,9 +729,6 @@ export class SimpleHeaderLayoutMap implements LayoutMapAPI { get columnObjects(): ColumnData[] { return this._columns; } - get headerObjectsIncludeHided(): HeaderData[] { - return this._headerObjectsIncludeHided; - } //对比multi-layout 那个里面有columWidths对象,保持结构一致 get columnWidths(): WidthData[] { if (this.leftRowSeriesNumberColumnCount) { @@ -1129,33 +1114,29 @@ export class SimpleHeaderLayoutMap implements LayoutMapAPI { c => results.push(c) ); } else { - const colDef = { + const colDef = hd; + this._columns.push({ id: this.seqId++, - field: hd.field, + field: colDef.field, // fieldKey: colDef.fieldKey, - fieldFormat: hd.fieldFormat, - width: hd.width, - minWidth: hd.minWidth, - maxWidth: hd.maxWidth, - icon: hd.icon, - cellType: hd.cellType ?? (hd as any).columnType ?? 'text', - chartModule: 'chartModule' in hd ? hd.chartModule : null, // todo: 放到对应的column对象中 - chartSpec: 'chartSpec' in hd ? hd.chartSpec : null, // todo: 放到对应的column对象中 - sparklineSpec: 'sparklineSpec' in hd ? hd.sparklineSpec : DefaultSparklineSpec, // todo: 放到对应的column对象中 - style: hd.style, - define: hd, - columnWidthComputeMode: hd.columnWidthComputeMode, - disableColumnResize: hd?.disableColumnResize, - aggregation: this._getAggregationForColumn(hd, col), + fieldFormat: colDef.fieldFormat, + width: colDef.width, + minWidth: colDef.minWidth, + maxWidth: colDef.maxWidth, + icon: colDef.icon, + cellType: colDef.cellType ?? (colDef as any).columnType ?? 'text', + chartModule: 'chartModule' in colDef ? colDef.chartModule : null, // todo: 放到对应的column对象中 + chartSpec: 'chartSpec' in colDef ? colDef.chartSpec : null, // todo: 放到对应的column对象中 + sparklineSpec: 'sparklineSpec' in colDef ? colDef.sparklineSpec : DefaultSparklineSpec, // todo: 放到对应的column对象中 + style: colDef.style, + define: colDef, + columnWidthComputeMode: colDef.columnWidthComputeMode, + disableColumnResize: colDef?.disableColumnResize, + aggregation: this._getAggregationForColumn(colDef, col), isChildNode: row >= 1 - }; - this._columnsIncludeHided.push(colDef); - if (hd.hide !== true) { - this._columns.push(colDef); - - for (let r = row + 1; r < this._headerCellIds.length; r++) { - this._headerCellIds[r][col] = id; - } + }); + for (let r = row + 1; r < this._headerCellIds.length; r++) { + this._headerCellIds[r][col] = id; } } }); diff --git a/packages/vtable/src/layout/tree-helper.ts b/packages/vtable/src/layout/tree-helper.ts index 6292ae6c2..e780de5c6 100644 --- a/packages/vtable/src/layout/tree-helper.ts +++ b/packages/vtable/src/layout/tree-helper.ts @@ -9,7 +9,6 @@ import type { HeaderData, ICustomRender, IDimension, - IHeaderTreeDefine, IIndicator, IRowDimension, LayoutObjectId @@ -44,7 +43,6 @@ interface ITreeLayoutBaseHeadNode { interface ITreeLayoutDimensionHeadNode extends ITreeLayoutBaseHeadNode { dimensionKey: string; - virtual?: boolean; } interface ITreeLayoutIndicatorHeadNode extends ITreeLayoutBaseHeadNode { indicatorKey: string; @@ -81,8 +79,8 @@ export class DimensionTree { // blockStartIndexMap: Map = new Map(); // blockEndIndexMap: Map = new Map(); dimensionKeys: NumberMap = new NumberMap(); - dimensionKeysIncludeVirtual: NumberMap = new NumberMap(); // dimensions: IDimension[] | undefined;//目前用不到这个 + cache: Map = new Map(); constructor( tree: ITreeLayoutHeadNode[], @@ -103,13 +101,12 @@ export class DimensionTree { // this.dimensions = dimensions; this.cache.clear(); this.dimensionKeys = new NumberMap(); - this.dimensionKeysIncludeVirtual = new NumberMap(); this.tree.children = tree as ITreeLayoutHeadNode[]; // const re = { totalLevel: 0 }; // if (updateTreeNode) this.updateTreeNode(this.tree, 0, re, this.tree); // else this.setTreeNode(this.tree, 0, this.tree); - // this.totalLevel = this.dimensionKeys.count(); + this.totalLevel = this.dimensionKeys.count(); } setTreeNode(node: ITreeLayoutHeadNode, startIndex: number, parent: ITreeLayoutHeadNode): number { node.startIndex = startIndex; @@ -120,22 +117,8 @@ export class DimensionTree { // if (!node.id) node.id = ++seqId; // } if (node.dimensionKey ?? node.indicatorKey) { - if ( - !node.virtual && - !this.dimensionKeys.contain(node.indicatorKey ? IndicatorDimensionKeyPlaceholder : node.dimensionKey) - ) { + !this.dimensionKeys.contain(node.indicatorKey ? IndicatorDimensionKeyPlaceholder : node.dimensionKey) && this.dimensionKeys.put(node.level, node.indicatorKey ? IndicatorDimensionKeyPlaceholder : node.dimensionKey); - } - if ( - !this.dimensionKeysIncludeVirtual.contain( - node.indicatorKey ? IndicatorDimensionKeyPlaceholder : node.dimensionKey - ) - ) { - this.dimensionKeysIncludeVirtual.put( - node.level, - node.indicatorKey ? IndicatorDimensionKeyPlaceholder : node.dimensionKey - ); - } if (!node.id) { node.id = ++this.sharedVar.seqId; } @@ -147,7 +130,6 @@ export class DimensionTree { if (children?.length >= 1) { children.forEach((n: any) => { n.level = (node.level ?? 0) + 1; - this.totalLevel = Math.max(this.totalLevel, n.level + 1); size += this.setTreeNode(n, size, node); }); } else { @@ -158,14 +140,12 @@ export class DimensionTree { //树形展示 有子节点 且下一层需要展开 children.forEach((n: any) => { n.level = (node.level ?? 0) + 1; - this.totalLevel = Math.max(this.totalLevel, n.level + 1); size += this.setTreeNode(n, size, node); }); } else if (node.hierarchyState === HierarchyState.collapse && children?.length >= 1) { //树形展示 有子节点 且下一层不需要展开 children.forEach((n: any) => { n.level = (node.level ?? 0) + 1; - this.totalLevel = Math.max(this.totalLevel, n.level + 1); this.setTreeNode(n, size, node); }); } else if ( @@ -178,7 +158,6 @@ export class DimensionTree { children?.length >= 1 && children.forEach((n: any) => { n.level = (node.level ?? 0) + 1; - this.totalLevel = Math.max(this.totalLevel, n.level + 1); size += this.setTreeNode(n, size, node); }); } else if (children?.length >= 1 || children === true) { @@ -187,7 +166,6 @@ export class DimensionTree { children?.length >= 1 && children.forEach((n: any) => { n.level = (node.level ?? 0) + 1; - this.totalLevel = Math.max(this.totalLevel, n.level + 1); this.setTreeNode(n, size, node); }); } else { @@ -366,7 +344,6 @@ export function generateLayoutTree(tree: LayouTreeNode[], children: ITreeLayoutH dimensionKey?: string; indicatorKey?: string; value: string; - virtual?: boolean; hierarchyState: HierarchyState; children: any; } = { @@ -374,8 +351,7 @@ export function generateLayoutTree(tree: LayouTreeNode[], children: ITreeLayoutH indicatorKey: node.indicatorKey, value: node.value, hierarchyState: node.hierarchyState, - children: undefined, - virtual: node.virtual ?? false + children: undefined }; tree.push(diemnsonNode); if (node.children) { @@ -442,7 +418,7 @@ export function dealHeader( headerType: indicatorInfo?.headerType ?? dimensionInfo?.headerType ?? 'text', headerIcon: indicatorInfo?.headerIcon ?? dimensionInfo?.headerIcon, // define: hd, - define: Object.assign({}, hd, indicatorInfo ?? Object.assign({}, dimensionInfo, { sort: undefined })), + define: Object.assign({}, hd, indicatorInfo ?? dimensionInfo), fieldFormat: indicatorInfo?.headerFormat ?? dimensionInfo?.headerFormat, // iconPositionList:[] dropDownMenu: indicatorInfo?.dropDownMenu ?? dimensionInfo?.dropDownMenu, @@ -456,7 +432,6 @@ export function dealHeader( minWidth: (dimensionInfo as IRowDimension)?.minWidth, maxWidth: (dimensionInfo as IRowDimension)?.maxWidth, showSort: indicatorInfo?.showSort ?? dimensionInfo?.showSort, - sort: indicatorInfo?.sort, description: dimensionInfo?.description }; diff --git a/packages/vtable/src/plugins/custom-cell-style.ts b/packages/vtable/src/plugins/custom-cell-style.ts index a7a89558f..32cec9446 100644 --- a/packages/vtable/src/plugins/custom-cell-style.ts +++ b/packages/vtable/src/plugins/custom-cell-style.ts @@ -27,7 +27,7 @@ export class CustomCellStylePlugin { const customStyleId = this.getCustomCellStyleId(col, row); if (customStyleId) { const styleOption = this.getCustomCellStyleOption(customStyleId); - return styleOption?.style; + return styleOption.style; } return undefined; } @@ -133,8 +133,6 @@ export class CustomCellStylePlugin { } updateCustomCell(customCellStyle: CustomCellStyle[], customCellStyleArrangement: CustomCellStyleArrangement[]) { - this.customCellStyle.length = 0; - this.customCellStyleArrangement.length = 0; customCellStyle.forEach((cellStyle: CustomCellStyle) => { this.registerCustomCellStyle(cellStyle.id, cellStyle.style); }); @@ -142,10 +140,6 @@ export class CustomCellStylePlugin { this.arrangeCustomCellStyle(cellStyle.cellPosition, cellStyle.customStyleId); }); } - - hasCustomCellStyle(customStyleId: string) { - return this.customCellStyle.some(style => style.id === customStyleId); - } } export function mergeStyle(cacheStyle: Style, customCellStyle: ColumnStyleOption): Style { diff --git a/packages/vtable/src/scenegraph/animation/appear.ts b/packages/vtable/src/scenegraph/animation/appear.ts deleted file mode 100644 index 5ed3bd720..000000000 --- a/packages/vtable/src/scenegraph/animation/appear.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { Text } from '@src/vrender'; -import type { BaseTableAPI } from '../../ts-types/base-table'; - -export function dealWithAnimationAppear(table: BaseTableAPI) { - if (!table.options.animationAppear) { - return; - } - - let duration: number; - let delay: number; - let type: 'all' | 'one-by-one'; - let direction: 'row' | 'column'; - - if (table.options.animationAppear === true) { - duration = 500; - delay = 0; - type = 'one-by-one'; - direction = 'column'; - } else { - duration = table.options.animationAppear.duration ?? 500; - delay = table.options.animationAppear.delay ?? 0; - type = table.options.animationAppear.type ?? 'one-by-one'; - direction = table.options.animationAppear.direction ?? 'row'; - } - - const { scenegraph: scene, frozenColCount, frozenRowCount } = table; - - // header cell - const { colStart, colEnd, rowStart, rowEnd } = scene.proxy; // to do: right bottom frozen - - for (let col = 0; col <= colEnd; col++) { - for (let row = 0; row <= rowEnd; row++) { - const cellGroup = scene.highPerformanceGetCell(col, row); - if (cellGroup && cellGroup.role === 'cell') { - cellGroup.forEachChildren((child: Text) => { - child.setAttribute('opacity', 0); - child - .animate() - .wait(type === 'one-by-one' ? (direction === 'row' ? row : col) * (duration - delay) : delay) - .to({ opacity: 1 }, duration, 'linear'); - }); - } - } - } -} diff --git a/packages/vtable/src/scenegraph/component/custom.ts b/packages/vtable/src/scenegraph/component/custom.ts index 38b484ea2..3022a71f0 100644 --- a/packages/vtable/src/scenegraph/component/custom.ts +++ b/packages/vtable/src/scenegraph/component/custom.ts @@ -10,7 +10,6 @@ import { } from '@src/vrender'; import { isArray, isFunction, isObject, isString, isValid } from '@visactor/vutils'; import type { - CellRange, ICustomLayout, ICustomRender, ICustomRenderElement, @@ -20,13 +19,6 @@ import type { import { Icon } from '../graphic/icon'; import type { BaseTableAPI } from '../../ts-types/base-table'; import type { percentCalcObj } from '../../render/layout'; -import { emptyCustomLayout } from '../../components/react/react-custom-layout'; -import { getTargetCell } from '../../event/util'; -import type { Group } from '../graphic/group'; - -export const CUSTOM_MERGE_PRE_NAME = '_custom_'; -export const CUSTOM_CONTAINER_NAME = 'custom-container'; -export const CUSTOM_MERGE_CONTAINER_NAME = CUSTOM_MERGE_PRE_NAME + '_0'; export function dealWithCustom( customLayout: ICustomLayout, @@ -38,7 +30,6 @@ export function dealWithCustom( autoWidth: boolean, autoHeight: boolean, padding: [number, number, number, number], - range: CellRange | undefined, table: BaseTableAPI ) { let renderDefault = true; @@ -48,10 +39,6 @@ export function dealWithCustom( let customElements; let elementsGroup: VGroup; - if (customLayout === 'react-custom-layout') { - // customLayout = table._reactCreateGraphic; - customLayout = table.reactCustomLayout?.getCustomLayoutFunc(col, row) || emptyCustomLayout; - } if (typeof customLayout === 'function') { const arg = { col, @@ -76,9 +63,7 @@ export function dealWithCustom( // expectedHeight = customRenderObj.expectedHeight; if (customRenderObj.rootContainer instanceof VGroup) { elementsGroup = customRenderObj.rootContainer; - elementsGroup.name = CUSTOM_CONTAINER_NAME; - (elementsGroup as any).col = col; - (elementsGroup as any).row = row; + elementsGroup.name = 'custom-container'; // } else if (customRenderObj.rootContainer) { // customElements = customRenderObj.rootContainer.getElements(undefined, false, false); } @@ -136,11 +121,6 @@ export function dealWithCustom( // for percent calc dealPercentCalc(elementsGroup, width, height); - // deal with merge cell attribute update - if (range && (range.start.col !== range.end.col || range.start.row !== range.end.row)) { - bindAttributeUpdate(elementsGroup, col, row, 0); - } - return { elementsGroup, renderDefault @@ -162,7 +142,7 @@ function adjustElementToGroup( stroke: false, pickable: false }); - customGroup.name = CUSTOM_CONTAINER_NAME; + customGroup.name = 'custom-container'; const elementsAdjusted = adjustElementsPos(elements, width, height, value); elementsAdjusted.forEach(element => { @@ -501,70 +481,3 @@ function parseToGraphic(g: any, props: any) { // } } } - -function bindAttributeUpdate(group: VGroup, col: number, row: number, index: number, preId?: string) { - if (!group) { - return; - } - group.name = `${CUSTOM_MERGE_PRE_NAME}${preId ?? ''}_${index}`; - group.onBeforeAttributeUpdate = onBeforeAttributeUpdate as any; - // group.on('afterAttributeUpdate', (e) => {console.log('afterAttributeUpdate', e)}) - if (group.type === 'group' && group.childrenCount) { - group.forEachChildren((child: VGroup, childIndex: number) => { - bindAttributeUpdate(child, col, row, childIndex, (preId ?? '') + '_' + index); - }); - } -} - -function onBeforeAttributeUpdate(val: Record, attribute: any) { - // @ts-ignore - const graphic = this as any; - if (graphic.skipMergeUpdate) { - return; - } - const cellGroup = getTargetCell(graphic) as Group; - const table = ((cellGroup as any).stage as any).table as BaseTableAPI; - graphic.skipAttributeUpdate = true; - const { mergeStartCol, mergeEndCol, mergeStartRow, mergeEndRow } = cellGroup; - if ( - isValid(mergeStartCol) && - isValid(mergeEndCol) && - isValid(mergeStartRow) && - isValid(mergeEndRow) && - (mergeStartCol !== mergeEndCol || mergeStartRow !== mergeEndRow) - ) { - for (let col = mergeStartCol; col <= mergeEndCol; col++) { - for (let row = mergeStartRow; row <= mergeEndRow; row++) { - if (col === cellGroup.col && row === cellGroup.row) { - continue; - } - // const cell = table.scenegraph.getCell(col, row); - const cell = table.scenegraph.highPerformanceGetCell(col, row); - if (cell.role === 'cell') { - const target = cell.getChildByName(graphic.name, true); - if (!target || target.skipAttributeUpdate) { - continue; - } - for (const key in val) { - // 表格内merge 单元格布局时,会使用dx dy定位,避免重复更新值,属性同步跳过 dx dy - // console.log( - // '[onBeforeAttributeUpdate]', - // target._uid, - // cellGroup.col, - // cellGroup.row, - // col, - // row, - // key, - // val[key] - // ); - if (val[key] !== target.attribute[key] && key !== 'dx' && key !== 'dy') { - target.setAttribute(key, val[key]); - } - } - } - } - } - graphic.skipAttributeUpdate = undefined; - // return attribute; - } -} diff --git a/packages/vtable/src/scenegraph/component/table-component.ts b/packages/vtable/src/scenegraph/component/table-component.ts index dcf46f92b..81e4fa053 100644 --- a/packages/vtable/src/scenegraph/component/table-component.ts +++ b/packages/vtable/src/scenegraph/component/table-component.ts @@ -7,7 +7,6 @@ import { DrillIcon } from './drill-icon'; import { CellMover } from './cell-mover'; import { getColX, getRowY } from './util'; import type { BaseTableAPI } from '../../ts-types/base-table'; -import { isValid } from '@visactor/vutils'; /** * @description: 表格内容外组件 @@ -269,20 +268,7 @@ export class TableComponent { const theme = this.table.theme; const scrollRailColor = theme.scrollStyle?.scrollRailColor as string; const scrollSliderColor = theme.scrollStyle?.scrollSliderColor as string; - const scrollSliderCornerRadius = theme.scrollStyle?.scrollSliderCornerRadius; const width = theme.scrollStyle?.width as number; - - let sliderStyle; - if (isValid(scrollSliderCornerRadius)) { - sliderStyle = { - cornerRadius: scrollSliderCornerRadius, - fill: scrollSliderColor - }; - } else { - sliderStyle = { - fill: scrollSliderColor - }; - } // const visible = theme.scrollStyle?.visible as string; // const hoverOn = theme.scrollStyle?.hoverOn as boolean; @@ -296,7 +282,9 @@ export class TableComponent { railStyle: { fill: scrollRailColor }, - sliderStyle, + sliderStyle: { + fill: scrollSliderColor + }, range: [0, 0.1], // scrollRange: [0.4, 0.8] visible: false @@ -315,7 +303,9 @@ export class TableComponent { railStyle: { fill: scrollRailColor }, - sliderStyle, + sliderStyle: { + fill: scrollSliderColor + }, range: [0, 0.1], visible: false }); @@ -344,13 +334,7 @@ export class TableComponent { const frozenColsWidth = this.table.getFrozenColsWidth(); const bottomFrozenRowsHeight = this.table.getBottomFrozenRowsHeight(); const rightFrozenColsWidth = this.table.getRightFrozenColsWidth(); - - // _disableColumnAndRowSizeRound环境中,可能出现 - // getAllColsWidth/getAllRowsHeight(A) + getAllColsWidth/getAllRowsHeight(B) < getAllColsWidth/getAllRowsHeight(A+B) - // (由于小数在取数时被省略) - // 这里加入tolerance,避免出现无用滚动 - const sizeTolerance = this.table.options.customConfig?._disableColumnAndRowSizeRound ? 1 : 0; - if (totalWidth > tableWidth + sizeTolerance) { + if (totalWidth > tableWidth) { const y = Math.min(tableHeight, totalHeight); const rangeEnd = Math.max(0.05, (tableWidth - frozenColsWidth) / (totalWidth - frozenColsWidth)); @@ -390,7 +374,7 @@ export class TableComponent { }); } - if (totalHeight > tableHeight + sizeTolerance) { + if (totalHeight > tableHeight) { const x = Math.min(tableWidth, totalWidth); const rangeEnd = Math.max(0.05, (tableHeight - frozenRowsHeight) / (totalHeight - frozenRowsHeight)); @@ -734,26 +718,15 @@ export class TableComponent { // scrollbar const scrollRailColor = theme.scrollStyle?.scrollRailColor as string; const scrollSliderColor = theme.scrollStyle?.scrollSliderColor as string; - const scrollSliderCornerRadius = theme.scrollStyle?.scrollSliderCornerRadius; const width = theme.scrollStyle?.width as number; - - let sliderStyle; - if (isValid(scrollSliderCornerRadius)) { - sliderStyle = { - cornerRadius: scrollSliderCornerRadius, - fill: scrollSliderColor - }; - } else { - sliderStyle = { - fill: scrollSliderColor - }; - } this.hScrollBar.setAttributes({ height: width, railStyle: { fill: scrollRailColor }, - sliderStyle + sliderStyle: { + fill: scrollSliderColor + } }); this.vScrollBar.setAttributes({ @@ -761,7 +734,9 @@ export class TableComponent { railStyle: { fill: scrollRailColor }, - sliderStyle + sliderStyle: { + fill: scrollSliderColor + } }); // columnResizeLine & columnResizeBgLine diff --git a/packages/vtable/src/scenegraph/graphic/chart.ts b/packages/vtable/src/scenegraph/graphic/chart.ts index e4e221b6d..f13d987f2 100644 --- a/packages/vtable/src/scenegraph/graphic/chart.ts +++ b/packages/vtable/src/scenegraph/graphic/chart.ts @@ -149,7 +149,7 @@ export class Chart extends Group { */ deactivate() { this.active = false; - // move active chart view box out of browser view + // move active chart view box out of broswer view // to avoid async render when chart is releasd this.activeChartInstance?.updateViewBox( { diff --git a/packages/vtable/src/scenegraph/graphic/contributions/group-contribution-render.ts b/packages/vtable/src/scenegraph/graphic/contributions/group-contribution-render.ts index 370056650..eec532b3c 100644 --- a/packages/vtable/src/scenegraph/graphic/contributions/group-contribution-render.ts +++ b/packages/vtable/src/scenegraph/graphic/contributions/group-contribution-render.ts @@ -13,10 +13,10 @@ import { BaseRenderContributionTime, createRectPath, injectable } from '@src/vre import type { Group } from '../group'; import { getCellHoverColor } from '../../../state/hover/is-cell-hover'; import type { BaseTableAPI } from '../../../ts-types/base-table'; +import { getQuadProps } from '../../utils/padding'; import { getCellMergeInfo } from '../../utils/get-cell-merge'; import { InteractionState } from '../../../ts-types'; import { isArray } from '@visactor/vutils'; -import { getCellSelectColor } from '../../../state/select/is-cell-select-highlight'; // const highlightDash: number[] = []; @@ -122,8 +122,8 @@ export class SplitGroupAfterRenderContribution implements IGroupRenderContributi ) => boolean ) { const { - // width = groupAttribute.width, - // height = groupAttribute.height, + width = groupAttribute.width, + height = groupAttribute.height, // 基础border stroke = groupAttribute.stroke, strokeArrayColor = (groupAttribute as any).strokeArrayColor, @@ -137,7 +137,6 @@ export class SplitGroupAfterRenderContribution implements IGroupRenderContributi // highlightStrokeArrayWidth = (groupAttribute as any).highlightStrokeArrayWidth, // highlightStrokeArrayPart = (groupAttribute as any).highlightStrokeArrayPart, } = group.attribute as any; - let { width = groupAttribute.width, height = groupAttribute.height } = group.attribute; // lineWidth === 0 不绘制 if (!stroke || (!Array.isArray(strokeArrayWidth) && lineWidth === 0)) { @@ -156,35 +155,30 @@ export class SplitGroupAfterRenderContribution implements IGroupRenderContributi return; } const bottomRight = table?.theme.cellBorderClipDirection === 'bottom-right'; - // let deltaWidth = 0; - // let deltaHeight = 0; + let deltaWidth = 0; + let deltaHeight = 0; if (bottomRight) { x = Math.floor(x) - 0.5; y = Math.floor(y) - 0.5; - // if (group.role === 'cell') { - // const col = (group as any).col as number; - // const row = (group as any).row as number; - // if (table && col === table.colCount - 1) { - // deltaWidth = 1; - // } - // if (table && row === table.rowCount - 1) { - // deltaHeight = 1; - // } - // } + if (group.role === 'cell') { + const col = (group as any).col as number; + const row = (group as any).row as number; + if (table && col === table.colCount - 1) { + deltaWidth = 1; + } + if (table && row === table.rowCount - 1) { + deltaHeight = 1; + } + } } else { x = Math.floor(x) + 0.5; y = Math.floor(y) + 0.5; } - if (table.options.customConfig?._disableColumnAndRowSizeRound) { - width = Math.round(width); - height = Math.round(height); - } const { width: widthFroDraw, height: heightFroDraw } = getCellSizeForDraw( group, - Math.ceil(width), - Math.ceil(height), - bottomRight + Math.ceil(width + deltaWidth), + Math.ceil(height + deltaHeight) ); widthForStroke = widthFroDraw; heightForStroke = heightFroDraw; @@ -268,9 +262,8 @@ export function renderStroke( context.setStrokeStyle(group, group.attribute, x, y, groupAttribute); // if (isHighlight) { // context.setLineDash(highlightDash); + // context.lineCap = 'butt'; // } - // const oldLineCap = context.lineCap; - // context.lineCap = 'square'; const { lineDash = groupAttribute.lineDash } = group.attribute as any; // const lineDash = context.getLineDash(); @@ -282,23 +275,16 @@ export function renderStroke( context.beginPath(); context.moveTo(x, y); - const strokeTop = (isStrokeTrue || stroke[0]) && (isWidthNumber || strokeArrayWidth[0]); - const strokeRight = (isStrokeTrue || stroke[1]) && (isWidthNumber || strokeArrayWidth[1]); - const strokeBottom = (isStrokeTrue || stroke[2]) && (isWidthNumber || strokeArrayWidth[2]); - const strokeLeft = (isStrokeTrue || stroke[3]) && (isWidthNumber || strokeArrayWidth[3]); - // top - if (strokeTop) { + if ((isStrokeTrue || stroke[0]) && (isWidthNumber || strokeArrayWidth[0])) { // context.lineTo(x + width, y); - const deltaLeft = (isWidthNumber ? widthInfo.width : strokeArrayWidth[0]) / 2; - const deltaRight = (isWidthNumber ? widthInfo.width : strokeArrayWidth[0]) / 2; if (isPart && Array.isArray(part[0])) { - context.moveTo(x - deltaLeft + (width + deltaLeft + deltaRight) * part[0][0], y); - context.lineTo(x - deltaLeft + (width + deltaLeft + deltaRight) * (part[0][1] - part[0][0]), y); - context.moveTo(x + width + deltaRight, y); + context.moveTo(x + width * part[0][0], y); + context.lineTo(x + width * (part[0][1] - part[0][0]), y); + context.moveTo(x + width, y); } else { - context.moveTo(x - deltaLeft, y); - context.lineTo(x + width + deltaRight, y); + context.moveTo(x, y); + context.lineTo(x + width, y); } if (isSplitDraw || isDash) { if (strokeArrayColor && strokeArrayColor[0]) { @@ -321,17 +307,15 @@ export function renderStroke( context.moveTo(x + width, y); } // right - if (strokeRight) { + if ((isStrokeTrue || stroke[1]) && (isWidthNumber || strokeArrayWidth[1])) { // context.lineTo(x + width, y + height); - const deltaTop = (isWidthNumber ? widthInfo.width : strokeArrayWidth[1]) / 2; - const deltaBottom = (isWidthNumber ? widthInfo.width : strokeArrayWidth[1]) / 2; if (isPart && Array.isArray(part[1])) { - context.moveTo(x + width, y - deltaTop + height * part[1][0]); - context.lineTo(x + width, y - deltaTop + (height + deltaTop + deltaBottom) * (part[1][1] - part[1][0])); - context.moveTo(x + width, y + height + deltaBottom); + context.moveTo(x + width, y + height * part[1][0]); + context.lineTo(x + width, y + height * (part[1][1] - part[1][0])); + context.moveTo(x + width, y + height); } else { - context.moveTo(x + width, y - deltaTop); - context.lineTo(x + width, y + height + deltaBottom); + context.moveTo(x + width, y); + context.lineTo(x + width, y + height); } if (isSplitDraw || isDash) { if (strokeArrayColor && strokeArrayColor[1]) { @@ -354,17 +338,15 @@ export function renderStroke( context.moveTo(x + width, y + height); } // bottom - if (strokeBottom) { + if ((isStrokeTrue || stroke[2]) && (isWidthNumber || strokeArrayWidth[2])) { // context.lineTo(x, y + height); - const deltaLeft = (isWidthNumber ? widthInfo.width : strokeArrayWidth[2]) / 2; - const deltaRight = (isWidthNumber ? widthInfo.width : strokeArrayWidth[2]) / 2; if (isPart && Array.isArray(part[2])) { - context.moveTo(x - deltaLeft + (width + deltaLeft + deltaRight) * part[2][0], y + height); - context.lineTo(x - deltaLeft + (width + deltaLeft + deltaRight) * (part[2][1] - part[2][0]), y + height); - context.moveTo(x - deltaLeft, y + height); + context.moveTo(x + width * part[2][0], y + height); + context.lineTo(x + width * (part[2][1] - part[2][0]), y + height); + context.moveTo(x, y + height); } else { - context.moveTo(x - deltaLeft, y + height); - context.lineTo(x + width + deltaRight, y + height); + context.moveTo(x, y + height); + context.lineTo(x + width, y + height); } if (isSplitDraw || isDash) { if (strokeArrayColor && strokeArrayColor[2]) { @@ -387,17 +369,15 @@ export function renderStroke( context.moveTo(x, y + height); } // left - if (strokeLeft) { + if ((isStrokeTrue || stroke[3]) && (isWidthNumber || strokeArrayWidth[3])) { // context.lineTo(x, y); - const deltaTop = (isWidthNumber ? widthInfo.width : strokeArrayWidth[3]) / 2; - const deltaBottom = (isWidthNumber ? widthInfo.width : strokeArrayWidth[3]) / 2; if (isPart && Array.isArray(part[3])) { - context.moveTo(x, y - deltaTop + (height + deltaTop + deltaBottom) * part[3][0]); - context.lineTo(x, y - deltaTop + (height + deltaTop + deltaBottom) * (part[3][1] - part[3][0])); - context.moveTo(x, y - deltaTop); + context.moveTo(x, y + height * part[3][0]); + context.lineTo(x, y + height * (part[3][1] - part[3][0])); + context.moveTo(x, y); } else { - context.moveTo(x, y - deltaTop); - context.lineTo(x, y + height + deltaBottom); + context.moveTo(x, y); + context.lineTo(x, y + height); } if (isSplitDraw || isDash) { if (strokeArrayColor && strokeArrayColor[3]) { @@ -428,7 +408,6 @@ export function renderStroke( context.stroke(); } context.lineDashOffset = 0; - // context.lineCap = oldLineCap; context.setLineDash([]); } @@ -473,7 +452,6 @@ export class DashGroupBeforeRenderContribution implements IGroupRenderContributi stroke && Array.isArray(lineDash) && lineDash.length && - lineDash[0]?.length && !Array.isArray(strokeArrayColor) && !Array.isArray(strokeArrayWidth) ) { @@ -518,50 +496,44 @@ export class DashGroupAfterRenderContribution implements IGroupRenderContributio if ( !stroke || - !(Array.isArray(lineDash) && lineDash.length && lineDash[0]?.length) || + !(Array.isArray(lineDash) && lineDash.length) || Array.isArray(strokeArrayColor) || Array.isArray(strokeArrayWidth) ) { return; } - const table = (group.stage as any).table as BaseTableAPI; - if (!table) { - return; - } - // convert lineDash to number[][] const splitLineDash = isArray(lineDash[0]) ? getQuadLineDash(lineDash) : [lineDash, lineDash, lineDash, lineDash]; // const { width = groupAttribute.width, height = groupAttribute.height } = group.attribute; let { width = groupAttribute.width, height = groupAttribute.height } = group.attribute; - if (table.options.customConfig?._disableColumnAndRowSizeRound) { - width = Math.round(width); - height = Math.round(height); - } else { - width = Math.ceil(width); - height = Math.ceil(height); - } + width = Math.ceil(width); + height = Math.ceil(height); let widthForStroke; let heightForStroke; if (lineWidth & 1) { - const bottomRight = table.theme.cellBorderClipDirection === 'bottom-right'; - const deltaWidth = 0; - const deltaHeight = 0; + const table = (group.stage as any).table as BaseTableAPI; + if (!table) { + return; + } + const bottomRight = table?.theme.cellBorderClipDirection === 'bottom-right'; + let deltaWidth = 0; + let deltaHeight = 0; if (bottomRight) { x = Math.floor(x) - 0.5; y = Math.floor(y) - 0.5; - // if (group.role === 'cell') { - // const col = (group as any).col as number; - // const row = (group as any).row as number; - // if (table && col === table.colCount - 1) { - // deltaWidth = 1; - // } - // if (table && row === table.rowCount - 1) { - // deltaHeight = 1; - // } - // } + if (group.role === 'cell') { + const col = (group as any).col as number; + const row = (group as any).row as number; + if (table && col === table.colCount - 1) { + deltaWidth = 1; + } + if (table && row === table.rowCount - 1) { + deltaHeight = 1; + } + } } else { x = Math.floor(x) + 0.5; y = Math.floor(y) + 0.5; @@ -570,8 +542,7 @@ export class DashGroupAfterRenderContribution implements IGroupRenderContributio const { width: widthFroDraw, height: heightFroDraw } = getCellSizeForDraw( group, Math.ceil(width + deltaWidth), - Math.ceil(height + deltaHeight), - bottomRight + Math.ceil(height + deltaHeight) ); widthForStroke = widthFroDraw; heightForStroke = heightFroDraw; @@ -710,7 +681,7 @@ export class AdjustPosGroupAfterRenderContribution implements IGroupRenderContri cornerRadius = groupAttribute.cornerRadius } = group.attribute as any; - let { width = groupAttribute.width, height = groupAttribute.height } = group.attribute; + const { width = groupAttribute.width, height = groupAttribute.height } = group.attribute; // width = Math.ceil(width); // height = Math.ceil(height); @@ -744,46 +715,37 @@ export class AdjustPosGroupAfterRenderContribution implements IGroupRenderContri // height -= 1; // } // } - + const { width: widthFroDraw, height: heightFroDraw } = getCellSizeForDraw( + group, + Math.ceil(width), + Math.ceil(height) + ); + context.beginPath(); const table = (group.stage as any).table as BaseTableAPI; if (!table) { return; } - if (table.options.customConfig?._disableColumnAndRowSizeRound) { - width = Math.round(width); - height = Math.round(height); - } - - context.beginPath(); - const bottomRight = table?.theme.cellBorderClipDirection === 'bottom-right'; - const deltaWidth = 0; - const deltaHeight = 0; + let deltaWidth = 0; + let deltaHeight = 0; if (bottomRight) { x = Math.floor(x) - 0.5; y = Math.floor(y) - 0.5; - // if (group.role === 'cell') { - // const col = (group as any).col as number; - // const row = (group as any).row as number; - // if (table && col === table.colCount - 1) { - // deltaWidth = 1; - // } - // if (table && row === table.rowCount - 1) { - // deltaHeight = 1; - // } - // } + if (group.role === 'cell') { + const col = (group as any).col as number; + const row = (group as any).row as number; + if (table && col === table.colCount - 1) { + deltaWidth = 1; + } + if (table && row === table.rowCount - 1) { + deltaHeight = 1; + } + } } else { x = Math.floor(x) + 0.5; y = Math.floor(y) + 0.5; } - const { width: widthFroDraw, height: heightFroDraw } = getCellSizeForDraw( - group, - Math.ceil(width), - Math.ceil(height), - bottomRight - ); - if (cornerRadius) { // 测试后,cache对于重绘性能提升不大,但是在首屏有一定性能损耗,因此rect不再使用cache createRectPath(context, x, y, widthFroDraw + deltaWidth, heightFroDraw + deltaHeight, cornerRadius); @@ -827,16 +789,10 @@ export class AdjustColorGroupBeforeRenderContribution implements IGroupRenderCon // 处理hover颜色 if ((group as Group).role === 'cell') { const table = (group.stage as any).table as BaseTableAPI; - if (table) { - const selectColor = getCellSelectColor(group as Group, table); - if (selectColor) { - // show select highlight when scrolling - (group.attribute as any)._vtableHightLightFill = selectColor; - } else if (table.stateManager.interactionState !== InteractionState.scrolling) { - const hoverColor = getCellHoverColor(group as Group, table); - if (hoverColor) { - (group.attribute as any)._vtableHightLightFill = hoverColor; - } + if (table && table.stateManager.interactionState !== InteractionState.scrolling) { + const hoverColor = getCellHoverColor(group as Group, table); + if (hoverColor) { + (group.attribute as any)._vtableHoverFill = hoverColor; } } } @@ -871,18 +827,18 @@ export class AdjustColorGroupAfterRenderContribution implements IGroupRenderCont ) => boolean ) { // 处理hover颜色 - if ((group.attribute as any)._vtableHightLightFill) { + if ((group.attribute as any)._vtableHoverFill) { if (fillCb) { // do nothing // fillCb(context, group.attribute, groupAttribute); } else if (fVisible) { const oldColor = group.attribute.fill; // draw hover fill - group.attribute.fill = (group.attribute as any)._vtableHightLightFill as any; + group.attribute.fill = (group.attribute as any)._vtableHoverFill as any; context.setCommonStyle(group, group.attribute, x, y, groupAttribute); context.fill(); group.attribute.fill = oldColor; - (group.attribute as any)._vtableHightLightFill = undefined; + (group.attribute as any)._vtableHoverFill = undefined; } } } @@ -1019,7 +975,7 @@ export class ClipBodyGroupAfterRenderContribution implements IGroupRenderContrib } } -function getCellSizeForDraw(group: any, width: number, height: number, bottomRight: boolean) { +function getCellSizeForDraw(group: any, width: number, height: number) { const table = group.stage.table as BaseTableAPI; if (group.role === 'cell') { let col = group.col as number; @@ -1030,25 +986,24 @@ function getCellSizeForDraw(group: any, width: number, height: number, bottomRig row = mergeInfo.end.row; } - if (table && col === table.colCount - 1 && !bottomRight) { + if (table && col === table.colCount - 1) { width -= 1; - } else if (table && col === table.frozenColCount - 1 && table.scrollLeft && !bottomRight) { + } else if (table && col === table.frozenColCount - 1 && table.scrollLeft) { width -= 1; } - if (table && row === table.rowCount - 1 && !bottomRight) { + if (table && row === table.rowCount - 1) { height -= 1; - } else if (table && row === table.frozenRowCount - 1 && table.scrollTop && !bottomRight) { + } else if (table && row === table.frozenRowCount - 1 && table.scrollTop) { height -= 1; } } else if (group.role === 'corner-frozen') { - if (table && table.scrollLeft && !bottomRight) { + if (table && table.scrollLeft) { width -= 1; } - if (table && table.scrollTop && !bottomRight) { + if (table && table.scrollTop) { height -= 1; } } - return { width, height }; } diff --git a/packages/vtable/src/scenegraph/graphic/group.ts b/packages/vtable/src/scenegraph/graphic/group.ts index e9e2f1908..90cd0aa66 100644 --- a/packages/vtable/src/scenegraph/graphic/group.ts +++ b/packages/vtable/src/scenegraph/graphic/group.ts @@ -1,8 +1,8 @@ -import type { IGraphic, IColor, IRect, INode, IGroupGraphicAttribute, ISetAttributeContext } from '@src/vrender'; +import type { IGraphic, IColor, IRect, INode } from '@src/vrender'; import { Group as VRenderGroup } from '@src/vrender'; import type { BaseTableAPI } from '../../ts-types/base-table'; import { InteractionState } from '../../ts-types'; -import { isNumber, type AABBBounds } from '@visactor/vutils'; +import type { AABBBounds } from '@visactor/vutils'; export class Group extends VRenderGroup { role?: string; @@ -22,31 +22,6 @@ export class Group extends VRenderGroup { needUpdateWidth?: boolean; needUpdateHeight?: boolean; - // changes for size align for fs - // constructor(attribute?: IGroupGraphicAttribute) { - // dealWidthSize(attribute, attribute); - // super(attribute); - // } - - // setAttribute(key: string, value: any, forceUpdateTag?: boolean, context?: ISetAttributeContext): void { - // if (key === 'x' || key === 'y' || key === 'width' || key === 'height') { - // this.attribute[`old${key}`]; - // } - // const values = { - // [key]: value - // }; - // this.setAttributes(values, forceUpdateTag, context); - // } - - // setAttributes( - // params: Partial, - // forceUpdateTag?: boolean, - // context?: ISetAttributeContext - // ): void { - // dealWidthSize(params, this.attribute); - // super.setAttributes(params, forceUpdateTag, context); - // } - /** * @description: 清空Group下全部子元素 * @return {*} @@ -364,20 +339,13 @@ export class Group extends VRenderGroup { this.colHeight += cellHeight; } } - - // doUpdateLocalMatrix() { - // const oldX = this.attribute.x; - // const oldY = this.attribute.y; - // this.attribute.x = Math.floor(this.attribute.x); - // this.attribute.y = Math.floor(this.attribute.y); - // super.doUpdateLocalMatrix(); - // this.attribute.x = oldX; - // this.attribute.y = oldY; - // } } function after(group: Group, selfChange: boolean) { - if (!group.stage || !group.stage.dirtyBounds || !group.stage.renderCount) { + if (!group.stage.dirtyBounds) { + return; + } + if (!(group.stage && group.stage.renderCount)) { return; } // group的子元素导致的bounds更新不用做dirtyBounds @@ -386,28 +354,3 @@ function after(group: Group, selfChange: boolean) { } group.stage.dirty(group.globalAABBBounds); } - -// function dealWidthSize(values: any, attributes: any) { -// const x = values.x ?? attributes.oldx ?? attributes.x ?? 0 + values.dx ?? attributes.dx ?? 0; -// const y = values.y ?? attributes.oldy ?? attributes.y ?? 0 + values.dy ?? attributes.dy ?? 0; -// const width = values.width ?? attributes.oldwidth ?? attributes.width ?? 0; -// const height = values.height ?? attributes.oldheight ?? attributes.height ?? 0; -// isNumber(values.width) && (values.oldwidth = values.width); -// isNumber(values.height) && (values.oldheight = values.height); -// isNumber(values.x) && (values.oldx = values.x); -// isNumber(values.y) && (values.oldy = values.y); - -// if (Math.floor(x + width) > Math.floor(width) + Math.floor(x)) { -// values.width = Math.ceil(width); -// } else { -// values.width = Math.floor(width); -// } - -// if (Math.floor(y + height) > Math.floor(height) + Math.floor(y)) { -// values.height = Math.ceil(height); -// } else { -// values.height = Math.floor(height); -// } -// isNumber(values.x) && (values.x = Math.floor(values.x)); -// isNumber(values.y) && (values.y = Math.floor(values.y)); -// } diff --git a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts index 756ef2074..67ba4a622 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-helper.ts @@ -8,6 +8,7 @@ import type { ColumnDefine, ColumnTypeOption, ImageColumnDefine, + MappingRule, ProgressbarColumnDefine, IRowSeriesNumber, TextColumnDefine, @@ -16,25 +17,27 @@ import type { import { dealWithCustom } from '../component/custom'; import type { Group } from '../graphic/group'; import { getProp } from '../utils/get-prop'; -import type { CreateChartCellGroup } from './cell-type/chart-cell'; -import type { CreateImageCellGroup } from './cell-type/image-cell'; -import type { CreateProgressBarCell } from './cell-type/progress-bar-cell'; -import type { CreateSparkLineCellGroup } from './cell-type/spark-line-cell'; -import type { CreateTextCellGroup } from './cell-type/text-cell'; -import type { CreateVideoCellGroup } from './cell-type/video-cell'; -import type { BaseTableAPI, HeaderData } from '../../ts-types/base-table'; +import { createChartCellGroup } from './cell-type/chart-cell'; +import { createImageCellGroup } from './cell-type/image-cell'; +import { createProgressBarCell } from './cell-type/progress-bar-cell'; +import { createSparkLineCellGroup } from './cell-type/spark-line-cell'; +import { createCellGroup } from './cell-type/text-cell'; +import { createVideoCellGroup } from './cell-type/video-cell'; +import type { BaseTableAPI, HeaderData, PivotTableProtected } from '../../ts-types/base-table'; import { getCellCornerRadius, getStyleTheme } from '../../core/tableHelper'; import { isPromise } from '../../tools/helper'; import { dealPromiseData } from '../utils/deal-promise-data'; -import type { ICartesianAxis } from '../../components/axis/axis'; -import { Factory } from '../../core/factory'; -import type { CreateCheckboxCellGroup } from './cell-type/checkbox-cell'; +import { CartesianAxis } from '../../components/axis/axis'; +import { createCheckboxCellGroup } from './cell-type/checkbox-cell'; +// import type { PivotLayoutMap } from '../../layout/pivot-layout'; +import type { PivotHeaderLayoutMap } from '../../layout/pivot-header-layout'; import { getHierarchyOffset } from '../utils/get-hierarchy-offset'; import { getQuadProps } from '../utils/padding'; +import { convertInternal } from '../../tools/util'; import { updateCellContentHeight, updateCellContentWidth } from '../utils/text-icon-layout'; import { isArray } from '@visactor/vutils'; import { breakString } from '../utils/break-string'; -import type { CreateRadioCellGroup } from './cell-type/radio-cell'; +import { createRadioCellGroup } from './cell-type/radio-cell'; export function createCell( type: ColumnTypeOption, @@ -153,7 +156,6 @@ export function createCell( // table.heightMode === 'autoHeight', table.isAutoRowHeight(row), padding, - range, table ); customElementsGroup = customResult.elementsGroup; @@ -161,8 +163,7 @@ export function createCell( } } - const createTextCellGroup = Factory.getFunction('createTextCellGroup') as CreateTextCellGroup; - cellGroup = createTextCellGroup( + cellGroup = createCellGroup( table, value, columnGroup, @@ -186,7 +187,6 @@ export function createCell( const axisConfig = table.internalProps.layoutMap.getAxisConfigInPivotChart(col, row); if (axisConfig) { - const CartesianAxis: ICartesianAxis = Factory.getComponent('axis'); const axis = new CartesianAxis(axisConfig, cellGroup.attribute.width, cellGroup.attribute.height, padding, table); cellGroup.clear(); cellGroup.appendChild(axis.component); @@ -202,7 +202,6 @@ export function createCell( } } else if (type === 'image') { // 创建图片单元格 - const createImageCellGroup = Factory.getFunction('createImageCellGroup') as CreateImageCellGroup; cellGroup = createImageCellGroup( columnGroup, 0, @@ -216,15 +215,12 @@ export function createCell( padding, textAlign, textBaseline, - mayHaveIcon, table, cellTheme, - range, isAsync ); } else if (type === 'video') { // 创建视频单元格 - const createVideoCellGroup = Factory.getFunction('createVideoCellGroup') as CreateVideoCellGroup; cellGroup = createVideoCellGroup( columnGroup, 0, @@ -238,15 +234,12 @@ export function createCell( padding, textAlign, textBaseline, - mayHaveIcon, table, cellTheme, - range, isAsync ); } else if (type === 'chart') { const chartInstance = table.internalProps.layoutMap.getChartInstance(col, row); - const createChartCellGroup = Factory.getFunction('createChartCellGroup') as CreateChartCellGroup; cellGroup = createChartCellGroup( null, columnGroup, @@ -271,8 +264,7 @@ export function createCell( const style = table._getCellStyle(col, row) as ProgressBarStyle; const dataValue = table.getCellOriginValue(col, row); // 创建基础文字单元格 - const createTextCellGroup = Factory.getFunction('createTextCellGroup') as CreateTextCellGroup; - cellGroup = createTextCellGroup( + cellGroup = createCellGroup( table, value, columnGroup, @@ -295,7 +287,6 @@ export function createCell( ); // 创建bar group - const createProgressBarCell = Factory.getFunction('createProgressBarCell') as CreateProgressBarCell; const progressBarGroup = createProgressBarCell( define as ProgressbarColumnDefine, style, @@ -314,7 +305,6 @@ export function createCell( cellGroup.appendChild(progressBarGroup); } } else if (type === 'sparkline') { - const createSparkLineCellGroup = Factory.getFunction('createSparkLineCellGroup') as CreateSparkLineCellGroup; cellGroup = createSparkLineCellGroup( null, columnGroup, @@ -330,7 +320,6 @@ export function createCell( isAsync ); } else if (type === 'checkbox') { - const createCheckboxCellGroup = Factory.getFunction('createCheckboxCellGroup') as CreateCheckboxCellGroup; cellGroup = createCheckboxCellGroup( null, columnGroup, @@ -344,15 +333,12 @@ export function createCell( padding, textAlign, textBaseline, - mayHaveIcon, table, cellTheme, define as CheckboxColumnDefine, - range, isAsync ); } else if (type === 'radio') { - const createRadioCellGroup = Factory.getFunction('createRadioCellGroup') as CreateRadioCellGroup; cellGroup = createRadioCellGroup( null, columnGroup, @@ -419,7 +405,6 @@ export function updateCell(col: number, row: number, table: BaseTableAPI, addNew // table.heightMode === 'autoHeight', table.isAutoRowHeight(row), [0, 0, 0, 0], - range, table ); } @@ -486,7 +471,7 @@ export function updateCell(col: number, row: number, table: BaseTableAPI, addNew const textMark = oldCellGroup.getChildByName('text'); if (textMark) { const text = table.getCellValue(col, row); - const { text: textArr, moreThanMaxCharacters } = breakString(text, table); + const textArr = breakString(text, table); const hierarchyOffset = getHierarchyOffset(col, row, table); const lineClamp = cellStyle.lineClamp; @@ -504,7 +489,6 @@ export function updateCell(col: number, row: number, table: BaseTableAPI, addNew const attribute = { text: textArr.length === 1 && !autoWrapText ? textArr[0] : textArr, // 单行(no-autoWrapText)为字符串,多行(autoWrapText)为字符串数组 - moreThanMaxCharacters, maxLineWidth: cellWidth - (padding[1] + padding[3] + hierarchyOffset), // fill: true, // textAlign: 'left', @@ -513,7 +497,7 @@ export function updateCell(col: number, row: number, table: BaseTableAPI, addNew lineClamp, wordBreak: 'break-word', // widthLimit: autoColWidth ? -1 : colWidth - (padding[1] + padding[3]), - heightLimit: cellHeight - Math.floor(padding[0] + padding[2]), + heightLimit: cellHeight - (padding[0] + padding[2]), pickable: false, dx: textAlign === 'left' ? hierarchyOffset : 0, x @@ -681,14 +665,6 @@ function updateCellContent( if (!addNew && (oldCellGroup.row !== row || oldCellGroup.col !== col)) { return null; } - if (!addNew && oldCellGroup.parent) { - // clear react container - if (table.reactCustomLayout) { - const reactGroup = oldCellGroup.getChildByName('custom-container'); - const { col, row } = reactGroup; - table.reactCustomLayout.removeCustomCell(col, row); - } - } const newCellGroup = createCell( type, value, @@ -712,7 +688,6 @@ function updateCellContent( customResult ); if (!addNew && oldCellGroup.parent) { - // update cell oldCellGroup.parent.insertAfter(newCellGroup, oldCellGroup); oldCellGroup.parent.removeChild(oldCellGroup); @@ -740,7 +715,7 @@ function canUseFastUpdate(col: number, row: number, oldCellGroup: Group, autoWra !autoWrapText && !autoRowHeight && !mayHaveIcon && - oldCellGroup.firstChild?.type === 'text' && // judgement for none text + oldCellGroup.firstChild?.type === 'text' && !isPromise(value) ) { return true; @@ -759,14 +734,9 @@ export function dealWithMergeCellSize( ) { for (let col = range.start.col; col <= range.end.col; col++) { for (let row = range.start.row; row <= range.end.row; row++) { - // const cellGroup = table.scenegraph.getCell(col, row, true); - const cellGroup = table.scenegraph.highPerformanceGetCell(col, row, true); - - if (cellGroup.role !== 'cell') { - continue; - } + const cellGroup = table.scenegraph.getCell(col, row, true); - if (range.start.row !== range.end.row && cellGroup.contentHeight !== cellHeight) { + if (cellGroup.role === 'cell' && range.start.row !== range.end.row && cellGroup.contentWidth !== cellWidth) { updateCellContentHeight( cellGroup, cellHeight, @@ -779,7 +749,7 @@ export function dealWithMergeCellSize( // 'middle' ); } - if (range.start.col !== range.end.col && cellGroup.contentWidth !== cellWidth) { + if (cellGroup.role === 'cell' && range.start.col !== range.end.col && cellGroup.contentHeight !== cellHeight) { updateCellContentWidth( cellGroup, cellWidth, @@ -819,33 +789,25 @@ export function resizeCellGroup( cellGroup.forEachChildren((child: IGraphic) => { // 利用_dx hack解决掉 合并单元格的范围内的格子依次执行该方法 如果挨个调用updateCell的话 执行多次后dx累计问题 if (typeof child._dx === 'number') { - child.skipMergeUpdate = true; child.setAttributes({ dx: (child._dx ?? 0) + dx }); - child.skipMergeUpdate = false; } else { - child.skipMergeUpdate = true; child._dx = child.attribute.dx ?? 0; child.setAttributes({ dx: (child.attribute.dx ?? 0) + dx }); - child.skipMergeUpdate = false; } if (typeof child._dy === 'number') { - child.skipMergeUpdate = true; child.setAttributes({ dy: (child._dy ?? 0) + dy }); - child.skipMergeUpdate = false; } else { child._dy = child.attribute.dy ?? 0; - child.skipMergeUpdate = true; child.setAttributes({ dy: (child.attribute.dy ?? 0) + dy }); - child.skipMergeUpdate = false; } }); @@ -869,13 +831,11 @@ export function resizeCellGroup( const widthChange = rangeWidth !== cellGroup.attribute.width; const heightChange = rangeHeight !== cellGroup.attribute.height; - (cellGroup as any).skipMergeUpdate = true; cellGroup.setAttributes({ width: rangeWidth, height: rangeHeight, strokeArrayWidth: newLineWidth } as any); - (cellGroup as any).skipMergeUpdate = false; cellGroup.mergeStartCol = range.start.col; cellGroup.mergeStartRow = range.start.row; @@ -912,7 +872,6 @@ export function getCustomCellMergeCustom(col: number, row: number, cellGroup: Gr // table.heightMode === 'autoHeight', table.isAutoRowHeight(row), [0, 0, 0, 0], - customMergeRange, table ); diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/chart-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/chart-cell.ts index a5fdc3ad5..35298652e 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/chart-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/chart-cell.ts @@ -123,5 +123,3 @@ export function createChartCellGroup( return cellGroup; } - -export type CreateChartCellGroup = typeof createChartCellGroup; diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/checkbox-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/checkbox-cell.ts index e85099cc0..f3b15e7bd 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/checkbox-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/checkbox-cell.ts @@ -1,6 +1,8 @@ -import type { IThemeSpec } from '@src/vrender'; +import type { ILine, ISymbol, IThemeSpec } from '@src/vrender'; +import { createLine, createSymbol } from '@src/vrender'; +import { PointScale, LinearScale } from '@visactor/vscale'; import { Group } from '../../graphic/group'; -import type { CellInfo, CellRange, CheckboxColumnDefine, CheckboxStyleOption, SparklineSpec } from '../../../ts-types'; +import type { CellInfo, CheckboxColumnDefine, CheckboxStyleOption, SparklineSpec } from '../../../ts-types'; import type { BaseTableAPI } from '../../../ts-types/base-table'; import { isObject } from '@visactor/vutils'; import type { CheckboxAttributes } from '@visactor/vrender-components'; @@ -10,7 +12,6 @@ import { getOrApply } from '../../../tools/helper'; import type { CheckboxStyle } from '../../../body-helper/style/CheckboxStyle'; import { getProp } from '../../utils/get-prop'; import { getCellBorderStrokeWidth } from '../../utils/cell-border-stroke-width'; -import { dealWithIconLayout } from '../../utils/text-icon-layout'; export function createCheckboxCellGroup( cellGroup: Group | null, @@ -19,17 +20,15 @@ export function createCheckboxCellGroup( yOrigin: number, col: number, row: number, - colWidth: number, + colWidth: number | 'auto', width: number, height: number, padding: number[], textAlign: CanvasTextAlign, textBaseline: CanvasTextBaseline, - mayHaveIcon: boolean, table: BaseTableAPI, cellTheme: IThemeSpec, define: CheckboxColumnDefine, - range: CellRange | undefined, isAsync: boolean ) { // cell @@ -83,84 +82,22 @@ export function createCheckboxCellGroup( } } - let icons; - if (mayHaveIcon) { - let iconCol = col; - let iconRow = row; - if (range) { - iconCol = range.start.col; - iconRow = range.start.row; - } - icons = table.getCellIcons(iconCol, iconRow); - } - - let iconWidth = 0; - let cellLeftIconWidth = 0; - let cellRightIconWidth = 0; - if (Array.isArray(icons) && icons.length !== 0) { - const { leftIconWidth, rightIconWidth, absoluteLeftIconWidth, absoluteRightIconWidth } = dealWithIconLayout( - icons, - cellGroup, - range, - table - ); - - iconWidth = leftIconWidth + rightIconWidth; - cellLeftIconWidth = leftIconWidth; - cellRightIconWidth = rightIconWidth; - - // 更新各个部分横向位置 - cellGroup.forEachChildren((child: any) => { - if (child.role === 'icon-left') { - child.setAttribute('x', child.attribute.x + padding[3]); - } else if (child.role === 'icon-right') { - child.setAttribute('x', child.attribute.x + width - rightIconWidth - padding[1]); - } else if (child.role === 'icon-absolute-right') { - child.setAttribute('x', child.attribute.x + width - absoluteRightIconWidth - padding[1]); - } - }); - - // 更新各个部分纵向位置 - cellGroup.forEachChildren((child: any) => { - if (textBaseline === 'middle') { - child.setAttribute('y', (height - child.AABBBounds.height()) / 2); - } else if (textBaseline === 'bottom') { - child.setAttribute('y', height - child.AABBBounds.height() - padding[2]); - } else { - child.setAttribute('y', padding[0]); - } - }); - } - // checkbox - const checkboxComponent = createCheckbox( - col, - row, - colWidth - iconWidth, - width, - height, - padding, - cellTheme, - define, - table - ); + const checkboxComponent = createCheckbox(col, row, colWidth, width, height, padding, cellTheme, define, table); if (checkboxComponent) { cellGroup.appendChild(checkboxComponent); } checkboxComponent.render(); - width -= padding[1] + padding[3] + iconWidth; + width -= padding[1] + padding[3]; height -= padding[0] + padding[2]; if (textAlign === 'center') { - checkboxComponent.setAttribute( - 'x', - padding[3] + cellLeftIconWidth + (width - checkboxComponent.AABBBounds.width()) / 2 - ); + checkboxComponent.setAttribute('x', padding[3] + (width - checkboxComponent.AABBBounds.width()) / 2); } else if (textAlign === 'right') { - checkboxComponent.setAttribute('x', padding[3] + cellLeftIconWidth + width - checkboxComponent.AABBBounds.width()); + checkboxComponent.setAttribute('x', padding[3] + width - checkboxComponent.AABBBounds.width()); } else { - checkboxComponent.setAttribute('x', padding[3] + cellLeftIconWidth); + checkboxComponent.setAttribute('x', padding[3]); } if (textBaseline === 'middle') { @@ -254,7 +191,7 @@ function createCheckbox( lineClamp, wordBreak: 'break-word', // widthLimit: autoColWidth ? -1 : colWidth - (padding[1] + padding[3]), - heightLimit: autoRowHeight ? -1 : cellHeight - Math.floor(padding[0] + padding[2]), + heightLimit: autoRowHeight ? -1 : cellHeight - (padding[0] + padding[2]), pickable: false, dx: hierarchyOffset, whiteSpace: text.length === 1 && !autoWrapText ? 'no-wrap' : 'normal' @@ -298,5 +235,3 @@ function createCheckbox( return checkbox; } - -export type CreateCheckboxCellGroup = typeof createCheckboxCellGroup; diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/image-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/image-cell.ts index 6cb59600e..0faa196bb 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/image-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/image-cell.ts @@ -11,8 +11,6 @@ import { isValid } from '@visactor/vutils'; import { getQuadProps } from '../../utils/padding'; import { getCellBorderStrokeWidth } from '../../utils/cell-border-stroke-width'; import type { BaseTableAPI } from '../../../ts-types/base-table'; -import type { CellRange } from '../../../ts-types'; -import { dealWithIconLayout } from '../../utils/text-icon-layout'; export function createImageCellGroup( columnGroup: Group, @@ -27,18 +25,14 @@ export function createImageCellGroup( padding: [number, number, number, number], textAlign: CanvasTextAlign, textBaseline: CanvasTextBaseline, - mayHaveIcon: boolean, table: BaseTableAPI, cellTheme: IThemeSpec, - range: CellRange | undefined, isAsync: boolean ) { const headerStyle = table._getCellStyle(col, row); // to be fixed const functionalPadding = getFunctionalProp('padding', headerStyle, col, row, table); // const margin = getProp('padding', headerStyle, col, row, table); - if (table.options.customConfig?.imageMargin) { - padding = getQuadProps(table.options.customConfig?.imageMargin); - } else if (isValid(functionalPadding)) { + if (isValid(functionalPadding)) { padding = functionalPadding; } if (cellTheme?.text?.textAlign) { @@ -98,64 +92,12 @@ export function createImageCellGroup( columnGroup?.addCellGroup(cellGroup); } - let cellIcons; - if (mayHaveIcon) { - let iconCol = col; - let iconRow = row; - if (range) { - iconCol = range.start.col; - iconRow = range.start.row; - } - cellIcons = table.getCellIcons(iconCol, iconRow); - } - - let iconWidth = 0; - let cellLeftIconWidth = 0; - let cellRightIconWidth = 0; - if (Array.isArray(cellIcons) && cellIcons.length !== 0) { - const { leftIconWidth, rightIconWidth, absoluteLeftIconWidth, absoluteRightIconWidth } = dealWithIconLayout( - cellIcons, - cellGroup, - range, - table - ); - - iconWidth = leftIconWidth + rightIconWidth; - cellLeftIconWidth = leftIconWidth; - cellRightIconWidth = rightIconWidth; - - // 更新各个部分横向位置 - cellGroup.forEachChildren((child: any) => { - if (child.role === 'icon-left') { - child.setAttribute('x', child.attribute.x + padding[3]); - } else if (child.role === 'icon-right') { - child.setAttribute('x', child.attribute.x + width - rightIconWidth - padding[1]); - } else if (child.role === 'icon-absolute-right') { - child.setAttribute('x', child.attribute.x + width - absoluteRightIconWidth - padding[1]); - } - }); - - // 更新各个部分纵向位置 - cellGroup.forEachChildren((child: any) => { - if (textBaseline === 'middle') { - child.setAttribute('y', (height - child.AABBBounds.height()) / 2); - } else if (textBaseline === 'bottom') { - child.setAttribute('y', height - child.AABBBounds.height() - padding[2]); - } else { - child.setAttribute('y', padding[0]); - } - }); - - (cellGroup as any)._cellLeftIconWidth = cellLeftIconWidth; - (cellGroup as any)._cellRightIconWidth = cellRightIconWidth; - } - // image const value = table.getCellValue(col, row); const image: IImage = createImage({ x: padding[3], y: padding[0], - width: width - padding[1] - padding[3] - iconWidth, + width: width - padding[1] - padding[3], height: height - padding[0] - padding[2], image: value, //?? (regedIcons.damage_pic as any).svg, cursor: 'pointer' as Cursor @@ -203,10 +145,10 @@ export function createImageCellGroup( image.resources.has(image.attribute.image) && image.resources.get(image.attribute.image).state === 'success' ) { - updateImageCellContentWhileResize(cellGroup, col, row, 0, 0, table); + updateImageCellContentWhileResize(cellGroup, col, row, table); } else { image.successCallback = () => { - updateImageCellContentWhileResize(cellGroup, col, row, 0, 0, table); + updateImageCellContentWhileResize(cellGroup, col, row, table); }; } } @@ -220,8 +162,6 @@ export function createImageCellGroup( return cellGroup; } -export type CreateImageCellGroup = typeof createImageCellGroup; - /** * 调整某个图片资源所在行列的行高列宽 之后重绘 * @param col @@ -289,14 +229,7 @@ export function _adjustWidthHeight( return false; } -export function updateImageCellContentWhileResize( - cellGroup: Group, - col: number, - row: number, - deltaX: number, - deltaY: number, - table: BaseTableAPI -) { +export function updateImageCellContentWhileResize(cellGroup: Group, col: number, row: number, table: BaseTableAPI) { const image = cellGroup.getChildByName('image') as Image; if (!image) { return; @@ -312,12 +245,7 @@ export function updateImageCellContentWhileResize( const headerStyle = table._getCellStyle(col, row); // to be fixed const textAlign = getProp('textAlign', headerStyle, col, row, table) ?? 'left'; const textBaseline = getProp('textBaseline', headerStyle, col, row, table) ?? 'middle'; - let padding: [number, number, number, number]; - if (table.options.customConfig?.imageMargin) { - padding = getQuadProps(table.options.customConfig?.imageMargin); - } else { - padding = getQuadProps(getProp('padding', headerStyle, col, row, table)) ?? [0, 0, 0, 0]; - } + const padding = getQuadProps(getProp('padding', headerStyle, col, row, table)) ?? [0, 0, 0, 0]; const { width: cellWidth, height: cellHeight, isMerge } = getCellRange(cellGroup, table); const colStart = cellGroup.mergeStartCol ?? cellGroup.col; @@ -325,9 +253,6 @@ export function updateImageCellContentWhileResize( const colEnd = cellGroup.mergeEndCol ?? cellGroup.col; const rowEnd = cellGroup.mergeEndCol ?? cellGroup.row; - const leftIconWidth = (cellGroup as any)._cellLeftIconWidth ?? 0; - const rightIconWidth = (cellGroup as any)._cellRightIconWidth ?? 0; - if ((image as any).keepAspectRatio) { const { width: imageWidth, height: imageHeight } = calcKeepAspectRatioSize( originImage.width || (originImage as any).videoWidth, @@ -370,11 +295,11 @@ export function updateImageCellContentWhileResize( const cellGroup = table.scenegraph.getCell(col, row); const image = cellGroup.getChildByName('image') as Image; image?.setAttributes({ - x: leftIconWidth + padding[3], + x: padding[3], y: padding[0], // width: cellGroup.attribute.width - padding[1] - padding[3], // height: cellGroup.attribute.height - padding[0] - padding[2] - width: cellWidth - padding[1] - padding[3] - rightIconWidth - leftIconWidth, + width: cellWidth - padding[1] - padding[3], height: cellHeight - padding[0] - padding[2] }); } @@ -409,30 +334,6 @@ export function updateImageCellContentWhileResize( } } - // 更新x方向位置 - cellGroup.forEachChildren((child: any) => { - if (child.role === 'icon-left') { - // do nothing - } else if (child.role === 'icon-right') { - child.setAttribute('x', child.attribute.x + deltaX); - } else if (child.role === 'icon-absolute-right') { - child.setAttribute('x', child.attribute.x + deltaX); - } - }); - - // 更新y方向位置 - cellGroup.forEachChildren((child: any) => { - if (child.type !== 'rect' && (!child.role || !child.role.startsWith('icon'))) { - // do nothing - } else if (textBaseline === 'middle') { - child.setAttribute('y', padding[0] + (cellHeight - padding[0] - padding[2] - child.AABBBounds.height()) / 2); - } else if (textBaseline === 'bottom') { - child.setAttribute('y', padding[0] + cellHeight - padding[0] - padding[2] - child.AABBBounds.height()); - } else { - child.setAttribute('y', padding[0]); - } - }); - if (isMerge) { updateImageDxDy( cellGroup.mergeStartCol, diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/index.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/index.ts deleted file mode 100644 index 36930f41a..000000000 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Factory } from '../../../core/factory'; -import { createChartCellGroup } from './chart-cell'; -import { createCheckboxCellGroup } from './checkbox-cell'; -import { createImageCellGroup } from './image-cell'; -import { createRadioCellGroup } from './radio-cell'; -import { createSparkLineCellGroup } from './spark-line-cell'; -import { createVideoCellGroup } from './video-cell'; -import { createCellGroup as createTextCellGroup } from './text-cell'; -import { createProgressBarCell } from './progress-bar-cell'; -import { getAxisDomainRangeAndLabels } from '../../../layout/chart-helper/get-axis-domain'; - -export const registerChartCell = () => { - Factory.registerFunction('createChartCellGroup', createChartCellGroup); - Factory.registerFunction('getAxisDomainRangeAndLabels', getAxisDomainRangeAndLabels); -}; - -export const registerCheckboxCell = () => { - Factory.registerFunction('createCheckboxCellGroup', createCheckboxCellGroup); -}; - -export const registerImageCell = () => { - Factory.registerFunction('createImageCellGroup', createImageCellGroup); -}; - -export const registerProgressBarCell = () => { - Factory.registerFunction('createProgressBarCell', createProgressBarCell); -}; - -export const registerRadioCell = () => { - Factory.registerFunction('createRadioCellGroup', createRadioCellGroup); -}; - -export const registerSparkLineCell = () => { - Factory.registerFunction('createSparkLineCellGroup', createSparkLineCellGroup); -}; - -export const registerTextCell = () => { - Factory.registerFunction('createTextCellGroup', createTextCellGroup); -}; - -export const registerVideoCell = () => { - Factory.registerFunction('createVideoCellGroup', createVideoCellGroup); -}; diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/progress-bar-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/progress-bar-cell.ts index b19a32ddb..a1e5bf61f 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/progress-bar-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/progress-bar-cell.ts @@ -560,5 +560,3 @@ export function createProgressBarCell( } return percentCompleteBarGroup; } - -export type CreateProgressBarCell = typeof createProgressBarCell; diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts index e62c97f9a..86aaf777c 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/radio-cell.ts @@ -98,8 +98,6 @@ export function createRadioCellGroup( return cellGroup; } -export type CreateRadioCellGroup = typeof createRadioCellGroup; - function createRadio( col: number, row: number, @@ -162,7 +160,7 @@ function createRadio( lineClamp, wordBreak: 'break-word', // widthLimit: autoColWidth ? -1 : colWidth - (padding[1] + padding[3]), - heightLimit: autoRowHeight ? -1 : cellHeight - Math.floor(padding[0] + padding[2]), + heightLimit: autoRowHeight ? -1 : cellHeight - (padding[0] + padding[2]), pickable: false, dx: hierarchyOffset // whiteSpace: text.length === 1 && !autoWrapText ? 'no-wrap' : 'normal' diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/spark-line-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/spark-line-cell.ts index a7fb271f8..58dee58c5 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/spark-line-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/spark-line-cell.ts @@ -85,8 +85,6 @@ export function createSparkLineCellGroup( return cellGroup; } -export type CreateSparkLineCellGroup = typeof createSparkLineCellGroup; - function createSparkLine( col: number, row: number, diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/text-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/text-cell.ts index c6cf7f6b3..1c1b9a1e3 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/text-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/text-cell.ts @@ -144,10 +144,8 @@ export function createCellGroup( typeof lineClamp === 'number' ? lineClamp : undefined, // autoColWidth ? 0 : colWidth, // table.getRowHeight(row), - // cellWidth, - // cellHeight, - cellGroup.attribute.width, - cellGroup.attribute.height, + cellWidth, + cellHeight, textAlign, textBaseline, table, @@ -179,8 +177,6 @@ export function createCellGroup( return cellGroup; } -export type CreateTextCellGroup = typeof createCellGroup; - // /** // * @description: 获取函数式赋值的样式,记录在cellTheme中 // * @param {BaseTableAPI} table diff --git a/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts b/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts index e2b024fa1..fdeea72a7 100644 --- a/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts +++ b/packages/vtable/src/scenegraph/group-creater/cell-type/video-cell.ts @@ -11,9 +11,6 @@ import { getFunctionalProp, getProp } from '../../utils/get-prop'; import { isValid } from '@visactor/vutils'; import type { BaseTableAPI } from '../../../ts-types/base-table'; import { getCellBorderStrokeWidth } from '../../utils/cell-border-stroke-width'; -import { getQuadProps } from '../../utils/padding'; -import type { CellRange } from '../../../ts-types'; -import { dealWithIconLayout } from '../../utils/text-icon-layout'; const regedIcons = icons.get(); @@ -30,18 +27,14 @@ export function createVideoCellGroup( padding: [number, number, number, number], textAlign: CanvasTextAlign, textBaseline: CanvasTextBaseline, - mayHaveIcon: boolean, table: BaseTableAPI, cellTheme: IThemeSpec, - range: CellRange | undefined, isAsync: boolean ) { const headerStyle = table._getCellStyle(col, row); // to be fixed const functionalPadding = getFunctionalProp('padding', headerStyle, col, row, table); // const margin = getProp('padding', headerStyle, col, row, table); - if (table.options.customConfig?.imageMargin) { - padding = getQuadProps(table.options.customConfig?.imageMargin); - } else if (isValid(functionalPadding)) { + if (isValid(functionalPadding)) { padding = functionalPadding; } if (cellTheme?.text?.textAlign) { @@ -101,58 +94,6 @@ export function createVideoCellGroup( columnGroup?.addCellGroup(cellGroup); } - let cellIcons; - if (mayHaveIcon) { - let iconCol = col; - let iconRow = row; - if (range) { - iconCol = range.start.col; - iconRow = range.start.row; - } - cellIcons = table.getCellIcons(iconCol, iconRow); - } - - let iconWidth = 0; - let cellLeftIconWidth = 0; - let cellRightIconWidth = 0; - if (Array.isArray(cellIcons) && cellIcons.length !== 0) { - const { leftIconWidth, rightIconWidth, absoluteLeftIconWidth, absoluteRightIconWidth } = dealWithIconLayout( - cellIcons, - cellGroup, - range, - table - ); - - iconWidth = leftIconWidth + rightIconWidth; - cellLeftIconWidth = leftIconWidth; - cellRightIconWidth = rightIconWidth; - - // 更新各个部分横向位置 - cellGroup.forEachChildren((child: any) => { - if (child.role === 'icon-left') { - child.setAttribute('x', child.attribute.x + padding[3]); - } else if (child.role === 'icon-right') { - child.setAttribute('x', child.attribute.x + width - rightIconWidth - padding[1]); - } else if (child.role === 'icon-absolute-right') { - child.setAttribute('x', child.attribute.x + width - absoluteRightIconWidth - padding[1]); - } - }); - - // 更新各个部分纵向位置 - cellGroup.forEachChildren((child: any) => { - if (textBaseline === 'middle') { - child.setAttribute('y', (height - child.AABBBounds.height()) / 2); - } else if (textBaseline === 'bottom') { - child.setAttribute('y', height - child.AABBBounds.height() - padding[2]); - } else { - child.setAttribute('y', padding[0]); - } - }); - - (cellGroup as any)._cellLeftIconWidth = cellLeftIconWidth; - (cellGroup as any)._cellRightIconWidth = cellRightIconWidth; - } - // video const value = table.getCellValue(col, row); const video = document.createElement('video'); @@ -262,5 +203,3 @@ export function createVideoCellGroup( return cellGroup; } - -export type CreateVideoCellGroup = typeof createVideoCellGroup; diff --git a/packages/vtable/src/scenegraph/group-creater/column-helper.ts b/packages/vtable/src/scenegraph/group-creater/column-helper.ts index e8ced2208..2fe3df34b 100644 --- a/packages/vtable/src/scenegraph/group-creater/column-helper.ts +++ b/packages/vtable/src/scenegraph/group-creater/column-helper.ts @@ -99,7 +99,6 @@ export function createComplexColumn( // table.heightMode === 'autoHeight', table.isAutoRowHeight(row), [0, 0, 0, 0], - range, table ); } @@ -234,10 +233,8 @@ export function createComplexColumn( columnGroup.updateColumnHeight(rangeHeight); y += rangeHeight; } else { - // columnGroup.updateColumnHeight(cellGroup.attribute.height); - // y += cellGroup.attribute.height; - columnGroup.updateColumnHeight(cellHeight); - y += cellHeight; + columnGroup.updateColumnHeight(cellGroup.attribute.height); + y += cellGroup.attribute.height; } } if (rowLimit && row > rowLimit) { diff --git a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts index b251d645e..0755fa15f 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts @@ -76,7 +76,7 @@ export function createGroupForFirstScreen( 0, // colStart table.frozenColCount - 1, // colEnd 0, // rowStart - table.frozenRowCount - 1, // rowEnd + table.columnHeaderLevelCount - 1, // rowEnd table.isListTable() ? 'columnHeader' : 'cornerHeader', // CellType table ); @@ -91,7 +91,7 @@ export function createGroupForFirstScreen( // Math.min(proxy.firstScreenColLimit, table.colCount - 1 - table.rightFrozenColCount), // colEnd distCol - table.rightFrozenColCount, 0, // rowStart - table.frozenRowCount - 1, // rowEnd + table.columnHeaderLevelCount - 1, // rowEnd 'columnHeader', // isHeader table ); @@ -105,7 +105,7 @@ export function createGroupForFirstScreen( yOrigin, 0, // colStart table.leftRowSeriesNumberCount - 1, // colEnd - table.frozenRowCount, // rowStart + table.columnHeaderLevelCount, // rowStart // Math.min(proxy.firstScreenRowLimit, table.rowCount - 1 - table.bottomFrozenRowCount), // rowEnd distRow - table.bottomFrozenRowCount, 'rowHeader', // isHeader @@ -119,7 +119,7 @@ export function createGroupForFirstScreen( yOrigin, table.leftRowSeriesNumberCount, // colStart table.leftRowSeriesNumberCount + table.rowHeaderLevelCount - 1, // colEnd - table.frozenRowCount, // rowStart + table.columnHeaderLevelCount, // rowStart // Math.min(proxy.firstScreenRowLimit, table.rowCount - 1 - table.bottomFrozenRowCount), // rowEnd distRow - table.bottomFrozenRowCount, 'rowHeader', // isHeader @@ -133,7 +133,7 @@ export function createGroupForFirstScreen( yOrigin, table.rowHeaderLevelCount + table.leftRowSeriesNumberCount, // colStart table.frozenColCount - 1, // colEnd - table.frozenRowCount, // rowStart + table.columnHeaderLevelCount, // rowStart // Math.min(proxy.firstScreenRowLimit, table.rowCount - 1 - table.bottomFrozenRowCount), // rowEnd distRow - table.bottomFrozenRowCount, 'body', @@ -240,7 +240,7 @@ export function createGroupForFirstScreen( table.colCount - 1 - table.rightFrozenColCount + 1, // colStart table.colCount - 1, // colEnd 0, // rowStart - table.frozenRowCount - 1, // rowEnd + table.columnHeaderLevelCount - 1, // rowEnd 'columnHeader', // isHeader table ); @@ -252,7 +252,7 @@ export function createGroupForFirstScreen( yOrigin, table.colCount - 1 - table.rightFrozenColCount + 1, // colStart table.colCount - 1, // colEnd - table.frozenRowCount, // rowStart + table.columnHeaderLevelCount, // rowStart // Math.min(proxy.firstScreenRowLimit, table.rowCount - 1 - table.bottomFrozenRowCount), // rowEnd distRow - table.bottomFrozenRowCount, table.isPivotChart() ? 'rowHeader' : 'body', // isHeader @@ -284,7 +284,7 @@ export function createGroupForFirstScreen( table.frozenColCount, // colStart // Math.min(proxy.firstScreenColLimit, table.colCount - 1 - table.rightFrozenColCount), // colEnd distCol - table.rightFrozenColCount, - table.frozenRowCount, // rowStart + table.columnHeaderLevelCount, // rowStart // Math.min(proxy.firstScreenRowLimit, table.rowCount - 1 - table.bottomFrozenRowCount), // rowEnd distRow - table.bottomFrozenRowCount, 'body', // isHeader diff --git a/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts b/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts index be6b44e8f..d706711ce 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/proxy.ts @@ -15,7 +15,6 @@ import { sortHorizontal } from './update-position/sort-horizontal'; import { updateAutoColumn } from './update-position/update-auto-column'; import { getDefaultHeight, getDefaultWidth } from './default-width-height'; import { handleTextStick } from '../../stick-text'; -import type { ColumnInfo, RowInfo } from '../../../ts-types'; export class SceneProxy { table: BaseTableAPI; @@ -69,19 +68,12 @@ export class SceneProxy { this.table = table; if (this.table.isPivotChart()) { - // this.rowLimit = 100; - // this.colLimit = 100; - this.rowLimit = Math.max(100, Math.ceil((table.tableNoFrameHeight * 2) / table.defaultRowHeight)); - this.colLimit = Math.max(100, Math.ceil((table.tableNoFrameWidth * 2) / table.defaultColWidth)); + this.rowLimit = 100; + this.colLimit = 100; } else if (this.table.heightMode === 'autoHeight') { - // this.rowLimit = 100; - this.rowLimit = Math.max(100, Math.ceil((table.tableNoFrameHeight * 2) / table.defaultRowHeight)); + this.rowLimit = 100; } else if (this.table.widthMode === 'autoWidth') { - // this.colLimit = 100; - this.colLimit = Math.max(100, Math.ceil((table.tableNoFrameWidth * 2) / table.defaultColWidth)); - } else { - this.rowLimit = Math.max(200, Math.ceil((table.tableNoFrameHeight * 2) / table.defaultRowHeight)); - this.colLimit = Math.max(100, Math.ceil((table.tableNoFrameWidth * 2) / table.defaultColWidth)); + this.colLimit = 100; } if (this.table.internalProps.transpose) { @@ -107,7 +99,6 @@ export class SceneProxy { this.totalActualBodyColCount = totalActualBodyColCount; this.totalCol = this.bodyLeftCol + totalActualBodyColCount - 1; // 目标渐进完成的col this.colStart = this.bodyLeftCol; - this.colEnd = this.totalCol; // temp for first screen, will replace in createGroupForFirstScreen() const defaultColWidth = this.table.defaultColWidth; // const defaultColWidth = getDefaultHeight(this.table); this.taskColCount = Math.ceil(this.table.tableNoFrameWidth / defaultColWidth) * 1; @@ -131,7 +122,7 @@ export class SceneProxy { } setParamsForRow() { - this.bodyTopRow = this.table.frozenRowCount; + this.bodyTopRow = this.table.columnHeaderLevelCount; this.bodyBottomRow = this.table.rowCount - 1 - this.table.bottomFrozenRowCount; // this.bodyLeftCol = 0; // this.bodyRightCol = this.table.colCount - 1 - this.table.rightFrozenColCount; @@ -141,7 +132,6 @@ export class SceneProxy { this.totalActualBodyRowCount = totalActualBodyRowCount; this.totalRow = this.bodyTopRow + totalActualBodyRowCount - 1; // 目标渐进完成的row this.rowStart = this.bodyTopRow; - this.rowEnd = this.totalRow; // temp for first screen, will replace in createGroupForFirstScreen() const defaultRowHeight = this.table.defaultRowHeight; // const defaultRowHeight = getDefaultWidth(this.table); this.taskRowCount = Math.ceil(this.table.tableNoFrameHeight / defaultRowHeight) * 1; @@ -232,7 +222,6 @@ export class SceneProxy { // await this.progress(); // } else if (this.colUpdatePos <= this.colEnd) { - // console.log('progress colUpdatePos', this.colUpdatePos); await this.updateColCellGroupsAsync(); await this.progress(); } else if (this.rowUpdatePos <= this.rowEnd) { @@ -277,8 +266,6 @@ export class SceneProxy { // compute rows height computeRowsHeight(this.table, this.currentRow + 1, endRow, false); - this.rowEnd = endRow; - if (this.table.frozenColCount) { // create row header row cellGroup let maxHeight = 0; @@ -347,7 +334,9 @@ export class SceneProxy { this.table.scenegraph.bodyGroup.setAttribute('height', maxHeight); this.currentRow = endRow; + this.rowEnd = endRow; this.rowUpdatePos = this.rowEnd; + // this.referenceRow = this.rowStart + Math.floor((endRow - this.rowStart) / 2); // update container group size and border this.table.scenegraph.updateContainer(); @@ -359,8 +348,6 @@ export class SceneProxy { const endCol = Math.min(this.totalCol, this.currentCol + onceCount); computeColsWidth(this.table, this.currentCol + 1, endCol); - this.colEnd = endCol; - // update last merge cell size for (let row = 0; row < this.table.rowCount; row++) { const cellGroup = this.highPerformanceGetCell(this.currentCol, row); @@ -370,7 +357,7 @@ export class SceneProxy { } // create column - if (this.table.frozenRowCount) { + if (this.table.columnHeaderLevelCount) { // create colGroup const lastColumnGroup = ( this.table.scenegraph.colHeaderGroup.lastChild instanceof Group @@ -387,7 +374,7 @@ export class SceneProxy { this.currentCol + 1, // colStart endCol, // colEnd 0, // rowStart - this.table.frozenRowCount - 1, // rowEnd + this.table.columnHeaderLevelCount - 1, // rowEnd 'columnHeader', // isHeader this.table ); @@ -443,9 +430,13 @@ export class SceneProxy { ); this.currentCol = endCol; + this.colEnd = endCol; this.colUpdatePos = this.colEnd; + // this.referenceCol = this.colStart + Math.floor((endCol - this.colStart) / 2); + // console.log('async', this.referenceCol, this.colStart, this.colEnd); // update container group size and border + // this.table.scenegraph.updateContainerAttrWidthAndX(); this.table.scenegraph.updateContainer(); this.table.scenegraph.updateBorderSizeAndPosition(); } @@ -454,12 +445,6 @@ export class SceneProxy { const yLimitTop = this.table.getRowsHeight(this.bodyTopRow, this.bodyTopRow + (this.rowEnd - this.rowStart + 1)) / 2; const yLimitBottom = this.table.getAllRowsHeight() - yLimitTop; - - const screenTop = this.table.getTargetRowAt(y + this.table.scenegraph.colHeaderGroup.attribute.height); - if (screenTop) { - this.screenTopRow = screenTop.row; - } - if (y < yLimitTop && this.rowStart === this.bodyTopRow) { // 执行真实body group坐标修改 this.updateDeltaY(y); @@ -478,7 +463,7 @@ export class SceneProxy { this.updateBody(y - this.deltaY); } else { // 执行动态更新节点 - this.dynamicSetY(y, screenTop, isEnd); + this.dynamicSetY(y, isEnd); } } @@ -486,12 +471,6 @@ export class SceneProxy { const xLimitLeft = this.table.getColsWidth(this.bodyLeftCol, this.bodyLeftCol + (this.colEnd - this.colStart + 1)) / 2; const xLimitRight = this.table.getAllColsWidth() - xLimitLeft; - - const screenLeft = this.table.getTargetColAt(x + this.table.scenegraph.rowHeaderGroup.attribute.width); - if (screenLeft) { - this.screenLeftCol = screenLeft.col; - } - if (x < xLimitLeft && this.colStart === this.bodyLeftCol) { // 执行真实body group坐标修改 this.updateDeltaX(x); @@ -509,15 +488,15 @@ export class SceneProxy { this.table.scenegraph.setBodyAndColHeaderX(-x + this.deltaX); } else { // 执行动态更新节点 - this.dynamicSetX(x, screenLeft, isEnd); + this.dynamicSetX(x, isEnd); } } - async dynamicSetY(y: number, screenTop: RowInfo | null, isEnd = false) { - dynamicSetY(y, screenTop, isEnd, this); + async dynamicSetY(y: number, isEnd = false) { + dynamicSetY(y, isEnd, this); } - async dynamicSetX(x: number, screenLeft: ColumnInfo | null, isEnd = false) { - dynamicSetX(x, screenLeft, isEnd, this); + async dynamicSetX(x: number, isEnd = false) { + dynamicSetX(x, isEnd, this); } updateBody(y: number) { @@ -704,7 +683,7 @@ export class SceneProxy { // } if ( - row >= this.table.frozenRowCount && // not column header + row >= this.table.columnHeaderLevelCount && // not column header row < this.table.rowCount - this.table.bottomFrozenRowCount && // not bottom frozen (row < this.rowStart || row > this.rowEnd) // not in proxy row range ) { @@ -822,10 +801,10 @@ function getCellByCache(cacheCellGroup: Group, row: number): Group | null { const prev = cacheCellGroup._prev as Group; const next = cacheCellGroup._next as Group; // cacheCellGroup may have wrong order - if (cacheCellGroup.row > row && prev && prev.row === cacheCellGroup.row - 1) { + if (cacheCellGroup.row > row && prev && prev.row === row - 1) { return getCellByCache(prev, row); } - if (cacheCellGroup.row < row && next && next.row === cacheCellGroup.row + 1) { + if (cacheCellGroup.row < row && next && next.row === row + 1) { return getCellByCache(next, row); } return null; diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts index 5f43d9b36..a325b533e 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-x.ts @@ -1,4 +1,3 @@ -import type { ColumnInfo } from '../../../../ts-types'; import type { BaseTableAPI } from '../../../../ts-types/base-table'; import type { Group } from '../../../graphic/group'; import { computeColsWidth } from '../../../layout/compute-col-width'; @@ -6,12 +5,16 @@ import type { SceneProxy } from '../proxy'; import { updateAutoColumn } from './update-auto-column'; import { checkFirstColMerge, getFirstChild, getLastChild } from './util'; -export async function dynamicSetX(x: number, screenLeft: ColumnInfo | null, isEnd: boolean, proxy: SceneProxy) { +export async function dynamicSetX(x: number, isEnd: boolean, proxy: SceneProxy) { + const screenLeft = (proxy.table as BaseTableAPI).getTargetColAt( + x + proxy.table.scenegraph.rowHeaderGroup.attribute.width + ); if (!screenLeft) { return; } const screenLeftCol = screenLeft.col; const screenLeftX = screenLeft.left; + proxy.screenLeftCol = screenLeftCol; let deltaCol; if (isEnd) { @@ -199,6 +202,13 @@ function updateColGroupContent(colGroup: Group, proxy: SceneProxy) { if (!colGroup) { return; } + // colGroup.forEachChildren((cellGroup: Group) => { + // proxy.updateCellGroupContent(cellGroup); + // }); + // for (let row = (colGroup.firstChild as Group).row; row <= (colGroup.lastChild as Group).row; row++) { + // const cellGroup = proxy.highPerformanceGetCell(colGroup.col, row); + // proxy.updateCellGroupContent(cellGroup); + // } let cellGroup = colGroup.firstChild; while (cellGroup) { const newCellGroup = proxy.updateCellGroupContent(cellGroup as Group); @@ -208,26 +218,6 @@ function updateColGroupContent(colGroup: Group, proxy: SceneProxy) { colGroup.setAttribute('width', proxy.table.getColWidth(colGroup.col)); } -// update cells async -function updateColGroupContentAsync(colGroup: Group, proxy: SceneProxy) { - if (!colGroup) { - return; - } - const screenTopRow = proxy.screenTopRow; - const topRow = Math.max(proxy.bodyTopRow, screenTopRow - proxy.screenRowCount * 1); - const bottomRow = Math.min(proxy.bodyBottomRow, screenTopRow + proxy.screenRowCount * 2); - - for (let row = topRow; row <= bottomRow; row++) { - // const cellGroup = proxy.table.scenegraph.getCell(col, row); - const cellGroup = proxy.highPerformanceGetCell(colGroup.col, row, true); - proxy.updateCellGroupContent(cellGroup); - } - proxy.rowUpdatePos = proxy.rowStart; - - colGroup.needUpdate = false; - colGroup.setAttribute('width', proxy.table.getColWidth(colGroup.col)); -} - function updatePartColPosition(startCol: number, endCol: number, direction: 'left' | 'right', proxy: SceneProxy) { for (let col = startCol; col <= endCol; col++) { if ( @@ -275,6 +265,9 @@ function updateColPosition(containerGroup: Group, direction: 'left' | 'right', p export function updateColContent(syncLeftCol: number, syncRightCol: number, proxy: SceneProxy) { for (let col = syncLeftCol; col <= syncRightCol; col++) { + const colGroup = proxy.table.scenegraph.getColGroup(col); + colGroup && updateColGroupContent(colGroup, proxy); + const colHeaderColGroup = proxy.table.scenegraph.getColGroup(col, true); colHeaderColGroup && updateColGroupContent(colHeaderColGroup, proxy); @@ -286,11 +279,7 @@ export function updateColContent(syncLeftCol: number, syncRightCol: number, prox const rightBottomColGroup = proxy.table.scenegraph.getColGroupInRightBottomCorner(col); rightBottomColGroup && updateColGroupContent(rightBottomColGroup, proxy); - - const colGroup = proxy.table.scenegraph.getColGroup(col); - colGroup && updateColGroupContentAsync(colGroup, proxy); } - proxy.progress(); } function updateAllColPosition(distStartColY: number, count: number, direction: 'left' | 'right', proxy: SceneProxy) { diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts index a51c21d1c..7c3930eb6 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/dynamic-set-y.ts @@ -1,16 +1,18 @@ -import type { RowInfo } from '../../../../ts-types'; import type { Group } from '../../../graphic/group'; import { computeRowsHeight } from '../../../layout/compute-row-height'; import type { SceneProxy } from '../proxy'; import { updateAutoRow } from './update-auto-row'; -export async function dynamicSetY(y: number, screenTop: RowInfo | null, isEnd: boolean, proxy: SceneProxy) { +export async function dynamicSetY(y: number, isEnd: boolean, proxy: SceneProxy) { + // 计算变动row range + // const screenTopRow = proxy.table.getRowAt(y).row; + const screenTop = (proxy.table as any).getTargetRowAt(y + proxy.table.scenegraph.colHeaderGroup.attribute.height); if (!screenTop) { return; } const screenTopRow = screenTop.row; const screenTopY = screenTop.top; - + proxy.screenTopRow = screenTopRow; let deltaRow; if (isEnd) { deltaRow = proxy.bodyBottomRow - proxy.rowEnd; @@ -106,8 +108,7 @@ async function moveCell( proxy.rowStart = direction === 'up' ? proxy.rowStart + count : proxy.rowStart - count; proxy.rowEnd = direction === 'up' ? proxy.rowEnd + count : proxy.rowEnd - count; - // 本次行更新是否同步完成,列数超过limit时为false - const sync = updateRowContent(syncTopRow, syncBottomRow, proxy, true); + updateRowContent(syncTopRow, syncBottomRow, proxy); if (proxy.table.heightMode === 'autoHeight') { // body group @@ -167,7 +168,7 @@ async function moveCell( proxy.referenceRow = proxy.rowStart + Math.floor((proxy.rowEnd - proxy.rowStart) / 2); // proxy.referenceRow = screenTopRow; // proxy.rowUpdatePos = Math.min(proxy.rowUpdatePos, distStartRow); - if (proxy.table.heightMode === 'autoHeight' && sync) { + if (proxy.table.heightMode === 'autoHeight') { proxy.rowUpdatePos = Math.min(proxy.rowUpdatePos, proxy.rowEnd + 1); } else { proxy.rowUpdatePos = Math.min(proxy.rowUpdatePos, distStartRow); @@ -175,7 +176,9 @@ async function moveCell( proxy.rowUpdateDirection = direction; proxy.table.scenegraph.updateNextFrame(); - await proxy.progress(); + if (proxy.table.heightMode !== 'autoHeight') { + await proxy.progress(); + } } else { const distStartRow = direction === 'up' ? proxy.rowStart + count : proxy.rowStart - count; const distEndRow = direction === 'up' ? proxy.rowEnd + count : proxy.rowEnd - count; @@ -199,7 +202,7 @@ async function moveCell( proxy.rowStart = distStartRow; proxy.rowEnd = distEndRow; - const sync = updateRowContent(syncTopRow, syncBottomRow, proxy, true); + updateRowContent(syncTopRow, syncBottomRow, proxy); if (proxy.table.heightMode === 'autoHeight') { // body group @@ -260,7 +263,7 @@ async function moveCell( ); proxy.referenceRow = proxy.rowStart + Math.floor((proxy.rowEnd - proxy.rowStart) / 2); // proxy.referenceRow = screenTopRow; - if (proxy.table.heightMode === 'autoHeight' && sync) { + if (proxy.table.heightMode === 'autoHeight') { proxy.rowUpdatePos = proxy.rowEnd + 1; } else { proxy.rowUpdatePos = proxy.rowStart; @@ -268,7 +271,9 @@ async function moveCell( proxy.rowUpdateDirection = distEndRow > proxy.bodyBottomRow - (proxy.rowEnd - proxy.rowStart + 1) ? 'down' : 'up'; proxy.table.scenegraph.updateNextFrame(); - await proxy.progress(); + if (proxy.table.heightMode !== 'autoHeight') { + await proxy.progress(); + } } } @@ -371,7 +376,7 @@ function updateAllRowPosition(distStartRowY: number, count: number, direction: ' } } -export function updateRowContent(syncTopRow: number, syncBottomRow: number, proxy: SceneProxy, async = false) { +export function updateRowContent(syncTopRow: number, syncBottomRow: number, proxy: SceneProxy) { // row header group for (let col = 0; col < proxy.table.frozenColCount; col++) { for (let row = syncTopRow; row <= syncBottomRow; row++) { @@ -389,18 +394,7 @@ export function updateRowContent(syncTopRow: number, syncBottomRow: number, prox } } // body group - let leftCol = proxy.bodyLeftCol; - let rightCol = proxy.bodyRightCol; - let sync = true; - if (async) { - const screenLeftCol = proxy.screenLeftCol; - leftCol = Math.max(proxy.bodyLeftCol, screenLeftCol - proxy.screenColCount * 1); - rightCol = Math.min(proxy.bodyRightCol, screenLeftCol + proxy.screenColCount * 2); - if (leftCol !== proxy.bodyLeftCol || rightCol !== proxy.bodyRightCol) { - sync = false; - } - } - for (let col = leftCol; col <= rightCol; col++) { + for (let col = proxy.bodyLeftCol; col <= proxy.bodyRightCol; col++) { for (let row = syncTopRow; row <= syncBottomRow; row++) { // const cellGroup = proxy.table.scenegraph.getCell(col, row); const cellGroup = proxy.highPerformanceGetCell(col, row); @@ -408,6 +402,4 @@ export function updateRowContent(syncTopRow: number, syncBottomRow: number, prox } } proxy.table.scenegraph.updateNextFrame(); - - return sync; } diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-horizontal.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-horizontal.ts index f52e87eb2..ce6cdb98d 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-horizontal.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-horizontal.ts @@ -14,13 +14,6 @@ export async function sortHorizontal(proxy: SceneProxy) { }); } }); - - // 更新同步范围 - const syncLeftCol = Math.max(proxy.bodyLeftCol, proxy.screenLeftCol - proxy.screenColCount * 1); - const syncRightCol = Math.min(proxy.bodyRightCol, proxy.screenLeftCol + proxy.screenColCount * 2); - - computeColsWidth(proxy.table, syncLeftCol, syncRightCol); - for (let col = proxy.colStart; col <= proxy.colEnd; col++) { // 将该列的chartInstance清除掉 const columnGroup = proxy.table.scenegraph.getColGroup(col); @@ -40,6 +33,11 @@ export async function sortHorizontal(proxy: SceneProxy) { proxy.table.scenegraph.updateCellContent(col, row); } } + // 更新同步范围 + const syncLeftCol = Math.max(proxy.bodyLeftCol, proxy.screenLeftCol - proxy.screenColCount * 1); + const syncRightCol = Math.min(proxy.bodyRightCol, proxy.screenLeftCol + proxy.screenColCount * 2); + + computeColsWidth(proxy.table, syncLeftCol, syncRightCol); updateColContent(syncLeftCol, syncRightCol, proxy); diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-vertical.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-vertical.ts index 6f8a21d3d..1dd54ec48 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-vertical.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/sort-vertical.ts @@ -15,28 +15,6 @@ export async function sortVertical(proxy: SceneProxy) { } }); - // 更新同步范围 - let syncTopRow; - let syncBottomRow; - if (proxy.table.heightMode === 'autoHeight') { - syncTopRow = proxy.rowStart; - syncBottomRow = proxy.rowEnd; - } else { - syncTopRow = Math.max(proxy.bodyTopRow, proxy.screenTopRow - proxy.screenRowCount * 1); - syncBottomRow = Math.min(proxy.bodyBottomRow, proxy.screenTopRow + proxy.screenRowCount * 2); - } - // console.log('sort更新同步范围', syncTopRow, syncBottomRow); - - const oldBodyHeight = proxy.table.getAllRowsHeight(); - - computeRowsHeight(proxy.table, syncTopRow, syncBottomRow); - - const newBodyHeight = proxy.table.getAllRowsHeight(); - - if (oldBodyHeight !== newBodyHeight) { - proxy.table.scenegraph.updateContainerHeight(proxy.table.frozenRowCount, newBodyHeight - oldBodyHeight); - } - for (let col = 0; col < proxy.table.frozenColCount ?? 0; col++) { // 将该列的chartInstance清除掉 const columnGroup = proxy.table.scenegraph.getColGroup(col); @@ -68,6 +46,28 @@ export async function sortVertical(proxy: SceneProxy) { } } + // 更新同步范围 + let syncTopRow; + let syncBottomRow; + if (proxy.table.heightMode === 'autoHeight') { + syncTopRow = proxy.rowStart; + syncBottomRow = proxy.rowEnd; + } else { + syncTopRow = Math.max(proxy.bodyTopRow, proxy.screenTopRow - proxy.screenRowCount * 1); + syncBottomRow = Math.min(proxy.bodyBottomRow, proxy.screenTopRow + proxy.screenRowCount * 2); + } + // console.log('sort更新同步范围', syncTopRow, syncBottomRow); + + const oldBodyHeight = proxy.table.getAllRowsHeight(); + + computeRowsHeight(proxy.table, syncTopRow, syncBottomRow); + + const newBodyHeight = proxy.table.getAllRowsHeight(); + + if (oldBodyHeight !== newBodyHeight) { + proxy.table.scenegraph.updateContainerHeight(proxy.table.frozenRowCount, newBodyHeight - oldBodyHeight); + } + updateRowContent(syncTopRow, syncBottomRow, proxy); if (proxy.table.heightMode === 'autoHeight') { diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts index dda7e6aff..cfe38d2cf 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/update-auto-row.ts @@ -11,13 +11,12 @@ export function updateAutoRow( direction: 'up' | 'down' = 'up', part?: boolean ) { - // return; // 更新y位置 if (direction === 'up') { for (let col = colStart; col <= colEnd; col++) { for (let row = rowStart; row <= rowEnd; row++) { const cellGroup = table.scenegraph.highPerformanceGetCell(col, row, true); - if (cellGroup.role !== 'cell' || !cellGroup.row) { + if (!cellGroup.row) { continue; } let y; @@ -28,13 +27,13 @@ export function updateAutoRow( const baseCellGroup = table.scenegraph.highPerformanceGetCell(col, rowEnd + 1, true); y = baseCellGroup.attribute.y; if (isValid(y)) { - for (let r = row; r <= rowEnd; r++) { + for (let r = rowStart; r <= rowEnd; r++) { y -= table.getRowHeight(r); } } } else { // 估计位置 - y = table.getRowsHeight(table.frozenRowCount, cellGroup.row - 1); + y = table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row - 1); } if (isValid(y)) { cellGroup.setAttribute('y', y); @@ -45,7 +44,7 @@ export function updateAutoRow( for (let col = colStart; col <= colEnd; col++) { for (let row = rowEnd; row >= rowStart; row--) { const cellGroup = table.scenegraph.highPerformanceGetCell(col, row, true); - if (cellGroup.role !== 'cell' || !cellGroup.row) { + if (!cellGroup.row) { continue; } let y; @@ -55,18 +54,15 @@ export function updateAutoRow( } else if (part) { const baseCellGroup = table.scenegraph.highPerformanceGetCell(col, rowStart - 1, true); y = baseCellGroup.attribute.y; - for (let r = rowStart - 1; r < row; r++) { - const height = table.getRowHeight(r); - y += height; + for (let r = rowStart - 1; r < rowEnd; r++) { + y += table.getRowHeight(r); } } else { // 估计位置 - y = table.getRowsHeight(table.frozenRowCount, cellGroup.row - 1); - // console.log('估计位置', table.getRowsHeight(table.frozenRowCount, cellGroup.row)); - } - if (isValid(y)) { - cellGroup.setAttribute('y', y); + y = table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row - 1); + // console.log('估计位置', table.getRowsHeight(table.columnHeaderLevelCount, cellGroup.row)); } + cellGroup.setAttribute('y', y); } } } @@ -77,20 +73,11 @@ export function updateAutoRow( table.scenegraph.proxy.bodyBottomRow - table.scenegraph.proxy.bodyTopRow + 1 ); // 渐进加载总row数量 - const totalBodyHeight = table.getRowsHeight(table.frozenRowCount, table.frozenRowCount + totalActualBodyRowCount); - const totalHeight = table.getRowsHeight(table.frozenRowCount, table.rowCount - 1); + const totalBodyHeight = table.getRowsHeight( + table.columnHeaderLevelCount, + table.columnHeaderLevelCount + totalActualBodyRowCount + ); + const totalHeight = table.getRowsHeight(table.columnHeaderLevelCount, table.rowCount - 1); table.scenegraph.proxy.yLimitTop = totalBodyHeight / 2; table.scenegraph.proxy.yLimitBottom = totalHeight - totalBodyHeight / 2; - - // // check - // const columnGroup = table.scenegraph.bodyGroup.firstChild; - // let y; - // columnGroup.forEachChildren(child => { - // if (!isValid(y)) { - // y = child.attribute.y + child.attribute.height; - // } else if (child.attribute.y !== y) { - // debugger; - // } - // y = child.attribute.y + child.attribute.height; - // }); } diff --git a/packages/vtable/src/scenegraph/group-creater/progress/update-position/util.ts b/packages/vtable/src/scenegraph/group-creater/progress/update-position/util.ts index 79788d12f..3e510473b 100644 --- a/packages/vtable/src/scenegraph/group-creater/progress/update-position/util.ts +++ b/packages/vtable/src/scenegraph/group-creater/progress/update-position/util.ts @@ -28,7 +28,10 @@ export function checkFirstRowMerge(row: number, proxy: SceneProxy) { newCellGroup.col = col; newCellGroup.row = row; - newCellGroup.setAttribute('y', proxy.table.getRowsHeight(proxy.table.frozenRowCount, range.start.row - 1)); + newCellGroup.setAttribute( + 'y', + proxy.table.getRowsHeight(proxy.table.columnHeaderLevelCount, range.start.row - 1) + ); oldCellGroup.parent.insertAfter(newCellGroup, oldCellGroup); oldCellGroup.parent.removeChild(oldCellGroup); @@ -47,7 +50,7 @@ export function checkFirstRowMerge(row: number, proxy: SceneProxy) { export function checkFirstColMerge(col: number, proxy: SceneProxy) { for (let row = 0; row < proxy.table.rowCount; row++) { if ( - (row >= proxy.table.frozenRowCount && row < proxy.rowStart) || + (row >= proxy.table.columnHeaderLevelCount && row < proxy.rowStart) || (row > proxy.rowEnd && row < proxy.table.rowCount - proxy.table.bottomFrozenRowCount) ) { continue; @@ -101,7 +104,7 @@ function clearHadMergedRow(rowStart: number, rowEnd: number, col: number, proxy: cellGroup.setAttributes({ width: 0, height: proxy.table.getRowHeight(cellGroup.row), - y: proxy.table.getRowsHeight(proxy.table.frozenRowCount, cellGroup.row - 1), + y: proxy.table.getRowsHeight(proxy.table.columnHeaderLevelCount, cellGroup.row - 1), x: 0 }); cellGroup.clear(); diff --git a/packages/vtable/src/scenegraph/icon/icon-update.ts b/packages/vtable/src/scenegraph/icon/icon-update.ts index 7da4ee306..c034b1221 100644 --- a/packages/vtable/src/scenegraph/icon/icon-update.ts +++ b/packages/vtable/src/scenegraph/icon/icon-update.ts @@ -137,7 +137,7 @@ export function setIconHoverStyle(baseIcon: Icon, col: number, row: number, cell iconBack.setAttributes({ x: (icon.attribute.x ?? 0) + - // (icon.attribute.dx ?? 0) + + (icon.attribute.dx ?? 0) + (icon.AABBBounds.width() - icon.backgroundWidth) / 2, y: (icon.attribute.y ?? 0) + (icon.AABBBounds.height() - icon.backgroundHeight) / 2, dx: icon.attribute.dx ?? 0, @@ -152,7 +152,7 @@ export function setIconHoverStyle(baseIcon: Icon, col: number, row: number, cell iconBack = createRect({ x: (icon.attribute.x ?? 0) + - // (icon.attribute.dx ?? 0) + + (icon.attribute.dx ?? 0) + (icon.AABBBounds.width() - icon.backgroundWidth) / 2, y: (icon.attribute.y ?? 0) + (icon.AABBBounds.height() - icon.backgroundHeight) / 2, dx: icon.attribute.dx ?? 0, @@ -194,7 +194,6 @@ export function setIconHoverStyle(baseIcon: Icon, col: number, row: number, cell }, placement: baseIcon.tooltip.placement }, - disappearDelay: baseIcon.tooltip.disappearDelay, style: Object.assign({}, scene.table.internalProps.theme?.tooltipStyle, baseIcon.tooltip?.style) }; if (!scene.table.internalProps.tooltipHandler.isBinded(tooltipOptions)) { diff --git a/packages/vtable/src/scenegraph/layout/compute-col-width.ts b/packages/vtable/src/scenegraph/layout/compute-col-width.ts index f7031bad5..aeebaa40d 100644 --- a/packages/vtable/src/scenegraph/layout/compute-col-width.ts +++ b/packages/vtable/src/scenegraph/layout/compute-col-width.ts @@ -14,10 +14,10 @@ import { getQuadProps } from '../utils/padding'; import { getProp } from '../utils/get-prop'; import type { BaseTableAPI, HeaderData } from '../../ts-types/base-table'; import type { PivotHeaderLayoutMap } from '../../layout/pivot-header-layout'; -import type { ComputeAxisComponentWidth } from '../../components/axis/get-axis-component-size'; -import { Factory } from '../../core/factory'; +import { getAxisConfigInPivotChart } from '../../layout/chart-helper/get-axis-config'; +import { computeAxisComponentWidth } from '../../components/axis/get-axis-component-size'; import { Group as VGroup } from '@src/vrender'; -import { isArray, isFunction, isNumber, isObject, isValid } from '@visactor/vutils'; +import { isArray, isNumber, isObject, isValid } from '@visactor/vutils'; import { decodeReactDom, dealPercentCalc } from '../component/custom'; import { breakString } from '../utils/break-string'; @@ -301,9 +301,8 @@ function computeAutoColWidth( // 判断透视图轴组件 if (table.isPivotChart()) { const layout = table.internalProps.layoutMap as PivotHeaderLayoutMap; - const axisConfig = layout.getAxisConfigInPivotChart(col, row); + const axisConfig = getAxisConfigInPivotChart(col, row, layout); if (axisConfig) { - const computeAxisComponentWidth: ComputeAxisComponentWidth = Factory.getFunction('computeAxisComponentWidth'); const axisWidth = computeAxisComponentWidth(axisConfig, table); if (typeof axisWidth === 'number') { maxWidth = Math.max(axisWidth, maxWidth); @@ -364,15 +363,9 @@ function computeAutoColWidth( if ((hd as HeaderData)?.define?.columnWidthComputeMode === 'only-body') { continue; } - if (isValid((hd as HeaderData)?.hierarchyLevel)) { + if ((hd as HeaderData)?.hierarchyLevel) { cellHierarchyIndent = ((hd as HeaderData).hierarchyLevel ?? 0) * ((layoutMap as PivotHeaderLayoutMap).rowHierarchyIndent ?? 0); - if ( - (layoutMap as PivotHeaderLayoutMap).rowHierarchyTextStartAlignment && - !table.internalProps.headerHelper.getHierarchyIcon(col, row) - ) { - cellHierarchyIndent += table.internalProps.headerHelper.getHierarchyIconWidth(); - } } } else { deltaRow = prepareDeltaRow; @@ -386,12 +379,6 @@ function computeAutoColWidth( Array.isArray(indexArr) && table.getHierarchyState(col, row) !== HierarchyState.none ? (indexArr.length - 1) * ((layoutMap as SimpleHeaderLayoutMap).hierarchyIndent ?? 0) : 0; - if ( - (layoutMap as SimpleHeaderLayoutMap).hierarchyTextStartAlignment && - !table.internalProps.bodyHelper.getHierarchyIcon(col, row) - ) { - cellHierarchyIndent += table.internalProps.headerHelper.getHierarchyIconWidth(); - } } } @@ -418,10 +405,6 @@ function computeAutoColWidth( return colMinWidth; } else if (maxWidth > colMaxWidth) { return colMaxWidth; - } else if (maxWidth <= 0) { - // In the case of partially hiding the header, the width calculation may be 0. - // In this case, the default value is used to prevent it from being unable to be displayed - maxWidth = table.defaultColWidth; } return maxWidth; } @@ -457,7 +440,7 @@ function computeCustomRenderWidth(col: number, row: number, table: BaseTableAPI) rect: getCellRect(col, row, table), table }; - if (isFunction(customLayout)) { + if (customLayout) { // 处理customLayout const customLayoutObj = customLayout(arg); if (customLayoutObj.rootContainer instanceof VGroup) { @@ -470,8 +453,6 @@ function computeCustomRenderWidth(col: number, row: number, table: BaseTableAPI) enableCellPadding = customLayoutObj.enableCellPadding; } else { width = 0; - renderDefault = customLayoutObj.renderDefault; - enableCellPadding = customLayoutObj.enableCellPadding; } } else if (typeof customRender === 'function') { // 处理customRender @@ -482,7 +463,6 @@ function computeCustomRenderWidth(col: number, row: number, table: BaseTableAPI) width = customRender?.expectedWidth ?? 0; renderDefault = customRender?.renderDefault; } - width = Math.ceil(width); if (enableCellPadding) { const actStyle = table._getCellStyle(col, row); const padding = getQuadProps(getProp('padding', actStyle, col, row, table)); @@ -594,11 +574,11 @@ function computeTextWidth(col: number, row: number, cellType: ColumnTypeOption, } else { text = cellValue; } - const lines = breakString(text, table).text; + const lines = breakString(text, table); if (lines.length >= 1) { // eslint-disable-next-line no-loop-func lines.forEach((line: string) => { - const width = table.measureText(line, { + const width = table.measureText(line.slice(0, table.options.maxCharactersNumber || 200), { fontSize, fontFamily, fontWeight @@ -693,8 +673,6 @@ export function getAdaptiveWidth( ) { let actualWidth = 0; const adaptiveColumns: number[] = []; - const sparklineColumns = []; - let totalSparklineAbleWidth = 0; for (let col = startCol; col < endColPlus1; col++) { const width = update ? newWidths[col] : table.getColWidth(col); const maxWidth = table.getMaxColWidth(col); @@ -706,40 +684,10 @@ export function getAdaptiveWidth( // fixed width, do not adaptive totalDrawWidth -= width; } - - if (table.options.customConfig?.shrinkSparklineFirst) { - const bodyCellType = table.getBodyColumnType(col, 0); - if (bodyCellType === 'sparkline') { - sparklineColumns.push({ col, width }); - totalSparklineAbleWidth += width - table.defaultColWidth; - } - } } const factor = totalDrawWidth / actualWidth; - if ( - table.options.customConfig?.shrinkSparklineFirst && - factor < 1 && - actualWidth - totalDrawWidth < totalSparklineAbleWidth - ) { - // only shrink sparkline column - for (let i = 0; i < sparklineColumns.length; i++) { - const { col, width } = sparklineColumns[i]; - const deltaWidth = (actualWidth - totalDrawWidth) / sparklineColumns.length; - const colWidth = Math.floor(width - deltaWidth); - - if (update) { - newWidths[col] = table._adjustColWidth(col, colWidth); - } else if (fromScenegraph) { - table.scenegraph.setColWidth(col, table._adjustColWidth(col, colWidth)); - } else { - table._setColWidth(col, table._adjustColWidth(col, colWidth), false, true); - } - } - return; - } - for (let i = 0; i < adaptiveColumns.length; i++) { const col = adaptiveColumns[i]; let colWidth; diff --git a/packages/vtable/src/scenegraph/layout/compute-row-height.ts b/packages/vtable/src/scenegraph/layout/compute-row-height.ts index 8ae8a201f..b9cbdd448 100644 --- a/packages/vtable/src/scenegraph/layout/compute-row-height.ts +++ b/packages/vtable/src/scenegraph/layout/compute-row-height.ts @@ -8,9 +8,9 @@ import type { ColumnData, ColumnDefine, TextColumnDefine } from '../../ts-types/ import { getProp } from '../utils/get-prop'; import { getQuadProps } from '../utils/padding'; import { dealWithRichTextIcon } from '../utils/text-icon-layout'; -import type { ComputeAxisComponentHeight } from '../../components/axis/get-axis-component-size'; -import { Factory } from '../../core/factory'; -import { isArray, isFunction, isNumber, isObject, isValid } from '@visactor/vutils'; +import { getAxisConfigInPivotChart } from '../../layout/chart-helper/get-axis-config'; +import { computeAxisComponentHeight } from '../../components/axis/get-axis-component-size'; +import { isArray, isNumber, isObject, isValid } from '@visactor/vutils'; import { CheckBox } from '@visactor/vrender-components'; import { decodeReactDom, dealPercentCalc } from '../component/custom'; import { getCellMergeRange } from '../../tools/merge-range'; @@ -351,10 +351,8 @@ export function computeRowHeight(row: number, startCol: number, endCol: number, // Axis component height calculation if (table.isPivotChart()) { const layout = table.internalProps.layoutMap as PivotHeaderLayoutMap; - const axisConfig = layout.getAxisConfigInPivotChart(col, row); + const axisConfig = getAxisConfigInPivotChart(col, row, layout); if (axisConfig) { - const computeAxisComponentHeight: ComputeAxisComponentHeight = - Factory.getFunction('computeAxisComponentHeight'); const axisWidth = computeAxisComponentHeight(axisConfig, table); if (typeof axisWidth === 'number') { maxHeight = isValid(maxHeight) ? Math.max(axisWidth, maxHeight) : axisWidth; @@ -504,9 +502,6 @@ function fillRowsHeight( table: BaseTableAPI, newHeights: number[] | undefined ) { - if (table.internalProps.useOneRowHeightFillAll) { - return; - } for (let row = startRow; row <= endRow; row++) { if (newHeights) { newHeights[row] = height; @@ -514,7 +509,6 @@ function fillRowsHeight( table._setRowHeight(row, height); } } - table.internalProps.useOneRowHeightFillAll = true; } /** @@ -548,7 +542,7 @@ function computeCustomRenderHeight(col: number, row: number, table: BaseTableAPI rect: getCellRect(col, row, table), table }; - if (isFunction(customLayout)) { + if (customLayout) { // 处理customLayout const customLayoutObj = customLayout(arg); if (customLayoutObj.rootContainer instanceof VGroup) { @@ -560,8 +554,6 @@ function computeCustomRenderHeight(col: number, row: number, table: BaseTableAPI enableCellPadding = customLayoutObj.enableCellPadding; } else { height = 0; - renderDefault = customLayoutObj.renderDefault; - enableCellPadding = customLayoutObj.enableCellPadding; } } else if (typeof customRender === 'function') { // 处理customRender @@ -659,7 +651,6 @@ function computeTextHeight(col: number, row: number, cellType: ColumnTypeOption, const lineHeight = getProp('lineHeight', actStyle, col, row, table) ?? fontSize; const fontFamily = getProp('fontFamily', actStyle, col, row, table); const autoWrapText = getProp('autoWrapText', actStyle, col, row, table); - const lineClamp = getProp('lineClamp', actStyle, col, row, table); let text; if ( cellType !== 'text' && @@ -683,7 +674,6 @@ function computeTextHeight(col: number, row: number, cellType: ColumnTypeOption, fontWeight, fontFamily, lineHeight, - lineClamp, padding, table ); @@ -701,14 +691,13 @@ function computeTextHeight(col: number, row: number, cellType: ColumnTypeOption, fontWeight, fontFamily, lineHeight, - lineClamp, padding, table ); } else { // text text = cellValue; - const lines = breakString(text, table).text; + const lines = breakString(text, table); const cellWidth = table.getColsWidth(col, endCol); if (iconInlineFront.length || iconInlineEnd.length) { @@ -760,17 +749,12 @@ function computeTextHeight(col: number, row: number, cellType: ColumnTypeOption, fontFamily, lineHeight, wordBreak: 'break-word', - whiteSpace: lines.length === 1 && !autoWrapText ? 'no-wrap' : 'normal', - lineClamp + whiteSpace: lines.length === 1 && !autoWrapText ? 'no-wrap' : 'normal' }); maxHeight = bounds.height() || (typeof lineHeight === 'number' ? lineHeight : fontSize); } else { // autoWrapText = false - if (table.options.customConfig?.multilinesForXTable) { - maxHeight = lineHeight; - } else { - maxHeight = lines.length * lineHeight; - } + maxHeight = lines.length * lineHeight; } } return (Math.max(maxHeight, iconHeight) + padding[0] + padding[2]) / spanRow; diff --git a/packages/vtable/src/scenegraph/layout/frozen.ts b/packages/vtable/src/scenegraph/layout/frozen.ts index e028d6c9a..e6124c84a 100644 --- a/packages/vtable/src/scenegraph/layout/frozen.ts +++ b/packages/vtable/src/scenegraph/layout/frozen.ts @@ -17,9 +17,6 @@ export function dealFrozen(scene: Scenegraph) { } } else if (scene.table.frozenColCount < scene.table.rowHeaderLevelCount) { // move columnGroup from rowHeaderGroup into bodyGroup(from cornerHeaderGroup into colHeaderGroup) - scene.bodyGroup.setAttribute('height', scene.rowHeaderGroup.attribute.height); - scene.bodyGroup.setAttribute('y', scene.rowHeaderGroup.attribute.y); - scene.colHeaderGroup.setAttribute('height', scene.cornerHeaderGroup.attribute.height); for (let i = 0; i < scene.table.rowHeaderLevelCount - scene.table.frozenColCount; i++) { moveColumnFromRowHeaderToBody(scene); moveColumnFromCornerHeaderToColHeader(scene); @@ -50,9 +47,6 @@ export function dealFrozen(scene: Scenegraph) { export function resetFrozen(scene: Scenegraph) { if (scene.frozenColCount > scene.table.frozenColCount) { // move columnGroup from rowHeaderGroup into bodyGroup(from cornerHeaderGroup into colHeaderGroup) - scene.bodyGroup.setAttribute('height', scene.rowHeaderGroup.attribute.height); - scene.bodyGroup.setAttribute('y', scene.rowHeaderGroup.attribute.y); - scene.colHeaderGroup.setAttribute('height', scene.cornerHeaderGroup.attribute.height); for (let i = 0; i < scene.frozenColCount - scene.table.frozenColCount; i++) { moveColumnFromRowHeaderToBody(scene); moveColumnFromCornerHeaderToColHeader(scene); @@ -72,7 +66,7 @@ export function resetFrozen(scene: Scenegraph) { scene.deleteAllSelectBorder(); scene.table.stateManager.select.ranges.forEach(range => { - scene.updateCellSelectBorder(range); + scene.updateCellSelectBorder(range.start.col, range.start.row, range.end.col, range.end.row); }); // scene.frozenColCount = scene.rowHeaderGroup.childrenCount; diff --git a/packages/vtable/src/scenegraph/layout/height-util.ts b/packages/vtable/src/scenegraph/layout/height-util.ts index 111327c75..b9eaf8df6 100644 --- a/packages/vtable/src/scenegraph/layout/height-util.ts +++ b/packages/vtable/src/scenegraph/layout/height-util.ts @@ -21,7 +21,6 @@ export function computeCheckboxCellHeight( fontWeight: string, fontFamily: string, lineHeight: number, - lineClamp: number | undefined, padding: [number, number, number, number], table: BaseTableAPI ) { @@ -42,8 +41,7 @@ export function computeCheckboxCellHeight( fontWeight, fontFamily, lineHeight, - wordBreak: 'break-word', - lineClamp + wordBreak: 'break-word' }, icon: { width: Math.floor(size / 1.4), // icon : box => 10 : 14 @@ -77,7 +75,6 @@ export function computeRadioCellHeight( fontWeight: string, fontFamily: string, lineHeight: number, - lineClamp: number | undefined, padding: [number, number, number, number], table: BaseTableAPI ) { @@ -103,7 +100,6 @@ export function computeRadioCellHeight( fontWeight, fontFamily, lineHeight, - lineClamp, padding, table ); @@ -128,7 +124,6 @@ export function computeRadioCellHeight( fontWeight, fontFamily, lineHeight, - lineClamp, padding, table ); @@ -151,7 +146,6 @@ export function computeRadioCellHeight( fontWeight, fontFamily, lineHeight, - lineClamp, padding, table ); @@ -170,7 +164,6 @@ export function computeSingleRadioCellHeight( fontWeight: string, fontFamily: string, lineHeight: number, - lineClamp: number | undefined, padding: [number, number, number, number], table: BaseTableAPI ) { @@ -196,8 +189,7 @@ export function computeSingleRadioCellHeight( fontWeight, fontFamily, lineHeight, - wordBreak: 'break-word', - lineClamp + wordBreak: 'break-word' }, circle: { outerRadius diff --git a/packages/vtable/src/scenegraph/layout/update-height.ts b/packages/vtable/src/scenegraph/layout/update-height.ts index 89be8e15b..c566d1cc1 100644 --- a/packages/vtable/src/scenegraph/layout/update-height.ts +++ b/packages/vtable/src/scenegraph/layout/update-height.ts @@ -1,14 +1,14 @@ import type { ProgressBarStyle } from '../../body-helper/style/ProgressBarStyle'; import type { Group } from '../graphic/group'; -import type { CreateProgressBarCell } from '../group-creater/cell-type/progress-bar-cell'; -import type { CreateSparkLineCellGroup } from '../group-creater/cell-type/spark-line-cell'; +import { createProgressBarCell } from '../group-creater/cell-type/progress-bar-cell'; +import { createSparkLineCellGroup } from '../group-creater/cell-type/spark-line-cell'; import type { Scenegraph } from '../scenegraph'; import { getCellMergeInfo } from '../utils/get-cell-merge'; import { getProp } from '../utils/get-prop'; import { getQuadProps } from '../utils/padding'; import { updateCellContentHeight } from '../utils/text-icon-layout'; import type { IProgressbarColumnBodyDefine } from '../../ts-types/list-table/define/progressbar-define'; -import { CUSTOM_CONTAINER_NAME, CUSTOM_MERGE_CONTAINER_NAME, dealWithCustom } from '../component/custom'; +import { dealWithCustom } from '../component/custom'; import { updateImageCellContentWhileResize } from '../group-creater/cell-type/image-cell'; import { getStyleTheme } from '../../core/tableHelper'; import { isMergeCellGroup } from '../utils/is-merge-cell-group'; @@ -17,7 +17,6 @@ import { resizeCellGroup, getCustomCellMergeCustom } from '../group-creater/cell import type { IGraphic } from '@src/vrender'; import { getCellMergeRange } from '../../tools/merge-range'; import type { ColumnDefine } from '../../ts-types'; -import { Factory } from '../../core/factory'; export function updateRowHeight(scene: Scenegraph, row: number, detaY: number, skipTableHeightMap?: boolean) { // 更新table行高存储 @@ -45,13 +44,13 @@ export function updateRowHeight(scene: Scenegraph, row: number, detaY: number, s let rowStart = 0; let rowEnd = 0; // 更新header 高度 - if (row < scene.table.frozenRowCount) { + if (row < scene.table.columnHeaderLevelCount) { // scene.colHeaderGroup.setAttribute('height', scene.colHeaderGroup.attribute.height + detaY); // scene.rowHeaderGroup.setAttribute('y', scene.rowHeaderGroup.attribute.y + detaY); // scene.bodyGroup.setAttribute('y', scene.bodyGroup.attribute.y + detaY); rowStart = row + 1; - rowEnd = scene.table.frozenRowCount - 1; + rowEnd = scene.table.columnHeaderLevelCount - 1; } else if (row >= scene.table.rowCount - scene.table.bottomFrozenRowCount) { rowStart = row + 1; rowEnd = scene.table.rowCount - 1; @@ -62,9 +61,9 @@ export function updateRowHeight(scene: Scenegraph, row: number, detaY: number, s } // 更新以下行位置 - for (let colIndex = 0; colIndex < scene.table.colCount; colIndex++) { - for (let rowIndex = rowStart; rowIndex <= rowEnd; rowIndex++) { - const cellGroup = scene.highPerformanceGetCell(colIndex, rowIndex); + for (let rowIndex = rowStart; rowIndex <= rowEnd; rowIndex++) { + for (let colIndex = 0; colIndex < scene.table.colCount; colIndex++) { + const cellGroup = scene.getCell(colIndex, rowIndex); if (cellGroup.role === 'cell') { cellGroup.setAttribute('y', cellGroup.attribute.y + detaY); } @@ -140,7 +139,6 @@ export function updateCellHeight( const dataValue = scene.table.getCellOriginValue(col, row); const padding = getQuadProps(getProp('padding', style, col, row, scene.table)); - const createProgressBarCell = Factory.getFunction('createProgressBarCell') as CreateProgressBarCell; const newBarCell = createProgressBarCell( columnDefine, style, @@ -165,7 +163,6 @@ export function updateCellHeight( cell.removeAllChild(); const headerStyle = scene.table._getCellStyle(col, row); const padding = getQuadProps(getProp('padding', headerStyle, col, row, scene.table)); - const createSparkLineCellGroup = Factory.getFunction('createSparkLineCellGroup') as CreateSparkLineCellGroup; createSparkLineCellGroup( cell, cell.parent, @@ -181,14 +178,12 @@ export function updateCellHeight( false ); } else if (type === 'image' || type === 'video') { - updateImageCellContentWhileResize(cell, col, row, 0, detaY, scene.table); + updateImageCellContentWhileResize(cell, col, row, scene.table); } else if (cell.firstChild?.name === 'axis') { (cell.firstChild as any)?.originAxis.resize(cell.attribute.width, cell.attribute.height); } else { let renderDefault = true; - const customContainer = - (cell.getChildByName(CUSTOM_CONTAINER_NAME) as Group) || - (cell.getChildByName(CUSTOM_MERGE_CONTAINER_NAME) as Group); + const customContainer = cell.getChildByName('custom-container') as Group; if (customContainer) { let customElementsGroup; customContainer.removeAllChild(); @@ -201,9 +196,7 @@ export function updateCellHeight( continue; } const mergedCell = scene.getCell(col, mergeRow); - const customContainer = - (cell.getChildByName(CUSTOM_CONTAINER_NAME) as Group) || - (cell.getChildByName(CUSTOM_MERGE_CONTAINER_NAME) as Group); + const customContainer = mergedCell.getChildByName('custom-container') as Group; customContainer.removeAllChild(); mergedCell.removeChild(customContainer); getCustomCellMergeCustom(col, mergeRow, mergedCell, scene.table); @@ -243,12 +236,6 @@ export function updateCellHeight( // scene.table.heightMode === 'autoHeight', scene.table.isAutoRowHeight(row), padding, - isMergeCellGroup(cell) - ? { - start: { col: cell.mergeStartCol, row: cell.mergeStartRow }, - end: { col: cell.mergeEndCol, row: cell.mergeEndRow } - } - : undefined, scene.table ); customElementsGroup = customResult.elementsGroup; diff --git a/packages/vtable/src/scenegraph/layout/update-width.ts b/packages/vtable/src/scenegraph/layout/update-width.ts index 81b480558..e4712c6fa 100644 --- a/packages/vtable/src/scenegraph/layout/update-width.ts +++ b/packages/vtable/src/scenegraph/layout/update-width.ts @@ -1,15 +1,14 @@ import type { IGraphic } from '@src/vrender'; import type { ProgressBarStyle } from '../../body-helper/style/ProgressBarStyle'; -import type { ICartesianAxis } from '../../components/axis/axis'; -import { Factory } from '../../core/factory'; +import { CartesianAxis } from '../../components/axis/axis'; import { getStyleTheme } from '../../core/tableHelper'; import type { BaseTableAPI, HeaderData } from '../../ts-types/base-table'; import type { IProgressbarColumnBodyDefine } from '../../ts-types/list-table/define/progressbar-define'; -import { CUSTOM_CONTAINER_NAME, CUSTOM_MERGE_CONTAINER_NAME, dealWithCustom } from '../component/custom'; +import { dealWithCustom } from '../component/custom'; import type { Group } from '../graphic/group'; import { updateImageCellContentWhileResize } from '../group-creater/cell-type/image-cell'; -import type { CreateProgressBarCell } from '../group-creater/cell-type/progress-bar-cell'; -import type { CreateSparkLineCellGroup } from '../group-creater/cell-type/spark-line-cell'; +import { createProgressBarCell } from '../group-creater/cell-type/progress-bar-cell'; +import { createSparkLineCellGroup } from '../group-creater/cell-type/spark-line-cell'; import { resizeCellGroup, getCustomCellMergeCustom } from '../group-creater/cell-helper'; import type { Scenegraph } from '../scenegraph'; import { getCellMergeInfo } from '../utils/get-cell-merge'; @@ -279,7 +278,6 @@ function updateCellWidth( const dataValue = scene.table.getCellOriginValue(col, row); const padding = getQuadProps(getProp('padding', style, col, row, scene.table)); - const createProgressBarCell = Factory.getFunction('createProgressBarCell') as CreateProgressBarCell; const newBarCell = createProgressBarCell( columnDefine, style, @@ -304,7 +302,6 @@ function updateCellWidth( cellGroup.removeAllChild(); const headerStyle = scene.table._getCellStyle(col, row); const padding = getQuadProps(getProp('padding', headerStyle, col, row, scene.table)); - const createSparkLineCellGroup = Factory.getFunction('createSparkLineCellGroup') as CreateSparkLineCellGroup; createSparkLineCellGroup( cellGroup, cellGroup.parent, @@ -323,14 +320,13 @@ function updateCellWidth( // // 只更新背景边框 // const rect = cell.firstChild as Rect; // rect.setAttribute('width', cell.attribute.width); - updateImageCellContentWhileResize(cellGroup, col, row, detaX, 0, scene.table); + updateImageCellContentWhileResize(cellGroup, col, row, scene.table); } else if (cellGroup.firstChild?.name === 'axis') { // recreate axis component const axisConfig = scene.table.internalProps.layoutMap.getAxisConfigInPivotChart(col, row); const cellStyle = scene.table._getCellStyle(col, row); const padding = getQuadProps(getProp('padding', cellStyle, col, row, scene.table)); if (axisConfig) { - const CartesianAxis: ICartesianAxis = Factory.getComponent('axis'); const axis = new CartesianAxis( axisConfig, cellGroup.attribute.width, @@ -346,9 +342,7 @@ function updateCellWidth( (cell.firstChild as any)?.originAxis.resize(cell.attribute.width, cell.attribute.height); } else { let renderDefault = true; - const customContainer = - (cell.getChildByName(CUSTOM_CONTAINER_NAME) as Group) || - (cell.getChildByName(CUSTOM_MERGE_CONTAINER_NAME) as Group); + const customContainer = cell.getChildByName('custom-container') as Group; if (customContainer) { let customElementsGroup; customContainer.removeAllChild(); @@ -361,9 +355,7 @@ function updateCellWidth( continue; } const mergedCell = scene.getCell(mergeCol, row); - const customContainer = - (mergedCell.getChildByName(CUSTOM_CONTAINER_NAME) as Group) || - (cell.getChildByName(CUSTOM_MERGE_CONTAINER_NAME) as Group); + const customContainer = mergedCell.getChildByName('custom-container') as Group; customContainer.removeAllChild(); mergedCell.removeChild(customContainer); getCustomCellMergeCustom(mergeCol, row, mergedCell, scene.table); @@ -403,12 +395,6 @@ function updateCellWidth( // scene.table.heightMode === 'autoHeight', scene.table.isAutoRowHeight(row), padding, - isMergeCellGroup(cellGroup) - ? { - start: { col: cellGroup.mergeStartCol, row: cellGroup.mergeStartRow }, - end: { col: cellGroup.mergeEndCol, row: cellGroup.mergeEndRow } - } - : undefined, scene.table ); customElementsGroup = customResult.elementsGroup; @@ -433,10 +419,7 @@ function updateCellWidth( ); isHeightChange = isHeightChange || cellChange; } - if (!autoWrapText) { - const style = scene.table._getCellStyle(col, row); - autoWrapText = style.autoWrapText; - } + return autoRowHeight && autoWrapText ? isHeightChange : false; } diff --git a/packages/vtable/src/scenegraph/refresh-node/update-chart.ts b/packages/vtable/src/scenegraph/refresh-node/update-chart.ts index d302c3780..3f4b06281 100644 --- a/packages/vtable/src/scenegraph/refresh-node/update-chart.ts +++ b/packages/vtable/src/scenegraph/refresh-node/update-chart.ts @@ -1,7 +1,6 @@ import { isEqual } from '@visactor/vutils'; import type { PivotChart } from '../../PivotChart'; -import type { ICartesianAxis } from '../../components/axis/axis'; -import { Factory } from '../../core/factory'; +import { CartesianAxis } from '../../components/axis/axis'; import type { BaseTableAPI } from '../../ts-types/base-table'; import type { Chart } from '../graphic/chart'; import type { Group } from '../graphic/group'; @@ -210,7 +209,6 @@ function updateTableAxes(containerGroup: Group, table: BaseTableAPI) { const axisConfig = table.internalProps.layoutMap.getAxisConfigInPivotChart(cell.col, cell.row); const cellStyle = table._getCellStyle(cell.col, cell.row); const padding = getQuadProps(getProp('padding', cellStyle, cell.col, cell.row, table)); - const CartesianAxis: ICartesianAxis = Factory.getComponent('axis'); const axis = new CartesianAxis(axisConfig, cell.attribute.width, cell.attribute.height, padding, table); cell.clear(); cell.appendChild(axis.component); diff --git a/packages/vtable/src/scenegraph/scenegraph.ts b/packages/vtable/src/scenegraph/scenegraph.ts index f144e14ab..4466732d4 100644 --- a/packages/vtable/src/scenegraph/scenegraph.ts +++ b/packages/vtable/src/scenegraph/scenegraph.ts @@ -66,13 +66,12 @@ import { createCornerCell } from './style/corner-cell'; import { updateCol } from './layout/update-col'; import { deduplication } from '../tools/util'; import { getDefaultHeight, getDefaultWidth } from './group-creater/progress/default-width-height'; -import { dealWithAnimationAppear } from './animation/appear'; // import { contextModule } from './context/module'; registerForVrender(); // VChart poptip theme -// loadPoptip(); +loadPoptip(); container.load(splitModule); container.load(textMeasureModule); // container.load(renderServiceModule); @@ -149,13 +148,11 @@ export class Scenegraph { background: table.theme.underlayBackgroundColor, dpr: table.internalProps.pixelRatio, enableLayout: true, - // enableHtmlAttribute: true, // pluginList: table.isPivotChart() ? ['poptipForText'] : undefined, afterRender: () => { this.table.fireListeners('after_render', null); // console.trace('after_render'); - }, - ...table.options.renderOption + } // event: { clickInterval: 400 } // autoRender: true }); @@ -345,10 +342,8 @@ export class Scenegraph { * @description: 依据数据创建表格场景树 * @return {*} */ - createSceneGraph(skipRowHeightClear = false) { - if (!skipRowHeightClear) { - this.table.rowHeightsMap.clear(); - } + createSceneGraph() { + this.table.rowHeightsMap.clear(); // if (this.table.heightMode === 'autoHeight') { // this.table.defaultRowHeight = getDefaultHeight(this.table); @@ -370,7 +365,7 @@ export class Scenegraph { this.clear = false; // this.frozenColCount = this.table.rowHeaderLevelCount; this.frozenColCount = this.table.frozenColCount; - this.frozenRowCount = this.table.frozenRowCount; + this.frozenRowCount = this.table.columnHeaderLevelCount; this.proxy = new SceneProxy(this.table); @@ -694,8 +689,14 @@ export class Scenegraph { deleteAllSelectBorder(this); } - updateCellSelectBorder(selectRange: CellRange & { skipBodyMerge?: boolean }, extendSelectRange: boolean = true) { - updateCellSelectBorder(this, selectRange, extendSelectRange); + updateCellSelectBorder( + newStartCol: number, + newStartRow: number, + newEndCol: number, + newEndRow: number, + extendSelectRange: boolean = true + ) { + updateCellSelectBorder(this, newStartCol, newStartRow, newEndCol, newEndRow, extendSelectRange); } removeFillHandleFromSelectComponents() { @@ -705,7 +706,7 @@ export class Scenegraph { recreateAllSelectRangeComponents() { deleteAllSelectBorder(this); this.table.stateManager.select.ranges.forEach((cellRange: CellRange) => { - updateCellSelectBorder(this, cellRange); + updateCellSelectBorder(this, cellRange.start.col, cellRange.start.row, cellRange.end.col, cellRange.end.row); }); moveSelectingRangeComponentsToSelectedRangeComponents(this); } @@ -812,7 +813,6 @@ export class Scenegraph { } recalculateRowHeights() { - this.table.internalProps.useOneRowHeightFillAll = false; computeRowsHeight(this.table, 0, this.table.rowCount - 1, true, true); } @@ -1221,12 +1221,6 @@ export class Scenegraph { handleTextStick(this.table); - // deal with animation - - if (this.table.options.animationAppear) { - dealWithAnimationAppear(this.table); - } - this.updateNextFrame(); } @@ -1535,8 +1529,6 @@ export class Scenegraph { this.updateTableSize(); this.component.updateScrollBar(); - this.updateDomContainer(); - this.updateNextFrame(); } @@ -1544,7 +1536,7 @@ export class Scenegraph { const type = this.table.getBodyColumnType(col, row); const cellGroup = this.getCell(col, row); if (type === 'image' || type === 'video') { - updateImageCellContentWhileResize(cellGroup, col, row, 0, 0, this.table); + updateImageCellContentWhileResize(cellGroup, col, row, this.table); } } @@ -1616,34 +1608,29 @@ export class Scenegraph { ): { col: number; row: number; x?: number; rightFrozen?: boolean } { let cell: { col: number; row: number; x?: number; rightFrozen?: boolean }; if (!cellGroup) { - const drawRange = this.table.getDrawRange(); - if (abstractY >= drawRange.top && abstractY <= drawRange.bottom) { - // to do: 处理最后一列外调整列宽 - cell = this.table.getCellAtRelativePosition(abstractX - offset, abstractY); - return cell; + // to do: 处理最后一列外调整列宽 + cell = this.table.getCellAt(abstractX - offset, abstractY); + } else { + if (abstractX < cellGroup.globalAABBBounds.x1 + offset) { + cell = { col: cellGroup.col - 1, row: cellGroup.row, x: cellGroup.globalAABBBounds.x1 }; + } else if (cellGroup.globalAABBBounds.x2 - offset < abstractX) { + cell = { col: cellGroup.col, row: cellGroup.row, x: cellGroup.globalAABBBounds.x2 }; + } + if ( + cell && + this.table.rightFrozenColCount > 0 && + cell.col === this.table.colCount - this.table.rightFrozenColCount - 1 && + this.table.tableNoFrameWidth - + this.table.getFrozenColsWidth() - + this.table.getRightFrozenColsWidth() + + this.table.scrollLeft < + this.bodyGroup.attribute.width + ) { + // 有右侧冻结列,并且横向没有滚动到最右侧时,右侧冻结列左侧调整对只对右侧冻结列生效 + cell.col = cell.col + 1; + cell.rightFrozen = true; } - return { col: -1, row: -1 }; - } - if (abstractX < cellGroup.globalAABBBounds.x1 + offset) { - cell = { col: cellGroup.col - 1, row: cellGroup.row, x: cellGroup.globalAABBBounds.x1 }; - } else if (cellGroup.globalAABBBounds.x2 - offset < abstractX) { - cell = { col: cellGroup.col, row: cellGroup.row, x: cellGroup.globalAABBBounds.x2 }; - } - if ( - cell && - this.table.rightFrozenColCount > 0 && - cell.col === this.table.colCount - this.table.rightFrozenColCount - 1 && - this.table.tableNoFrameWidth - - this.table.getFrozenColsWidth() - - this.table.getRightFrozenColsWidth() + - this.table.scrollLeft < - this.bodyGroup.attribute.width - ) { - // 有右侧冻结列,并且横向没有滚动到最右侧时,右侧冻结列左侧调整对只对右侧冻结列生效 - cell.col = cell.col + 1; - cell.rightFrozen = true; } - if (cell) { return cell; } @@ -1752,9 +1739,6 @@ export class Scenegraph { const text = cellGroup.getChildByName('text', true) as unknown as Text | RichText; if (text && text.type === 'text') { - if ((text.attribute as any).moreThanMaxCharacters) { - return this.table.getCellValue(col, row); - } const textAttributeStr = isArray(text.attribute.text) ? text.attribute.text.join('') : (text.attribute.text as string); @@ -1767,8 +1751,7 @@ export class Scenegraph { }); } if (cacheStr !== textAttributeStr) { - // return textAttributeStr; - return this.table.getCellValue(col, row); + return textAttributeStr; } } else if (text && text.type === 'richtext') { const richtext = text; @@ -1778,8 +1761,7 @@ export class Scenegraph { richtext.attribute.height < richtext._frameCache.actualHeight ) { const textConfig = richtext.attribute.textConfig.find((item: any) => item.text); - // return (textConfig as any).text as string; - return this.table.getCellValue(col, row); + return (textConfig as any).text as string; } } return null; @@ -1808,7 +1790,6 @@ export class Scenegraph { updateRow(removeCells: CellAddress[], addCells: CellAddress[], updateCells: CellAddress[] = []) { this.table.internalProps.layoutMap.clearCellRangeMap(); - this.table.internalProps.useOneRowHeightFillAll = false; const addRows = deduplication(addCells.map(cell => cell.row)).sort((a, b) => a - b); const updateRows = deduplication(updateCells.map(cell => cell.row)).sort((a, b) => a - b); //这个值是后续为了autoFillHeight判断逻辑中用到的 判断是否更新前是未填满的情况 @@ -1905,12 +1886,12 @@ export class Scenegraph { } getCellGroupY(row: number) { - if (row < this.table.frozenRowCount) { + if (row < this.table.columnHeaderLevelCount) { // column header return this.table.getRowsHeight(0, row - 1); } else if (row < this.table.rowCount - this.table.bottomFrozenRowCount) { // body - return this.table.getRowsHeight(this.table.frozenRowCount, row - 1); + return this.table.getRowsHeight(this.table.columnHeaderLevelCount, row - 1); } else if (row < this.table.rowCount) { // bottom frozen return this.table.getRowsHeight(this.table.rowCount - this.table.bottomFrozenRowCount, row - 1); @@ -1934,18 +1915,4 @@ export class Scenegraph { // updateCellValue(col: number, row: number) { // updateCell(col, row, this.table); // } - updateDomContainer() { - const { headerDomContainer, bodyDomContainer } = this.table.internalProps; - if (headerDomContainer) { - headerDomContainer.style.width = `${headerDomContainer.parentElement?.offsetWidth ?? 1 - 1}px`; - headerDomContainer.style.height = `${this.table.getFrozenRowsHeight()}px`; - } - if (bodyDomContainer) { - bodyDomContainer.style.width = `${bodyDomContainer.parentElement?.offsetWidth ?? 1 - 1}px`; - bodyDomContainer.style.height = `${ - bodyDomContainer.parentElement?.offsetHeight ?? 1 - 1 - this.table.getFrozenRowsHeight() - }px`; - bodyDomContainer.style.top = `${this.table.getFrozenRowsHeight()}px`; - } - } } diff --git a/packages/vtable/src/scenegraph/select/update-select-border.ts b/packages/vtable/src/scenegraph/select/update-select-border.ts index 1385309f9..c5a54fb9b 100644 --- a/packages/vtable/src/scenegraph/select/update-select-border.ts +++ b/packages/vtable/src/scenegraph/select/update-select-border.ts @@ -1,6 +1,6 @@ import type { IRect } from '@src/vrender'; import type { Scenegraph } from '../scenegraph'; -import type { CellRange, CellSubLocation } from '../../ts-types'; +import type { CellSubLocation } from '../../ts-types'; import { getCellMergeInfo } from '../utils/get-cell-merge'; export function updateAllSelectComponent(scene: Scenegraph) { @@ -21,7 +21,6 @@ function updateComponent( key: string, scene: Scenegraph ) { - const table = scene.table; const [startColStr, startRowStr, endColStr, endRowStr] = key.split('-'); const startCol = parseInt(startColStr, 10); const startRow = parseInt(startRowStr, 10); @@ -36,14 +35,14 @@ function updateComponent( let visibleCellRange; switch (selectComp.role) { case 'rowHeader': - visibleCellRange = table.getBodyVisibleRowRange(); + visibleCellRange = scene.table.getBodyVisibleRowRange(); if (visibleCellRange) { computeRectCellRangeStartRow = Math.max(startRow, visibleCellRange.rowStart - 1); computeRectCellRangeEndRow = Math.min(endRow, visibleCellRange.rowEnd + 1); } break; case 'columnHeader': - visibleCellRange = table.getBodyVisibleCellRange(); + visibleCellRange = scene.table.getBodyVisibleCellRange(); if (visibleCellRange) { computeRectCellRangeStartCol = Math.max(startCol, visibleCellRange.colStart - 1); computeRectCellRangeEndCol = Math.min(endCol, visibleCellRange.colEnd + 1); @@ -52,14 +51,14 @@ function updateComponent( case 'cornerHeader': break; case 'bottomFrozen': - visibleCellRange = table.getBodyVisibleCellRange(); + visibleCellRange = scene.table.getBodyVisibleCellRange(); if (visibleCellRange) { computeRectCellRangeStartCol = Math.max(startCol, visibleCellRange.colStart - 1); computeRectCellRangeEndCol = Math.min(endCol, visibleCellRange.colEnd + 1); } break; case 'rightFrozen': - visibleCellRange = table.getBodyVisibleCellRange(); + visibleCellRange = scene.table.getBodyVisibleCellRange(); if (visibleCellRange) { computeRectCellRangeStartRow = Math.max(startRow, visibleCellRange.rowStart - 1); computeRectCellRangeEndRow = Math.min(endRow, visibleCellRange.rowEnd + 1); @@ -72,7 +71,7 @@ function updateComponent( case 'rightBottomCorner': break; default: - visibleCellRange = table.getBodyVisibleCellRange(); + visibleCellRange = scene.table.getBodyVisibleCellRange(); if (visibleCellRange) { computeRectCellRangeStartRow = Math.max(startRow, visibleCellRange.rowStart - 1); computeRectCellRangeEndRow = Math.min(endRow, visibleCellRange.rowEnd + 1); @@ -81,11 +80,11 @@ function updateComponent( } break; } - // const cellRange = table.getCellRange(startCol, startRow); - // const colsWidth = table.getColsWidth(cellRange.start.col, endCol); - // const rowsHeight = table.getRowsHeight(cellRange.start.row, endRow); - const colsWidth = table.getColsWidth(computeRectCellRangeStartCol, computeRectCellRangeEndCol); - const rowsHeight = table.getRowsHeight(computeRectCellRangeStartRow, computeRectCellRangeEndRow); + // const cellRange = scene.table.getCellRange(startCol, startRow); + // const colsWidth = scene.table.getColsWidth(cellRange.start.col, endCol); + // const rowsHeight = scene.table.getRowsHeight(cellRange.start.row, endRow); + const colsWidth = scene.table.getColsWidth(computeRectCellRangeStartCol, computeRectCellRangeEndCol); + const rowsHeight = scene.table.getRowsHeight(computeRectCellRangeStartRow, computeRectCellRangeEndRow); const firstCellBound = scene.highPerformanceGetCell( computeRectCellRangeStartCol, computeRectCellRangeStartRow @@ -103,7 +102,7 @@ function updateComponent( visible: true }); if (selectComp.fillhandle) { - selectComp.fillhandle?.setAttributes({ + selectComp.fillhandle.setAttributes({ x: lastCellBound.x2 - scene.tableGroup.attribute.x - 3, // 调整小方块位置 y: lastCellBound.y2 - scene.tableGroup.attribute.y - 3, // 调整小方块位置 width: 6, @@ -113,42 +112,14 @@ function updateComponent( } //#region 判断是不是按着表头部分的选中框 因为绘制层级的原因 线宽会被遮住一半,因此需要动态调整层级 - let isNearRowHeader = table.frozenColCount ? startCol === table.frozenColCount : false; - if (!isNearRowHeader && table.frozenColCount && table.scrollLeft > 0 && startCol >= table.frozenColCount) { - const startColRelativePosition = table.getColsWidth(0, startCol - 1) - table.scrollLeft; - if (startColRelativePosition < table.getFrozenColsWidth()) { - isNearRowHeader = true; - } - } - - let isNearRightRowHeader = table.rightFrozenColCount - ? table.rightFrozenColCount > 0 && endCol === table.colCount - table.rightFrozenColCount - 1 + const isNearRowHeader = scene.table.frozenColCount ? startCol === scene.table.frozenColCount : false; + const isNearRightRowHeader = scene.table.rightFrozenColCount + ? scene.table.rightFrozenColCount > 0 && endCol === scene.table.colCount - scene.table.rightFrozenColCount - 1 : false; - if (!isNearRightRowHeader && table.rightFrozenColCount && endCol < table.colCount - table.rightFrozenColCount) { - const endColRelativePosition = table.getColsWidth(0, endCol) - table.scrollLeft; - if (endColRelativePosition > table.tableNoFrameWidth - table.getRightFrozenColsWidth()) { - isNearRightRowHeader = true; - } - } - - let isNearColHeader = table.frozenRowCount ? startRow === table.frozenRowCount : true; - if (!isNearColHeader && table.frozenRowCount && table.scrollTop > 0 && startRow >= table.frozenRowCount) { - const startRowRelativePosition = table.getRowsHeight(0, startRow - 1) - table.scrollTop; - if (startRowRelativePosition < table.getFrozenRowsHeight()) { - isNearColHeader = true; - } - } - - let isNearBottomColHeader = table.bottomFrozenRowCount - ? endRow === table.rowCount - table.bottomFrozenRowCount - 1 + const isNearColHeader = scene.table.frozenRowCount ? startRow === scene.table.frozenRowCount : true; + const isNearBottomColHeader = scene.table.bottomFrozenRowCount + ? endRow === scene.table.rowCount - scene.table.bottomFrozenRowCount - 1 : false; - if (!isNearBottomColHeader && table.bottomFrozenRowCount && endRow < table.rowCount - table.bottomFrozenRowCount) { - const endRowRelativePosition = table.getRowsHeight(0, endRow) - table.scrollTop; - if (endRowRelativePosition > table.tableNoFrameHeight - table.getBottomFrozenRowsHeight()) { - isNearBottomColHeader = true; - } - } - if ( (isNearRowHeader && selectComp.rect.attribute.stroke[3]) || (isNearRightRowHeader && selectComp.rect.attribute.stroke[1]) || @@ -200,23 +171,24 @@ function updateComponent( //#region 调整层级后 滚动情况下会出现绘制范围出界 如body的选中框 渲染在了rowheader上面,所有需要调整选中框rect的 边界 if ( - selectComp.rect.attribute.x < table.getFrozenColsWidth() && + selectComp.rect.attribute.x < scene.table.getFrozenColsWidth() && // selectComp.rect.attribute.x + selectComp.rect.attribute.width > scene.rowHeaderGroup.attribute.width && - table.scrollLeft > 0 && + scene.table.scrollLeft > 0 && (selectComp.role === 'body' || selectComp.role === 'columnHeader' || selectComp.role === 'bottomFrozen') ) { - const width = selectComp.rect.attribute.width - (table.getFrozenColsWidth() - selectComp.rect.attribute.x); + const width = selectComp.rect.attribute.width - (scene.table.getFrozenColsWidth() - selectComp.rect.attribute.x); selectComp.rect.setAttributes({ - x: selectComp.rect.attribute.x + (table.getFrozenColsWidth() - selectComp.rect.attribute.x), + x: selectComp.rect.attribute.x + (scene.table.getFrozenColsWidth() - selectComp.rect.attribute.x), width: width > 0 ? width : 0 }); - selectComp.fillhandle?.setAttributes({ - visible: width > 0 - }); + // selectComp.fillhandle.setAttributes({ + // x: selectComp.rect.attribute.x + (scene.table.getFrozenColsWidth() - selectComp.rect.attribute.x), + // width: width > 0 ? width : 0 + // }); } if ( // selectComp.rect.attribute.x < scene.rightFrozenGroup.attribute.x && - table.getRightFrozenColsWidth() > 0 && // right冻结列存在的情况下 + scene.table.getRightFrozenColsWidth() > 0 && // right冻结列存在的情况下 scene.rightFrozenGroup.attribute.height > 0 && selectComp.rect.attribute.x + selectComp.rect.attribute.width > scene.rightFrozenGroup.attribute.x && (selectComp.role === 'body' || selectComp.role === 'columnHeader' || selectComp.role === 'bottomFrozen') @@ -226,13 +198,14 @@ function updateComponent( x: selectComp.rect.attribute.x, width: width > 0 ? width : 0 }); - selectComp.fillhandle?.setAttributes({ - visible: width - colsWidth > 0 - }); + // selectComp.fillhandle.setAttributes({ + // x: selectComp.rect.attribute.x, + // width: width > 0 ? width : 0 + // }); } if ( selectComp.rect.attribute.y < scene.colHeaderGroup.attribute.height && - table.scrollTop > 0 && + scene.table.scrollTop > 0 && (selectComp.role === 'body' || selectComp.role === 'rowHeader' || selectComp.role === 'rightFrozen') ) { const height = @@ -241,9 +214,10 @@ function updateComponent( y: selectComp.rect.attribute.y + (scene.colHeaderGroup.attribute.height - selectComp.rect.attribute.y), height: height > 0 ? height : 0 }); - selectComp.fillhandle?.setAttributes({ - visible: height > 0 - }); + // selectComp.fillhandle.setAttributes({ + // y: selectComp.rect.attribute.y + (scene.colHeaderGroup.attribute.height - selectComp.rect.attribute.y), + // height: height > 0 ? height : 0 + // }); } if ( scene.bottomFrozenGroup.attribute.width > 0 && @@ -256,9 +230,10 @@ function updateComponent( y: selectComp.rect.attribute.y, height: height > 0 ? height : 0 }); - selectComp.fillhandle?.setAttributes({ - visible: height - rowsHeight > 0 - }); + // selectComp.fillhandle.setAttributes({ + // y: selectComp.fillhandle.attribute.y, + // height: height > 0 ? height : 0 + // }); } //#endregion } else { @@ -290,14 +265,14 @@ function updateComponent( if (typeof selectComp.rect.attribute.lineWidth === 'number') { diffSize = Math.ceil(selectComp.rect.attribute.lineWidth / 2); } - if (endCol === table.colCount - 1) { + if (endCol === scene.table.colCount - 1) { if (Array.isArray(selectComp.rect.attribute.lineWidth)) { diffSize = Math.ceil((selectComp.rect.attribute.lineWidth[1] ?? 0) / 2); } selectComp.rect.setAttributes({ width: selectComp.rect.attribute.width - diffSize }); - // selectComp.fillhandle?.setAttributes({ + // selectComp.fillhandle.setAttributes({ // width: selectComp.rect.attribute.width - diffSize // }); } @@ -309,19 +284,19 @@ function updateComponent( x: selectComp.rect.attribute.x + diffSize, width: selectComp.rect.attribute.width - diffSize }); - // selectComp.fillhandle?.setAttributes({ + // selectComp.fillhandle.setAttributes({ // x: selectComp.rect.attribute.x + diffSize, // width: selectComp.rect.attribute.width - diffSize // }); } - if (endRow === table.rowCount - 1) { + if (endRow === scene.table.rowCount - 1) { if (Array.isArray(selectComp.rect.attribute.lineWidth)) { diffSize = Math.ceil((selectComp.rect.attribute.lineWidth[2] ?? 0) / 2); } selectComp.rect.setAttributes({ height: selectComp.rect.attribute.height - diffSize }); - // selectComp.fillhandle?.setAttributes({ + // selectComp.fillhandle.setAttributes({ // height: selectComp.rect.attribute.height - diffSize // }); } @@ -333,7 +308,7 @@ function updateComponent( y: selectComp.rect.attribute.y + diffSize, height: selectComp.rect.attribute.height - diffSize }); - // selectComp.fillhandle?.setAttributes({ + // selectComp.fillhandle.setAttributes({ // y: selectComp.rect.attribute.y + diffSize, // height: selectComp.rect.attribute.height - diffSize // }); @@ -343,30 +318,23 @@ function updateComponent( export function updateCellSelectBorder( scene: Scenegraph, - selectRange: CellRange & { skipBodyMerge?: boolean }, + newStartCol: number, + newStartRow: number, + newEndCol: number, + newEndRow: number, ifExtendSelectRange: boolean = true ) { - const table = scene.table; - const newStartCol = selectRange.start.col; - const newStartRow = selectRange.start.row; - const newEndCol = selectRange.end.col; - const newEndRow = selectRange.end.row; - const skipBodyMerge = selectRange.skipBodyMerge; - let startCol = Math.max(Math.min(newEndCol, newStartCol), 0); let startRow = Math.max(Math.min(newEndRow, newStartRow), 0); - let endCol = Math.min(Math.max(newEndCol, newStartCol), table.colCount - 1); - let endRow = Math.min(Math.max(newEndRow, newStartRow), table.rowCount - 1); + let endCol = Math.min(Math.max(newEndCol, newStartCol), scene.table.colCount - 1); + let endRow = Math.min(Math.max(newEndRow, newStartRow), scene.table.rowCount - 1); //#region region 校验四周的单元格有没有合并的情况,如有则扩大范围 const extendSelectRange = () => { let isExtend = false; for (let col = startCol; col <= endCol; col++) { if (col === startCol) { for (let row = startRow; row <= endRow; row++) { - if (!table.isHeader(col, row) && skipBodyMerge) { - continue; - } - const mergeInfo = getCellMergeInfo(table, col, row); + const mergeInfo = getCellMergeInfo(scene.table, col, row); if (mergeInfo && mergeInfo.start.col < startCol) { startCol = mergeInfo.start.col; isExtend = true; @@ -376,11 +344,8 @@ export function updateCellSelectBorder( } if (!isExtend && col === endCol) { for (let row = startRow; row <= endRow; row++) { - if (!table.isHeader(col, row) && skipBodyMerge) { - continue; - } - const mergeInfo = getCellMergeInfo(table, col, row); - if (mergeInfo && Math.min(mergeInfo.end.col, table.colCount - 1) > endCol) { + const mergeInfo = getCellMergeInfo(scene.table, col, row); + if (mergeInfo && Math.min(mergeInfo.end.col, scene.table.colCount - 1) > endCol) { endCol = mergeInfo.end.col; isExtend = true; break; @@ -396,10 +361,7 @@ export function updateCellSelectBorder( for (let row = startRow; row <= endRow; row++) { if (row === startRow) { for (let col = startCol; col <= endCol; col++) { - if (!table.isHeader(col, row) && skipBodyMerge) { - continue; - } - const mergeInfo = getCellMergeInfo(table, col, row); + const mergeInfo = getCellMergeInfo(scene.table, col, row); if (mergeInfo && mergeInfo.start.row < startRow) { startRow = mergeInfo.start.row; isExtend = true; @@ -409,11 +371,8 @@ export function updateCellSelectBorder( } if (!isExtend && row === endRow) { for (let col = startCol; col <= endCol; col++) { - if (!table.isHeader(col, row) && skipBodyMerge) { - continue; - } - const mergeInfo = getCellMergeInfo(table, col, row); - if (mergeInfo && Math.min(mergeInfo.end.row, table.rowCount - 1) > endRow) { + const mergeInfo = getCellMergeInfo(scene.table, col, row); + if (mergeInfo && Math.min(mergeInfo.end.row, scene.table.rowCount - 1) > endRow) { endRow = mergeInfo.end.row; isExtend = true; break; @@ -449,63 +408,66 @@ export function updateCellSelectBorder( let needRightTopCornerHeader = false; let needRightBottomCornerHeader = false; let needLeftBottomCornerHeader = false; - if (startCol <= table.frozenColCount - 1 && startRow <= table.frozenRowCount - 1) { + if (startCol <= scene.table.frozenColCount - 1 && startRow <= scene.table.frozenRowCount - 1) { needCornerHeader = true; } - if (endCol >= table.colCount - table.rightFrozenColCount && startRow <= table.frozenRowCount - 1) { + if (endCol >= scene.table.colCount - scene.table.rightFrozenColCount && startRow <= scene.table.frozenRowCount - 1) { needRightTopCornerHeader = true; } - if (startCol <= table.frozenColCount - 1 && endRow >= table.rowCount - table.bottomFrozenRowCount) { + if (startCol <= scene.table.frozenColCount - 1 && endRow >= scene.table.rowCount - scene.table.bottomFrozenRowCount) { needLeftBottomCornerHeader = true; } - if (endCol >= table.colCount - table.rightFrozenColCount && endRow >= table.rowCount - table.bottomFrozenRowCount) { + if ( + endCol >= scene.table.colCount - scene.table.rightFrozenColCount && + endRow >= scene.table.rowCount - scene.table.bottomFrozenRowCount + ) { needRightBottomCornerHeader = true; } if ( - startCol <= table.frozenColCount - 1 && - endRow >= table.frozenRowCount && - startRow <= table.rowCount - table.bottomFrozenRowCount - 1 + startCol <= scene.table.frozenColCount - 1 && + endRow >= scene.table.frozenRowCount && + startRow <= scene.table.rowCount - scene.table.bottomFrozenRowCount - 1 ) { needRowHeader = true; } if ( - endCol >= table.colCount - table.rightFrozenColCount && - endRow >= table.frozenRowCount && - startRow <= table.rowCount - table.bottomFrozenRowCount - 1 + endCol >= scene.table.colCount - scene.table.rightFrozenColCount && + endRow >= scene.table.frozenRowCount && + startRow <= scene.table.rowCount - scene.table.bottomFrozenRowCount - 1 ) { needRightRowHeader = true; } if ( - startRow <= table.frozenRowCount - 1 && - endCol >= table.frozenColCount && - startCol <= table.colCount - table.rightFrozenColCount - 1 + startRow <= scene.table.frozenRowCount - 1 && + endCol >= scene.table.frozenColCount && + startCol <= scene.table.colCount - scene.table.rightFrozenColCount - 1 ) { needColumnHeader = true; } if ( - endRow >= table.rowCount - table.bottomFrozenRowCount && - endCol >= table.frozenColCount && - startCol <= table.colCount - table.rightFrozenColCount - 1 + endRow >= scene.table.rowCount - scene.table.bottomFrozenRowCount && + endCol >= scene.table.frozenColCount && + startCol <= scene.table.colCount - scene.table.rightFrozenColCount - 1 ) { needBottomColumnHeader = true; } if ( - startCol <= table.colCount - table.rightFrozenColCount - 1 && - endCol >= table.frozenColCount && - startRow <= table.rowCount - table.bottomFrozenRowCount - 1 && - endRow >= table.frozenRowCount + startCol <= scene.table.colCount - scene.table.rightFrozenColCount - 1 && + endCol >= scene.table.frozenColCount && + startRow <= scene.table.rowCount - scene.table.bottomFrozenRowCount - 1 && + endRow >= scene.table.frozenRowCount ) { needBody = true; } // TODO 可以尝试不拆分三个表头和body【前提是theme中合并配置】 用一个SelectBorder 需要结合clip,并动态设置border的范围【依据区域范围 已经是否跨表头及body】 if (needCornerHeader) { - const cornerEndCol = Math.min(endCol, table.frozenColCount - 1); - const cornerEndRow = Math.min(endRow, table.frozenRowCount - 1); + const cornerEndCol = Math.min(endCol, scene.table.frozenColCount - 1); + const cornerEndRow = Math.min(endRow, scene.table.frozenRowCount - 1); const strokeArray = [true, !needColumnHeader, !needRowHeader, true]; scene.createCellSelectBorder( startCol, @@ -518,8 +480,8 @@ export function updateCellSelectBorder( ); } if (needRightTopCornerHeader) { - const cornerStartCol = Math.max(startCol, table.colCount - table.rightFrozenColCount); - const cornerEndRow = Math.min(endRow, table.frozenRowCount - 1); + const cornerStartCol = Math.max(startCol, scene.table.colCount - scene.table.rightFrozenColCount); + const cornerEndRow = Math.min(endRow, scene.table.frozenRowCount - 1); const strokeArray = [true, true, !needRightRowHeader, !needColumnHeader]; scene.createCellSelectBorder( cornerStartCol, @@ -533,8 +495,8 @@ export function updateCellSelectBorder( } if (needLeftBottomCornerHeader) { - const cornerEndCol = Math.min(endCol, table.frozenColCount - 1); - const cornerStartRow = Math.max(startRow, table.rowCount - table.bottomFrozenRowCount); + const cornerEndCol = Math.min(endCol, scene.table.frozenColCount - 1); + const cornerStartRow = Math.max(startRow, scene.table.rowCount - scene.table.bottomFrozenRowCount); const strokeArray = [!needRowHeader, !needBottomColumnHeader, true, true]; scene.createCellSelectBorder( startCol, @@ -547,8 +509,8 @@ export function updateCellSelectBorder( ); } if (needRightBottomCornerHeader) { - const cornerStartCol = Math.max(startCol, table.colCount - table.rightFrozenColCount); - const cornerStartRow = Math.max(startRow, table.rowCount - table.bottomFrozenRowCount); + const cornerStartCol = Math.max(startCol, scene.table.colCount - scene.table.rightFrozenColCount); + const cornerStartRow = Math.max(startRow, scene.table.rowCount - scene.table.bottomFrozenRowCount); const strokeArray = [!needRightRowHeader, true, true, !needBottomColumnHeader]; scene.createCellSelectBorder( cornerStartCol, @@ -561,9 +523,9 @@ export function updateCellSelectBorder( ); } if (needColumnHeader) { - const columnHeaderStartCol = Math.max(startCol, table.frozenColCount); - const columnHeaderEndCol = Math.min(endCol, table.colCount - table.rightFrozenColCount - 1); - const columnHeaderEndRow = Math.min(endRow, table.frozenRowCount - 1); + const columnHeaderStartCol = Math.max(startCol, scene.table.frozenColCount); + const columnHeaderEndCol = Math.min(endCol, scene.table.colCount - scene.table.rightFrozenColCount - 1); + const columnHeaderEndRow = Math.min(endRow, scene.table.frozenRowCount - 1); const strokeArray = [true, !needRightTopCornerHeader, !needBody, !needCornerHeader]; scene.createCellSelectBorder( columnHeaderStartCol, @@ -576,9 +538,9 @@ export function updateCellSelectBorder( ); } if (needBottomColumnHeader) { - const columnHeaderStartCol = Math.max(startCol, table.frozenColCount); - const columnHeaderEndCol = Math.min(endCol, table.colCount - table.rightFrozenColCount - 1); - const columnHeaderStartRow = Math.max(startRow, table.rowCount - table.bottomFrozenRowCount); + const columnHeaderStartCol = Math.max(startCol, scene.table.frozenColCount); + const columnHeaderEndCol = Math.min(endCol, scene.table.colCount - scene.table.rightFrozenColCount - 1); + const columnHeaderStartRow = Math.max(startRow, scene.table.rowCount - scene.table.bottomFrozenRowCount); const strokeArray = [!needBody, !needRightBottomCornerHeader, true, !needLeftBottomCornerHeader]; scene.createCellSelectBorder( columnHeaderStartCol, @@ -591,9 +553,9 @@ export function updateCellSelectBorder( ); } if (needRowHeader) { - const columnHeaderStartRow = Math.max(startRow, table.frozenRowCount); - const columnHeaderEndRow = Math.min(endRow, table.rowCount - table.bottomFrozenRowCount - 1); - const columnHeaderEndCol = Math.min(endCol, table.frozenColCount - 1); + const columnHeaderStartRow = Math.max(startRow, scene.table.frozenRowCount); + const columnHeaderEndRow = Math.min(endRow, scene.table.rowCount - scene.table.bottomFrozenRowCount - 1); + const columnHeaderEndCol = Math.min(endCol, scene.table.frozenColCount - 1); const strokeArray = [!needCornerHeader, !needBody, !needLeftBottomCornerHeader, true]; scene.createCellSelectBorder( startCol, @@ -606,9 +568,9 @@ export function updateCellSelectBorder( ); } if (needRightRowHeader) { - const columnHeaderStartRow = Math.max(startRow, table.frozenRowCount); - const columnHeaderEndRow = Math.min(endRow, table.rowCount - table.bottomFrozenRowCount - 1); - const columnHeaderStartCol = Math.max(startCol, table.colCount - table.rightFrozenColCount); + const columnHeaderStartRow = Math.max(startRow, scene.table.frozenRowCount); + const columnHeaderEndRow = Math.min(endRow, scene.table.rowCount - scene.table.bottomFrozenRowCount - 1); + const columnHeaderStartCol = Math.max(startCol, scene.table.colCount - scene.table.rightFrozenColCount); const strokeArray = [!needRightTopCornerHeader, true, !needRightBottomCornerHeader, !needBody]; scene.createCellSelectBorder( columnHeaderStartCol, @@ -621,10 +583,10 @@ export function updateCellSelectBorder( ); } if (needBody) { - const columnHeaderStartCol = Math.max(startCol, table.frozenColCount); - const columnHeaderStartRow = Math.max(startRow, table.frozenRowCount); - const columnHeaderEndCol = Math.min(endCol, table.colCount - table.rightFrozenColCount - 1); - const columnHeaderEndRow = Math.min(endRow, table.rowCount - table.bottomFrozenRowCount - 1); + const columnHeaderStartCol = Math.max(startCol, scene.table.frozenColCount); + const columnHeaderStartRow = Math.max(startRow, scene.table.frozenRowCount); + const columnHeaderEndCol = Math.min(endCol, scene.table.colCount - scene.table.rightFrozenColCount - 1); + const columnHeaderEndRow = Math.min(endRow, scene.table.rowCount - scene.table.bottomFrozenRowCount - 1); const strokeArray = [!needColumnHeader, !needRightRowHeader, !needBottomColumnHeader, !needRowHeader]; scene.createCellSelectBorder( columnHeaderStartCol, diff --git a/packages/vtable/src/scenegraph/style/frame-border.ts b/packages/vtable/src/scenegraph/style/frame-border.ts index 0919e3e1f..bc6d88797 100644 --- a/packages/vtable/src/scenegraph/style/frame-border.ts +++ b/packages/vtable/src/scenegraph/style/frame-border.ts @@ -72,7 +72,6 @@ export function createFrameBorder( if (Array.isArray(borderColor)) { (rectAttributes as any).strokeArrayColor = getQuadProps(borderColor as any); } - if (Array.isArray(borderLineWidth)) { (rectAttributes as any).strokeArrayWidth = getQuadProps(borderLineWidth); (rectAttributes as any).lineWidth = 1; @@ -118,9 +117,6 @@ export function createFrameBorder( rectAttributes.y = borderTop / 2; rectAttributes.pickable = false; if (isTableGroup) { - if (cornerRadius) { - rectAttributes.cornerRadius = cornerRadius + (rectAttributes.lineWidth ?? 0) / 2; - } if (frameTheme.innerBorder) { rectAttributes.x = group.attribute.x + borderLeft / 2; rectAttributes.y = group.attribute.y + borderTop / 2; diff --git a/packages/vtable/src/scenegraph/utils/break-string.ts b/packages/vtable/src/scenegraph/utils/break-string.ts index 11350ca34..ba789de3b 100644 --- a/packages/vtable/src/scenegraph/utils/break-string.ts +++ b/packages/vtable/src/scenegraph/utils/break-string.ts @@ -1,14 +1,7 @@ -import { isString } from '@visactor/vutils'; import { convertInternal } from '../../tools/util'; import type { BaseTableAPI } from '../../ts-types/base-table'; -export function breakString(textStr: string, table: BaseTableAPI) { - let moreThanMaxCharacters = false; - if (isString(textStr) && textStr.length > (table.options.maxCharactersNumber || 200)) { - textStr = textStr.slice(0, table.options.maxCharactersNumber || 200); - textStr += '\u2026'; - moreThanMaxCharacters = true; - } +export function breakString(textStr: string, table: BaseTableAPI): string[] { let text; if (!table.internalProps.enableLineBreak && !table.options.customConfig?.multilinesForXTable) { text = [convertInternal(textStr)]; @@ -17,12 +10,9 @@ export function breakString(textStr: string, table: BaseTableAPI) { } // clear empty string in array end - while (text.length && text.length > 1 && !text[text.length - 1]) { + while (text.length && !text[text.length - 1]) { text.pop(); } - return { - text, - moreThanMaxCharacters - }; + return text; } diff --git a/packages/vtable/src/scenegraph/utils/text-icon-layout.ts b/packages/vtable/src/scenegraph/utils/text-icon-layout.ts index fd059fad4..8fb12ca9b 100644 --- a/packages/vtable/src/scenegraph/utils/text-icon-layout.ts +++ b/packages/vtable/src/scenegraph/utils/text-icon-layout.ts @@ -11,7 +11,7 @@ import type { Scenegraph } from '../scenegraph'; import { getCellMergeInfo } from './get-cell-merge'; import { getHierarchyOffset } from './get-hierarchy-offset'; import type { BaseTableAPI } from '../../ts-types/base-table'; -import { isNil, isNumber, isValid, isValidNumber } from '@visactor/vutils'; +import { isNil, isNumber, isValid } from '@visactor/vutils'; import { isMergeCellGroup } from './is-merge-cell-group'; import { breakString } from './break-string'; @@ -54,28 +54,28 @@ export function createCellContent( cellTheme: IThemeSpec, range: CellRange | undefined ) { - // const leftIcons: ColumnIconOption[] = []; - // const rightIcons: ColumnIconOption[] = []; - // const contentLeftIcons: ColumnIconOption[] = []; - // const contentRightIcons: ColumnIconOption[] = []; - // const inlineFrontIcons: ColumnIconOption[] = []; - // const inlineEndIcons: ColumnIconOption[] = []; - // const absoluteLeftIcons: ColumnIconOption[] = []; - // const absoluteRightIcons: ColumnIconOption[] = []; + const leftIcons: ColumnIconOption[] = []; + const rightIcons: ColumnIconOption[] = []; + const contentLeftIcons: ColumnIconOption[] = []; + const contentRightIcons: ColumnIconOption[] = []; + const inlineFrontIcons: ColumnIconOption[] = []; + const inlineEndIcons: ColumnIconOption[] = []; + const absoluteLeftIcons: ColumnIconOption[] = []; + const absoluteRightIcons: ColumnIconOption[] = []; let contentWidth: number; let contentHeight: number; let leftIconWidth = 0; - // let leftIconHeight = 0; + let leftIconHeight = 0; let rightIconWidth = 0; - // let rightIconHeight = 0; - // let absoluteLeftIconWidth = 0; + let rightIconHeight = 0; + let absoluteLeftIconWidth = 0; let absoluteRightIconWidth = 0; if (!Array.isArray(icons) || icons.length === 0) { if (isValid(textStr)) { // 没有icon,cellGroup只添加WrapText - const { text, moreThanMaxCharacters } = breakString(textStr, table); + const text = breakString(textStr, table); const hierarchyOffset = range ? getHierarchyOffset(range.start.col, range.start.row, table) @@ -91,7 +91,6 @@ export function createCellContent( } const attribute = { text: text.length === 1 ? text[0] : text, - moreThanMaxCharacters, maxLineWidth: autoColWidth ? Infinity : cellWidth - (padding[1] + padding[3] + hierarchyOffset), // fill: true, // textAlign: 'left', @@ -103,7 +102,7 @@ export function createCellContent( heightLimit: autoRowHeight && !table.options.customConfig?.multilinesForXTable ? -1 - : cellHeight - Math.floor(padding[0] + padding[2]), + : cellHeight - (padding[0] + padding[2]), pickable: false, dx: (textAlign === 'left' ? hierarchyOffset : 0) + _contentOffset, whiteSpace: text.length === 1 && !autoWrapText ? 'no-wrap' : 'normal' @@ -118,98 +117,78 @@ export function createCellContent( contentHeight = wrapText.AABBBounds.height(); } } else { - // // icon分类 - // icons.forEach(icon => { - // switch (icon.positionType) { - // case IconPosition.left: - // leftIcons.push(icon); - // break; - // case IconPosition.right: - // rightIcons.push(icon); - // break; - // case IconPosition.contentLeft: - // contentLeftIcons.push(icon); - // break; - // case IconPosition.contentRight: - // contentRightIcons.push(icon); - // break; - // // case IconPosition.absoluteLeft: - // // absoluteLeftIcons.push(icon); - // // break; - // case IconPosition.absoluteRight: - // absoluteRightIcons.push(icon); - // break; - // case IconPosition.inlineFront: - // inlineFrontIcons.push(icon); - // break; - // case IconPosition.inlineEnd: - // inlineEndIcons.push(icon); - // break; - // } - // }); - - // // 添加非cell icon & absolute icon - // leftIcons.forEach(icon => { - // const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); - // iconMark.role = 'icon-left'; - // iconMark.name = icon.name; - // iconMark.setAttribute('x', leftIconWidth + (iconMark.attribute.marginLeft ?? 0)); - // leftIconWidth += - // iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); - // leftIconHeight = Math.max(leftIconHeight, iconMark.AABBBounds.height()); - // cellGroup.appendChild(iconMark); - // }); - - // rightIcons.forEach(icon => { - // const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); - // iconMark.role = 'icon-right'; - // iconMark.name = icon.name; - // iconMark.setAttribute('x', rightIconWidth + (iconMark.attribute.marginLeft ?? 0)); - // rightIconWidth += - // iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); - // rightIconHeight = Math.max(rightIconHeight, iconMark.AABBBounds.height()); - // cellGroup.appendChild(iconMark); - // }); - - // absoluteLeftIcons.forEach(icon => { - // const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); - // iconMark.role = 'icon-absolute-left'; - // iconMark.name = icon.name; - // iconMark.setAttribute('x', absoluteLeftIconWidth + (iconMark.attribute.marginLeft ?? 0)); - // absoluteLeftIconWidth += - // iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); - // cellGroup.appendChild(iconMark); - // }); - - // absoluteRightIcons.forEach(icon => { - // const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); - // iconMark.role = 'icon-absolute-right'; - // iconMark.name = icon.name; - // iconMark.setAttribute('x', absoluteRightIconWidth + (iconMark.attribute.marginLeft ?? 0)); - // absoluteRightIconWidth += - // iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); - // cellGroup.appendChild(iconMark); - // }); - - const { - inlineFrontIcons, - inlineEndIcons, - contentLeftIcons, - contentRightIcons, - leftIconWidth: layoutLeftIconWidth, - // leftIconHeight: layoutLeftIconHeight, - rightIconWidth: layoutRightIconWidth, - // rightIconHeight: layoutRightIconHeight, - // absoluteLeftIconWidth: layoutAbsoluteLeftIconWidth, - absoluteRightIconWidth: layoutAbsoluteRightIconWidth - } = dealWithIconLayout(icons, cellGroup, range, table); - - leftIconWidth = layoutLeftIconWidth; - // leftIconHeight = layoutLeftIconHeight; - rightIconWidth = layoutRightIconWidth; - // rightIconHeight = layoutRightIconHeight; - // absoluteLeftIconWidth = layoutAbsoluteLeftIconWidth; - absoluteRightIconWidth = layoutAbsoluteRightIconWidth; + // icon分类 + icons.forEach(icon => { + switch (icon.positionType) { + case IconPosition.left: + leftIcons.push(icon); + break; + case IconPosition.right: + rightIcons.push(icon); + break; + case IconPosition.contentLeft: + contentLeftIcons.push(icon); + break; + case IconPosition.contentRight: + contentRightIcons.push(icon); + break; + // case IconPosition.absoluteLeft: + // absoluteLeftIcons.push(icon); + // break; + case IconPosition.absoluteRight: + absoluteRightIcons.push(icon); + break; + case IconPosition.inlineFront: + inlineFrontIcons.push(icon); + break; + case IconPosition.inlineEnd: + inlineEndIcons.push(icon); + break; + } + }); + + // 添加非cell icon & absolute icon + leftIcons.forEach(icon => { + const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); + iconMark.role = 'icon-left'; + iconMark.name = icon.name; + iconMark.setAttribute('x', leftIconWidth + (iconMark.attribute.marginLeft ?? 0)); + leftIconWidth += + iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); + leftIconHeight = Math.max(leftIconHeight, iconMark.AABBBounds.height()); + cellGroup.appendChild(iconMark); + }); + + rightIcons.forEach(icon => { + const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); + iconMark.role = 'icon-right'; + iconMark.name = icon.name; + iconMark.setAttribute('x', rightIconWidth + (iconMark.attribute.marginLeft ?? 0)); + rightIconWidth += + iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); + rightIconHeight = Math.max(rightIconHeight, iconMark.AABBBounds.height()); + cellGroup.appendChild(iconMark); + }); + + absoluteLeftIcons.forEach(icon => { + const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); + iconMark.role = 'icon-absolute-left'; + iconMark.name = icon.name; + iconMark.setAttribute('x', absoluteLeftIconWidth + (iconMark.attribute.marginLeft ?? 0)); + absoluteLeftIconWidth += + iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); + cellGroup.appendChild(iconMark); + }); + + absoluteRightIcons.forEach(icon => { + const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); + iconMark.role = 'icon-absolute-right'; + iconMark.name = icon.name; + iconMark.setAttribute('x', absoluteRightIconWidth + (iconMark.attribute.marginLeft ?? 0)); + absoluteRightIconWidth += + iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); + cellGroup.appendChild(iconMark); + }); // 添加text & content icon & inline icon let textMark; @@ -226,11 +205,10 @@ export function createCellContent( const hierarchyOffset = range ? getHierarchyOffset(range.start.col, range.start.row, table) : getHierarchyOffset(cellGroup.col, cellGroup.row, table); - const { text, moreThanMaxCharacters } = breakString(textStr, table); + const text = breakString(textStr, table); const attribute = { text: text.length === 1 ? text[0] : text, - moreThanMaxCharacters, maxLineWidth: autoColWidth ? Infinity : cellWidth - (padding[1] + padding[3]) - leftIconWidth - rightIconWidth - hierarchyOffset, @@ -241,13 +219,15 @@ export function createCellContent( heightLimit: autoRowHeight && !table.options.customConfig?.multilinesForXTable ? -1 - : cellHeight - Math.floor(padding[0] + padding[2]), + : cellHeight - (padding[0] + padding[2]), pickable: false, autoWrapText, lineClamp, wordBreak: 'break-word', whiteSpace: text.length === 1 && !autoWrapText ? 'no-wrap' : 'normal', - dx: (textAlign === 'left' ? (!contentLeftIcons.length ? hierarchyOffset : 0) : 0) + _contentOffset + dx: + (textAlign === 'left' ? (!contentLeftIcons.length && !contentRightIcons.length ? hierarchyOffset : 0) : 0) + + _contentOffset }; const wrapText = new Text(cellTheme.text ? (Object.assign({}, cellTheme.text, attribute) as any) : attribute); wrapText.name = 'text'; @@ -307,33 +287,15 @@ export function createCellContent( align: textAlign, baseline: textBaseline }); - const dealWithIconComputeVar = { - addedHierarchyOffset: 0 - }; //为了只增加一次indent的缩进值,如果有两个icon都dealWithIcon的话 + contentLeftIcons.forEach(icon => { - const iconMark = dealWithIcon( - icon, - undefined, - cellGroup.col, - cellGroup.row, - range, - table, - dealWithIconComputeVar - ); + const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); iconMark.role = 'icon-content-left'; iconMark.name = icon.name; cellContent.addLeftOccupyingIcon(iconMark); }); contentRightIcons.forEach(icon => { - const iconMark = dealWithIcon( - icon, - undefined, - cellGroup.col, - cellGroup.row, - range, - table, - dealWithIconComputeVar - ); + const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); iconMark.role = 'icon-content-right'; iconMark.name = icon.name; cellContent.addRightOccupyingIcon(iconMark); @@ -415,10 +377,7 @@ export function dealWithIcon( col?: number, row?: number, range?: CellRange, - table?: BaseTableAPI, - dealWithIconComputeVar?: { - addedHierarchyOffset: number; - } + table?: BaseTableAPI ): Icon { // positionType在外部处理 const iconAttribute = {} as any; @@ -444,23 +403,16 @@ export function dealWithIcon( let hierarchyOffset = 0; if ( - (!dealWithIconComputeVar || dealWithIconComputeVar?.addedHierarchyOffset === 0) && isNumber(col) && isNumber(row) && table && - (icon.funcType === IconFuncTypeEnum.collapse || - icon.funcType === IconFuncTypeEnum.expand || - icon.positionType === IconPosition.contentLeft || - icon.positionType === IconPosition.contentRight) + (icon.funcType === IconFuncTypeEnum.collapse || icon.funcType === IconFuncTypeEnum.expand) ) { // compute hierarchy offset // hierarchyOffset = getHierarchyOffset(col, row, table); hierarchyOffset = range ? getHierarchyOffset(range.start.col, range.start.row, table) : getHierarchyOffset(col, row, table); - if (dealWithIconComputeVar) { - dealWithIconComputeVar.addedHierarchyOffset = 1; - } } iconAttribute.marginLeft = (icon.marginLeft ?? 0) + hierarchyOffset; @@ -565,9 +517,6 @@ export function updateCellContentWidth( textBaseline: CanvasTextBaseline, scene: Scenegraph ): boolean { - if (isValidNumber(cellGroup.contentWidth)) { - detaX = distWidth - (cellGroup.contentWidth ?? cellGroup.attribute.width); - } let leftIconWidth = 0; let leftIconHeight = 0; let rightIconWidth = 0; @@ -592,12 +541,7 @@ export function updateCellContentWidth( oldTextHeight = textMark.AABBBounds.height(); textMark.setAttribute( 'maxLineWidth', - distWidth - - leftIconWidth - - rightIconHeight - - (padding[1] + padding[3]) - - (textMark.attribute.dx ?? 0) - - (scene.table.theme._contentOffset ?? 0) + distWidth - leftIconWidth - rightIconHeight - (padding[1] + padding[3]) - (textMark.attribute.dx ?? 0) ); // contentWidth = textMark.AABBBounds.width(); contentHeight = textMark.AABBBounds.height(); @@ -623,7 +567,7 @@ export function updateCellContentWidth( child.setAttribute('x', child.attribute.x + detaX); } else if (child.role === 'icon-absolute-right') { child.setAttribute('x', child.attribute.x + detaX); - } else if (child.name === 'content' || (child.name === 'text' && child.type !== 'richtext')) { + } else if (child.name === 'content' || child.name === 'text') { const childTextAlign = child.attribute.textAlign ?? textAlign; if (childTextAlign === 'center') { child.setAttribute( @@ -644,7 +588,7 @@ export function updateCellContentWidth( if (autoRowHeight) { let newHeight = Math.max(leftIconHeight, contentHeight, rightIconHeight); // + padding[0] + padding[2] - if (isCellHeightUpdate(scene, cellGroup, Math.round(newHeight + padding[0] + padding[2]), oldCellHeight)) { + if (isCellHeightUpdate(scene, cellGroup, newHeight + padding[0] + padding[2], oldCellHeight)) { // cellGroup.setAttribute('height', newHeight + padding[0] + padding[2]); return true; } @@ -696,7 +640,7 @@ export function updateCellContentHeight( textAlign: CanvasTextAlign, textBaseline: CanvasTextBaseline ) { - const newHeight = distHeight - Math.floor(padding[0] + padding[2]); + const newHeight = distHeight - (padding[0] + padding[2]); const textMark = cellGroup.getChildByName('text'); @@ -771,116 +715,3 @@ function isCellHeightUpdate(scene: Scenegraph, cellGroup: Group, newHeight: numb return false; } - -export function dealWithIconLayout( - icons: ColumnIconOption[], - cellGroup: Group, - range: CellRange | undefined, - table: BaseTableAPI -) { - const leftIcons: ColumnIconOption[] = []; - const rightIcons: ColumnIconOption[] = []; - const contentLeftIcons: ColumnIconOption[] = []; - const contentRightIcons: ColumnIconOption[] = []; - const inlineFrontIcons: ColumnIconOption[] = []; - const inlineEndIcons: ColumnIconOption[] = []; - const absoluteLeftIcons: ColumnIconOption[] = []; - const absoluteRightIcons: ColumnIconOption[] = []; - - let leftIconWidth = 0; - let leftIconHeight = 0; - let rightIconWidth = 0; - let rightIconHeight = 0; - let absoluteLeftIconWidth = 0; - let absoluteRightIconWidth = 0; - - // icon分类 - icons.forEach(icon => { - switch (icon.positionType) { - case IconPosition.left: - leftIcons.push(icon); - break; - case IconPosition.right: - rightIcons.push(icon); - break; - case IconPosition.contentLeft: - contentLeftIcons.push(icon); - break; - case IconPosition.contentRight: - contentRightIcons.push(icon); - break; - // case IconPosition.absoluteLeft: - // absoluteLeftIcons.push(icon); - // break; - case IconPosition.absoluteRight: - absoluteRightIcons.push(icon); - break; - case IconPosition.inlineFront: - inlineFrontIcons.push(icon); - break; - case IconPosition.inlineEnd: - inlineEndIcons.push(icon); - break; - } - }); - - // 添加非cell icon & absolute icon - leftIcons.forEach(icon => { - const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); - iconMark.role = 'icon-left'; - iconMark.name = icon.name; - iconMark.setAttribute('x', leftIconWidth + (iconMark.attribute.marginLeft ?? 0)); - leftIconWidth += - iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); - leftIconHeight = Math.max(leftIconHeight, iconMark.AABBBounds.height()); - cellGroup.appendChild(iconMark); - }); - - rightIcons.forEach(icon => { - const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); - iconMark.role = 'icon-right'; - iconMark.name = icon.name; - iconMark.setAttribute('x', rightIconWidth + (iconMark.attribute.marginLeft ?? 0)); - rightIconWidth += - iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); - rightIconHeight = Math.max(rightIconHeight, iconMark.AABBBounds.height()); - cellGroup.appendChild(iconMark); - }); - - absoluteLeftIcons.forEach(icon => { - const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); - iconMark.role = 'icon-absolute-left'; - iconMark.name = icon.name; - iconMark.setAttribute('x', absoluteLeftIconWidth + (iconMark.attribute.marginLeft ?? 0)); - absoluteLeftIconWidth += - iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); - cellGroup.appendChild(iconMark); - }); - - absoluteRightIcons.forEach(icon => { - const iconMark = dealWithIcon(icon, undefined, cellGroup.col, cellGroup.row, range, table); - iconMark.role = 'icon-absolute-right'; - iconMark.name = icon.name; - iconMark.setAttribute('x', absoluteRightIconWidth + (iconMark.attribute.marginLeft ?? 0)); - absoluteRightIconWidth += - iconMark.AABBBounds.width() + (iconMark.attribute.marginLeft ?? 0) + (iconMark.attribute.marginRight ?? 0); - cellGroup.appendChild(iconMark); - }); - - return { - leftIcons, - rightIcons, - contentLeftIcons, - contentRightIcons, - inlineFrontIcons, - inlineEndIcons, - absoluteLeftIcons, - absoluteRightIcons, - leftIconWidth, - leftIconHeight, - rightIconWidth, - rightIconHeight, - absoluteLeftIconWidth, - absoluteRightIconWidth - }; -} diff --git a/packages/vtable/src/scenegraph/utils/text-measure.ts b/packages/vtable/src/scenegraph/utils/text-measure.ts index 078dd9206..d55b3fcb2 100644 --- a/packages/vtable/src/scenegraph/utils/text-measure.ts +++ b/packages/vtable/src/scenegraph/utils/text-measure.ts @@ -275,9 +275,6 @@ const utilTextMark = new Text({ }); export function measureTextBounds(attribute: ITextGraphicAttribute) { - utilTextMark.initAttributes({ - ...attribute, - ignoreBuf: true - }); + utilTextMark.setAttributes(attribute); return utilTextMark.AABBBounds; } diff --git a/packages/vtable/src/state/cell-move/adjust-header.ts b/packages/vtable/src/state/cell-move/adjust-header.ts index ae018d70f..48ba3705f 100644 --- a/packages/vtable/src/state/cell-move/adjust-header.ts +++ b/packages/vtable/src/state/cell-move/adjust-header.ts @@ -31,9 +31,9 @@ export function adjustMoveHeaderTarget(source: CellAddress, target: CellAddress, } // tree模式[透视表行表头] if (layoutMap.rowHierarchyType === 'tree') { - const sourceRowHeaderPaths = layoutMap.getCellHeaderPathsWithTreeNode(source.col, source.row) + const sourceRowHeaderPaths = layoutMap.getCellHeaderPathsWidthTreeNode(source.col, source.row) .rowHeaderPaths as any; - const targetRowHeaderPaths = layoutMap.getCellHeaderPathsWithTreeNode(target.col, target.row) + const targetRowHeaderPaths = layoutMap.getCellHeaderPathsWidthTreeNode(target.col, target.row) .rowHeaderPaths as any; if (sourceRowHeaderPaths.length <= targetRowHeaderPaths.length) { const targetPathNode = targetRowHeaderPaths[sourceRowHeaderPaths.length - 1]; //找到共同层级节点 diff --git a/packages/vtable/src/state/cell-move/index.ts b/packages/vtable/src/state/cell-move/index.ts index 8a23d0d28..3d159a38a 100644 --- a/packages/vtable/src/state/cell-move/index.ts +++ b/packages/vtable/src/state/cell-move/index.ts @@ -29,9 +29,8 @@ export function startMoveCol(col: number, row: number, x: number, y: number, sta state.table.scenegraph.component.showMoveCol(col, row, delta); // 调整列顺序期间清空选中清空 - const isHasSelected = !!state.select.ranges?.length; state.table.stateManager.updateSelectPos(-1, -1); - state.table.stateManager.endSelectCells(true, isHasSelected); + state.table.scenegraph.updateNextFrame(); } @@ -130,7 +129,6 @@ export function endMoveCol(state: StateManager) { // 更新状态 if (moveContext) { - state.table.internalProps.useOneRowHeightFillAll = false; state.table.internalProps.layoutMap.clearCellRangeMap(); const sourceMergeInfo = state.table.getCellRange(state.columnMove.colSource, state.columnMove.rowSource); const targetMergeInfo = state.table.getCellRange(state.columnMove.colTarget, state.columnMove.rowTarget); @@ -177,7 +175,6 @@ export function endMoveCol(state: StateManager) { ) ) { state.table.changeRecordOrder(moveContext.sourceIndex, moveContext.targetIndex); - state.changeCheckboxAndRadioOrder(moveContext.sourceIndex, moveContext.targetIndex); } // clear columns width and rows height cache if (moveContext.moveType === 'column') { diff --git a/packages/vtable/src/state/checkbox/checkbox.ts b/packages/vtable/src/state/checkbox/checkbox.ts index df0cd52aa..feb3729d3 100644 --- a/packages/vtable/src/state/checkbox/checkbox.ts +++ b/packages/vtable/src/state/checkbox/checkbox.ts @@ -225,19 +225,3 @@ export function setCellCheckboxState(col: number, row: number, checked: boolean, } } } - -export function changeCheckboxOrder(sourceIndex: number, targetIndex: number, state: StateManager) { - const { checkedState, table } = state; - if (table.internalProps.transpose) { - sourceIndex = table.getRecordShowIndexByCell(sourceIndex, 0); - targetIndex = table.getRecordShowIndexByCell(targetIndex, 0); - } else { - sourceIndex = table.getRecordShowIndexByCell(0, sourceIndex); - targetIndex = table.getRecordShowIndexByCell(0, targetIndex); - } - if (sourceIndex !== targetIndex) { - const sourceRecord = checkedState[sourceIndex]; - checkedState[sourceIndex] = checkedState[targetIndex]; - checkedState[targetIndex] = sourceRecord; - } -} diff --git a/packages/vtable/src/state/radio/radio.ts b/packages/vtable/src/state/radio/radio.ts index 146f87ddc..faa7bf342 100644 --- a/packages/vtable/src/state/radio/radio.ts +++ b/packages/vtable/src/state/radio/radio.ts @@ -138,19 +138,3 @@ export function setCellRadioState(col: number, row: number, index: number | unde radio?._handlePointerUp(); } } - -export function changeRadioOrder(sourceIndex: number, targetIndex: number, state: StateManager) { - const { radioState, table } = state; - if (table.internalProps.transpose) { - sourceIndex = table.getRecordShowIndexByCell(sourceIndex, 0); - targetIndex = table.getRecordShowIndexByCell(targetIndex, 0); - } else { - sourceIndex = table.getRecordShowIndexByCell(0, sourceIndex); - targetIndex = table.getRecordShowIndexByCell(0, targetIndex); - } - if (sourceIndex !== targetIndex) { - const sourceRecord = radioState[sourceIndex]; - radioState[sourceIndex] = radioState[targetIndex]; - radioState[targetIndex] = sourceRecord; - } -} diff --git a/packages/vtable/src/state/resize/update-resize-column.ts b/packages/vtable/src/state/resize/update-resize-column.ts index ed1f4afa9..026297f36 100644 --- a/packages/vtable/src/state/resize/update-resize-column.ts +++ b/packages/vtable/src/state/resize/update-resize-column.ts @@ -188,9 +188,7 @@ function updateResizeColForIndicatorGroup(detaX: number, state: StateManager) { const layout = state.table.internalProps.layoutMap as PivotHeaderLayoutMap; //通过getCellHeaderPaths接口获取列表头最后一层指标维度的path const headerPaths = layout.getCellHeaderPaths(state.columnResize.col, state.table.columnHeaderLevelCount); - const node = layout.getHeadNodeByRowOrColDimensions( - headerPaths.colHeaderPaths.slice(0, headerPaths.colHeaderPaths.length - 1) - ) as any; + const node = layout.getHeadNode(headerPaths.colHeaderPaths.slice(0, headerPaths.colHeaderPaths.length - 1)) as any; // 计算宽度受影响列的起止 const startCol = node.startInTotal + state.table.frozenColCount; const endCol = node.startInTotal + state.table.frozenColCount + node.size - 1; diff --git a/packages/vtable/src/state/resize/update-resize-row.ts b/packages/vtable/src/state/resize/update-resize-row.ts index 3409b6ece..f12eaa1a8 100644 --- a/packages/vtable/src/state/resize/update-resize-row.ts +++ b/packages/vtable/src/state/resize/update-resize-row.ts @@ -95,9 +95,9 @@ function updateResizeColForIndicator(detaY: number, state: StateManager) { resizeIndicatorKey = layout.getIndicatorKey(state.table.rowHeaderLevelCount, state.rowResize.row); } else { const headerPaths = layout.getCellHeaderPaths(state.table.rowHeaderLevelCount - 1, state.rowResize.row); - const headerPath = headerPaths.rowHeaderPaths?.[headerPaths.rowHeaderPaths.length - 1]; - resizeDimensionKey = headerPath?.dimensionKey; - resizeDimensionValue = headerPath?.value; + const headerPath = headerPaths.rowHeaderPaths[headerPaths.rowHeaderPaths.length - 1]; + resizeDimensionKey = headerPath.dimensionKey; + resizeDimensionValue = headerPath.value; } for ( let row = state.table.columnHeaderLevelCount; @@ -110,7 +110,7 @@ function updateResizeColForIndicator(detaY: number, state: StateManager) { state.table.internalProps._heightResizedRowMap.add(row); } else if (layout.indicatorsAsCol) { const headerPaths = layout.getCellHeaderPaths(state.table.rowHeaderLevelCount - 1, row); - const headerPath = headerPaths?.rowHeaderPaths?.[headerPaths.rowHeaderPaths.length - 1]; + const headerPath = headerPaths?.rowHeaderPaths[headerPaths.rowHeaderPaths.length - 1]; if (headerPath && resizeDimensionKey === headerPath.dimensionKey && resizeDimensionValue === headerPath.value) { state.table.scenegraph.updateRowHeight(row, detaY); state.table.internalProps._heightResizedRowMap.add(row); @@ -124,9 +124,7 @@ function updateResizeColForIndicatorGroup(detaY: number, state: StateManager) { const layout = state.table.internalProps.layoutMap as PivotHeaderLayoutMap; //通过getCellHeaderPaths接口获取列表头最后一层指标维度的path const headerPaths = layout.getCellHeaderPaths(state.table.rowHeaderLevelCount, state.rowResize.row); - const node = layout.getHeadNodeByRowOrColDimensions( - headerPaths.rowHeaderPaths.slice(0, headerPaths.rowHeaderPaths.length - 1) - ) as any; + const node = layout.getHeadNode(headerPaths.rowHeaderPaths.slice(0, headerPaths.rowHeaderPaths.length - 1)) as any; // 计算宽度受影响列的起止 const startRow = node.startInTotal + state.table.frozenRowCount; const endRow = node.startInTotal + state.table.frozenRowCount + node.size - 1; diff --git a/packages/vtable/src/state/select/is-cell-select-highlight.ts b/packages/vtable/src/state/select/is-cell-select-highlight.ts deleted file mode 100644 index 2abaa146d..000000000 --- a/packages/vtable/src/state/select/is-cell-select-highlight.ts +++ /dev/null @@ -1,115 +0,0 @@ -import type { StateManager } from '../state'; -import type { Group } from '../../scenegraph/graphic/group'; -import { getProp } from '../../scenegraph/utils/get-prop'; -import type { BaseTableAPI } from '../../ts-types/base-table'; -import type { ColumnDefine } from '../../ts-types'; -import { HighlightScope } from '../../ts-types'; -import { isValid } from '@visactor/vutils'; -import { getCellMergeRange } from '../../tools/merge-range'; - -export function getCellSelectColor(cellGroup: Group, table: BaseTableAPI): string | undefined { - let colorKey; - if ( - cellGroup.role === 'cell' && - isValid(cellGroup.mergeStartCol) && - isValid(cellGroup.mergeStartRow) && - isValid(cellGroup.mergeEndCol) && - isValid(cellGroup.mergeEndRow) - ) { - const { colStart, colEnd, rowStart, rowEnd } = getCellMergeRange(cellGroup, table.scenegraph); - for (let col = colStart; col <= colEnd; col++) { - for (let row = rowStart; row <= rowEnd; row++) { - const key = isCellSelected(table.stateManager, col, row, cellGroup); - if (key && (!colorKey || key === 'cellBgColor')) { - colorKey = key; - } - } - } - } else if (cellGroup.role === 'cell') { - colorKey = isCellSelected(table.stateManager, cellGroup.col, cellGroup.row, cellGroup); - } - - if (!colorKey) { - return undefined; - } - - let selectStyle; - const layout = table.internalProps.layoutMap; - if (layout.isCornerHeader(cellGroup.col, cellGroup.row)) { - selectStyle = table.theme.cornerHeaderStyle?.select || table.theme.headerStyle?.select; - } else if (layout.isColumnHeader(cellGroup.col, cellGroup.row)) { - selectStyle = table.theme.headerStyle?.select; - } else if (layout.isRowHeader(cellGroup.col, cellGroup.row)) { - selectStyle = table.theme.rowHeaderStyle?.select; - } else if (layout.isBottomFrozenRow(cellGroup.col, cellGroup.row)) { - selectStyle = - table.theme.bottomFrozenStyle?.select || - (table.isListTable() ? table.theme.bodyStyle?.select : table.theme.headerStyle?.select); - } else if (layout.isRightFrozenColumn(cellGroup.col, cellGroup.row)) { - selectStyle = - table.theme.rightFrozenStyle?.select || - (table.isListTable() ? table.theme.bodyStyle?.select : table.theme.rowHeaderStyle?.select); - } else if (!table.isHeader(cellGroup.col, cellGroup.row)) { - selectStyle = table.theme.bodyStyle?.select; - } - const fillColor = getProp(colorKey, selectStyle, cellGroup.col, cellGroup.row, table); - return fillColor; -} - -export function isCellSelected(state: StateManager, col: number, row: number, cellGroup: Group): string | undefined { - const { highlightScope, disableHeader, cellPos, ranges } = state.select; - - let selectMode; - if (ranges?.length === 1 && ranges[0].end.col === ranges[0].start.col && ranges[0].end.row === ranges[0].start.row) { - const table = state.table; - - const isHeader = table.isHeader(col, row); - if (isHeader && disableHeader) { - return undefined; - } - - if (highlightScope === HighlightScope.single && cellPos.col === col && cellPos.row === row) { - selectMode = 'cellBgColor'; - } else if (highlightScope === HighlightScope.column && cellPos.col === col) { - if (cellPos.col === col && cellPos.row === row) { - selectMode = 'cellBgColor'; - } else { - selectMode = 'inlineColumnBgColor'; - } - } else if (highlightScope === HighlightScope.row && cellPos.row === row) { - if (cellPos.col === col && cellPos.row === row) { - selectMode = 'cellBgColor'; - } else { - selectMode = 'inlineRowBgColor'; - } - } else if (highlightScope === HighlightScope.cross) { - if (cellPos.col === col && cellPos.row === row) { - selectMode = 'cellBgColor'; - } else if (cellPos.col === col) { - selectMode = 'inlineColumnBgColor'; - } else if (cellPos.row === row) { - selectMode = 'inlineRowBgColor'; - } - } - - if (selectMode) { - let cellDisable; - if (isHeader) { - const define = table.getHeaderDefine(col, row); - cellDisable = (define as ColumnDefine)?.disableHeaderSelect; - - // if (cellGroup.firstChild && cellGroup.firstChild.name === 'axis' && table.options.select?.disableAxisHover) { - // cellDisable = true; - // } - } else { - const define = table.getBodyColumnDefine(col, row); - cellDisable = (define as ColumnDefine)?.disableSelect; - } - - if (cellDisable) { - selectMode = undefined; - } - } - } - return selectMode; -} diff --git a/packages/vtable/src/state/select/update-position.ts b/packages/vtable/src/state/select/update-position.ts index c662c2ecf..afd54a5d2 100644 --- a/packages/vtable/src/state/select/update-position.ts +++ b/packages/vtable/src/state/select/update-position.ts @@ -1,6 +1,5 @@ import type { SimpleHeaderLayoutMap } from '../../layout'; import type { Scenegraph } from '../../scenegraph/scenegraph'; -import type { SelectAllOnCtrlAOption } from '../../ts-types'; import { InteractionState } from '../../ts-types'; import type { StateManager } from '../state'; /** @@ -17,17 +16,12 @@ export function updateSelectPosition( isShift: boolean, isCtrl: boolean, isSelectAll: boolean, - isSelectMoving: boolean = false, - skipBodyMerge: boolean = false + isSelectMoving: boolean = false ) { const { table, interactionState } = state; const { scenegraph } = table; const { highlightScope, disableHeader, cellPos } = state.select; - if ((disableHeader && table.isHeader(col, row)) || highlightScope === 'none') { - if (col !== -1 && row !== -1 && !isSelectMoving) { - table._makeVisibleCell(col, row); - } col = -1; row = -1; } @@ -62,27 +56,18 @@ export function updateSelectPosition( if (isSelectAll) { state.select.ranges = []; scenegraph.deleteAllSelectBorder(); - let _startCol = 0; - let _startRow = 0; - const { disableHeaderSelect, disableRowSeriesNumberSelect } = - (table.options.keyboardOptions?.selectAllOnCtrlA as SelectAllOnCtrlAOption) || {}; - - // 表头选中 - if (disableHeaderSelect) { - _startCol = table.rowHeaderLevelCount; - _startRow = table.columnHeaderLevelCount; - } - // 行号列选中 - if ((disableRowSeriesNumberSelect || disableHeaderSelect) && table.options.rowSeriesNumber) { - _startCol += 1; - } - state.select.ranges.push({ - start: { col: _startCol, row: _startRow }, + start: { col: 0, row: 0 }, end: { col: table.colCount - 1, row: table.rowCount - 1 } }); const currentRange = state.select.ranges[state.select.ranges.length - 1]; - scenegraph.updateCellSelectBorder(currentRange, false); + scenegraph.updateCellSelectBorder( + currentRange.start.col, + currentRange.start.row, + currentRange.end.col, + currentRange.end.row, + false + ); } else if (cellPos.col !== -1 && cellPos.row !== -1 && (col === -1 || row === -1)) { // 输入-1清空选中状态 // clearMultiSelect(scenegraph, ranges, highlightScope, singleStyle); @@ -98,10 +83,6 @@ export function updateSelectPosition( ) { const currentRange = state.select.ranges[state.select.ranges.length - 1]; if (isShift && currentRange) { - if (!isCtrl) { - cellPos.col = col; - cellPos.row = row; - } if (state.select.headerSelectMode !== 'cell' && table.isColumnHeader(col, row)) { const startCol = Math.min(currentRange.start.col, currentRange.end.col, col); const endCol = Math.max(currentRange.start.col, currentRange.end.col, col); @@ -121,7 +102,12 @@ export function updateSelectPosition( currentRange.end = { col, row }; } scenegraph.deleteLastSelectedRangeComponents(); - scenegraph.updateCellSelectBorder(currentRange); + scenegraph.updateCellSelectBorder( + currentRange.start.col, + currentRange.start.row, + currentRange.end.col, + currentRange.end.row + ); // } else if (isCtrl) { // cellPos.col = col; // cellPos.row = row; @@ -135,7 +121,7 @@ export function updateSelectPosition( // // 更新select border // // calculateAndUpdateMultiSelectBorder(scenegraph, col, row, col, row, state.select.ranges); // // 更新select border - // scenegraph.updateCellSelectBorder(cellPos); + // scenegraph.updateCellSelectBorder(cellPos.col, cellPos.row, cellPos.col, cellPos.row); } else { let extendSelectRange = true; // 单选或多选开始 @@ -144,51 +130,48 @@ export function updateSelectPosition( scenegraph.deleteAllSelectBorder(); } if (state.select.headerSelectMode !== 'cell' && table.isColumnHeader(col, row)) { - // 选中行表头 const cellRange = table.getCellRange(col, row); state.select.ranges.push({ start: { col: cellRange.start.col, row }, - end: { col: cellRange.end.col, row: table.rowCount - 1 }, - skipBodyMerge: true + end: { col: cellRange.end.col, row: table.rowCount - 1 } }); } else if (state.select.headerSelectMode !== 'cell' && table.isRowHeader(col, row)) { - // 选中列表头 const cellRange = table.getCellRange(col, row); state.select.ranges.push({ start: { col, row: cellRange.start.row }, - end: { col: table.colCount - 1, row: cellRange.end.row }, - skipBodyMerge: true + end: { col: table.colCount - 1, row: cellRange.end.row } }); } else if ((table.internalProps.layoutMap as SimpleHeaderLayoutMap).isSeriesNumberInHeader(col, row)) { - // 选中表头行号单元格 extendSelectRange = false; state.select.ranges.push({ start: { col: 0, row: 0 }, - end: { col: table.colCount - 1, row: table.rowCount - 1 }, - skipBodyMerge: true + end: { col: table.colCount - 1, row: table.rowCount - 1 } }); } else if ((table.internalProps.layoutMap as SimpleHeaderLayoutMap).isSeriesNumberInBody(col, row)) { - // 选中内容行号单元格 extendSelectRange = false; state.select.ranges.push({ start: { col, row: row }, - end: { col: table.colCount - 1, row: row }, - skipBodyMerge: true + end: { col: table.colCount - 1, row: row } }); } else if (col >= 0 && row >= 0) { - // 选中普通单元格 - const cellRange = skipBodyMerge ? { start: { col, row }, end: { col, row } } : table.getCellRange(col, row); + const cellRange = table.getCellRange(col, row); state.select.ranges.push({ start: { col: cellRange.start.col, row: cellRange.start.row }, - end: { col: cellRange.end.col, row: cellRange.end.row }, - skipBodyMerge: skipBodyMerge || undefined + end: { col: cellRange.end.col, row: cellRange.end.row } }); } cellPos.col = col; cellPos.row = row; // scenegraph.setCellNormalStyle(col, row); const currentRange = state.select.ranges?.[state.select.ranges.length - 1]; - currentRange && scenegraph.updateCellSelectBorder(currentRange, extendSelectRange); + currentRange && + scenegraph.updateCellSelectBorder( + currentRange.start.col, + currentRange.start.row, + currentRange.end.col, + currentRange.end.row, + extendSelectRange + ); } } else if ( (interactionState === InteractionState.grabing || table.eventManager.isDraging) && @@ -279,12 +262,15 @@ export function updateSelectPosition( col, row }; - if (skipBodyMerge) { - currentRange.skipBodyMerge = true; - } } } - scenegraph.updateCellSelectBorder(currentRange, extendSelectRange); + scenegraph.updateCellSelectBorder( + currentRange.start.col, + currentRange.start.row, + currentRange.end.col, + currentRange.end.row, + extendSelectRange + ); } } scenegraph.updateNextFrame(); diff --git a/packages/vtable/src/state/sort/index.ts b/packages/vtable/src/state/sort/index.ts index c32383268..149e1f697 100644 --- a/packages/vtable/src/state/sort/index.ts +++ b/packages/vtable/src/state/sort/index.ts @@ -67,14 +67,11 @@ export function dealSort(col: number, row: number, table: ListTableAPI, event: E } // clear cell range cache - table.internalProps.useOneRowHeightFillAll = false; table.internalProps.layoutMap.clearCellRangeMap(); table.scenegraph.sortCell(); // 排序后,清除选中效果 - const isHasSelected = !!table.stateManager.select.ranges?.length; table.stateManager.updateSelectPos(-1, -1); - table.stateManager.endSelectCells(true, isHasSelected); } function executeSort(newState: SortState, table: BaseTableAPI, headerDefine: HeaderDefine): void { diff --git a/packages/vtable/src/state/state.ts b/packages/vtable/src/state/state.ts index 3562e0ba4..ee472875c 100644 --- a/packages/vtable/src/state/state.ts +++ b/packages/vtable/src/state/state.ts @@ -6,6 +6,7 @@ import type { CellAddress, CellPosition, CellRange, + CheckboxColumnDefine, DropDownMenuHighlightInfo, IDimensionInfo, ListTableAPI, @@ -14,7 +15,7 @@ import type { SortOrder, SortState } from '../ts-types'; -import { HighlightScope, InteractionState, SortType } from '../ts-types'; +import { HighlightScope, InteractionState } from '../ts-types'; import { IconFuncTypeEnum } from '../ts-types'; import { checkMultiCellInSelect } from './common/check-in-select'; import { updateHoverPosition } from './hover/update-position'; @@ -36,9 +37,8 @@ import { getIconAndPositionFromTarget } from '../scenegraph/utils/icon'; import type { BaseTableAPI, HeaderData } from '../ts-types/base-table'; import { debounce } from '../tools/debounce'; import { updateResizeColumn } from './resize/update-resize-column'; -import { changeRadioOrder, setRadioState, syncRadioState } from './radio/radio'; +import { setRadioState, syncRadioState } from './radio/radio'; import { - changeCheckboxOrder, initCheckedState, initLeftRecordsCheckState, setCheckedState, @@ -48,7 +48,6 @@ import { } from './checkbox/checkbox'; import { updateResizeRow } from './resize/update-resize-row'; import { deleteAllSelectingBorder } from '../scenegraph/select/delete-select-border'; -import type { PivotTable } from '../PivotTable'; export class StateManager { table: BaseTableAPI; @@ -63,7 +62,7 @@ export class StateManager { interactionState: InteractionState; // select记录两个位置,第二个位置只在range模式生效 select: { - ranges: (CellRange & { skipBodyMerge?: boolean })[]; + ranges: CellRange[]; highlightScope: HighlightScope; cellPos: CellPosition; // cellPosStart: CellPosition; @@ -408,16 +407,14 @@ export class StateManager { /** 点击表头单元格时连带body整行或整列选中 或仅选中当前单元格,默认或整行或整列选中*/ headerSelectMode, disableSelect, - disableHeaderSelect, - highlightMode + disableHeaderSelect } = Object.assign( {}, { /** 点击表头单元格时连带body整行或整列选中 或仅选中当前单元格,默认或整行或整列选中*/ headerSelectMode: 'inline', disableSelect: false, - disableHeaderSelect: false, - highlightMode: 'cell' + disableHeaderSelect: false }, this.table.options.select ); @@ -430,15 +427,7 @@ export class StateManager { // this.select.highlightScope = HighlightScope.column; // } else if (!disableSelect) { - if (highlightMode === 'cross') { - this.select.highlightScope = HighlightScope.cross; - } else if (highlightMode === 'row') { - this.select.highlightScope = HighlightScope.row; - } else if (highlightMode === 'column') { - this.select.highlightScope = HighlightScope.column; - } else { - this.select.highlightScope = HighlightScope.single; - } + this.select.highlightScope = HighlightScope.single; } else { this.select.highlightScope = HighlightScope.none; } @@ -511,13 +500,12 @@ export class StateManager { isShift: boolean = false, isCtrl: boolean = false, isSelectAll: boolean = false, - isSelectMoving: boolean = false, - skipBodyMerge: boolean = false + isSelectMoving: boolean = false ) { if (row !== -1 && row !== -1) { this.select.selecting = true; } - updateSelectPosition(this, col, row, isShift, isCtrl, isSelectAll, isSelectMoving, skipBodyMerge); + updateSelectPosition(this, col, row, isShift, isCtrl, isSelectAll, isSelectMoving); } checkCellRangeInSelect(cellPosStart: CellAddress, cellPosEnd: CellAddress) { @@ -572,8 +560,7 @@ export class StateManager { this.table.internalProps.theme?.tooltipStyle, inlineIcon.tooltip?.style, inlineIcon.attribute?.tooltip?.style - ), - disappearDelay: inlineIcon.attribute.tooltip.disappearDelay + ) }; if (!this.table.internalProps.tooltipHandler.isBinded(tooltipOptions)) { this.table.showTooltip(col, row, tooltipOptions); @@ -610,7 +597,7 @@ export class StateManager { isSelecting(): boolean { return this.select.selecting; } - endSelectCells(fireListener: boolean = true, fireClear: boolean = true) { + endSelectCells(fireListener: boolean = true) { if (this.select.selecting) { this.select.selecting = false; if (this.select.ranges.length === 0) { @@ -651,10 +638,6 @@ export class StateManager { col: lastCol, row: lastRow }); - } else if (fireClear) { - if (this.select.ranges.length === 0) { - this.table.fireListeners(TABLE_EVENT_TYPE.SELECTED_CLEAR, {}); - } } } @@ -676,9 +659,8 @@ export class StateManager { this.table.scenegraph.component.showResizeCol(col, y, isRightFrozen); // 调整列宽期间清空选中清空 - const isHasSelected = !!this.select.ranges?.length; this.updateSelectPos(-1, -1); - this.endSelectCells(true, isHasSelected); + this.table.scenegraph.updateNextFrame(); } updateResizeCol(xInTable: number, yInTable: number) { @@ -703,9 +685,8 @@ export class StateManager { this.table.scenegraph.component.showResizeRow(row, x, isBottomFrozen); // 调整列宽期间清空选中清空 - const isHasSelected = !!this.select.ranges?.length; this.updateSelectPos(-1, -1); - this.endSelectCells(true, isHasSelected); + this.table.scenegraph.updateNextFrame(); } updateResizeRow(xInTable: number, yInTable: number) { @@ -764,7 +745,7 @@ export class StateManager { checkFrozen(): boolean { // 判断固定列的总宽度 是否过大 - let originalFrozenColCount = + const originalFrozenColCount = this.table.isListTable() && !this.table.internalProps.transpose ? this.table.options.frozenColCount : this.table.isPivotChart() @@ -774,9 +755,6 @@ export class StateManager { this.table.options.frozenColCount ?? 0 ); if (originalFrozenColCount) { - if (originalFrozenColCount > this.table.colCount) { - originalFrozenColCount = this.table.colCount; - } if (this.table.tableNoFrameWidth - this.table.getColsWidth(0, originalFrozenColCount - 1) <= 120) { this.table._setFrozenColCount(0); this.setFrozenCol(-1); @@ -903,12 +881,7 @@ export class StateManager { setScrollTop(top: number) { // 矫正top值范围 const totalHeight = this.table.getAllRowsHeight(); - // _disableColumnAndRowSizeRound环境中,可能出现 - // getAllColsWidth/getAllRowsHeight(A) + getAllColsWidth/getAllRowsHeight(B) < getAllColsWidth/getAllRowsHeight(A+B) - // (由于小数在取数时被省略) - // 这里加入tolerance,避免出现无用滚动 - const sizeTolerance = this.table.options.customConfig?._disableColumnAndRowSizeRound ? 1 : 0; - top = Math.max(0, Math.min(top, totalHeight - this.table.scenegraph.height - sizeTolerance)); + top = Math.max(0, Math.min(top, totalHeight - this.table.scenegraph.height)); top = Math.ceil(top); // 滚动期间清空选中清空 如果调用接口hover状态需要保留,但是如果不调用updateHoverPos透视图处于hover状态的图就不能及时更新 所以这里单独判断了isPivotChart if (top !== this.scroll.verticalBarPos || this.table.isPivotChart()) { @@ -948,13 +921,7 @@ export class StateManager { const totalWidth = this.table.getAllColsWidth(); const frozenWidth = this.table.getFrozenColsWidth(); - // _disableColumnAndRowSizeRound环境中,可能出现 - // getAllColsWidth/getAllRowsHeight(A) + getAllColsWidth/getAllRowsHeight(B) < getAllColsWidth/getAllRowsHeight(A+B) - // (由于小数在取数时被省略) - // 这里加入tolerance,避免出现无用滚动 - const sizeTolerance = this.table.options.customConfig?._disableColumnAndRowSizeRound ? 1 : 0; - - left = Math.max(0, Math.min(left, totalWidth - this.table.scenegraph.width - sizeTolerance)); + left = Math.max(0, Math.min(left, totalWidth - this.table.scenegraph.width)); left = Math.ceil(left); // 滚动期间清空选中清空 if (left !== this.scroll.horizontalBarPos) { @@ -1190,13 +1157,7 @@ export class StateManager { triggerSort(col: number, row: number, iconMark: Icon, event: Event) { if (this.table.isPivotTable()) { // 透视表不执行sort操作 - const sortState = (this.table as PivotTableAPI).getPivotSortState(col, row); - - const order = sortState ? (sortState.toUpperCase() as SortOrder) : 'DESC'; - // const new_order = order === 'ASC' ? 'DESC' : order === 'DESC' ? 'NORMAL' : 'ASC'; - const new_order = order === 'ASC' ? 'DESC' : 'ASC'; - (this.table as PivotTable).sort(col, row, new_order); - + const order = (this.table as PivotTableAPI).getPivotSortState(col, row); // // 触发透视表排序按钮点击 this.table.fireListeners(PIVOT_TABLE_EVENT_TYPE.PIVOT_SORT_CLICK, { col: col, @@ -1399,13 +1360,4 @@ export class StateManager { ) { return syncRadioState(col, row, field, radioType, indexInCell, isChecked, this); } - - changeCheckboxAndRadioOrder(sourceIndex: number, targetIndex: number) { - if (this.checkedState.length) { - changeCheckboxOrder(sourceIndex, targetIndex, this); - } - if (this.radioState.length) { - changeRadioOrder(sourceIndex, targetIndex, this); - } - } } diff --git a/packages/vtable/src/themes/DEFAULT.ts b/packages/vtable/src/themes/DEFAULT.ts index a1f714acb..1989eda43 100644 --- a/packages/vtable/src/themes/DEFAULT.ts +++ b/packages/vtable/src/themes/DEFAULT.ts @@ -118,6 +118,8 @@ export default { selectionStyle: { cellBgColor: 'rgba(0, 0, 255,0.1)', cellBorderLineWidth: 2, + inlineColumnBgColor: '#CCE0FF', + inlineRowBgColor: '#CCE0FF', cellBorderColor: '#0000ff' }, tooltipStyle: { diff --git a/packages/vtable/src/themes/theme.ts b/packages/vtable/src/themes/theme.ts index c924f2b19..768d931aa 100644 --- a/packages/vtable/src/themes/theme.ts +++ b/packages/vtable/src/themes/theme.ts @@ -121,7 +121,6 @@ export class TableTheme implements ITableThemeDefine { get defaultStyle(): RequiredTableThemeDefine['defaultStyle'] { // const defaultStyle = getProp(obj, superTheme, ["defaultStyle"]); - const that = this; if (!this._defaultStyle) { const { obj, superTheme } = this.internalTheme; const defaultStyle: ThemeStyle = ingoreNoneValueMerge({}, superTheme.defaultStyle, obj.defaultStyle); @@ -190,33 +189,42 @@ export class TableTheme implements ITableThemeDefine { } return undefined; }, - get select(): InteractionStyle | undefined { - if (defaultStyle.select) { - return { - get inlineColumnBgColor(): ColorPropertyDefine | undefined { - return ( - defaultStyle.select?.inlineColumnBgColor ?? - that.selectionStyle?.inlineColumnBgColor ?? - (that.selectionStyle?.cellBgColor && typeof that.selectionStyle.cellBgColor === 'string' - ? changeColor(that.selectionStyle.cellBgColor, 0.1, false) - : undefined) ?? - undefined - ); - }, - get inlineRowBgColor(): ColorPropertyDefine | undefined { - return ( - defaultStyle.select?.inlineRowBgColor ?? - that.selectionStyle.inlineRowBgColor ?? - (that.selectionStyle?.cellBgColor && typeof that.selectionStyle.cellBgColor === 'string' - ? changeColor(that.selectionStyle.cellBgColor, 0.1, false) - : undefined) ?? - undefined - ); - } - }; - } - return undefined; - }, + // get click(): InteractionStyle | undefined { + // if (defaultStyle.click) + // return { + // get cellBgColor(): ColorPropertyDefine | undefined { + // return defaultStyle.click?.cellBgColor ?? undefined; + // }, + // get cellBorderColor(): ColorsPropertyDefine | undefined { + // return defaultStyle.click?.cellBorderColor ?? undefined; + // }, + // get cellBorderLineWidth(): LineWidthsPropertyDefine | undefined { + // return defaultStyle.click?.cellBorderLineWidth ?? undefined; + // }, + // // get cellBorderLineDash(): LineDashsPropertyDefine |undefined{ + // // return defaultStyle.click?.cellBorderLineDash??undefined + // // }, + // get inlineColumnBgColor(): ColorPropertyDefine | undefined { + // return ( + // // defaultStyle.click?.inlineColumnBgColor ?? + // (defaultStyle.click?.cellBgColor && + // typeof defaultStyle.click?.cellBgColor === 'string' + // ? changeColor(defaultStyle.click?.cellBgColor, 0.1, false) + // : undefined) ?? undefined + // ); + // }, + // get inlineRowBgColor(): ColorPropertyDefine | undefined { + // return ( + // // defaultStyle.click?.inlineRowBgColor ?? + // (defaultStyle.click?.cellBgColor && + // typeof defaultStyle.click?.cellBgColor === 'string' + // ? changeColor(defaultStyle.click?.cellBgColor, 0.1, false) + // : undefined) ?? undefined + // ); + // }, + // }; + // return undefined; + // }, get padding(): PaddingsPropertyDefine { return defaultStyle.padding ?? [10, 16, 10, 16]; }, @@ -451,9 +459,6 @@ export class TableTheme implements ITableThemeDefine { get scrollSliderColor(): string | undefined { return scroll.scrollSliderColor ?? '#C0C0C0'; }, - get scrollSliderCornerRadius(): number | undefined { - return scroll.scrollSliderCornerRadius; - }, get scrollRailColor(): string | undefined { return scroll.scrollRailColor; }, @@ -493,12 +498,6 @@ export class TableTheme implements ITableThemeDefine { }, get color(): string | undefined { return tooltip.color ?? '#FFF'; - }, - get maxWidth(): number | undefined { - return tooltip.maxWidth; - }, - get maxHeight(): number | undefined { - return tooltip.maxHeight; } }; } @@ -659,12 +658,6 @@ export class TableTheme implements ITableThemeDefine { }, get cellBorderLineWidth(): number | undefined { return selectionStyle?.cellBorderLineWidth ?? 2; - }, - get inlineColumnBgColor(): string | undefined { - return selectionStyle?.inlineColumnBgColor; - }, - get inlineRowBgColor(): string | undefined { - return selectionStyle?.inlineRowBgColor; } }; } @@ -729,10 +722,9 @@ export class TableTheme implements ITableThemeDefine { return hasThemeProperty(obj, names) || hasThemeProperty(superTheme, names); } extends(obj: PartialTableThemeDefine): TableTheme { - return new TableTheme(obj, this.internalTheme.superTheme || this.internalTheme.obj); + return new TableTheme(obj, this); } private getStyle(style: ThemeStyle) { - const that = this; return { get fontSize(): FontSizePropertyDefine | undefined { return style.fontSize; @@ -755,9 +747,6 @@ export class TableTheme implements ITableThemeDefine { get color(): ColorPropertyDefine | undefined { return style.color; }, - get strokeColor(): ColorPropertyDefine | undefined { - return style.strokeColor; - }, get borderColor(): ColorsPropertyDefine | undefined { return style.borderColor; }, @@ -773,6 +762,12 @@ export class TableTheme implements ITableThemeDefine { get cellBgColor(): ColorPropertyDefine | undefined { return style.hover?.cellBgColor ?? undefined; }, + // get cellBorderColor(): ColorsPropertyDefine | undefined { + // return style.hover?.cellBorderColor ?? undefined; + // }, + // get cellBorderLineWidth(): LineWidthsPropertyDefine | undefined { + // return style.hover?.cellBorderLineWidth ?? undefined; + // }, get inlineColumnBgColor(): ColorPropertyDefine | undefined { return ( style.hover?.inlineColumnBgColor ?? @@ -795,34 +790,40 @@ export class TableTheme implements ITableThemeDefine { } return undefined; }, - get select(): InteractionStyle | undefined { - // if (style.select) { - return { - get inlineColumnBgColor(): ColorPropertyDefine | undefined { - return ( - style.select?.inlineColumnBgColor ?? - that.selectionStyle?.inlineColumnBgColor ?? - (that.selectionStyle?.cellBgColor && typeof that.selectionStyle.cellBgColor === 'string' - ? changeColor(that.selectionStyle.cellBgColor, 0.1, false) - : undefined) ?? - undefined - ); - }, - get inlineRowBgColor(): ColorPropertyDefine | undefined { - return ( - style.select?.inlineRowBgColor ?? - that.selectionStyle.inlineRowBgColor ?? - (that.selectionStyle?.cellBgColor && typeof that.selectionStyle.cellBgColor === 'string' - ? changeColor(that.selectionStyle.cellBgColor, 0.1, false) - : undefined) ?? - undefined - ); - } - }; - // } - // return undefined; - }, - + // get click(): InteractionStyle | undefined { + // if (style.click) + // return { + // get cellBgColor(): ColorPropertyDefine | undefined { + // return style.click?.cellBgColor ?? undefined; + // }, + // get cellBorderColor(): ColorsPropertyDefine | undefined { + // return style.click?.cellBorderColor ?? undefined; + // }, + // get cellBorderLineWidth(): LineWidthsPropertyDefine | undefined { + // return style.click?.cellBorderLineWidth ?? undefined; + // }, + // // get cellBorderLineDash(): LineDashsPropertyDefine |undefined{ + // // return style.click?.cellBorderLineDash??undefined + // // }, + // get inlineColumnBgColor(): ColorPropertyDefine | undefined { + // return ( + // // style.click?.inlineColumnBgColor ?? + // (style.click?.cellBgColor && typeof style.click?.cellBgColor === 'string' + // ? changeColor(style.click?.cellBgColor, 0.1, false) + // : undefined) ?? undefined + // ); + // }, + // get inlineRowBgColor(): ColorPropertyDefine | undefined { + // return ( + // // style.click?.inlineRowBgColor ?? + // (style.click?.cellBgColor && typeof style.click?.cellBgColor === 'string' + // ? changeColor(style.click?.cellBgColor, 0.1, false) + // : undefined) ?? undefined + // ); + // }, + // }; + // return undefined; + // }, get frameStyle(): FrameStyle | undefined { if (style.frameStyle) { return { diff --git a/packages/vtable/src/tools/get-data-path/create-dataset.ts b/packages/vtable/src/tools/get-data-path/create-dataset.ts index 420fad202..86693a4fd 100644 --- a/packages/vtable/src/tools/get-data-path/create-dataset.ts +++ b/packages/vtable/src/tools/get-data-path/create-dataset.ts @@ -1,7 +1,4 @@ import { Dataset } from '../../dataset/dataset'; -import { supplementIndicatorNodesForCustomTree } from '../../layout/layout-helper'; -import type { ITreeLayoutHeadNode } from '../../layout/tree-helper'; -import { DimensionTree } from '../../layout/tree-helper'; import type { AggregationRule, AggregationRules, @@ -14,44 +11,26 @@ import { AggregationType } from '../../ts-types'; import type { IChartColumnIndicator } from '../../ts-types/pivot-table/indicator/chart-indicator'; export function createDataset(options: PivotChartConstructorOptions) { - const layoutNodeId = { seqId: 0 }; const dataConfig: IPivotChartDataConfig = { isPivotChart: true }; - let columnDimensionTree; - let rowDimensionTree; - let columnTree; - let rowTree; - if (options.columnTree) { - if (options.indicatorsAsCol !== false) { - columnTree = supplementIndicatorNodesForCustomTree(options.columnTree, options.indicators); - } - columnDimensionTree = new DimensionTree((options.columnTree as ITreeLayoutHeadNode[]) ?? [], layoutNodeId); - } - if (options.rowTree) { - if (options.indicatorsAsCol === false) { - rowTree = supplementIndicatorNodesForCustomTree(options.rowTree, options.indicators); - } - rowDimensionTree = new DimensionTree((options.rowTree as ITreeLayoutHeadNode[]) ?? [], layoutNodeId); - } - const rowKeys = rowDimensionTree.dimensionKeys?.count - ? rowDimensionTree.dimensionKeys.valueArr() - : options.rows?.reduce((keys, rowObj) => { - if (typeof rowObj === 'string') { - keys.push(rowObj); - } else { - keys.push(rowObj.dimensionKey); - } - return keys; - }, []) ?? []; - const columnKeys = columnDimensionTree.dimensionKeys?.count - ? columnDimensionTree.dimensionKeys.valueArr() - : options.columns?.reduce((keys, columnObj) => { - if (typeof columnObj === 'string') { - keys.push(columnObj); - } else { - keys.push(columnObj.dimensionKey); - } - return keys; - }, []) ?? []; + + const rowKeys = + options.rows?.reduce((keys, rowObj) => { + if (typeof rowObj === 'string') { + keys.push(rowObj); + } else { + keys.push(rowObj.dimensionKey); + } + return keys; + }, []) ?? []; + const columnKeys = + options.columns?.reduce((keys, columnObj) => { + if (typeof columnObj === 'string') { + keys.push(columnObj); + } else { + keys.push(columnObj.dimensionKey); + } + return keys; + }, []) ?? []; const indicatorKeys = options.indicators?.reduce((keys, indicatorObj) => { if (typeof indicatorObj === 'string') { @@ -75,12 +54,12 @@ export function createDataset(options: PivotChartConstructorOptions) { options.indicatorsAsCol ?? true, options.records, undefined, - columnTree || options.columnTree, - rowTree || options.rowTree, + options.columnTree, + options.rowTree, true ); - return { dataset, columnDimensionTree, rowDimensionTree, layoutNodeId }; + return dataset; } function _generateCollectValuesConfig( diff --git a/packages/vtable/src/tools/get-data-path/index.ts b/packages/vtable/src/tools/get-data-path/index.ts index dcf5eb4f1..3b9973089 100644 --- a/packages/vtable/src/tools/get-data-path/index.ts +++ b/packages/vtable/src/tools/get-data-path/index.ts @@ -3,9 +3,6 @@ import type { PivotChart } from '../../PivotChart'; import type { IPivotTableCellHeaderPaths, PivotChartConstructorOptions } from '../../ts-types'; import { createDataset } from './create-dataset'; import { PivotHeaderLayoutMap } from '../../layout/pivot-header-layout'; -import type { ITreeLayoutHeadNode } from '../../layout/tree-helper'; -import { DimensionTree } from '../../layout/tree-helper'; -import { IndicatorDimensionKeyPlaceholder } from '../global'; export function getDataCellPath( options: PivotChartConstructorOptions, @@ -13,27 +10,11 @@ export function getDataCellPath( compareFunc?: (a: any, b: any) => boolean ): IPivotTableCellHeaderPaths | undefined { // mock dataset - const results = createDataset(options); - let columnDimensionTree = results.columnDimensionTree; - let rowDimensionTree = results.rowDimensionTree; + const dataset = createDataset(options); - let isNeedResetColumnDimensionTree = false; - let isNeedResetRowDimensionTree = false; - if (options.columnTree) { - if (options.indicatorsAsCol && !columnDimensionTree.dimensionKeys.contain(IndicatorDimensionKeyPlaceholder)) { - isNeedResetColumnDimensionTree = true; - } - } - if (options.rowTree) { - if (!options.indicatorsAsCol && !rowDimensionTree.dimensionKeys.contain(IndicatorDimensionKeyPlaceholder)) { - isNeedResetRowDimensionTree = true; - } - } - const { dataset, layoutNodeId } = results; // mock pivotChart const mockTable = { options, - layoutNodeId, internalProps: options, isPivotChart: () => true, pivotChartAxes: [] as any[], @@ -46,19 +27,9 @@ export function getDataCellPath( }; } }; - if (!options.columnTree || isNeedResetColumnDimensionTree) { - columnDimensionTree = new DimensionTree((dataset.colHeaderTree as ITreeLayoutHeadNode[]) ?? [], layoutNodeId); - } - if (!options.rowTree || isNeedResetRowDimensionTree) { - rowDimensionTree = new DimensionTree((dataset.rowHeaderTree as ITreeLayoutHeadNode[]) ?? [], layoutNodeId); - } + // mock layoutMap - const layoutMap = new PivotHeaderLayoutMap( - mockTable as unknown as PivotChart, - dataset, - columnDimensionTree, - rowDimensionTree - ); + const layoutMap = new PivotHeaderLayoutMap(mockTable as unknown as PivotChart, dataset); // compare data for (let col = 0; col < layoutMap.colCount; col++) { diff --git a/packages/vtable/src/tools/helper.ts b/packages/vtable/src/tools/helper.ts index e0bff01fe..aa6443095 100644 --- a/packages/vtable/src/tools/helper.ts +++ b/packages/vtable/src/tools/helper.ts @@ -248,16 +248,11 @@ export function cellInRange(range: CellRange, col: number, row: number): boolean ); } export function cellInRanges(ranges: CellRange[], col: number, row: number): boolean { - // cell range may in wrong order for (let i = 0; i < ranges.length; i++) { const range = ranges[i]; - const startCol = Math.min(range.start.col, range.end.col); - const endCol = Math.max(range.start.col, range.end.col); - const startRow = Math.min(range.start.row, range.end.row); - const endRow = Math.max(range.start.row, range.end.row); if ( - (startCol <= col && col <= endCol && startRow <= row && row <= endRow) || - (endCol <= col && col <= startCol && endRow <= row && row <= startRow) + (range.start.col <= col && col <= range.end.col && range.start.row <= row && row <= range.end.row) || + (range.end.col <= col && col <= range.start.col && range.end.row <= row && row <= range.start.row) ) { return true; } diff --git a/packages/vtable/src/tools/pixel-ratio.ts b/packages/vtable/src/tools/pixel-ratio.ts index c667cca72..6162868b0 100644 --- a/packages/vtable/src/tools/pixel-ratio.ts +++ b/packages/vtable/src/tools/pixel-ratio.ts @@ -4,7 +4,7 @@ export let defaultPixelRatio = 1; /* * @Description: 设置像素比 */ -export function getPixelRatio(): number { +function setPixelRatio(): void { if (isNode) { defaultPixelRatio = 1; } else { @@ -14,6 +14,5 @@ export function getPixelRatio(): number { defaultPixelRatio += 1; } } - return defaultPixelRatio; } -getPixelRatio(); +setPixelRatio(); diff --git a/packages/vtable/src/tools/util.ts b/packages/vtable/src/tools/util.ts index 6a7f3f46e..3e639a4d9 100644 --- a/packages/vtable/src/tools/util.ts +++ b/packages/vtable/src/tools/util.ts @@ -422,13 +422,3 @@ export function deduplication(array: number[]) { } return result; } - -/** 判断div中的文本是否有被选中 */ -export function isDivSelected(div: HTMLDivElement) { - const selection = window.getSelection(); - if (selection.rangeCount) { - const range = selection.getRangeAt(0); - return range.endOffset > range.startOffset && div.contains(range.commonAncestorContainer); - } - return false; -} diff --git a/packages/vtable/src/ts-types/animation/appear.ts b/packages/vtable/src/ts-types/animation/appear.ts deleted file mode 100644 index 262f3d159..000000000 --- a/packages/vtable/src/ts-types/animation/appear.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface IAnimationAppear { - duration?: number; - delay?: number; - type?: 'all' | 'one-by-one'; - direction?: 'row' | 'column'; -} diff --git a/packages/vtable/src/ts-types/base-table.ts b/packages/vtable/src/ts-types/base-table.ts index 69a9a1440..5e536ea64 100644 --- a/packages/vtable/src/ts-types/base-table.ts +++ b/packages/vtable/src/ts-types/base-table.ts @@ -67,10 +67,7 @@ import type { ColumnSeriesNumber, ColumnStyleOption, WidthAdaptiveModeDef, - HeightAdaptiveModeDef, - ColumnInfo, - RowInfo, - CellAddressWithBound + HeightAdaptiveModeDef } from '.'; import type { TooltipOptions } from './tooltip'; import type { IWrapTextGraphicAttribute } from '../scenegraph/graphic/text'; @@ -93,11 +90,7 @@ import type { DiscreteTableLegend } from '../components/legend/discrete-legend/d import type { ContinueTableLegend } from '../components/legend/continue-legend/continue-legend'; import type { NumberRangeMap } from '../layout/row-height-map'; import type { RowSeriesNumberHelper } from '../core/row-series-number-helper'; -import type { ReactCustomLayout } from '../components/react/react-custom-layout'; import type { ISortedMapItem } from '../data/DataSource'; -import type { IAnimationAppear } from './animation/appear'; -import type { IEmptyTip } from './component/empty-tip'; -import type { EmptyTip } from '../components/empty-tip/empty-tip'; export interface IBaseTableProtected { element: HTMLElement; @@ -201,8 +194,6 @@ export interface IBaseTableProtected { renderMode: 'html' | 'canvas'; /** 代替原来hover:isShowTooltip配置 */ isShowOverflowTextTooltip: boolean; - /** 缩略文字提示框 延迟消失时间 */ - overflowTextTooltipDisappearDelay?: number; /** 弹框是否需要限定在表格区域内 */ confine: boolean; }; @@ -239,9 +230,8 @@ export interface IBaseTableProtected { limitMinHeight?: number; title?: Title; - legends?: (DiscreteTableLegend | ContinueTableLegend)[]; + legends?: DiscreteTableLegend | ContinueTableLegend; - emptyTip?: EmptyTip; //是否开启图表异步渲染 renderChartAsync?: boolean; // // 开启图表异步渲染 每批次渐进渲染图表个数 @@ -255,12 +245,6 @@ export interface IBaseTableProtected { * 设置为 'none' 时, 表格滚动到顶部/底部时, 不再触发父容器滚动 * */ overscrollBehavior?: 'auto' | 'none'; - - // react component container - bodyDomContainer?: HTMLElement; - headerDomContainer?: HTMLElement; - // 已使用一行的高度填充所有行 - useOneRowHeightFillAll?: boolean; } export interface BaseTableConstructorOptions { // /** 指定表格的行数 */ @@ -272,7 +256,6 @@ export interface BaseTableConstructorOptions { * 当前需要冻结的列数 基本表格生效 */ frozenColCount?: number; - frozenRowCount?: number; rightFrozenColCount?: number; bottomFrozenRowCount?: number; @@ -328,7 +311,7 @@ export interface BaseTableConstructorOptions { /** hover交互配置 */ hover?: { /** hover交互响应模式:十字交叉 整列 整行 或者单个单元格 */ - highlightMode?: 'cross' | 'column' | 'row' | 'cell'; + highlightMode: 'cross' | 'column' | 'row' | 'cell'; /** 不响应鼠标hover交互 */ disableHover?: boolean; /** 单独设置表头不响应鼠标hover交互 */ @@ -338,18 +321,12 @@ export interface BaseTableConstructorOptions { }; /** 选择单元格交互配置 */ select?: { - /** 高亮范围模式:十字交叉 整列 整行 或者单个单元格。默认`cell` */ - highlightMode?: 'cross' | 'column' | 'row' | 'cell'; /** 点击表头单元格时连带body整行或整列选中 或仅选中当前单元格,默认或整行或整列选中*/ headerSelectMode?: 'inline' | 'cell'; /** 不响应鼠标select交互 */ disableSelect?: boolean; /** 单独设置表头不响应鼠标select交互 */ disableHeaderSelect?: boolean; - /** 点击空白区域是否取消选中 */ - blankAreaClickDeselect?: boolean; - /** 点击外部区域是否取消选中 */ - outsideClickDeselect?: boolean; // }; /** 下拉菜单的相关配置。消失时机:显示后点击菜单区域外自动消失*/ menu?: { @@ -366,10 +343,8 @@ export interface BaseTableConstructorOptions { tooltip?: { /** html目前实现较完整 先默认html渲染方式 */ renderMode?: 'html'; // 目前暂不支持canvas方案 - /** 是否显示缩略文字提示框。 代替原来hover:isShowTooltip配置 暂时需要将renderMode配置为html才能显示,canvas的还未开发*/ + /** 代替原来hover:isShowTooltip配置 暂时需要将renderMode配置为html才能显示,canvas的还未开发*/ isShowOverflowTextTooltip?: boolean; - /** 缩略文字提示框 延迟消失时间 */ - overflowTextTooltipDisappearDelay?: number; /** 是否将 tooltip 框限制在画布区域内,默认开启。针对renderMode:"html"有效 */ confine?: boolean; }; @@ -420,9 +395,9 @@ export interface BaseTableConstructorOptions { // maximum number of data items maintained in table instance maintainedDataCount?: number; - legends?: ITableLegendOption | ITableLegendOption[]; + legends?: ITableLegendOption; title?: ITitle; - emptyTip?: true | IEmptyTip; + /** 是否开启图表异步渲染 */ renderChartAsync?: boolean; /** 开启图表异步渲染 每批次渐进渲染图表个数 默认是5个 */ @@ -431,7 +406,7 @@ export interface BaseTableConstructorOptions { customMergeCell?: CustomMergeCell; // #region for nodejs - mode?: 'node' | 'browser'; + mode?: 'node' | 'broswer'; modeParams?: any; canvasWidth?: number; canvasHeight?: number; @@ -451,24 +426,10 @@ export interface BaseTableConstructorOptions { customCellStyleArrangement?: CustomCellStyleArrangement[]; columnWidthComputeMode?: 'normal' | 'only-header' | 'only-body'; + + customConfig?: any; // 部分特殊配置,兼容xTable等作用 + clearDOM?: boolean; - customConfig?: { - /** xTable对于没有配置autoWrapText并且有'\n'的文本,在计算行高是会当做一行处理,但是在渲染时会解析'\n';显示效果就是单元格高度为一行文本高度,只显示第一个'\n'前的文字,后面显示'...';multilinesForXTable配置实现和该功能对齐的样式 */ - multilinesForXTable?: boolean; - /** 这里可以配置为false 来走flatDataToObject的数据处理逻辑 而不走dataset的分析 */ - enableDataAnalysis?: boolean; - /** 禁用行高列宽计算取整数逻辑 对齐xTable */ - _disableColumnAndRowSizeRound?: boolean; - imageMargin?: number; - // 是否创建react custom container - createReactContainer?: boolean; - // adaptive 模式下优先缩小迷你图 - shrinkSparklineFirst?: boolean; - }; // 部分特殊配置,兼容xTable等作用 - - animationAppear?: boolean | IAnimationAppear; - - renderOption?: any; } export interface BaseTableAPI { /** 数据总条目数 */ @@ -562,7 +523,7 @@ export interface BaseTableAPI { ) => EventListenerId; // &((type: string, listener: AnyListener) => EventListenerId); - _vDataSet?: DataSet; + _vDataSet: DataSet; /** 场景树对象 */ scenegraph: Scenegraph; /** 状态管理模块 */ @@ -579,9 +540,6 @@ export interface BaseTableAPI { columnWidthComputeMode?: 'normal' | 'only-header' | 'only-body'; - _rowRangeHeightsMap: Map; - _colRangeWidthsMap: Map; - /** 获取表格绘制的范围 不包括frame的宽度 */ getDrawRange: () => Rect; /** 将鼠标坐标值 转换成表格坐标系中的坐标位置 */ @@ -602,14 +560,12 @@ export interface BaseTableAPI { getDefaultRowHeight: (row: number) => number | 'auto'; getDefaultColumnWidth: (col: number) => number | 'auto'; _setRowHeight: (row: number, height: number, clearCache?: boolean) => void; - setRowHeight: (row: number, height: number) => void; getColWidth: (col: number) => number; getColWidthDefined: (col: number) => string | number; // setColWidthDefined: (col: number, width: number) => void; getColWidthDefinedNumber: (col: number) => number; // getColWidthDefine: (col: number) => string | number; _setColWidth: (col: number, width: number | string, clearCache?: boolean, skipCheckFrozen?: boolean) => void; - setColWidth: (col: number, width: number) => void; _getColContentWidth: (col: number) => number; _setColContentWidth: (col: number, width: number | string, clearCache?: boolean) => void; getMaxColWidth: (col: number) => number; @@ -625,8 +581,7 @@ export interface BaseTableAPI { isFrozenCell: (col: number, row: number) => { row: boolean; col: boolean } | null; getRowAt: (absoluteY: number) => { top: number; row: number; bottom: number }; getColAt: (absoluteX: number) => { left: number; col: number; right: number }; - getCellAt: (absoluteX: number, absoluteY: number) => CellAddressWithBound; - getCellAtRelativePosition: (absoluteX: number, absoluteY: number) => CellAddressWithBound; + getCellAt: (absoluteX: number, absoluteY: number) => CellAddress; _makeVisibleCell: (col: number, row: number) => void; // setFocusCursor(col: number, row: number): void; // focusCell(col: number, row: number): void; @@ -643,7 +598,7 @@ export interface BaseTableAPI { getFrozenColsWidth: () => number; getBottomFrozenRowsHeight: () => number; getRightFrozenColsWidth: () => number; - selectCell: (col: number, row: number, isShift?: boolean, isCtrl?: boolean) => void; + selectCell: (col: number, row: number) => void; selectCells: (cellRanges: CellRange[]) => void; getAllRowsHeight: () => number; getAllColsWidth: () => number; @@ -775,10 +730,16 @@ export interface BaseTableAPI { getMergeCellRect: (col: number, row: number) => Rect; - getTargetColAt: (absoluteX: number) => ColumnInfo | null; - getTargetRowAt: (absoluteY: number) => RowInfo | null; - getTargetColAtConsiderRightFrozen: (absoluteX: number, isConsider: boolean) => ColumnInfo | null; - getTargetRowAtConsiderBottomFrozen: (absoluteY: number, isConsider: boolean) => RowInfo | null; + getTargetColAt: (absoluteX: number) => { col: number; left: number; right: number; width: number } | null; + getTargetRowAt: (absoluteY: number) => { row: number; top: number; bottom: number; height: number } | null; + getTargetColAtConsiderRightFrozen: ( + absoluteX: number, + isConsider: boolean + ) => { col: number; left: number; right: number; width: number } | null; + getTargetRowAtConsiderBottomFrozen: ( + absoluteY: number, + isConsider: boolean + ) => { row: number; top: number; bottom: number; height: number } | null; renderWithRecreateCells: () => void; //#endregion tableAPI @@ -829,22 +790,7 @@ export interface BaseTableAPI { leftRowSeriesNumberCount: number; isAutoRowHeight: (row: number) => boolean; - reactCustomLayout?: ReactCustomLayout; - checkReactCustomLayout: () => void; setSortedIndexMap: (field: FieldDef, filedMap: ISortedMapItem) => void; - - exportImg: () => string; - exportCellImg: ( - col: number, - row: number, - options?: { disableBackground?: boolean; disableBorder?: boolean } - ) => string; - exportCellRangeImg: (cellRange: CellRange) => string; - exportCanvas: () => HTMLCanvasElement; - setPixelRatio: (pixelRatio: number) => void; - - bodyDomContainer?: HTMLElement; - headerDomContainer?: HTMLElement; } export interface ListTableProtected extends IBaseTableProtected { /** 表格数据 */ @@ -856,10 +802,15 @@ export interface ListTableProtected extends IBaseTableProtected { export interface PivotTableProtected extends IBaseTableProtected { /** 表格数据 */ - records: any[] | undefined; - recordsIsTwoDimensionalArray?: boolean; + records: any[] | null; layoutMap: PivotHeaderLayoutMap; dataConfig?: IPivotTableDataConfig; + /** + * 透视表是否开启数据分析 + * 如果传入数据是明细数据需要聚合分析则开启 + * 如传入数据是经过聚合好的为了提升性能这里设置为false,同时需要传入columnTree和rowTree + */ + enableDataAnalysis?: boolean; /** 列表头树型结构 */ columnTree?: IHeaderTreeDefine[]; diff --git a/packages/vtable/src/ts-types/column/style.ts b/packages/vtable/src/ts-types/column/style.ts index 102c2020c..fcfdd6f1c 100644 --- a/packages/vtable/src/ts-types/column/style.ts +++ b/packages/vtable/src/ts-types/column/style.ts @@ -56,7 +56,6 @@ export interface IStyleOption { textAlign?: TextAlignType; textBaseline?: TextBaselineType; color?: ColorPropertyDefine; - strokeColor?: ColorPropertyDefine; fontSize?: FontSizePropertyDefine; fontFamily?: FontFamilyPropertyDefine; diff --git a/packages/vtable/src/ts-types/common.ts b/packages/vtable/src/ts-types/common.ts index 9c321c270..732dff55d 100644 --- a/packages/vtable/src/ts-types/common.ts +++ b/packages/vtable/src/ts-types/common.ts @@ -42,12 +42,6 @@ export type BaseCellInfo = { /**原始值 */ dataValue: FieldData; }; -export type MergeCellInfo = { - colStart: number; - colEnd: number; - rowStart: number; - rowEnd: number; -}; export type CellInfo = { col: number; row: number; @@ -82,9 +76,17 @@ export type IListTableCellHeaderPaths = { }; export type IPivotTableCellHeaderPaths = { /** 列表头各级path表头信息 */ - readonly colHeaderPaths?: IDimensionInfo[]; + readonly colHeaderPaths?: { + dimensionKey?: string; + indicatorKey?: string; + value?: string; + }[]; /** 行表头各级path表头信息 */ - readonly rowHeaderPaths?: IDimensionInfo[]; + readonly rowHeaderPaths?: { + dimensionKey?: string; + indicatorKey?: string; + value?: string; + }[]; cellLocation: CellLocation; }; @@ -93,7 +95,6 @@ export interface IDimensionInfo { value?: string; indicatorKey?: string; isPivotCorner?: boolean; - virtual?: boolean; } /** @@ -126,7 +127,7 @@ export enum HighlightScope { 'none' = 'none' } -export type SortOrder = 'asc' | 'desc' | 'normal' | 'ASC' | 'DESC' | 'NORMAL'; +export type SortOrder = 'asc' | 'desc' | 'normal'; export type CustomCellStyle = { id: string; diff --git a/packages/vtable/src/ts-types/component/empty-tip.ts b/packages/vtable/src/ts-types/component/empty-tip.ts deleted file mode 100644 index 332fa629d..000000000 --- a/packages/vtable/src/ts-types/component/empty-tip.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { ColumnIconOption } from '../icon'; - -export type IEmptyTip = { - spaceBetweenTextAndIcon?: number; - text?: string; - textStyle?: { - fontSize?: number; - fontFamily?: string; - fontWeight?: string | number; - fontVariant?: string; - lineHeight?: number | string; - underline?: number; - lineThrough?: number; - color?: string; - }; - icon?: { - /** icon的高度 */ - width?: number; - /** icon的高度 */ - height?: number; // 如果是font图标 不设的话默认是字体高度 - image: string; - }; -}; diff --git a/packages/vtable/src/ts-types/component/title.ts b/packages/vtable/src/ts-types/component/title.ts index 7aa2952c7..0e706174e 100644 --- a/packages/vtable/src/ts-types/component/title.ts +++ b/packages/vtable/src/ts-types/component/title.ts @@ -150,9 +150,6 @@ export type ITitle = { character?: IRichTextCharacter[]; } & Partial & Partial; - - dx?: number; - dy?: number; }; export interface IPadding { top?: number; diff --git a/packages/vtable/src/ts-types/customLayout.ts b/packages/vtable/src/ts-types/customLayout.ts index 11a8d5153..a82ab4c50 100644 --- a/packages/vtable/src/ts-types/customLayout.ts +++ b/packages/vtable/src/ts-types/customLayout.ts @@ -15,4 +15,4 @@ export type ICustomLayoutObj = { export type ICustomLayoutFuc = (args: CustomRenderFunctionArg) => ICustomLayoutObj; -export type ICustomLayout = ICustomLayoutFuc | 'react-custom-layout'; +export type ICustomLayout = ICustomLayoutFuc; diff --git a/packages/vtable/src/ts-types/events.ts b/packages/vtable/src/ts-types/events.ts index a3a61a8f3..54bdc9a90 100644 --- a/packages/vtable/src/ts-types/events.ts +++ b/packages/vtable/src/ts-types/events.ts @@ -1,7 +1,7 @@ import type { CellAddress, CellRange, CellLocation, FieldDef, CellAddressWithBound } from './table-engine'; import type { DropDownMenuEventArgs, MenuListItem, PivotInfo } from './menu'; -import type { IDimensionInfo, MergeCellInfo, RectProps, SortOrder } from './common'; +import type { IDimensionInfo, RectProps, SortOrder } from './common'; import type { IconFuncTypeEnum, CellInfo, HierarchyState } from '.'; import type { Icon } from '../scenegraph/graphic/icon'; import type { FederatedPointerEvent, IEventTarget } from '@src/vrender'; @@ -44,8 +44,6 @@ export type MousePointerCellEvent = CellAddressWithBound & event?: MouseEvent | PointerEvent | TouchEvent; federatedEvent?: FederatedPointerEvent; target: IEventTarget | undefined; - - mergeCellInfo?: MergeCellInfo; }; // 多单元格的事件传出参数 需要将当前鼠标处的单元格的信息FocusedCellInfo也带着 export type MousePointerMultiCellEvent = MousePointerCellEvent & { @@ -61,7 +59,6 @@ export type MousePointerSparklineEvent = MousePointerCellEvent & { export interface TableEventHandlersEventArgumentMap { selected_cell: SelectedCellEvent; - selected_clear: {}; click_cell: MousePointerCellEvent; dblclick_cell: MousePointerCellEvent; mouseenter_table: { event?: MouseEvent | PointerEvent | TouchEvent }; @@ -204,7 +201,6 @@ export interface DrillMenuEventInfo { } export interface TableEventHandlersReturnMap { selected_cell: void; - selected_clear: void; click_cell: void; dblclick_cell: void; mouseenter_table: void; diff --git a/packages/vtable/src/ts-types/icon.ts b/packages/vtable/src/ts-types/icon.ts index 26c289dee..4a008f0ab 100644 --- a/packages/vtable/src/ts-types/icon.ts +++ b/packages/vtable/src/ts-types/icon.ts @@ -63,10 +63,7 @@ export interface IIconBase { padding?: number[]; bgColor?: string; arrowMark?: boolean; - maxWidth?: number; - maxHeight?: number; }; - disappearDelay?: number; }; /** * 是否可交互 默认为true 目前已知不可交互按钮:下拉菜单状态 diff --git a/packages/vtable/src/ts-types/list-table/define/basic-define.ts b/packages/vtable/src/ts-types/list-table/define/basic-define.ts index f2328514f..b74ecf5cb 100644 --- a/packages/vtable/src/ts-types/list-table/define/basic-define.ts +++ b/packages/vtable/src/ts-types/list-table/define/basic-define.ts @@ -80,8 +80,6 @@ export interface IBasicColumnBodyDefine { // style?: ColumnStyleOption | null; /** 是否对相同内容合并单元格 **/ mergeCell?: MergeCellOption; - /** 是否隐藏 */ - hide?: boolean; customRender?: ICustomRender; customLayout?: ICustomLayout; editor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); diff --git a/packages/vtable/src/ts-types/list-table/layout-map/api.ts b/packages/vtable/src/ts-types/list-table/layout-map/api.ts index 8a6b32ba3..b1af5c8d2 100644 --- a/packages/vtable/src/ts-types/list-table/layout-map/api.ts +++ b/packages/vtable/src/ts-types/list-table/layout-map/api.ts @@ -20,8 +20,7 @@ import type { SparklineSpec, HierarchyState, Aggregation, - IRowSeriesNumber, - SortOption + IRowSeriesNumber } from '../../'; import type { Aggregator } from '../../../dataset/statistics-helper'; import type { BaseTableAPI } from '../../base-table'; @@ -83,7 +82,6 @@ export interface HeaderData extends WidthData { columnWidthComputeMode?: 'normal' | 'only-header' | 'only-body'; showSort?: boolean; - sort?: SortOption; /** * 表头描述 鼠标hover会提示该信息 diff --git a/packages/vtable/src/ts-types/menu.ts b/packages/vtable/src/ts-types/menu.ts index d5b8b84ae..9eb7834fc 100644 --- a/packages/vtable/src/ts-types/menu.ts +++ b/packages/vtable/src/ts-types/menu.ts @@ -34,7 +34,7 @@ export type MenuListItem = export type PivotInfo = { value: string; - dimensionKey: string; + dimensionKey: string | number; isPivotCorner: boolean; customInfo?: any; }; diff --git a/packages/vtable/src/ts-types/new-data-set.ts b/packages/vtable/src/ts-types/new-data-set.ts index fc22e6614..89cdb0404 100644 --- a/packages/vtable/src/ts-types/new-data-set.ts +++ b/packages/vtable/src/ts-types/new-data-set.ts @@ -18,8 +18,7 @@ export enum AggregationType { MAX = 'MAX', AVG = 'AVG', COUNT = 'COUNT', - CUSTOM = 'CUSTOM', - RECALCULATE = 'RECALCULATE' + CUSTOM = 'CUSTOM' } export enum SortType { ASC = 'ASC', @@ -169,29 +168,11 @@ export type MappingFuncRule = { }; //#endregion 映射规则 - -//#region 派生字段规则 export interface DerivedFieldRule { fieldName?: string; derivedFunc?: (record: Record) => any; } export type DerivedFieldRules = DerivedFieldRule[]; -//#endregion 派生字段规则 - -//#region 计算字段规则 -export interface CalculateddFieldRule { - /** 唯一标识,可以当做新指标的key,用于配置在 indicators 中在透视表中展示。 */ - key: string; - /** 计算字段依赖的指标,可以是在 records 中具体对应的指标字段 or 不是数据records 中的字段 - * 如果依赖的指标不在 records 中,则需要在 aggregationRules 中明确配置,具体指明聚合规则和 indicatorKey 以在 dependIndicatorKeys 所使用。 */ - dependIndicatorKeys: string[]; - /** 计算字段的计算函数,依赖的指标值作为参数传入,返回值作为计算字段的值。 */ - calculateFun?: (dependFieldsValue: any) => any; -} - -export type CalculateddFieldRules = CalculateddFieldRule[]; -//#endregion 计算字段规则 - /** * 基本表数据处理配置 */ @@ -215,7 +196,6 @@ export interface IPivotTableDataConfig { */ mappingRules?: MappingRules; derivedFieldRules?: DerivedFieldRules; - calculatedFieldRules?: CalculateddFieldRules; } /** diff --git a/packages/vtable/src/ts-types/pivot-table/corner.ts b/packages/vtable/src/ts-types/pivot-table/corner.ts index 9427ea95a..45c87a86c 100644 --- a/packages/vtable/src/ts-types/pivot-table/corner.ts +++ b/packages/vtable/src/ts-types/pivot-table/corner.ts @@ -1,8 +1,5 @@ -import type { IEditor } from '@visactor/vtable-editors'; import type { IImageStyleOption, ITextStyleOption, IStyleOption } from '../column'; import type { ShowColumnRowType } from '../table-engine'; -import type { BaseCellInfo } from '../common'; -import type { BaseTableAPI } from '../base-table'; interface IBasicCornerDefine { titleOnDimension?: ShowColumnRowType; //角头标题是否显示列维度名称 否则显示行维度名称 @@ -18,19 +15,16 @@ interface IBasicCornerDefine { interface ITextCornerDefine extends IBasicCornerDefine { headerType?: 'text'; headerStyle?: Omit; - headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); } interface IImageCornerDefine extends IBasicCornerDefine { headerType: 'image'; headerStyle?: Omit; - headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); } interface ILinkCornerDefine extends IBasicCornerDefine { headerType: 'link'; headerStyle?: Omit; - headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); } export type ICornerDefine = IImageCornerDefine | ILinkCornerDefine | ITextCornerDefine; diff --git a/packages/vtable/src/ts-types/pivot-table/dimension/basic-dimension.ts b/packages/vtable/src/ts-types/pivot-table/dimension/basic-dimension.ts index 8a2289bf5..bcef1487a 100644 --- a/packages/vtable/src/ts-types/pivot-table/dimension/basic-dimension.ts +++ b/packages/vtable/src/ts-types/pivot-table/dimension/basic-dimension.ts @@ -3,7 +3,7 @@ import type { ICustomLayout } from '../../customLayout'; import type { FieldFormat } from '../../table-engine'; import type { ColumnIconOption } from '../../icon'; import type { MenuListItem } from '../../menu'; -import type { BaseCellInfo, CellInfo, SortOption } from '../../common'; +import type { BaseCellInfo, CellInfo } from '../../common'; import type { IEditor } from '@visactor/vtable-editors'; import type { BaseTableAPI } from '../../base-table'; @@ -37,12 +37,8 @@ export interface IBasicDimension { dropDownMenu?: MenuListItem[]; /** 角头单元格显示下拉按钮及下拉菜单*/ cornerDropDownMenu?: MenuListItem[]; - /** sort排序规则 */ - sort?: SortOption; - /** 显示sort排序icon。为了仅仅显示图标,无排序逻辑 */ + /** 是否显示排序icon */ showSort?: boolean; - /** 在角头的维度名称单元格中是否显示排序 */ - showSortInCorner?: boolean; /** 是否可以拖拽表头换位置 */ dragHeader?: boolean; /** 表头自定义渲染内容定义 */ diff --git a/packages/vtable/src/ts-types/pivot-table/indicator/basic-indicator.ts b/packages/vtable/src/ts-types/pivot-table/indicator/basic-indicator.ts index c0ca9628a..341b7b5af 100644 --- a/packages/vtable/src/ts-types/pivot-table/indicator/basic-indicator.ts +++ b/packages/vtable/src/ts-types/pivot-table/indicator/basic-indicator.ts @@ -24,10 +24,7 @@ export interface IBasicHeaderIndicator { // sparklineSpec?: SparklineSpec | ((arg0: CustomRenderFunctionArg) => SparklineSpec); dropDownMenu?: MenuListItem[]; // 针对单独指标上配置下拉按钮 - /** sort排序规则 */ - sort?: boolean; - /** 显示sort排序icon。为了仅仅显示图标,无排序逻辑 */ - showSort?: boolean; + showSort?: boolean; // 否显示排序icon disableColumnResize?: boolean; // 是否禁用调整列宽,如果是转置表格或者是透视表的指标是行方向指定 那该配置不生效 /** 指标名称表头自定义渲染内容定义 */ diff --git a/packages/vtable/src/ts-types/style-define.ts b/packages/vtable/src/ts-types/style-define.ts index f8caeeb8e..dc755bc3b 100644 --- a/packages/vtable/src/ts-types/style-define.ts +++ b/packages/vtable/src/ts-types/style-define.ts @@ -81,7 +81,6 @@ export type CellStyle = { padding: PaddingsDef; textBaseline: CanvasTextBaseline; color: CanvasRenderingContext2D['fillStyle']; - strokeColor?: CanvasRenderingContext2D['fillStyle']; bgColor: CanvasRenderingContext2D['fillStyle']; // font: string; fontSize: number; diff --git a/packages/vtable/src/ts-types/table-engine.ts b/packages/vtable/src/ts-types/table-engine.ts index 9dd669770..c47f45555 100644 --- a/packages/vtable/src/ts-types/table-engine.ts +++ b/packages/vtable/src/ts-types/table-engine.ts @@ -22,7 +22,7 @@ import type { ITitleDefine } from './pivot-table'; import type { ColumnsDefine } from './list-table'; -import type { ITableAxisOption } from './component/axis'; +import type { ICellAxisOption, ITableAxisOption } from './component/axis'; import type { IEditor } from '@visactor/vtable-editors'; import type { ITextStyleOption } from '../body-helper/style'; import type { DataSource } from '../data'; @@ -64,7 +64,7 @@ export type WidthModeDef = 'standard' | 'adaptive' | 'autoWidth'; export type HeightModeDef = 'standard' | 'adaptive' | 'autoHeight'; export type WidthAdaptiveModeDef = 'only-body' | 'all'; export type HeightAdaptiveModeDef = 'only-body' | 'all'; -export type ShowColumnRowType = 'column' | 'row' | 'none' | 'all'; +export type ShowColumnRowType = 'column' | 'row' | 'none'; /** 单元格所处表格哪部分 */ export type CellLocation = 'body' | 'rowHeader' | 'columnHeader' | 'cornerHeader'; export type CellSubLocation = @@ -80,11 +80,6 @@ export type CellSubLocation = | 'rowSeriesNumber' | 'colSeriesNumber'; -export interface SelectAllOnCtrlAOption { - disableHeaderSelect?: boolean; - disableRowSeriesNumberSelect?: boolean; -} - export interface TableKeyboardOptions { /** tab键 默认为true。开启tab键移动选中单元格,如果当前是在编辑单元格 则移动到下一个单元格也是编辑状态 */ moveFocusCellOnTab?: boolean; @@ -93,7 +88,7 @@ export interface TableKeyboardOptions { /** 默认不开启即false。开启这个配置的话,如果当前是在编辑中的单元格,方向键可以移动到下个单元格并进入编辑状态,而不是编辑文本内字符串的光标移动。上下左右方向键切换选中单元格不受该配置影响,*/ moveEditCellOnArrowKeys?: boolean; /** 开启快捷键全选 默认:false */ - selectAllOnCtrlA?: boolean | SelectAllOnCtrlAOption; + selectAllOnCtrlA?: boolean; /** 快捷键复制 默认:false*/ copySelected?: boolean; //这个copy是和浏览器的快捷键一致的 /** 快捷键粘贴,默认:false 。粘贴内容到指定位置(即粘贴前要有选中的单元格);支持批量粘贴;粘贴生效仅针对配置了编辑 editor 的单元格;*/ @@ -124,8 +119,6 @@ export interface IRowSeriesNumber { // selectRangeInclude?: boolean; /** 是否可拖拽顺序 */ dragOrder?: boolean; - /** 是否禁止列宽调整 */ - disableColumnResize?: boolean; } export interface ColumnSeriesNumber { @@ -226,7 +219,8 @@ export interface ListTableConstructorOptions extends BaseTableConstructorOptions * 排序状态 */ sortState?: SortState | SortState[]; - + /** 数据分析相关配置 enableDataAnalysis开启后该配置才会有效 */ + // dataConfig?: IListTableDataConfig; /** 全局设置表头编辑器 */ headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); /** 全局设置编辑器 */ @@ -353,7 +347,7 @@ export interface PivotTableConstructorOptions extends BaseTableConstructorOption */ rowHeaderTitle?: ITitleDefine; //#endregion - /** 数据分析相关配置 */ + /** 数据分析相关配置 enableDataAnalysis开启后该配置才会有效 */ dataConfig?: IPivotTableDataConfig; /** 指标标题 用于显示到角头的值*/ @@ -365,8 +359,6 @@ export interface PivotTableConstructorOptions extends BaseTableConstructorOption editor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); /** 全局设置表头编辑器 */ headerEditor?: string | IEditor | ((args: BaseCellInfo & { table: BaseTableAPI }) => string | IEditor); - /** 是否需要补充指标节点到对应的自定义表头中如rowTree或者columnTree. 默认为true */ - supplementIndicatorNodes?: boolean; } export interface PivotChartConstructorOptions extends BaseTableConstructorOptions { /** @@ -424,10 +416,7 @@ export interface PivotTableAPI extends BaseTableAPI { options: PivotTableConstructorOptions; editorManager: EditManeger; // internalProps: PivotTableProtected; - pivotSortState: { - dimensions: IDimensionInfo[]; - order: SortOrder; - }[]; + pivotSortState: PivotSortState[]; isListTable: () => false; isPivotTable: () => true; getPivotSortState: (col: number, row: number) => SortOrder; @@ -521,8 +510,6 @@ export interface IDimensionHeaderNode { children?: IHeaderTreeDefine[] | true; /** 折叠状态 TODO */ hierarchyState?: HierarchyState; - /** 是否为虚拟节点 在基于records数据做分析时忽略该维度字段 */ - virtual?: boolean; } export interface IExtensionRowDefine { @@ -540,6 +527,3 @@ export type CustomMerge = { customLayout?: ICustomLayout; customRender?: ICustomRender; }; - -export type ColumnInfo = { col: number; left: number; right: number; width: number }; -export type RowInfo = { row: number; top: number; bottom: number; height: number }; diff --git a/packages/vtable/src/ts-types/theme.ts b/packages/vtable/src/ts-types/theme.ts index d52e983f2..3bd499e6d 100644 --- a/packages/vtable/src/ts-types/theme.ts +++ b/packages/vtable/src/ts-types/theme.ts @@ -2,16 +2,14 @@ import type { ColorsDef, LineDashsDef, LineWidthsDef, LineWidthsPropertyDefine, LineDashsPropertyDefine } from '.'; import type { CheckboxStyle, ITextStyleOption, RadioStyle } from './column/style'; import type { ColorPropertyDefine, ColorsPropertyDefine } from './style-define'; +import type { ColumnIconOption } from './icon'; import type { ICellAxisOption } from './component/axis'; import type { PopTipAttributes } from '@visactor/vrender-components'; // ****** Custom Theme ******* export type PartialTableThemeDefine = Partial; export type ThemeStyle = ITextStyleOption & { hover?: Omit; //鼠标hover到某个单元格 - select?: { - inlineRowBgColor?: ColorPropertyDefine; //交互所在整行的背景颜色 - inlineColumnBgColor?: ColorPropertyDefine; //交互所在整列的背景颜色 - }; + // click?: Omit; //鼠标点击到某个单元格 frameStyle?: FrameStyle; }; export type InteractionStyle = { @@ -52,8 +50,6 @@ export type ScrollStyle = { scrollRailColor?: string; /**滚动条滑块的颜色 */ scrollSliderColor?: string; - /**滚动条滑块的圆角半径 */ - scrollSliderCornerRadius?: number; /**滚动条宽度大小 */ width?: number; /**滚动条是否可见 'always' | 'scrolling' | 'none' | 'focus',常驻|滚动时|不显示|聚焦在画布上时 */ @@ -72,8 +68,6 @@ export type TooltipStyle = { color?: string; padding?: number[]; bgColor?: string; - maxWidth?: number; - maxHeight?: number; /** !目前未实现该逻辑。触发行为:hover or click */ // trigger?: string | string[]; /**气泡框位置,可选 top left right bottom */ @@ -140,8 +134,6 @@ export interface ITableThemeDefine { cellBorderColor?: string; //边框颜色 cellBorderLineWidth?: number; //边框线宽度 cellBgColor?: string; //选择框背景颜色 - inlineRowBgColor?: string; //交互所在整行的背景颜色 - inlineColumnBgColor?: string; //交互所在整列的背景颜色 }; // style for axis diff --git a/packages/vtable/src/ts-types/tooltip.ts b/packages/vtable/src/ts-types/tooltip.ts index 12ff04e68..ee3633a37 100644 --- a/packages/vtable/src/ts-types/tooltip.ts +++ b/packages/vtable/src/ts-types/tooltip.ts @@ -26,9 +26,5 @@ export type TooltipOptions = { color?: string; padding?: number[]; arrowMark?: boolean; - maxWidth?: number; - maxHeight?: number; }; - /** 设置tooltip的消失时间 */ - disappearDelay?: number; }; diff --git a/packages/vtable/src/vrender.ts b/packages/vtable/src/vrender.ts index 4c650f2e4..1827c4287 100644 --- a/packages/vtable/src/vrender.ts +++ b/packages/vtable/src/vrender.ts @@ -1,9 +1,7 @@ -import { loadPoptip } from '@visactor/vrender-components'; import '@visactor/vrender-core'; import { container, isBrowserEnv, isNodeEnv, preLoadAllModule } from '@visactor/vrender-core'; +import { loadBrowserEnv, loadNodeEnv } from '@visactor/vrender-kits'; import { - loadBrowserEnv, - loadNodeEnv, registerArc, registerArc3d, registerArea, @@ -41,31 +39,24 @@ export function registerForVrender() { loadNodeEnv(container); } registerArc(); - // registerArc3d(); - // registerArea(); + registerArc3d(); + registerArea(); registerCircle(); - // registerGlyph(); + registerGlyph(); registerGroup(); registerImage(); registerLine(); - // registerPath(); - // registerPolygon(); - // registerPyramid3d(); + registerPath(); + registerPolygon(); + registerPyramid3d(); registerRect(); - // registerRect3d(); + registerRect3d(); registerRichtext(); - // registerShadowRoot(); + registerShadowRoot(); registerSymbol(); registerText(); - // registerWrapText(); - - loadPoptip(); + registerWrapText(); } -export { Direction } from '@visactor/vrender-core'; -export { GroupFadeIn } from '@visactor/vrender-core'; -export { GroupFadeOut } from '@visactor/vrender-core'; - export * from '@visactor/vrender-core'; export * from '@visactor/vrender-kits'; -export * from '@visactor/vrender-components'; diff --git a/packages/vtable/src/vutil-extension-temp/algorithm/binary-search.ts b/packages/vtable/src/vutil-extension-temp/algorithm/binary-search.ts new file mode 100644 index 000000000..fe7c09731 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/algorithm/binary-search.ts @@ -0,0 +1,28 @@ +/** + * 二分靠近框架,返回数组中第一个大于等于目标值的数的索引 + * @param arr 数组 + * @param compareFn 比较函数,返回(当前值-目标值) + */ +export const binaryFuzzySearch = (arr: T[], compareFn: (value: T) => number) => { + return binaryFuzzySearchInNumberRange(0, arr.length, value => compareFn(arr[value])); +}; + +/** + * 二分靠近框架,返回数字区间中第一个大于等于目标值的数字 + * @param x1 区间上界 + * @param x2 区间下界(不包含) + * @param compareFn 比较函数,返回(当前值-目标值) + */ +export const binaryFuzzySearchInNumberRange = (x1: number, x2: number, compareFn: (value: number) => number) => { + let left = x1; + let right = x2; + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (compareFn(mid) >= 0) { + right = mid; // 第一个大于等于目标值的数 + } else { + left = mid + 1; + } + } + return left; +}; diff --git a/packages/vtable/src/vutil-extension-temp/algorithm/index.ts b/packages/vtable/src/vutil-extension-temp/algorithm/index.ts new file mode 100644 index 000000000..e10f75227 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/algorithm/index.ts @@ -0,0 +1 @@ +export * from './binary-search'; diff --git a/packages/vtable/src/vutil-extension-temp/index.ts b/packages/vtable/src/vutil-extension-temp/index.ts new file mode 100644 index 000000000..f9d6e21f1 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/index.ts @@ -0,0 +1,4 @@ +export * from './transform/tick-data'; +export * from './utils'; +export * from './algorithm'; +export * from './spec'; diff --git a/packages/vtable/src/vutil-extension-temp/spec/clone-deep.ts b/packages/vtable/src/vutil-extension-temp/spec/clone-deep.ts new file mode 100644 index 000000000..74aec2e98 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/spec/clone-deep.ts @@ -0,0 +1,61 @@ +import { isArray, isBoolean, isDate, isNumber, isString, isValid } from '@visactor/vutils'; +import { isDataView, isHTMLElement } from './common'; + +/** + * 深拷贝 spec,为避免循环引用,DataView 维持原有引用 + * @param spec 原spec + */ +export function cloneDeepSpec(spec: any, excludeKeys: string[] = ['data']) { + const value = spec; + + let result; + if (!isValid(value) || typeof value !== 'object') { + return value; + } + + // 判断是不是不能深拷贝的对象 + if (isDataView(value) || isHTMLElement(value)) { + return value; + } + + const isArr = isArray(value); + const length = value.length; + // 不考虑特殊数组的额外处理 + if (isArr) { + result = new Array(length); + } + // 不考虑 buffer / arguments 类型的处理以及 prototype 的额外处理 + else if (typeof value === 'object') { + result = {}; + } + // 不建议使用作为 Boolean / Number / String 作为构造器 + else if (isBoolean(value) || isNumber(value) || isString(value)) { + result = value; + } else if (isDate(value)) { + result = new Date(+value); + } + // 不考虑 ArrayBuffer / DataView / TypedArray / map / set / regexp / symbol 类型 + else { + result = undefined; + } + + // 不考虑 map / set / TypedArray 类型的赋值 + + // 不考虑对象的 symbol 属性 + const props = isArr ? undefined : Object.keys(Object(value)); + + let index = -1; + if (result) { + while (++index < (props || value).length) { + const key = props ? props[index] : index; + const subValue = value[key]; + if (excludeKeys?.includes(key.toString())) { + result[key] = subValue; + } else { + result[key] = cloneDeepSpec(subValue, excludeKeys); + } + } + } + + return result; +} diff --git a/packages/vtable/src/vutil-extension-temp/spec/common.ts b/packages/vtable/src/vutil-extension-temp/spec/common.ts new file mode 100644 index 000000000..a11af544c --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/spec/common.ts @@ -0,0 +1,23 @@ +import { DataView } from '@visactor/vdataset'; + +export function isDataView(obj: any): obj is DataView { + return obj instanceof DataView; +} + +export function isHTMLElement(obj: any): obj is Element { + try { + return obj instanceof Element; + } catch { + // 跨端 plan B + const htmlElementKeys: (keyof Element)[] = [ + 'children', + 'innerHTML', + 'classList', + 'setAttribute', + 'tagName', + 'getBoundingClientRect' + ]; + const keys = Object.keys(obj); + return htmlElementKeys.every(key => keys.includes(key)); + } +} diff --git a/packages/vtable/src/vutil-extension-temp/spec/index.ts b/packages/vtable/src/vutil-extension-temp/spec/index.ts new file mode 100644 index 000000000..1245ec93d --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/spec/index.ts @@ -0,0 +1,3 @@ +export * from './clone-deep'; +export * from './common'; +export * from './merge-spec'; diff --git a/packages/vtable/src/vutil-extension-temp/spec/merge-spec.ts b/packages/vtable/src/vutil-extension-temp/spec/merge-spec.ts new file mode 100644 index 000000000..b7d3a8433 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/spec/merge-spec.ts @@ -0,0 +1,130 @@ +import { isArray, isArrayLike, isObject, isPlainObject, isValid } from '@visactor/vutils'; + +function baseMerge(target: any, source: any, shallowArray = false) { + if (source) { + if (target === source) { + return; + } + if (isValid(source) && typeof source === 'object') { + // baseFor + const iterable = Object(source); + const props = []; + // keysIn + for (const key in iterable) { + props.push(key); + } + let { length } = props; + let propIndex = -1; + while (length--) { + const key = props[++propIndex]; + if ( + isValid(iterable[key]) && + typeof iterable[key] === 'object' && + !isArray(target[key]) // VChart 特有逻辑 + ) { + baseMergeDeep(target, source, key, shallowArray); + } else { + assignMergeValue(target, key, iterable[key]); + } + } + } + } +} + +// 由于目前 VChart 内部对 spec 会先执行一次深拷贝,merge 暂时不考虑 source 中有环的问题 +function baseMergeDeep(target: object, source: object, key: string, shallowArray = false) { + const objValue = target[key]; + const srcValue = source[key]; + let newValue = source[key]; + let isCommon = true; + // 不考虑 buffer / typedArray 类型 + if (isArray(srcValue)) { + if (shallowArray) { + // 依据参数对数组做浅拷贝 + newValue = []; + } else if (isArray(objValue)) { + newValue = objValue; + } else if (isArrayLike(objValue)) { + // 如果 source 为数组,则 target 的 arrayLike 对象也视作为数组处理 + newValue = new Array(objValue.length); + let index = -1; + const length = objValue.length; + while (++index < length) { + newValue[index] = objValue[index]; + } + } + } + // else if (isArray(srcValue) && shallowArray) { + // newValue = []; + // } + // 不考虑 argument 类型 + else if (isPlainObject(srcValue)) { + newValue = objValue ?? {}; + // 不考虑 prototype 的额外处理 + if (typeof objValue === 'function' || typeof objValue !== 'object') { + newValue = {}; + } + } else { + isCommon = false; + } + // 对 class 等复杂对象或者浅拷贝的 array 不做拷贝处理 + if (isCommon) { + baseMerge(newValue, srcValue, shallowArray); + } + assignMergeValue(target, key, newValue); +} + +function assignMergeValue(target: object, key: string, value: any) { + if ((value !== undefined && !eq(target[key], value)) || (value === undefined && !(key in target))) { + // 不考虑 __proto__ 的赋值处理 + target[key] = value; + } +} + +function eq(value: any, other: any) { + return value === other || (Number.isNaN(value) && Number.isNaN(other)); +} + +/* 与原生的 lodash merge 差异在于对数组是否应用最后一个 source 的结果 + * 以及对一些特殊情况的处理,比如对数组类型 padding 和对象类型的 padding 的 merge + */ +export function mergeSpec(target: any, ...sources: any[]): any { + let sourceIndex = -1; + const length = sources.length; + while (++sourceIndex < length) { + const source = sources[sourceIndex]; + baseMerge(target, source, true); + } + return target; +} + +export function mergeSpecWithFilter( + target: any, + filter: string | { type: string; index: number }, + spec: any, + forceMerge: boolean +) { + Object.keys(target).forEach(k => { + if (isObject(filter)) { + if (filter.type === k) { + if (isArray(target[k])) { + if (target[k].length >= filter.index) { + target[k][filter.index] = forceMerge ? mergeSpec({}, target[k][filter.index], spec) : spec; + } + } else { + target[k] = forceMerge ? mergeSpec({}, target[k], spec) : spec; + } + } + } else { + // filter === user id + if (isArray(target[k])) { + const index = target[k].findIndex((_s: { id: string | number }) => _s.id === filter); + if (index >= 0) { + target[k][index] = forceMerge ? mergeSpec({}, target[k][index], spec) : spec; + } + } else if (target.id === filter) { + target[k] = forceMerge ? mergeSpec({}, target[k], spec) : spec; + } + } + }); +} diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/config.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/config.ts new file mode 100644 index 000000000..af2881fac --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/transform/tick-data/config.ts @@ -0,0 +1,2 @@ +/** 连续轴默认 tick 数量 */ +export const DEFAULT_CONTINUOUS_TICK_COUNT = 5; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/continuous.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/continuous.ts new file mode 100644 index 000000000..981390e38 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/transform/tick-data/continuous.ts @@ -0,0 +1,92 @@ +import type { LinearScale, ContinuousScale } from '@visactor/vscale'; +// eslint-disable-next-line no-duplicate-imports +import { isContinuous } from '@visactor/vscale'; +import { isFunction, isValid, last } from '@visactor/vutils'; +import { DEFAULT_CONTINUOUS_TICK_COUNT } from './config'; +import type { ICartesianTickDataOpt, ITickData, ITickDataOpt } from './interface'; +import type { ILabelItem } from './util'; +// eslint-disable-next-line no-duplicate-imports +import { convertDomainToTickData, getCartesianLabelBounds, hasOverlap, intersect } from './util'; + +/** + * 对于连续轴: + * - 如果spec配了tickCount、forceTickCount、tickStep,则直接输出LinearScale的ticks()、forceTicks()、stepTicks()结果; + * - 默认输出tickCount为10的ticks()结果。 + * + * @param scale + * @param op + * @returns + */ +export const continuousTicks = (scale: ContinuousScale, op: ITickDataOpt): ITickData[] => { + if (!isContinuous(scale.type)) { + return convertDomainToTickData(scale.domain()); + } + // if range is so small + const range = scale.range(); + const rangeSize = Math.abs(range[range.length - 1] - range[0]); + if (rangeSize < 2) { + return convertDomainToTickData([scale.domain()[0]]); + } + + const { tickCount, forceTickCount, tickStep, noDecimals = false, labelStyle } = op; + + let scaleTicks: number[]; + if (isValid(tickStep)) { + scaleTicks = (scale as LinearScale).stepTicks(tickStep); + } else if (isValid(forceTickCount)) { + scaleTicks = (scale as LinearScale).forceTicks(forceTickCount); + } else if (op.tickMode === 'd3') { + const count = isFunction(tickCount) ? tickCount({ axisLength: rangeSize, labelStyle }) : tickCount; + scaleTicks = (scale as LinearScale).d3Ticks(count ?? DEFAULT_CONTINUOUS_TICK_COUNT, { noDecimals }); + } else { + const count = isFunction(tickCount) ? tickCount({ axisLength: rangeSize, labelStyle }) : tickCount; + scaleTicks = (scale as LinearScale).ticks(count ?? DEFAULT_CONTINUOUS_TICK_COUNT, { noDecimals }); + } + + if (op.sampling) { + // 判断重叠 + if (op.coordinateType === 'cartesian' || (op.coordinateType === 'polar' && op.axisOrientType === 'radius')) { + const { labelGap = 4, labelFlush } = op as ICartesianTickDataOpt; + let items = getCartesianLabelBounds(scale, scaleTicks, op as ICartesianTickDataOpt).map( + (bounds, i) => + ({ + AABBBounds: bounds, + value: scaleTicks[i] + } as ILabelItem) + ); + while (items.length >= 3 && hasOverlap(items, labelGap)) { + items = methods.parity(items); + } + const ticks = items.map(item => item.value); + + if (ticks.length < 3 && labelFlush) { + if (ticks.length > 1) { + ticks.pop(); + } + if (last(ticks) !== last(scaleTicks)) { + ticks.push(last(scaleTicks)); + } + } + + scaleTicks = ticks; + } + } + + return convertDomainToTickData(scaleTicks); +}; + +const methods = { + parity: function (items: ILabelItem[]) { + return items.filter((item, i) => i % 2 === 0); + }, + greedy: function (items: ILabelItem[], sep: number) { + let a: ILabelItem; + return items.filter((b, i) => { + if (!i || !intersect(a.AABBBounds, b.AABBBounds, sep)) { + a = b; + return true; + } + return false; + }); + } +}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/linear.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/linear.ts new file mode 100644 index 000000000..83cce6834 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/linear.ts @@ -0,0 +1,241 @@ +import type { BandScale, IBaseScale } from '@visactor/vscale'; +import { isFunction, isValid, maxInArray, minInArray } from '@visactor/vutils'; +import type { ICartesianTickDataOpt, ITickData } from '../interface'; +import { convertDomainToTickData, getCartesianLabelBounds, isAxisHorizontal } from '../util'; +import { binaryFuzzySearchInNumberRange } from '../../../algorithm'; + +/** x1, x2, length */ +type OneDimensionalBounds = [number, number, number]; + +const getOneDimensionalLabelBounds = ( + scale: IBaseScale, + domain: any[], + op: ICartesianTickDataOpt, + isHorizontal: boolean +): OneDimensionalBounds[] => { + const labelBoundsList = getCartesianLabelBounds(scale, domain, op); + return labelBoundsList.map(bounds => { + if (isHorizontal) { + return [bounds.x1, bounds.x2, bounds.width()]; + } + return [bounds.y1, bounds.y2, bounds.height()]; + }); +}; + +/** 判断两个 bounds 是否有重叠情况 */ +const boundsOverlap = (prevBounds: OneDimensionalBounds, nextBounds: OneDimensionalBounds, gap = 0): boolean => { + return Math.max(prevBounds[0], nextBounds[0]) - gap / 2 <= Math.min(prevBounds[1], nextBounds[1]) + gap / 2; +}; + +/** 判断两个不相交的 bounds 相隔的距离 */ +export const boundsDistance = (prevBounds: OneDimensionalBounds, nextBounds: OneDimensionalBounds): number => { + if (prevBounds[1] < nextBounds[0]) { + return nextBounds[0] - prevBounds[1]; + } else if (nextBounds[1] < prevBounds[0]) { + return prevBounds[0] - nextBounds[1]; + } + return 0; +}; + +/** + * 对于离散轴: + * - 如果spec配了tickCount、forceTickCount、tickStep,则直接输出BandScale的ticks()、forceTicks()、stepTicks()结果; + * - 估算所有轴label的宽度(或高度,在竖轴的情况下)并存为数组domainLengthList; + * - 通过循环来寻找最小的step,使:如果在这个step下采样,轴标签互不遮挡(此处用到domainLengthList和scale.range()); + * - 如果用户配置了spec.label.lastVisible,则处理右边界:强制采样最后一个tick数据,并删掉这个tick的label所覆盖的那些tick数据。 + * + * @param scale + * @param op + * @returns + */ +export const linearDiscreteTicks = (scale: BandScale, op: ICartesianTickDataOpt): ITickData[] => { + const domain = scale.domain(); + if (!domain.length) { + return []; + } + const { tickCount, forceTickCount, tickStep, labelGap = 4, axisOrientType, labelStyle } = op; + const isHorizontal = isAxisHorizontal(axisOrientType); + const range = scale.range(); + + // if range is so small + const rangeSize = scale.calculateWholeRangeSize(); + if (rangeSize < 2) { + if (op.labelLastVisible) { + return convertDomainToTickData([domain[domain.length - 1]]); + } + return convertDomainToTickData([domain[0]]); + } + + let scaleTicks; + if (isValid(tickStep)) { + scaleTicks = scale.stepTicks(tickStep); + } else if (isValid(forceTickCount)) { + scaleTicks = scale.forceTicks(forceTickCount); + } else if (isValid(tickCount)) { + const count = isFunction(tickCount) ? tickCount({ axisLength: rangeSize, labelStyle }) : tickCount; + scaleTicks = scale.ticks(count); + } else if (op.sampling) { + const fontSize = (op.labelStyle.fontSize ?? 12) + 2; + const rangeStart = minInArray(range); + const rangeEnd = maxInArray(range); + + if (domain.length <= rangeSize / fontSize) { + const incrementUnit = (rangeEnd - rangeStart) / domain.length; + const labelBoundsList = getOneDimensionalLabelBounds(scale, domain, op, isHorizontal); + const minBoundsLength = Math.min(...labelBoundsList.map(bounds => bounds[2])); + + const stepResult = getStep( + domain, + labelBoundsList, + labelGap, + op.labelLastVisible, + Math.floor(minBoundsLength / incrementUnit), // 给step赋上合适的初值,有效改善外层循环次数 + false + ); + + scaleTicks = (scale as BandScale).stepTicks(stepResult.step); + if (op.labelLastVisible) { + if (stepResult.delCount) { + scaleTicks = scaleTicks.slice(0, scaleTicks.length - stepResult.delCount); + } + scaleTicks.push(domain[domain.length - 1]); + } + } else { + // only check first middle last, use the max size to sampling + const tempDomain = [domain[0], domain[Math.floor(domain.length / 2)], domain[domain.length - 1]]; + const tempList = getOneDimensionalLabelBounds(scale, tempDomain, op, isHorizontal); + let maxBounds: OneDimensionalBounds = null; + tempList.forEach(current => { + if (!maxBounds) { + maxBounds = current; + return; + } + if (maxBounds[2] < current[2]) { + maxBounds = current; + } + }); + + const step = + rangeEnd - rangeStart - labelGap > 0 + ? Math.ceil((domain.length * (labelGap + maxBounds[2])) / (rangeEnd - rangeStart - labelGap)) + : domain.length - 1; + + scaleTicks = (scale as BandScale).stepTicks(step); + + if ( + op.labelLastVisible && + (!scaleTicks.length || scaleTicks[scaleTicks.length - 1] !== domain[domain.length - 1]) + ) { + if ( + scaleTicks.length && + Math.abs(scale.scale(scaleTicks[scaleTicks.length - 1]) - scale.scale(domain[domain.length - 1])) < + maxBounds[2] + ) { + scaleTicks = scaleTicks.slice(0, -1); + } + scaleTicks.push(domain[domain.length - 1]); + } + } + } else { + scaleTicks = scale.domain(); + } + + return convertDomainToTickData(scaleTicks); +}; + +/** 计算合适的step */ +const getStep = ( + domain: any[], + labelBoundsList: OneDimensionalBounds[], + labelGap: number, + labelLastVisible: boolean, + defaultStep: number, + areAllBoundsSame: boolean +) => { + let resultDelCount = 0; + let resultStep = 0; + let resultTickCount = -1; + let minDiff = Number.MAX_VALUE; + + /** 验证在当前 step 下是否会产生重叠 */ + const validateStep = (step: number) => { + let success = true; + let ptr = 0; + do { + if (ptr + step < domain.length && boundsOverlap(labelBoundsList[ptr], labelBoundsList[ptr + step], labelGap)) { + success = false; + } + ptr += step; + } while (success && ptr < domain.length); + return success; + }; + + // 通过二分来寻找最小的step,使:如果在这个step下采样,轴标签互不遮挡 + const minValidStep = binaryFuzzySearchInNumberRange(defaultStep, domain.length, step => + validateStep(step) ? 1 : -1 + ); + + // 对 step 进行微调 + let step = minValidStep; + do { + if (step > minValidStep && !areAllBoundsSame) { + if (!validateStep(step)) { + step++; + continue; + } + } + if (labelLastVisible) { + const lastIndex = domain.length - 1; + let delCount = 0; + let ptr; + if (domain.length % step > 0) { + ptr = domain.length - (domain.length % step) + step; + } else { + ptr = domain.length; + } + do { + ptr -= step; // 获取最后一个label位置 + if (ptr === lastIndex || boundsOverlap(labelBoundsList[ptr], labelBoundsList[lastIndex], labelGap)) { + delCount++; + } else { + break; + } + } while (ptr > 0); + if (ptr === lastIndex) { + // 采到的最后的一个 label 刚好是最后一项,直接退出 + resultStep = step; + resultDelCount = delCount; + break; + } else { + // 尝试获取最均匀的结果,防止倒数第二项和最后一项有大的空档 + const tickCount = Math.floor(domain.length / step) - delCount + 1; + if (tickCount < resultTickCount) { + break; + } else { + resultTickCount = tickCount; + const distance1 = boundsDistance(labelBoundsList[ptr], labelBoundsList[lastIndex]); // 倒数第2项和最后一项的距离 + const distance2 = + ptr - step >= 0 ? boundsDistance(labelBoundsList[ptr - step], labelBoundsList[ptr]) : distance1; // 倒数第3项和倒数第2项的距离 + const diff = Math.abs(distance1 - distance2); + if (diff < minDiff) { + minDiff = diff; + resultStep = step; // 记录最均匀的 step + resultDelCount = delCount; + } + if (distance1 <= distance2) { + break; + } + } + } + } else { + resultStep = step; + break; + } + step++; + } while (step <= domain.length); + + return { + step: resultStep, + delCount: resultDelCount + }; +}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/polar-angle.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/polar-angle.ts new file mode 100644 index 000000000..361072dda --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/transform/tick-data/discrete/polar-angle.ts @@ -0,0 +1,101 @@ +import type { BandScale } from '@visactor/vscale'; +import { isFunction, isValid, maxInArray, minInArray } from '@visactor/vutils'; +import type { IPolarTickDataOpt, ITickData } from '../interface'; +import { convertDomainToTickData, getPolarAngleLabelBounds, labelOverlap } from '../util'; +import type { AABBBounds } from '@visactor/vutils'; + +/** + * 对于离散轴: + * - 如果spec配了tickCount、forceTickCount、tickStep,则直接输出BandScale的ticks()、forceTicks()、stepTicks()结果; + * - 估算所有轴label的宽高并存为数组labelBoundsList; + * - 通过循环来寻找最小的step,使:如果在这个step下采样,轴标签互不遮挡(此处用到labelBoundsList和scale.range()); + * + * @param scale + * @param op + * @returns + */ +export const polarAngleAxisDiscreteTicks = (scale: BandScale, op: IPolarTickDataOpt): ITickData[] => { + const { tickCount, forceTickCount, tickStep, getRadius, labelOffset, labelGap = 0, labelStyle } = op; + const radius = getRadius?.(); + if (!radius) { + return convertDomainToTickData(scale.domain()); + } + + let scaleTicks; + if (isValid(tickStep)) { + scaleTicks = scale.stepTicks(tickStep); + } else if (isValid(forceTickCount)) { + scaleTicks = scale.forceTicks(forceTickCount); + } else if (isValid(tickCount)) { + const range = scale.range(); + const rangeSize = Math.abs(range[range.length - 1] - range[0]); + const count = isFunction(tickCount) ? tickCount({ axisLength: rangeSize, labelStyle }) : tickCount; + scaleTicks = scale.ticks(count); + } else if (op.sampling) { + const domain = scale.domain(); + const range = scale.range(); + + const labelBoundsList = getPolarAngleLabelBounds(scale, domain, op); + + const rangeStart = minInArray(range); + const rangeEnd = maxInArray(range); + + const axisLength = Math.abs(rangeEnd - rangeStart) * (radius + labelOffset); + const incrementUnit = axisLength / domain.length; + const { step, delCount } = getStep( + domain, + labelBoundsList, + labelGap, + Math.floor( + labelBoundsList.reduce((min, curBounds) => { + return Math.min(min, curBounds.width(), curBounds.height()); + }, Number.MAX_VALUE) / incrementUnit + ) // 给step赋上合适的初值,有效改善外层循环次数 + ); + + scaleTicks = (scale as BandScale).stepTicks(step); + scaleTicks = scaleTicks.slice(0, scaleTicks.length - delCount); + } else { + scaleTicks = scale.domain(); + } + + return convertDomainToTickData(scaleTicks); +}; + +/** 计算合适的step */ +const getStep = (domain: any[], labelBoundsList: AABBBounds[], labelGap: number, defaultStep: number) => { + let step = defaultStep; + // 通过循环来寻找最小的step,使:如果在这个step下采样,轴标签互不遮挡 + do { + let success = true; + step++; + let ptr = 0; + do { + if (ptr + step < domain.length && labelOverlap(labelBoundsList[ptr], labelBoundsList[ptr + step], labelGap)) { + success = false; + } + ptr += step; + } while (success && ptr < domain.length); + if (success) { + break; + } + } while (step <= domain.length); + + let delCount = 0; + if (domain.length > 2) { + let ptr = domain.length - (domain.length % step); + if (ptr >= domain.length) { + ptr -= step; + } + // 判断首尾是否互相覆盖 + while (ptr > 0 && labelOverlap(labelBoundsList[0], labelBoundsList[ptr])) { + delCount++; + ptr -= step; + } + } + + return { + step, + delCount + }; +}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/index.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/index.ts new file mode 100644 index 000000000..549fb07f7 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/transform/tick-data/index.ts @@ -0,0 +1,27 @@ +import type { BandScale, ContinuousScale, IBaseScale } from '@visactor/vscale'; +// eslint-disable-next-line no-duplicate-imports +import { isContinuous, isDiscrete } from '@visactor/vscale'; +import { continuousTicks } from './continuous'; +import { linearDiscreteTicks } from './discrete/linear'; +import { polarAngleAxisDiscreteTicks } from './discrete/polar-angle'; +import type { ICartesianTickDataOpt, IPolarTickDataOpt, ITickData, ITickDataOpt } from './interface'; +import { convertDomainToTickData } from './util'; + +export * from './interface'; +export { convertDomainToTickData }; + +// 总入口 +export const ticks = (scale: IBaseScale, op: ITickDataOpt): ITickData[] => { + if (isContinuous(scale.type)) { + return continuousTicks(scale as ContinuousScale, op); + } else if (isDiscrete(scale.type)) { + if (op.coordinateType === 'cartesian') { + return linearDiscreteTicks(scale as BandScale, op as ICartesianTickDataOpt); + } else if (op.coordinateType === 'polar') { + if (op.axisOrientType === 'angle') { + return polarAngleAxisDiscreteTicks(scale as BandScale, op as IPolarTickDataOpt); + } + } + } + return convertDomainToTickData(scale.domain()); +}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/interface.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/interface.ts new file mode 100644 index 000000000..1c70971cd --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/transform/tick-data/interface.ts @@ -0,0 +1,57 @@ +import type { ITextGraphicAttribute } from '@visactor/vrender-core'; + +export type CoordinateType = 'cartesian' | 'polar' | 'geo' | 'none'; +export type IOrientType = 'left' | 'top' | 'right' | 'bottom' | 'z'; +export type IPolarOrientType = 'radius' | 'angle'; + +export interface ITickDataOpt { + /** + * 是否进行轴采样 + */ + sampling?: boolean; + tickCount?: number | ((option: ITickCallbackOption) => number); + forceTickCount?: number; + tickStep?: number; + tickMode?: 'average' | 'd3' | string; + noDecimals?: boolean; + + coordinateType: CoordinateType; + axisOrientType: IOrientType | IPolarOrientType; + startAngle?: number; + + labelFormatter?: (value: any) => string; + labelStyle: ITextGraphicAttribute; + labelGap?: number; +} + +export interface ICartesianTickDataOpt extends ITickDataOpt { + axisOrientType: IOrientType; + labelLastVisible: boolean; + labelFlush: boolean; +} + +export interface IPolarTickDataOpt extends ITickDataOpt { + axisOrientType: IPolarOrientType; + getRadius: () => number; + labelOffset: number; + inside: boolean; +} + +export interface ITickData { + index: number; + value: number | string; + // label: string; +} + +type ITickCallbackOption = { + /** + * 坐标轴占据的画布大小。 + * 直角坐标系中为轴的宽度或高度。 + * 极坐标系中半径轴的长度。 + */ + axisLength?: number; + /** + * 轴标签的样式 + */ + labelStyle?: ITextGraphicAttribute; +}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/util.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/util.ts new file mode 100644 index 000000000..abc95029a --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/transform/tick-data/util.ts @@ -0,0 +1,182 @@ +import type { IBaseScale } from '@visactor/vscale'; +import type { IBoundsLike } from '@visactor/vutils'; +// eslint-disable-next-line no-duplicate-imports +import { AABBBounds, degreeToRadian } from '@visactor/vutils'; +import type { IGraphic, TextAlignType, TextBaselineType } from '@visactor/vrender-core'; +import { initTextMeasure } from '../../utils/text'; +import type { ICartesianTickDataOpt, IOrientType, IPolarTickDataOpt, ITickData } from './interface'; +import { getLabelPosition } from './utils/polar-label-position'; + +export const convertDomainToTickData = (domain: any[]): ITickData[] => { + const ticks = domain.map((t: number, index: number) => { + return { + index, + value: t + }; + }); + return ticks; +}; + +/** 判断两个label是否有重叠情况 */ +export const labelOverlap = (prevLabel: AABBBounds, nextLabel: AABBBounds, gap = 0): boolean => { + const prevBounds = new AABBBounds(prevLabel).expand(gap / 2); + const nextBounds = new AABBBounds(nextLabel).expand(gap / 2); + return prevBounds.intersects(nextBounds); +}; + +/** 判断两个不相交的label相隔的距离 */ +export const labelDistance = (prevLabel: AABBBounds, nextLabel: AABBBounds): [number, number] => { + let horizontal = 0; + if (prevLabel.x2 < nextLabel.x1) { + horizontal = nextLabel.x1 - prevLabel.x2; + } else if (nextLabel.x2 < prevLabel.x1) { + horizontal = prevLabel.x1 - nextLabel.x2; + } + + let vertical = 0; + if (prevLabel.y2 < nextLabel.y1) { + vertical = nextLabel.y1 - prevLabel.y2; + } else if (nextLabel.y2 < prevLabel.y1) { + vertical = prevLabel.y1 - nextLabel.y2; + } + + return [horizontal, vertical]; +}; + +export function intersect(a: IBoundsLike, b: IBoundsLike, sep: number) { + return sep > Math.max(b.x1 - a.x2, a.x1 - b.x2, b.y1 - a.y2, a.y1 - b.y2); +} + +export interface ILabelItem extends Pick { + value?: T; +} + +export function hasOverlap(items: ILabelItem[], pad: number): boolean { + for (let i = 1, n = items.length, a = items[0], b; i < n; a = b, ++i) { + b = items[i]; + if (intersect(a.AABBBounds, b.AABBBounds, pad)) { + return true; + } + } + return false; +} + +export const MIN_TICK_GAP = 12; + +export const getCartesianLabelBounds = (scale: IBaseScale, domain: any[], op: ICartesianTickDataOpt): AABBBounds[] => { + const { labelStyle, axisOrientType, labelFlush, labelFormatter, startAngle = 0 } = op; + let labelAngle = labelStyle.angle ?? 0; + if (labelStyle.direction === 'vertical') { + labelAngle += degreeToRadian(90); + } + const isHorizontal = ['bottom', 'top'].includes(axisOrientType); + const isVertical = ['left', 'right'].includes(axisOrientType); + let scaleX = 1; + let scaleY = 0; + if (isHorizontal) { + // nothing to update + } else if (isVertical) { + scaleX = 0; + scaleY = 1; + } else if (startAngle) { + scaleX = Math.cos(startAngle); + scaleY = -Math.sin(startAngle); + } + + const textMeasure = initTextMeasure(labelStyle); + const labelBoundsList = domain.map((v: any, i: number) => { + const str = labelFormatter ? labelFormatter(v) : `${v}`; + + // 估算文本宽高 + const { width, height } = textMeasure.quickMeasure(str); + const textWidth = Math.max(width, MIN_TICK_GAP); + const textHeight = Math.max(height, MIN_TICK_GAP); + + // 估算文本位置 + const pos = scale.scale(v); + const baseTextX = scaleX * pos; + const baseTextY = scaleY * pos; + let textX = baseTextX; + let textY = baseTextY; + + let align: TextAlignType; + if (labelFlush && isHorizontal && i === 0) { + align = 'left'; + } else if (labelFlush && isHorizontal && i === domain.length - 1) { + align = 'right'; + } else { + align = labelStyle.textAlign ?? 'center'; + } + if (align === 'right') { + textX -= textWidth; + } else if (align === 'center') { + textX -= textWidth / 2; + } + + let baseline: TextBaselineType; + if (labelFlush && isVertical && i === 0) { + baseline = 'top'; + } else if (labelFlush && isVertical && i === domain.length - 1) { + baseline = 'bottom'; + } else { + baseline = labelStyle.textBaseline ?? 'middle'; + } + if (baseline === 'bottom') { + textY -= textHeight; + } else if (baseline === 'middle') { + textY -= textHeight / 2; + } + + // 计算 label 包围盒 + const bounds = new AABBBounds().set(textX, textY, textX + textWidth, textY + textHeight); + + if (labelAngle) { + bounds.rotate(labelAngle, baseTextX, baseTextY); + } + + return bounds; + }); + + return labelBoundsList; +}; + +export const getPolarAngleLabelBounds = (scale: IBaseScale, domain: any[], op: IPolarTickDataOpt): AABBBounds[] => { + const { labelStyle, getRadius, labelOffset, labelFormatter, inside } = op; + const radius = getRadius?.(); + const labelAngle = labelStyle.angle ?? 0; + + const textMeasure = initTextMeasure(labelStyle); + const labelBoundsList = domain.map((v: any) => { + const str = labelFormatter ? labelFormatter(v) : `${v}`; + + // 估算文本宽高 + const { width, height } = textMeasure.quickMeasure(str); + const textWidth = Math.max(width, MIN_TICK_GAP); + const textHeight = Math.max(height, MIN_TICK_GAP); + + // 估算文本位置 + const angle = scale.scale(v); + let textX = 0; + let textY = 0; + const orient = { + align: labelStyle.textAlign ?? 'center', + baseline: labelStyle.textBaseline ?? 'middle' + }; + + const { x, y } = getLabelPosition(angle, { x: 0, y: 0 }, radius, labelOffset, inside, str, labelStyle); + textX = x + (orient.align === 'right' ? -textWidth : orient.align === 'center' ? -textWidth / 2 : 0); + textY = y + (orient.baseline === 'bottom' ? -textHeight : orient.baseline === 'middle' ? -textHeight / 2 : 0); + + // 计算 label 包围盒 + const bounds = new AABBBounds() + .set(textX, textY, textX + textWidth, textY + textHeight) + .rotate(labelAngle, textX + textWidth / 2, textY + textHeight / 2); + return bounds; + }); + + return labelBoundsList; +}; + +export const isAxisHorizontal = (axisOrientType: IOrientType) => { + return (['bottom', 'top', 'z'] as IOrientType[]).includes(axisOrientType); +}; diff --git a/packages/vtable/src/vutil-extension-temp/transform/tick-data/utils/polar-label-position.ts b/packages/vtable/src/vutil-extension-temp/transform/tick-data/utils/polar-label-position.ts new file mode 100644 index 000000000..cef160c38 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/transform/tick-data/utils/polar-label-position.ts @@ -0,0 +1,18 @@ +import type { ITextGraphicAttribute } from '@visactor/vrender-core'; +import { getCircleLabelPosition, getCircleVerticalVector, getVerticalCoord } from '@visactor/vrender-components'; +import { polarToCartesian } from '@visactor/vutils'; + +export function getLabelPosition( + angle: number, + center: { x: number; y: number }, + radius: number, + labelOffset: number, + inside: boolean, + text: string | number, + style: Partial +) { + const point = polarToCartesian({ x: 0, y: 0 }, radius, angle); + const labelPoint = getVerticalCoord(point, getCircleVerticalVector(labelOffset, point, center, inside)); + const vector = getCircleVerticalVector(labelOffset || 1, labelPoint, center, inside); + return getCircleLabelPosition(labelPoint, vector, text, style); +} diff --git a/packages/vtable/src/vutil-extension-temp/utils/index.ts b/packages/vtable/src/vutil-extension-temp/utils/index.ts new file mode 100644 index 000000000..35641ed3a --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/utils/index.ts @@ -0,0 +1,3 @@ +export * from './object'; +export * from './polar'; +export * from './text'; diff --git a/packages/vtable/src/vutil-extension-temp/utils/object.ts b/packages/vtable/src/vutil-extension-temp/utils/object.ts new file mode 100644 index 000000000..8798664d3 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/utils/object.ts @@ -0,0 +1,51 @@ +import { get, isArray, isFunction, isNil, isObject } from '@visactor/vutils'; + +/** + * 判断一个 spec 是否包含另一个 spec 片段 + * @param spec 原始 spec + * @param searchSpec 要匹配的 spec 片段 + */ +export const includeSpec = (spec: Partial, searchSpec: Partial): boolean => { + if (spec === searchSpec) { + return true; + } + if (isFunction(spec) || isFunction(searchSpec)) { + return false; + } + if (isArray(spec) && isArray(searchSpec)) { + return searchSpec.every(searchItem => spec.some(item => includeSpec(item, searchItem))); + } + if (isObject(spec) && isObject(searchSpec)) { + return Object.keys(searchSpec).every(key => includeSpec(spec[key], searchSpec[key])); + } + return false; +}; + +export const setProperty = (target: T, path: Array, value: any): T => { + if (isNil(path)) { + return target; + } + const key = path[0]; + if (isNil(key)) { + return target; + } + if (path.length === 1) { + target[key] = value; + return target; + } + if (isNil(target[key])) { + if (typeof path[1] === 'number') { + target[key] = []; + } else { + target[key] = {}; + } + } + return setProperty(target[key], path.slice(1), value); +}; + +export const getProperty = (target: any, path: Array, defaultValue?: T): T => { + if (isNil(path)) { + return undefined; + } + return get(target, path as string[], defaultValue) as T; +}; diff --git a/packages/vtable/src/vutil-extension-temp/utils/polar.ts b/packages/vtable/src/vutil-extension-temp/utils/polar.ts new file mode 100644 index 000000000..c64ea2cf4 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/utils/polar.ts @@ -0,0 +1,47 @@ +import type { TextAlignType, TextBaselineType } from '@visactor/vrender-core'; + +/** + * 角度标准化处理 + * @param angle 弧度角 + */ +export function normalizeAngle(angle: number): number { + while (angle < 0) { + angle += Math.PI * 2; + } + while (angle >= Math.PI * 2) { + angle -= Math.PI * 2; + } + return angle; +} + +/** + * 计算对应角度下的角度轴标签定位属性 + * @param angle 弧度角,需要注意是逆时针计算的 + * @returns + */ +export function angleLabelOrientAttribute(angle: number) { + let align: TextAlignType = 'center'; + let baseline: TextBaselineType = 'middle'; + + angle = normalizeAngle(angle); + + // left: 5/3 - 1/3; right: 2/3 - 4/3; center: 5/3 - 1/3 & 2/3 - 4/3 + if (angle >= Math.PI * (5 / 3) || angle <= Math.PI * (1 / 3)) { + align = 'left'; + } else if (angle >= Math.PI * (2 / 3) && angle <= Math.PI * (4 / 3)) { + align = 'right'; + } else { + align = 'center'; + } + + // bottom: 7/6 - 11/6; top: 1/6 - 5/6; middle: 11/6 - 1/6 & 5/6 - 7/6 + if (angle >= Math.PI * (7 / 6) && angle <= Math.PI * (11 / 6)) { + baseline = 'bottom'; + } else if (angle >= Math.PI * (1 / 6) && angle <= Math.PI * (5 / 6)) { + baseline = 'top'; + } else { + baseline = 'middle'; + } + + return { align, baseline }; +} diff --git a/packages/vtable/src/vutil-extension-temp/utils/text.ts b/packages/vtable/src/vutil-extension-temp/utils/text.ts new file mode 100644 index 000000000..e39d0a183 --- /dev/null +++ b/packages/vtable/src/vutil-extension-temp/utils/text.ts @@ -0,0 +1,28 @@ +import type { ITextMeasureOption } from '@visactor/vutils'; +// eslint-disable-next-line no-duplicate-imports +import { TextMeasure } from '@visactor/vutils'; +import type { ITextGraphicAttribute } from '@visactor/vrender-core'; +import { getTextBounds } from '@visactor/vrender-core'; + +export const initTextMeasure = ( + textSpec?: Partial, + option?: Partial, + useNaiveCanvas?: boolean, + defaultFontParams?: Partial +): TextMeasure => { + return new TextMeasure( + { + defaultFontParams: { + fontFamily: + // eslint-disable-next-line max-len + 'PingFang SC,Helvetica Neue,Microsoft Yahei,system-ui,-apple-system,segoe ui,Roboto,Helvetica,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol', + fontSize: 14, + ...defaultFontParams + }, + getTextBounds: useNaiveCanvas ? undefined : getTextBounds, + specialCharSet: '-/: .,@%\'"~' + TextMeasure.ALPHABET_CHAR_SET + TextMeasure.ALPHABET_CHAR_SET.toUpperCase(), + ...(option ?? {}) + }, + textSpec + ); +}; diff --git a/packages/vue-vtable/.eslintrc.js b/packages/vue-vtable/.eslintrc.js new file mode 100644 index 000000000..51d0b5241 --- /dev/null +++ b/packages/vue-vtable/.eslintrc.js @@ -0,0 +1,272 @@ +/* eslint-disable no-undef */ +require('@rushstack/eslint-patch/modern-module-resolution'); + +module.exports = { + extends: ['@internal/eslint-config/profile/lib', '@internal/eslint-config/profile/vue'], + parserOptions: { + tsconfigRootDir: __dirname, + parser: '@typescript-eslint/parser', // 如果您使用 TypeScript + project: './tscofig.eslint.json', + extraFileExtensions: ['.vue'] + }, + plugins: [ + // ... 其他 plugins + 'vue' + ], + parser: 'vue-eslint-parser', + overrides: [ + { + files: ['**/__tests__/**', '**/*.test.ts'], + // 测试文件允许以下规则 + rules: { + '@typescript-eslint/no-empty-function': 'off', + 'no-console': 'off', + 'dot-notation': 'off' + } + } + ], + globals: { + __VERSION__: 'readonly' + }, + rules: { + 'prettier/prettier': ['warn'], + 'linebreak-style': [0, 'error', 'windows'], + // 强制换行时操作符在行首 + // 与prettier冲突 + // "operator-linebreak": ["error", "before", { "overrides": { "=": "after" } }], + // 允许给能自动推断出类型的primitive类型变量额外添加类型声明 + '@typescript-eslint/no-inferrable-types': 'off', + // 在类型导入时推荐import type写法 + '@typescript-eslint/consistent-type-imports': 'warn', + // 禁止出现空接口定义 + '@typescript-eslint/no-empty-interface': 'error', + // 禁止出现空函数 + '@typescript-eslint/no-empty-function': 'error', + '@typescript-eslint/no-this-alias': 'off', + // 禁止使用namespace + '@typescript-eslint/no-namespace': 'error', + // 禁止使用for-in Array + '@typescript-eslint/no-for-in-array': 'error', + // 禁止在optional chain语句后加非空断言 + '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', + // 接口定义中使用函数属性而不是对象方法声明 + '@typescript-eslint/method-signature-style': 'error', + // 默认省略除属性以外的public修饰符 + '@typescript-eslint/explicit-member-accessibility': [ + 'warn', + { + overrides: { + accessors: 'off', + constructors: 'no-public', + methods: 'no-public', + properties: 'no-public', + parameterProperties: 'explicit' + } + } + ], + 'no-console': [ + 1, // 开发期间先关闭 + { + // allow: ["warn", "error"] + allow: ['warn', 'error'] + } + ], + // 如果一个变量不会被重新赋值,最好使用const进行声明 + 'prefer-const': 2, + // 禁止在条件中使用常量表达式 + 'no-constant-condition': 0, + 'no-debugger': 2, + // 禁止对象字面量中出现重复的 key + 'no-dupe-keys': 2, + // 禁止在正则表达式中使用空字符集 + 'no-empty-character-class': 2, + // 禁止对 catch 子句的参数重新赋值 + 'no-ex-assign': 2, + 'no-extra-boolean-cast': 0, + // 禁止对 function 声明重新赋值 + 'no-func-assign': 2, + // 禁止在嵌套的块中出现变量声明或 function 声明 + 'no-inner-declarations': 2, + // 禁止 RegExp 构造函数中存在无效的正则表达式字符串 + 'no-invalid-regexp': 2, + // 禁止对关系运算符的左操作数使用否定操作符 + 'no-unsafe-negation': 2, + // 禁止把全局对象作为函数调用 + 'no-obj-calls': 2, + // 禁用稀疏数组 + 'no-sparse-arrays': 2, + // 禁止在 return、throw、continue 和 break 语句之后出现不可达代码 + 'no-unreachable': 2, + // 要求使用 isNaN() 检查 NaN + 'use-isnan': 2, + // 强制 typeof 表达式与有效的字符串进行比较 + 'valid-typeof': 2, + // 要求使用 === 和 !==,除了与 null 字面量进行比较时 + eqeqeq: [ + 'error', + 'always', + { + null: 'ignore' + } + ], + // 允许 if 语句中 return 语句之后有 else 块 + 'no-else-return': 1, + // 禁用标签语句 + 'no-labels': [ + 2, + { + // 忽略循环语句中的标签 + allowLoop: true + } + ], + // 禁用 eval() + 'no-eval': 2, + // 禁止扩展原生类型 + 'no-extend-native': 2, + // 禁止不必要的 .bind() 调用 + 'no-extra-bind': 0, + // 禁止使用类似 eval() 的方法 + 'no-implied-eval': 2, + // 禁用 __iterator__ 属性 + 'no-iterator': 2, + // 禁止不规则的空白 + 'no-irregular-whitespace': 2, + // 禁用不必要的嵌套块 + 'no-lone-blocks': 2, + // 禁止循环中存在函数 + 'no-loop-func': 2, + // 禁止多行字符串 + 'no-multi-str': 2, + // 禁止对原生对象或只读的全局对象进行赋值 + 'no-global-assign': 2, + // 禁止对 String,Number 和 Boolean 使用 new 操作符 + 'no-new-wrappers': 2, + // 禁用八进制字面量 + 'no-octal': 2, + // 禁止在字符串中使用八进制转义序列 + 'no-octal-escape': 2, + // 禁用 __proto__ 属性 + 'no-proto': 2, + // 禁止自身比较 + 'no-self-compare': 2, + // 禁止可以在有更简单的可替代的表达式时使用三元操作符 + 'no-unneeded-ternary': 2, + // 禁用 with 语句 + 'no-with': 2, + // 强制在 parseInt() 使用基数参数 + radix: 2, + // 要求 IIFE 使用括号括起来 + 'wrap-iife': [2, 'any'], + // 禁止删除变量 + 'no-delete-var': 2, + // 禁止 function 定义中出现重名参数 + 'no-dupe-args': 2, + // 禁止出现重复的 case 标签 + 'no-duplicate-case': 2, + // 不允许标签与变量同名 + 'no-label-var': 2, + // 禁止将标识符定义为受限的名字 + 'no-shadow-restricted-names': 2, + // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到 + 'no-undef': 2, + // 禁止将变量初始化为 undefined + 'no-undef-init': 2, + // 允许在变量定义之前使用它们 + 'no-use-before-define': 'off', + '@typescript-eslint/no-use-before-define': 0, + // 强制或禁止调用无参构造函数时有圆括号 + 'new-parens': 2, + // 禁用 Array 构造函数 + 'no-array-constructor': 2, + // 禁用 Object 的构造函数 + 'no-new-object': 2, + // 禁止不必要的括号 + 'no-extra-parens': [2, 'functions'], + // 禁止使用 空格 和 tab 混合缩进 + 'no-mixed-spaces-and-tabs': 2, + // 强制函数中的变量在分开声明 + 'one-var': [2, 'never'], + // 建议回调函数最大嵌套深度不超过5 + 'max-nested-callbacks': [1, 5], + // 建议可嵌套的块的最大深度不超过6 + 'max-depth': [1, 6], + // 强制一行的最大长度不超过120,不包括注释和url + 'max-len': [ + 'error', + { + code: 120, + ignoreUrls: true, + ignoreComments: true + } + ], + // 建议函数定义中最多允许的参数数量不超过15个 + 'max-params': [1, 15], + // 强制非一元操作符周围有空格 + 'space-infix-ops': 2, + // 强制尽可能地使用点号 + 'dot-notation': [ + 2, + { + // 避免对是保留字的属性使用点号 + allowKeywords: true, + allowPattern: '^catch$' + } + ], + // 强制箭头函数的箭头前后使用一致的空格 + 'arrow-spacing': 2, + // 要求在构造函数中有 super() 的调用 + 'constructor-super': 2, + // 禁止在可能与比较操作符相混淆的地方使用箭头函数 + // 与prettier冲突 + // "no-confusing-arrow": [ + // 2, + // { + // // 该规则不那么严格,将括号作为有效防止混淆的语法。 + // "allowParens": true + // } + // ], + // 禁止修改类声明的变量 + 'no-class-assign': 2, + // 禁止修改 const 声明的变量 + 'no-const-assign': 2, + // 允许在构造函数中,在调用 super() 之前使用 this 或 super + 'no-this-before-super': 0, + // 要求使用 let 或 const 而不是 var + 'no-var': 2, + // 重复模块导入 + // "no-duplicate-imports": 1, + '@typescript-eslint/no-duplicate-imports': 1, + // 建议使用剩余参数而不是 arguments + 'prefer-rest-params': 1, + // 禁止 Unicode 字节顺序标记 (BOM) + 'unicode-bom': 2, + // 强制每一行中所允许的最大语句数量为2 + 'max-statements-per-line': 2, + // 允许不必要的构造函数 + 'no-useless-constructor': 0, + // 允许在函数标识符和其调用之间有空格 + 'func-call-spacing': 'off', + '@typescript-eslint/func-call-spacing': 'error', + // 允许出现未使用过的变量 + 'no-unused-vars': 'off', + '@typescript-eslint/no-unused-vars': [ + 1, + { + // 仅仅检测本作用域中声明的变量是否使用,允许不使用全局环境中的变量。 + vars: 'local', + // 不检查参数 + args: 'none' + } + ], + // 禁用特定的全局变量 + 'no-restricted-globals': [2, 'event', 'name', 'length', 'orientation', 'top', 'parent', 'location', 'closed'], + // 不允许省略大括号 + curly: 'error', + 'promise/catch-or-return': 'warn', + // indent: [1, 2], + 'no-multi-spaces': 1, + 'no-multiple-empty-lines': [1, { max: 1 }], + 'no-trailing-spaces': 1 + }, + ignorePatterns: ['*.config.ts'] +}; diff --git a/packages/vue-vtable/README.md b/packages/vue-vtable/README.md new file mode 100644 index 000000000..7ee1e2015 --- /dev/null +++ b/packages/vue-vtable/README.md @@ -0,0 +1,93 @@ + + +
+

React-VTable

+
+ +
+ +VTable is not just a high-performance multidimensional data analysis table, but also a grid artist that creates art between rows and columns.React-VTable is a React wrapper of VTable. + +[![npm Version](https://img.shields.io/npm/v/@visactor/vtable.svg)](https://www.npmjs.com/package/@visactor/vue-vtable) +[![npm Download](https://img.shields.io/npm/dm/@visactor/vtable.svg)](https://www.npmjs.com/package/@visactor/vue-vtable) +[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/visactor/vtable/blob/main/LICENSE) + +
+ +# Usage + +## Installation + +[npm package](https://www.npmjs.com/package/@visactor/vue-vtable) + +```bash +// npm +npm install @visactor/vue-vtable + +// yarn +yarn add @visactor/vue-vtable +``` + +## Quick Start + +```jsx +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import { ListTable } from "@visactor/vue-vtable"; + +const option = { + header: [ + { + field: "0", + caption: "name", + }, + { + field: "1", + caption: "age", + }, + { + field: "2", + caption: "gender", + }, + { + field: "3", + caption: "hobby", + }, + ], + records: new Array(1000).fill(["John", 18, "male", "🏀"]), +}; + +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( + +); +``` + +## + +[More demos and detailed tutorials](https://visactor.io/vtable) + +# Related Links + +- [Official website](https://visactor.io/vtable) + +# Ecosystem + +| Project | Description | +| -------------------------------------------------------- | ----------------------------- | +| [AI-generated Components](https://visactor.io/ai-vtable) | AI-generated table component. | + +# Contribution + +If you would like to contribute, please read the [Code of Conduct ](./CODE_OF_CONDUCT.md) 和 [ Guide](./CONTRIBUTING.zh-CN.md) first。 + +Small streams converge to make great rivers and seas! + + + +# License + +[MIT License](./LICENSE) diff --git a/packages/vue-vtable/bundler.config.js b/packages/vue-vtable/bundler.config.js new file mode 100644 index 000000000..24d8ed4be --- /dev/null +++ b/packages/vue-vtable/bundler.config.js @@ -0,0 +1,17 @@ +/** + * @type {Partial} + */ +module.exports = { + formats: ['cjs', 'es', 'umd'], + noEmitOnError: false, + copy: ['css'], + name: 'VueVTable', + umdOutputFilename: 'vue-vtable', + rollupOptions: { + treeshake: true + }, + globals: { + '@visactor/vtable': 'VTable' + }, + external: ['@visactor/vtable'] +}; diff --git a/packages/vue-vtable/demo/index.html b/packages/vue-vtable/demo/index.html new file mode 100644 index 000000000..a5649bbf9 --- /dev/null +++ b/packages/vue-vtable/demo/index.html @@ -0,0 +1,12 @@ + + + + + + Vite + Vue + TS + + +
+ + + diff --git a/packages/vue-vtable/demo/src/App.vue b/packages/vue-vtable/demo/src/App.vue new file mode 100644 index 000000000..dd2c5347b --- /dev/null +++ b/packages/vue-vtable/demo/src/App.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/packages/vue-vtable/demo/src/components/content.vue b/packages/vue-vtable/demo/src/components/content.vue new file mode 100644 index 000000000..ca47155c7 --- /dev/null +++ b/packages/vue-vtable/demo/src/components/content.vue @@ -0,0 +1,75 @@ + + + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/components/sidebar.vue b/packages/vue-vtable/demo/src/components/sidebar.vue new file mode 100644 index 000000000..2b19142aa --- /dev/null +++ b/packages/vue-vtable/demo/src/components/sidebar.vue @@ -0,0 +1,116 @@ + + + + + diff --git a/packages/vue-vtable/demo/src/index.css b/packages/vue-vtable/demo/src/index.css new file mode 100644 index 000000000..4fb97b8f4 --- /dev/null +++ b/packages/vue-vtable/demo/src/index.css @@ -0,0 +1,75 @@ +html, body, #root { + width: 100%; + height: 100%; + margin: 0; +} + +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/packages/vue-vtable/demo/src/main.ts b/packages/vue-vtable/demo/src/main.ts new file mode 100644 index 000000000..b43f8920b --- /dev/null +++ b/packages/vue-vtable/demo/src/main.ts @@ -0,0 +1,10 @@ +import { createApp } from 'vue'; +import App from './App.vue'; +import { ListTable, PivotTable, PivotChart } from '../../src/index'; +// import './index.css'; + +const app = createApp(App); +app.component('VueListTable', ListTable); +app.component('VuePivotTable', PivotTable); +app.component('VuePivotChart', PivotChart); +app.mount('#app'); diff --git a/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-custom.vue b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-custom.vue new file mode 100644 index 000000000..430c82247 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-custom.vue @@ -0,0 +1,206 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-destruction.vue b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-destruction.vue new file mode 100644 index 000000000..a846129a7 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-destruction.vue @@ -0,0 +1,133 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-editor.vue b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-editor.vue new file mode 100644 index 000000000..da18a8cc8 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-editor.vue @@ -0,0 +1,194 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-fetch.vue b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-fetch.vue new file mode 100644 index 000000000..ef670ffdb --- /dev/null +++ b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-fetch.vue @@ -0,0 +1,47 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-tree.vue b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-tree.vue new file mode 100644 index 000000000..1a4026144 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable-tree.vue @@ -0,0 +1,94 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable.vue b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable.vue new file mode 100644 index 000000000..18144410a --- /dev/null +++ b/packages/vue-vtable/demo/src/table/gramatical/composition/ListTable.vue @@ -0,0 +1,66 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/gramatical/composition/PivotChartPie.vue b/packages/vue-vtable/demo/src/table/gramatical/composition/PivotChartPie.vue new file mode 100644 index 000000000..b6835a23e --- /dev/null +++ b/packages/vue-vtable/demo/src/table/gramatical/composition/PivotChartPie.vue @@ -0,0 +1,179 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/gramatical/options/ListTable-v-for.vue b/packages/vue-vtable/demo/src/table/gramatical/options/ListTable-v-for.vue new file mode 100644 index 000000000..c8c5dda72 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/gramatical/options/ListTable-v-for.vue @@ -0,0 +1,54 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/gramatical/options/PivotTable.vue b/packages/vue-vtable/demo/src/table/gramatical/options/PivotTable.vue new file mode 100644 index 000000000..4b6b9bca2 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/gramatical/options/PivotTable.vue @@ -0,0 +1,171 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/unified/composition/list-table/list-table-custom.vue b/packages/vue-vtable/demo/src/table/unified/composition/list-table/list-table-custom.vue new file mode 100644 index 000000000..538e64b80 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/composition/list-table/list-table-custom.vue @@ -0,0 +1,422 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/unified/composition/list-table/list-table-editor.vue b/packages/vue-vtable/demo/src/table/unified/composition/list-table/list-table-editor.vue new file mode 100644 index 000000000..77bea708e --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/composition/list-table/list-table-editor.vue @@ -0,0 +1,193 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/unified/composition/list-table/list-table-pagination.vue b/packages/vue-vtable/demo/src/table/unified/composition/list-table/list-table-pagination.vue new file mode 100644 index 000000000..9e2b5f0fc --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/composition/list-table/list-table-pagination.vue @@ -0,0 +1,188 @@ + + + diff --git a/packages/vue-vtable/demo/src/table/unified/composition/pivot-chart/pivot-chart-listTable.vue b/packages/vue-vtable/demo/src/table/unified/composition/pivot-chart/pivot-chart-listTable.vue new file mode 100644 index 000000000..07bf3bb0f --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/composition/pivot-chart/pivot-chart-listTable.vue @@ -0,0 +1,244 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/unified/composition/pivot-chart/pivot-chart.vue b/packages/vue-vtable/demo/src/table/unified/composition/pivot-chart/pivot-chart.vue new file mode 100644 index 000000000..a1058785d --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/composition/pivot-chart/pivot-chart.vue @@ -0,0 +1,506 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/unified/composition/pivot-table/pivot-table-lazyTreeload.vue b/packages/vue-vtable/demo/src/table/unified/composition/pivot-table/pivot-table-lazyTreeload.vue new file mode 100644 index 000000000..b8d67e1b3 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/composition/pivot-table/pivot-table-lazyTreeload.vue @@ -0,0 +1,480 @@ + + + diff --git a/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table-checkbox.vue b/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table-checkbox.vue new file mode 100644 index 000000000..23e365424 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table-checkbox.vue @@ -0,0 +1,55 @@ + + + diff --git a/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table-fetch.vue b/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table-fetch.vue new file mode 100644 index 000000000..31d6edb29 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table-fetch.vue @@ -0,0 +1,40 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table-transpose.vue b/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table-transpose.vue new file mode 100644 index 000000000..8f537c32b --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table-transpose.vue @@ -0,0 +1,59 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table.vue b/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table.vue new file mode 100644 index 000000000..ac779da6e --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/options/list-table/list-table.vue @@ -0,0 +1,36 @@ + + + diff --git a/packages/vue-vtable/demo/src/table/unified/options/pivot-table/pivot-table-titleOnDimension.vue b/packages/vue-vtable/demo/src/table/unified/options/pivot-table/pivot-table-titleOnDimension.vue new file mode 100644 index 000000000..6e8cd24cc --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/options/pivot-table/pivot-table-titleOnDimension.vue @@ -0,0 +1,151 @@ + + + diff --git a/packages/vue-vtable/demo/src/table/unified/options/pivot-table/pivot-table-tree.vue b/packages/vue-vtable/demo/src/table/unified/options/pivot-table/pivot-table-tree.vue new file mode 100644 index 000000000..63fc1d8f3 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/options/pivot-table/pivot-table-tree.vue @@ -0,0 +1,247 @@ + + + diff --git a/packages/vue-vtable/demo/src/table/unified/options/pivot-table/pivot-table.vue b/packages/vue-vtable/demo/src/table/unified/options/pivot-table/pivot-table.vue new file mode 100644 index 000000000..abb18dee5 --- /dev/null +++ b/packages/vue-vtable/demo/src/table/unified/options/pivot-table/pivot-table.vue @@ -0,0 +1,386 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/demo/tsconfig.json b/packages/vue-vtable/demo/tsconfig.json new file mode 100644 index 000000000..505603ea7 --- /dev/null +++ b/packages/vue-vtable/demo/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve" + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/packages/vue-vtable/demo/tsconfig.node.json b/packages/vue-vtable/demo/tsconfig.node.json new file mode 100644 index 000000000..b242ad07b --- /dev/null +++ b/packages/vue-vtable/demo/tsconfig.node.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "composite": true, + "module": "ESNext", + "moduleResolution": "Node", + "allowSyntheticDefaultImports": true + }, + "include": [ + "vite.config.ts", + "vite.config.local.ts" + ] +} \ No newline at end of file diff --git a/packages/vue-vtable/demo/vite.config.ts b/packages/vue-vtable/demo/vite.config.ts new file mode 100644 index 000000000..2200e9668 --- /dev/null +++ b/packages/vue-vtable/demo/vite.config.ts @@ -0,0 +1,34 @@ +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue' +import path from 'path'; + +// let localConf: UserConfig = {}; + +// try { +// localConf = require('./vite.config.local').default; +// } catch (e) { +// console.warn('vite.config.local.ts not found', e); +// } + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [vue()], + define: { + __DEV__: true, + __VERSION__: JSON.stringify(require('../../vtable/package.json').version) + }, + optimizeDeps: {}, + server: { + host: '0.0.0.0', + port: 3100 + // port: localConf.server?.port || 3100 + }, + resolve: { + alias: { + '@visactor/vtable': path.resolve(__dirname, '../../vtable/src/index.ts'), + '@src': path.resolve(__dirname, '../../vtable/src/'), + '@vutils-extension': path.resolve(__dirname, '../../vtable/src/vutil-extension-temp') + // ...localConf.resolve?.alias + } + } +}); diff --git a/packages/vue-vtable/package.json b/packages/vue-vtable/package.json new file mode 100644 index 000000000..d71d0370f --- /dev/null +++ b/packages/vue-vtable/package.json @@ -0,0 +1,98 @@ +{ + "name": "@visactor/vue-vtable", + "version": "0.25.5", + "description": "The vue version of VTable", + "keywords": [ + "vue", + "grid", + "table", + "pivottable", + "visualization", + "VTable", + "VisActor", + "spreadsheet", + "canvas", + "datagrid", + "datatable" + ], + "author": { + "name": "VisActor", + "url": "https://VisActor.io/" + }, + "license": "MIT", + "sideEffects": false, + "main": "cjs/index.js", + "module": "es/index.js", + "types": "es/index.d.ts", + "files": [ + "cjs", + "es", + "dist" + ], + "exports": { + ".": { + "require": "./cjs/index.js", + "import": "./es/index.js" + } + }, + "scripts": { + "start": "vite ./demo", + "build": "bundle --clean", + "compile": "tsc --noEmit", + "eslint": "eslint --debug --fix src/" + }, + "unpkg": "latest", + "unpkgFiles": [ + "dist/vue-vtable.js" + ], + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@visactor/vtable": "workspace:*", + "@visactor/vutils": "~0.18.1" + }, + "devDependencies": { + "@visactor/vchart": "1.10.5", + "@internal/bundler": "workspace:*", + "@internal/eslint-config": "workspace:*", + "@internal/ts-config": "workspace:*", + "@rushstack/eslint-patch": "~1.1.4", + "vue": "^3.4.14", + "@vitejs/plugin-vue": "^5.0.3", + "eslint": "~8.18.0", + "vite": "3.2.6", + "typescript": "4.9.5", + "@babel/core": "7.20.12", + "@babel/preset-env": "7.20.2", + "@types/chai": "4.2.22", + "@types/jest": "^26.0.0", + "@types/mocha": "9.0.0", + "@types/node": "*", + "@types/offscreencanvas": "2019.6.4", + "chai": "4.3.4", + "jest": "^26.0.0", + "jest-electron": "^0.1.12", + "jest-transform-stub": "^2.0.0", + "magic-string": "^0.25.7", + "mocha": "9.1.3", + "postcss": "8.4.21", + "rimraf": "3.0.2", + "sass": "1.43.5", + "ts-jest": "^26.0.0", + "ts-loader": "9.2.6", + "ts-node": "10.9.0", + "tslib": "2.3.1", + "ttypescript": "1.5.13", + "typescript-transform-paths": "3.3.1", + "json-formatter-js": "^2.3.4", + "inversify": "6.0.1", + "vite-plugin-markdown": "^2.1.0", + "markdown-it": "^13.0.0", + "node-fetch": "2.6.7", + "form-data": "~4.0.0", + "axios": "^1.4.0", + "eslint-plugin-vue": "^9.26.0", + "vue-eslint-parser": "^9.4.2" + } +} \ No newline at end of file diff --git a/packages/vue-vtable/setup-mock.js b/packages/vue-vtable/setup-mock.js new file mode 100644 index 000000000..b0df380be --- /dev/null +++ b/packages/vue-vtable/setup-mock.js @@ -0,0 +1,2 @@ +global.__DEV__ = true; +global.__VERSION__ = true; diff --git a/packages/vue-vtable/src/components/component/menu.tsx b/packages/vue-vtable/src/components/component/menu.tsx new file mode 100644 index 000000000..a4cd99700 --- /dev/null +++ b/packages/vue-vtable/src/components/component/menu.tsx @@ -0,0 +1,13 @@ +import type { VNode } from 'vue'; +import type { TYPES } from '@visactor/vtable'; + +export type MenuProps = { + renderMode?: 'canvas' | 'html'; + defaultHeaderMenuItems?: TYPES.MenuListItem[]; + contextMenuItems?: TYPES.MenuListItem[] | ((field: string, row: number, col: number) => TYPES.MenuListItem[]); + dropDownMenuHighlight?: TYPES.DropDownMenuHighlightInfo[]; +}; + +export default function Menu(props: MenuProps): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/component/tooltip.tsx b/packages/vue-vtable/src/components/component/tooltip.tsx new file mode 100644 index 000000000..ef0574843 --- /dev/null +++ b/packages/vue-vtable/src/components/component/tooltip.tsx @@ -0,0 +1,11 @@ +import type { VNode } from 'vue'; + +export type TooltipProps = { + renderMode?: 'html'; + isShowOverflowTextTooltip?: boolean; + confine?: boolean; +}; + +export default function Tooltip(props: TooltipProps): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/custom/checkBox.tsx b/packages/vue-vtable/src/components/custom/checkBox.tsx new file mode 100644 index 000000000..f2c818df3 --- /dev/null +++ b/packages/vue-vtable/src/components/custom/checkBox.tsx @@ -0,0 +1,21 @@ +import type { VNode } from 'vue'; + +////需要等待更新,修改interface中的any为具体的类型 +export interface CheckboxProps { + children?: string; + textStyle?: any; + boxStyle?: any; + iconStyle?: any; + checked?: boolean; + indeterminate?: boolean; + interactive?: boolean; + disabled?: boolean; + disableCursor?: any; + spaceBetweenTextAndIcon?: number; + visible?: boolean; + onChange?: (checked: boolean) => void; +} + +export default function CheckBox(props: CheckboxProps): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/custom/custom-layout.tsx b/packages/vue-vtable/src/components/custom/custom-layout.tsx new file mode 100644 index 000000000..d05299bdc --- /dev/null +++ b/packages/vue-vtable/src/components/custom/custom-layout.tsx @@ -0,0 +1,27 @@ +import type { VNode } from 'vue'; + +export interface CustomComponentProps { + style?: any; + // className?: string | string[]; + className?: string; + + // for table + displayMode: 'position' | 'cell'; + x?: number; + y?: number; + width?: number | string; + height?: number | string; + // width?: number; + // height?: number; + row?: number; + col?: number; + anchor?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; + dx?: number | string; + dy?: number | string; + // dx?: number; + // dy?: number; +} + +export default function CustomLayout(props: CustomComponentProps): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/custom/group.tsx b/packages/vue-vtable/src/components/custom/group.tsx new file mode 100644 index 000000000..5fdac12b2 --- /dev/null +++ b/packages/vue-vtable/src/components/custom/group.tsx @@ -0,0 +1,5 @@ +import type { VNode } from 'vue'; + +export default function Group(): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/custom/image.tsx b/packages/vue-vtable/src/components/custom/image.tsx new file mode 100644 index 000000000..992b2bc4a --- /dev/null +++ b/packages/vue-vtable/src/components/custom/image.tsx @@ -0,0 +1,5 @@ +import type { VNode } from 'vue'; + +export default function Image(): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/custom/radio.tsx b/packages/vue-vtable/src/components/custom/radio.tsx new file mode 100644 index 000000000..eb0e8d71f --- /dev/null +++ b/packages/vue-vtable/src/components/custom/radio.tsx @@ -0,0 +1,19 @@ +import type { VNode } from 'vue'; + +//需要等待更新,修改interface中的any为具体的类型 +export interface RadioProps { + children?: string; + textStyle?: any; + circleStyle?: any; + checked?: boolean; + interactive?: boolean; + disabled?: boolean; + disableCursor?: any; + spaceBetweenTextAndIcon?: number; + visible?: boolean; + onChange?: (checked: boolean) => void; +} + +export default function Radio(props: RadioProps): any { + return null; +} diff --git a/packages/vue-vtable/src/components/custom/tag.tsx b/packages/vue-vtable/src/components/custom/tag.tsx new file mode 100644 index 000000000..0a232eb56 --- /dev/null +++ b/packages/vue-vtable/src/components/custom/tag.tsx @@ -0,0 +1,17 @@ +import type { VNode } from 'vue'; + +//需要等待更新,修改interface中的any为具体的类型 +export interface TagProps { + attribute?: any; + children?: string; + textStyle?: any; + panelStyle?: any; + padding?: any; + minWidth?: number; + maxWidth?: number; + visible?: boolean; +} + +export default function Tag(props: TagProps): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/custom/text.tsx b/packages/vue-vtable/src/components/custom/text.tsx new file mode 100644 index 000000000..71a60e3e2 --- /dev/null +++ b/packages/vue-vtable/src/components/custom/text.tsx @@ -0,0 +1,5 @@ +import type { VNode } from 'vue'; + +export default function Text(): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/index.ts b/packages/vue-vtable/src/components/index.ts new file mode 100644 index 000000000..4a25a9a8a --- /dev/null +++ b/packages/vue-vtable/src/components/index.ts @@ -0,0 +1,19 @@ +export { default as ListColumn } from './list/list-column'; + +export { default as PivotColumnDimension } from './pivot/pivot-column-dimension'; +export { default as PivotRowDimension } from './pivot/pivot-row-dimension'; +export { default as PivotColumnHeaderTitle } from './pivot/pivot-column-header-title'; +export { default as PivotRowHeaderTitle } from './pivot/pivot-row-header-title'; +export { default as PivotIndicator } from './pivot/pivot-indicator'; +export { default as PivotCorner } from './pivot/pivot-corner'; + +export { default as Menu } from './component/menu'; +export { default as Tooltip } from './component/tooltip'; + +// export { default as CustomLayout } from './custom/custom-layout'; +export { default as Group } from './custom/group'; +export { default as Image } from './custom/image'; +export { default as Text } from './custom/text'; +export { default as Tag } from './custom/tag'; +export { default as Radio } from './custom/radio'; +export { default as CheckBox } from './custom/checkBox'; diff --git a/packages/vue-vtable/src/components/list/list-column.tsx b/packages/vue-vtable/src/components/list/list-column.tsx new file mode 100644 index 000000000..e1e81665c --- /dev/null +++ b/packages/vue-vtable/src/components/list/list-column.tsx @@ -0,0 +1,6 @@ +import type { VNode } from 'vue'; +import type { ColumnDefine } from '@visactor/vtable'; + +export default function ListColumn(props: ColumnDefine): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/pivot/pivot-column-dimension.tsx b/packages/vue-vtable/src/components/pivot/pivot-column-dimension.tsx new file mode 100644 index 000000000..77007145e --- /dev/null +++ b/packages/vue-vtable/src/components/pivot/pivot-column-dimension.tsx @@ -0,0 +1,12 @@ +import type { VNode } from 'vue'; +import type { IDimension } from '@visactor/vtable'; + +interface ObjectHandler { + objectHandler?: string | Array; +} + +export type PivotColumnDimensionProps = IDimension & ObjectHandler; + +export default function PivotColumnDimension(props: PivotColumnDimensionProps): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/pivot/pivot-column-header-title.tsx b/packages/vue-vtable/src/components/pivot/pivot-column-header-title.tsx new file mode 100644 index 000000000..7c3c0934c --- /dev/null +++ b/packages/vue-vtable/src/components/pivot/pivot-column-header-title.tsx @@ -0,0 +1,6 @@ +import type { VNode } from 'vue'; +import type { ITitleDefine } from '@visactor/vtable'; + +export default function PivotColumnHeaderTitle(props: ITitleDefine): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/pivot/pivot-corner.tsx b/packages/vue-vtable/src/components/pivot/pivot-corner.tsx new file mode 100644 index 000000000..16ef6a1c9 --- /dev/null +++ b/packages/vue-vtable/src/components/pivot/pivot-corner.tsx @@ -0,0 +1,6 @@ +import type { VNode } from 'vue'; +import type { ICornerDefine } from '@visactor/vtable'; + +export default function PivotCorner(props: ICornerDefine): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/pivot/pivot-indicator.tsx b/packages/vue-vtable/src/components/pivot/pivot-indicator.tsx new file mode 100644 index 000000000..cb3994a31 --- /dev/null +++ b/packages/vue-vtable/src/components/pivot/pivot-indicator.tsx @@ -0,0 +1,6 @@ +import type { VNode } from 'vue'; +import type { IIndicator } from '@visactor/vtable'; + +export default function PivotIndicator(props: IIndicator): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/pivot/pivot-row-dimension.tsx b/packages/vue-vtable/src/components/pivot/pivot-row-dimension.tsx new file mode 100644 index 000000000..4f3f093db --- /dev/null +++ b/packages/vue-vtable/src/components/pivot/pivot-row-dimension.tsx @@ -0,0 +1,12 @@ +import type { VNode } from 'vue'; +import type { IDimension } from '@visactor/vtable'; + +interface ObjectHandler { + objectHandler?: string | Array; +} + +export type PivotColumnDimensionProps = IDimension & ObjectHandler; + +export default function PivotRowDimension(props: PivotColumnDimensionProps): VNode { + return null; +} diff --git a/packages/vue-vtable/src/components/pivot/pivot-row-header-title.tsx b/packages/vue-vtable/src/components/pivot/pivot-row-header-title.tsx new file mode 100644 index 000000000..3b1b70f53 --- /dev/null +++ b/packages/vue-vtable/src/components/pivot/pivot-row-header-title.tsx @@ -0,0 +1,6 @@ +import type { VNode } from 'vue'; +import type { ITitleDefine } from '@visactor/vtable'; + +export default function PivotRowHeaderTitle(props: ITitleDefine): VNode { + return null; +} diff --git a/packages/vue-vtable/src/constants.ts b/packages/vue-vtable/src/constants.ts new file mode 100644 index 000000000..9efd91803 --- /dev/null +++ b/packages/vue-vtable/src/constants.ts @@ -0,0 +1 @@ +export const REACT_PRIVATE_PROPS = ['children', 'hooks', 'ref']; diff --git a/packages/vue-vtable/src/eventsUtils.ts b/packages/vue-vtable/src/eventsUtils.ts new file mode 100644 index 000000000..e373b2d0b --- /dev/null +++ b/packages/vue-vtable/src/eventsUtils.ts @@ -0,0 +1,181 @@ +import { ListTable, PivotTable, PivotChart } from '@visactor/vtable'; +import type { IVTable } from './tables/base-table'; +import type { TYPES } from '@visactor/vtable'; + +export type EventCallback = (params: Params) => void; + +const EVENT_TYPE = { + ...ListTable.EVENT_TYPE, + ...PivotTable.EVENT_TYPE, + ...PivotChart.EVENT_TYPE +}; + +export interface EventsProps { + onClickCell?: EventCallback; + onDblClickCell?: EventCallback; + onMouseDownCell?: EventCallback; + onMouseUpCell?: EventCallback; + onSelectedCell?: EventCallback; + onKeyDown?: EventCallback; + onMouseEnterTable?: EventCallback; + onMouseLeaveTable?: EventCallback; + onMouseDownTable?: EventCallback; + onMouseMoveCell?: EventCallback; + onMouseEnterCell?: EventCallback; + onMouseLeaveCell?: EventCallback; + onContextMenuCell?: EventCallback; + onResizeColumn?: EventCallback; + onResizeColumnEnd?: EventCallback; + onChangeHeaderPosition?: EventCallback; + onSortClick?: EventCallback; + onFreezeClick?: EventCallback; + onScroll?: EventCallback; + onDropdownMenuClick?: EventCallback; + onMouseOverChartSymbol?: EventCallback; + onDragSelectEnd?: EventCallback; + + onDropdownIconClick?: EventCallback; + onDropdownMenuClear?: EventCallback; + + onTreeHierarchyStateChange?: EventCallback; + + onShowMenu?: EventCallback; + onHideMenu?: EventCallback; + + onIconClick?: EventCallback; + + onLegendItemClick?: EventCallback; + onLegendItemHover?: EventCallback; + onLegendItemUnHover?: EventCallback; + onLegendChange?: EventCallback; + + onMouseEnterAxis?: EventCallback; + onMouseLeaveAxis?: EventCallback; + + onCheckboxStateChange?: EventCallback; + onRadioStateChange?: EventCallback; + onAfterRender?: EventCallback; + onInitialized?: EventCallback; + + // pivot table only + onPivotSortClick?: EventCallback; + onDrillMenuClick?: EventCallback; + + // pivot chart only + onVChartEventType?: EventCallback; + + onChangCellValue?: EventCallback; + + onMousedownFillHandle?: EventCallback; + onDragFillHandleEnd?: EventCallback; + onDblclickFillHandle?: EventCallback; + + onScrollVerticalEnd?: EventCallback; + onScrollHorizontalEnd?: EventCallback; +} + +export const TABLE_EVENTS = { + onClickCell: EVENT_TYPE.CLICK_CELL, + onDblClickCell: EVENT_TYPE.DBLCLICK_CELL, + onMouseDownCell: EVENT_TYPE.MOUSEDOWN_CELL, + onMouseUpCell: EVENT_TYPE.MOUSEUP_CELL, + onSelectedCell: EVENT_TYPE.SELECTED_CELL, + onKeyDown: EVENT_TYPE.KEYDOWN, + onMouseEnterTable: EVENT_TYPE.MOUSEENTER_TABLE, + onMouseLeaveTable: EVENT_TYPE.MOUSELEAVE_TABLE, + onMouseDownTable: EVENT_TYPE.MOUSEDOWN_TABLE, + onMouseMoveCell: EVENT_TYPE.MOUSEMOVE_CELL, + onMouseEnterCell: EVENT_TYPE.MOUSEENTER_CELL, + onMouseLeaveCell: EVENT_TYPE.MOUSELEAVE_CELL, + onContextMenuCell: EVENT_TYPE.CONTEXTMENU_CELL, + onResizeColumn: EVENT_TYPE.RESIZE_COLUMN, + onResizeColumnEnd: EVENT_TYPE.RESIZE_COLUMN_END, + onChangeHeaderPosition: EVENT_TYPE.CHANGE_HEADER_POSITION, + onSortClick: EVENT_TYPE.SORT_CLICK, + onFreezeClick: EVENT_TYPE.FREEZE_CLICK, + onScroll: EVENT_TYPE.SCROLL, + onDropdownMenuClick: EVENT_TYPE.DROPDOWN_MENU_CLICK, + onMouseOverChartSymbol: EVENT_TYPE.MOUSEOVER_CHART_SYMBOL, + onDragSelectEnd: EVENT_TYPE.DRAG_SELECT_END, + + onDropdownIconClick: EVENT_TYPE.DROPDOWN_ICON_CLICK, + onDropdownMenuClear: EVENT_TYPE.DROPDOWN_MENU_CLEAR, + + onTreeHierarchyStateChange: EVENT_TYPE.TREE_HIERARCHY_STATE_CHANGE, + + onShowMenu: EVENT_TYPE.SHOW_MENU, + onHideMenu: EVENT_TYPE.HIDE_MENU, + + onIconClick: EVENT_TYPE.ICON_CLICK, + + onLegendItemClick: EVENT_TYPE.LEGEND_ITEM_CLICK, + onLegendItemHover: EVENT_TYPE.LEGEND_ITEM_HOVER, + onLegendItemUnHover: EVENT_TYPE.LEGEND_ITEM_UNHOVER, + onLegendChange: EVENT_TYPE.LEGEND_CHANGE, + + onMouseEnterAxis: EVENT_TYPE.MOUSEENTER_AXIS, + onMouseLeaveAxis: EVENT_TYPE.MOUSELEAVE_AXIS, + + onCheckboxStateChange: EVENT_TYPE.CHECKBOX_STATE_CHANGE, + onRadioStateChange: EVENT_TYPE.RADIO_STATE_CHANGE, + onAfterRender: EVENT_TYPE.AFTER_RENDER, + onInitialized: EVENT_TYPE.INITIALIZED, + + // pivot table only + onPivotSortClick: EVENT_TYPE.PIVOT_SORT_CLICK, + onDrillMenuClick: EVENT_TYPE.DRILLMENU_CLICK, + + // pivot chart only + onVChartEventType: EVENT_TYPE.VCHART_EVENT_TYPE, + + onChangCellValue: EVENT_TYPE.CHANGE_CELL_VALUE, + onMousedownFillHandle: EVENT_TYPE.MOUSEDOWN_FILL_HANDLE, + onDragFillHandleEnd: EVENT_TYPE.DRAG_FILL_HANDLE_END, + onDblclickFillHandle: EVENT_TYPE.DBLCLICK_FILL_HANDLE, + onScrollVerticalEnd: EVENT_TYPE.SCROLL_VERTICAL_END, + onScrollHorizontalEnd: EVENT_TYPE.SCROLL_HORIZONTAL_END +}; + +export const TABLE_EVENTS_KEYS = Object.keys(TABLE_EVENTS); + +// export const findEventProps = ( +// props: T, +// supportedEvents: Record = TABLE_EVENTS +// ): EventsProps => { +// const result: EventsProps = {}; + +// Object.keys(props).forEach(key => { +// if (supportedEvents[key] && props[key]) { +// result[key] = props[key]; +// } +// }); + +// return result; +// }; + +// export const bindEventsToTable = ( +// table: IVTable, +// newProps?: T | null, +// prevProps?: T | null, +// supportedEvents: Record = TABLE_EVENTS +// ) => { +// if (!table) return false; +// const prevEventProps = prevProps ? findEventProps(prevProps, supportedEvents) : {}; +// const newEventProps = newProps ? findEventProps(newProps, supportedEvents) : {}; + +// Object.keys(supportedEvents).forEach(eventKey => { +// const prevHandler = prevEventProps[eventKey]; +// const newHandler = newEventProps[eventKey]; + +// if (prevHandler !== newHandler) { +// if (prevHandler) { +// table.off(supportedEvents[eventKey], prevHandler); +// } +// if (newHandler) { +// table.on(supportedEvents[eventKey] as keyof TYPES.TableEventHandlersEventArgumentMap, newHandler); +// } +// } +// }); + +// return true; +// }; diff --git a/packages/vue-vtable/src/global.d.ts b/packages/vue-vtable/src/global.d.ts new file mode 100644 index 000000000..415c2c827 --- /dev/null +++ b/packages/vue-vtable/src/global.d.ts @@ -0,0 +1 @@ +declare const __VERSION__: string; diff --git a/packages/vue-vtable/src/index.ts b/packages/vue-vtable/src/index.ts new file mode 100644 index 000000000..9f2eccb9f --- /dev/null +++ b/packages/vue-vtable/src/index.ts @@ -0,0 +1,7 @@ +import * as VTable from '@visactor/vtable'; + +export * from './tables'; +export * from './components'; +export { VTable }; + +export const version = __VERSION__; diff --git a/packages/vue-vtable/src/tables/base-table.ts b/packages/vue-vtable/src/tables/base-table.ts new file mode 100644 index 000000000..69fbaf07a --- /dev/null +++ b/packages/vue-vtable/src/tables/base-table.ts @@ -0,0 +1,28 @@ +import type * as VTable from '@visactor/vtable'; +import type { EventsProps } from '../eventsUtils'; + +export type IVTable = VTable.ListTable | VTable.PivotTable | VTable.PivotChart; +export type IOption = + | VTable.ListTableConstructorOptions + | VTable.PivotTableConstructorOptions + | VTable.PivotChartConstructorOptions; + +export interface BaseTableProps extends EventsProps { + type?: string; + /** 上层container */ + container?: HTMLDivElement; + /** option */ + option?: any; + /** 数据 */ + records?: Record[]; + /** 画布宽度 */ + width?: number; + /** 画布高度 */ + height?: number; + skipFunctionDiff?: boolean; + + /** 表格渲染完成事件 */ + onReady?: (instance: IVTable, isInitial: boolean) => void; + /** throw error when chart run into an error */ + onError?: (err: Error) => void; +} diff --git a/packages/vue-vtable/src/tables/base-table.vue b/packages/vue-vtable/src/tables/base-table.vue new file mode 100644 index 000000000..b33e71237 --- /dev/null +++ b/packages/vue-vtable/src/tables/base-table.vue @@ -0,0 +1,165 @@ + + + diff --git a/packages/vue-vtable/src/tables/chartModule.ts b/packages/vue-vtable/src/tables/chartModule.ts new file mode 100644 index 000000000..1c825e091 --- /dev/null +++ b/packages/vue-vtable/src/tables/chartModule.ts @@ -0,0 +1,5 @@ +import * as VTable from '@visactor/vtable'; + +export const registerChartModule = (name: string, chart: any) => { + VTable.register.chartModule(name, chart); +}; diff --git a/packages/vue-vtable/src/tables/index.ts b/packages/vue-vtable/src/tables/index.ts new file mode 100644 index 000000000..300fbd090 --- /dev/null +++ b/packages/vue-vtable/src/tables/index.ts @@ -0,0 +1,4 @@ +export { default as ListTable } from './list-table.vue'; +export { default as PivotTable } from './pivot-table.vue'; +export { default as PivotChart } from './pivot-chart.vue'; +export { registerChartModule } from './chartModule'; diff --git a/packages/vue-vtable/src/tables/list-table.vue b/packages/vue-vtable/src/tables/list-table.vue new file mode 100644 index 000000000..266a10500 --- /dev/null +++ b/packages/vue-vtable/src/tables/list-table.vue @@ -0,0 +1,106 @@ + + + diff --git a/packages/vue-vtable/src/tables/pivot-chart.vue b/packages/vue-vtable/src/tables/pivot-chart.vue new file mode 100644 index 000000000..0ea0b6652 --- /dev/null +++ b/packages/vue-vtable/src/tables/pivot-chart.vue @@ -0,0 +1,90 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/src/tables/pivot-table.vue b/packages/vue-vtable/src/tables/pivot-table.vue new file mode 100644 index 000000000..91eedb7d4 --- /dev/null +++ b/packages/vue-vtable/src/tables/pivot-table.vue @@ -0,0 +1,86 @@ + + + \ No newline at end of file diff --git a/packages/vue-vtable/src/tables/utils.ts b/packages/vue-vtable/src/tables/utils.ts new file mode 100644 index 000000000..e95f87cbc --- /dev/null +++ b/packages/vue-vtable/src/tables/utils.ts @@ -0,0 +1,71 @@ +import * as VTable from '@visactor/vtable'; +// 展平嵌套的虚拟节点 +export function flattenVNodes(vnodes: any[]): any[] { + return vnodes.flatMap(vnode => (Array.isArray(vnode.children) ? flattenVNodes(vnode.children) : vnode)); +} +export function createCustomLayout(children: any): any { + // 组件映射 + const componentMap: Record = { + Group: VTable.CustomLayout.Group, + Image: VTable.CustomLayout.Image, + Text: VTable.CustomLayout.Text, + Tag: VTable.CustomLayout.Tag, + Radio: VTable.CustomLayout.Radio, + CheckBox: VTable.CustomLayout.CheckBox + }; + + // 创建组件的函数 + function createComponent(child: any): any { + if (!child) { + return null; + } + + const { type, props, children: childChildren } = child; + const componentName = type?.name || type; + const ComponentClass = componentMap[componentName]; + + if (!ComponentClass) { + return null; + } + + const component = new ComponentClass({ ...props }); + + // 特殊组件的事件绑定 + bindComponentEvents(component, componentName, props); + + // 递归创建子组件 + const subChildren = resolveChildren(childChildren); + subChildren.forEach((subChild: any) => { + const subComponent = createComponent(subChild); + if (subComponent) { + component.add(subComponent); + } else if (subChild.type === Symbol.for('v-fgt')) { + subChild.children.forEach((nestedChild: any) => { + const nestedComponent = createComponent(nestedChild); + if (nestedComponent) { + component.add(nestedComponent); + } + }); + } + }); + + return component; + } + + // 处理子节点 + function resolveChildren(childChildren: any): any[] { + return childChildren?.default?.() || childChildren || []; + } + + // 绑定组件事件 + function bindComponentEvents(component: any, componentName: string, props: any): void { + if (componentName === 'Radio' && props?.onRadio_checked) { + component.addEventListener('radio_checked', props.onRadio_checked); + } + if (componentName === 'CheckBox' && props?.onCheckbox_state_change) { + component.addEventListener('checkbox_state_change', props.onCheckbox_state_change); + } + } + + return { rootComponent: createComponent(children) }; +} diff --git a/packages/vue-vtable/src/vue-shims.d.ts b/packages/vue-vtable/src/vue-shims.d.ts new file mode 100644 index 000000000..506bf2e5c --- /dev/null +++ b/packages/vue-vtable/src/vue-shims.d.ts @@ -0,0 +1,5 @@ +declare module '*.vue' { + import { DefineComponent } from 'vue'; + const component: DefineComponent<{}, {}, any>; + export default component; +} diff --git a/packages/vue-vtable/tscofig.eslint.json b/packages/vue-vtable/tscofig.eslint.json new file mode 100644 index 000000000..a8b2b56da --- /dev/null +++ b/packages/vue-vtable/tscofig.eslint.json @@ -0,0 +1,20 @@ +{ + "extends": "@internal/ts-config/tsconfig.base.json", + "compilerOptions": { + "types": [ + "jest", + "offscreencanvas", + "node" + ], + "lib": [ + "DOM", + "ESNext" + ], + "baseUrl": "./", + "rootDir": "./" + }, + "include": [ + "src", + "demo" + ] +} \ No newline at end of file diff --git a/packages/vue-vtable/tsconfig.json b/packages/vue-vtable/tsconfig.json new file mode 100644 index 000000000..acb1be920 --- /dev/null +++ b/packages/vue-vtable/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "@internal/ts-config/tsconfig.base.json", + "compilerOptions": { + "jsx": "react", + "types": ["jest", "offscreencanvas", "node"], + "lib": ["DOM", "ESNext"], + "baseUrl": "./", + "rootDir": "./src", + "paths": {} + }, + "ts-node": { + "transpileOnly": true, + "compilerOptions": { + "module": "commonjs" + } + }, + "references": [ + { + "path": "../vtable" + } + ], + "include": ["src"] +} diff --git a/rush.json b/rush.json index 49ba6a59f..c2c25c6cc 100644 --- a/rush.json +++ b/rush.json @@ -83,6 +83,15 @@ "shouldPublish": true, "versionPolicyName": "vtableMain" }, + { + "packageName": "@visactor/vue-vtable", + "projectFolder": "packages/vue-vtable", + "tags": [ + "package" + ], + "shouldPublish": true, + "versionPolicyName": "vtableMain" + }, { "packageName": "@visactor/openinula-vtable", "projectFolder": "packages/openinula-vtable", diff --git a/share/eslint-config/package.json b/share/eslint-config/package.json index 8a17883c3..dbf93fdd0 100644 --- a/share/eslint-config/package.json +++ b/share/eslint-config/package.json @@ -11,7 +11,8 @@ "eslint-plugin-react-hooks": "4.6.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.8.8" + "prettier": "^2.8.8", + "eslint-plugin-vue": "^9.26.0" }, "devDependencies": { "eslint": "~8.18.0", @@ -21,4 +22,4 @@ "eslint": "~8.18.0", "typescript": ">=4" } -} +} \ No newline at end of file diff --git a/share/eslint-config/profile/common.js b/share/eslint-config/profile/common.js index ce406497c..0475e345e 100644 --- a/share/eslint-config/profile/common.js +++ b/share/eslint-config/profile/common.js @@ -11,7 +11,10 @@ var reactExtends = [ 'plugin:react/jsx-runtime', "plugin:react-hooks/recommended", ]; - +var vueExtends = [ + "plugin:vue/vue3-recommended", + // 其他需要的插件和配置 +]; /** * * @param {'react' | 'lib'} type @@ -21,7 +24,7 @@ module.exports = function buildConfig(type) { var isJsx = false; var settings = {}; var reactRules = {}; - + var vueRules={}; var _extends = baseExtends; if (type === "react") { @@ -43,6 +46,23 @@ module.exports = function buildConfig(type) { "react-hooks/rules-of-hooks": "warn", "react/react-in-jsx-scope": "off" }; + } else if (type === "vue") { // 处理Vue的情况 + baseFiles.push("*.vue"); + + _extends = baseExtends.concat(vueExtends); + + isJsx = true; + + settings.vue = { // Vue的设置 + version: "detect", + }; + + vueRules = { + // 添加Vue相关的规则 + "vue/require-v-for-key": "warn", + "vue/no-unused-components": "warn", + // 其他Vue规则... + }; } return { @@ -91,6 +111,7 @@ module.exports = function buildConfig(type) { "promise/always-return": "off", "promise/no-callback-in-promise": "off", ...reactRules, + ...vueRules, }, }, ], diff --git a/share/eslint-config/profile/vue.js b/share/eslint-config/profile/vue.js new file mode 100644 index 000000000..0b148609f --- /dev/null +++ b/share/eslint-config/profile/vue.js @@ -0,0 +1 @@ +module.exports = require('./common')('vue') \ No newline at end of file diff --git a/tools/bundler/package.json b/tools/bundler/package.json index c083dd97c..e20790a11 100644 --- a/tools/bundler/package.json +++ b/tools/bundler/package.json @@ -39,6 +39,8 @@ "@rollup/plugin-url": "8.0.1", "@rollup/plugin-json": "4.1.0", "@rollup/plugin-strip": "3.0.2", + "rollup-plugin-typescript2": "0.36.0", + "@vitejs/plugin-vue": "^5.0.3", "@trufflesuite/spinnies": "0.1.1", "autoprefixer": "10.4.13", "babel-plugin-import": "1.13.6", diff --git a/tools/bundler/src/logic/rollup.config.ts b/tools/bundler/src/logic/rollup.config.ts index ddd295fd8..9d3b82abc 100644 --- a/tools/bundler/src/logic/rollup.config.ts +++ b/tools/bundler/src/logic/rollup.config.ts @@ -6,13 +6,15 @@ import type { BabelPlugins } from './babel.config'; import resolve from '@rollup/plugin-node-resolve'; import babel from '@rollup/plugin-babel'; import commonjs from '@rollup/plugin-commonjs'; -import typescript from '@rollup/plugin-typescript'; +import typescript from 'rollup-plugin-typescript2'; +// import typescript from '@rollup/plugin-typescript'; import replace from '@rollup/plugin-replace'; import terser from '@rollup/plugin-terser'; import url from '@rollup/plugin-url'; import Alias from '@rollup/plugin-alias'; import postcss from 'rollup-plugin-postcss'; import strip from '@rollup/plugin-strip'; +import vue from '@vitejs/plugin-vue'; import * as path from 'path'; import { Config } from './config'; @@ -43,14 +45,10 @@ export function getRollupOptions( plugins: [ resolve(), commonjs(), + vue(), + typescript(), babel({ ...babelPlugins, babelHelpers: 'bundled' }), replace({ ...config.envs, preventAssignment: true }), - typescript({ - tsconfig: path.resolve(projectRoot, config.tsconfig), - compilerOptions: { - declaration: false - } - }), postcss({ extensions: ['.css'] }),