123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- <script setup lang="ts">
- import { magicApi } from "@/utils/database/magic-api-request";
- import { useResizeObserver } from "@vueuse/core";
- import { stringIsBlank } from "@/utils/blank-utils";
- defineOptions({
- name: "RenderTable",
- });
- const props = defineProps<{
- htmlData: string;
- wardCode: string;
- }>();
- const store = reactive({
- htmlData: "",
- data: [],
- spans: [] as { span: HTMLSpanElement; code: string }[],
- business: new Set(),
- businessData: {},
- });
- const divRaf = ref<HTMLDivElement>();
- useResizeObserver(divRaf, () => {
- if (stringIsBlank(props.htmlData)) return;
- nextTick(() => {
- if (props.htmlData) renderTable(false);
- });
- });
- async function replace(query = true) {
- if (query) {
- store.businessData = await magicApi({
- url: "/public/dashboard/dataSource",
- method: "post",
- data: {
- isSource: false,
- business: Array.from(store.business.values()),
- wardCode: props.wardCode,
- },
- })
- .then(res => {
- return res;
- })
- .catch(() => {
- return {};
- });
- }
- store.spans.forEach(item => {
- item.span.innerHTML = store.businessData[item.code] ?? "";
- });
- await nextTick();
- store.spans.forEach(item => {
- const td = (item.span as Element).closest("td");
- if (td == null) {
- return;
- }
- if (!(td.className as string).includes("td-text_hidden")) {
- td.className += " td-text_hidden " + td.className;
- }
- if (td.clientWidth !== td.scrollWidth) {
- const marqueeDiv = document.createElement("div");
- marqueeDiv.className = "marquee";
- marqueeDiv.style.setProperty(
- "--translate-scroll-px",
- `-${td.scrollWidth}px`
- );
- marqueeDiv.innerHTML = td.innerHTML;
- td.innerHTML = "";
- td.appendChild(marqueeDiv);
- }
- });
- }
- function getBusiness(spans: HTMLSpanElement[]) {
- spans.forEach(span => {
- const code = span.getAttribute("data-element-code");
- span.innerHTML = "";
- store.business.add(code);
- store.spans.push({
- span,
- code,
- });
- });
- }
- async function renderTable(query = true) {
- await nextTick();
- store.business = new Set();
- store.spans = [];
- divRaf.value.innerHTML = store.htmlData;
- const table = divRaf.value.querySelector("table");
- const trs = table.querySelectorAll("tr");
- trs.forEach(tr => {
- const tds = tr.querySelectorAll("td");
- tds.forEach(td => {
- const business = td.querySelectorAll("span[data-element-code]");
- if (business.length > 0) {
- // @ts-ignore
- getBusiness(business);
- }
- });
- });
- replace(query);
- }
- watch(
- () => props.htmlData,
- async () => {
- await nextTick();
- store.htmlData = props.htmlData;
- renderTable();
- }
- );
- defineExpose({
- reloadData() {
- renderTable();
- },
- });
- </script>
- <template>
- <div class="layout_container render-table" ref="divRaf"></div>
- </template>
- <style lang="scss">
- .render-table {
- background: #0f1628;
- font-size: 1.13rem;
- table {
- width: 100%;
- border-collapse: collapse;
- border: 1px solid white;
- height: 100% !important;
- table-layout: fixed;
- color: white;
- }
- td {
- border: 1px solid white;
- text-align: center !important;
- }
- .td-text_hidden {
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
- }
- .marquee {
- white-space: nowrap; /* 不换行 */
- animation: marquee 10s linear infinite; /* 动画效果 */
- line-height: 100%;
- text-align: center;
- }
- @keyframes marquee {
- 0% {
- transform: translateX(0px);
- }
- 100% {
- transform: translateX(var(--translate-scroll-px));
- }
- }
- }
- </style>
|