| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106 |
- <template>
- <view
- class="section"
- :style="{
- position: 'relative',
- zIndex: dropdownOpen || dropdownRegionOpen ? 9 : 'auto',
- }"
- >
- <view v-if="showHeader" class="section-header">
- <text class="section-title">{{ title }}</text>
- <view :style="{ display: 'flex' }">
- <view
- v-if="showSelector && tableType === 'variety'"
- class="selector-wrap"
- >
- <view class="selector" @click.stop="toggleDropdownRegion">
- <text class="selector-text">{{
- region?.regionCode ? region.regionName : "选择片区"
- }}</text>
- <text
- class="selector-arrow"
- :class="{ open: dropdownRegionOpen }"
- ></text>
- </view>
- <view
- class="dropdown"
- v-show="dropdownRegionOpen"
- :style="
- dropdownDirection === 'top'
- ? { top: 'auto', bottom: '48rpx' }
- : {}
- "
- @click.stop
- >
- <view class="dropdown-search-bar">
- <input
- class="dropdown-search-input"
- v-model="regionSearchText"
- @input="onRegionSearch"
- placeholder="搜索..."
- />
- </view>
- <scroll-view
- scroll-y="true"
- class="dropdown-scroll-view"
- lower-threshold="80"
- @scrolltolower="loadMoreRegions"
- >
- <view
- class="dropdown-item"
- v-for="(p, i) in regionList"
- :key="p.regionCode || i"
- :style="
- p.regionCode === region?.regionCode ||
- (!region?.regionCode && i == 0)
- ? {
- backgroundColor: '#2c69ff',
- color: '#fff',
- }
- : {}
- "
- @click.stop="selectProduct('region', p)"
- >{{ p.regionName || p }}</view
- >
- <view
- v-if="regionList.length === 0"
- class="dropdown-item"
- style="text-align: center; color: #999"
- >暂无数据
- </view>
- </scroll-view>
- </view>
- </view>
- <view v-if="showSelector" class="selector-wrap">
- <view class="selector" @click.stop="toggleDropdown">
- <text class="selector-text">{{
- product?.drugEntBaseInfoId ? product.physicName : "选择品种"
- }}</text>
- <text class="selector-arrow" :class="{ open: dropdownOpen }"></text>
- </view>
- <view
- class="dropdown"
- v-show="dropdownOpen"
- :style="
- dropdownDirection === 'top'
- ? {
- top: 'auto',
- bottom: '48rpx',
- }
- : {}
- "
- @click.stop
- >
- <view class="dropdown-search-bar">
- <input
- class="dropdown-search-input"
- v-model="productSearchText"
- @input="onProductSearch"
- placeholder="搜索..."
- />
- </view>
- <scroll-view
- scroll-y="true"
- class="dropdown-scroll-view"
- lower-threshold="80"
- @scrolltolower="loadMoreProducts"
- >
- <view
- class="dropdown-item"
- v-for="(p, i) in productList"
- :key="p.drugEntBaseInfoId || i"
- :style="
- p.drugEntBaseInfoId === product?.drugEntBaseInfoId ||
- (!product?.drugEntBaseInfoId && i == 0)
- ? {
- backgroundColor: '#2c69ff',
- color: '#fff',
- }
- : {}
- "
- @click.stop="selectProduct('product', p)"
- >{{ p.physicName }}</view
- >
- <view
- v-if="productList.length === 0"
- class="dropdown-item"
- style="text-align: center; color: #999"
- >暂无数据
- </view>
- </scroll-view>
- </view>
- </view>
- </view>
- </view>
- <view
- class="table-scroll-x"
- :style="{
- height:
- tableHeightAuto || list.length < 7
- ? 'auto'
- : tableBodyHeight + 80 + 'rpx',
- maxHeight: tableHeightAuto,
- }"
- >
- <scroll-view
- class="no-scrollbar"
- :style="{ height: '100%' }"
- scroll-x="true"
- scroll-y="true"
- enhanced
- :show-scrollbar="false"
- @scrolltolower="onScrollToLower"
- >
- <view class="card" :style="{ width: tableWidth }">
- <view
- class="table-header"
- :style="{
- position: 'sticky',
- top: '0',
- zIndex: 10,
- fontWeight: headerBold ? 'bold' : 'normal',
- }"
- >
- <view
- v-for="(col, ci) in columnList"
- :key="getUid()"
- class="cell"
- :style="{
- ...headerCellStyle(ci, col),
- }"
- >
- <view
- v-if="isPlainTitle(col.title)"
- :style="{
- display: 'flex',
- alignItems: 'center',
- position: 'relative',
- }"
- >
- <text>{{ col.title }}</text>
- <uni-icons
- v-if="col.tooltip"
- type="help"
- size="16"
- color="#2c69ff"
- @tap.stop.prevent="toggleHeaderTooltip(ci)"
- ></uni-icons>
- <view
- v-if="headerTooltip[ci]"
- class="header-tooltip-wrap"
- @click.stop
- >
- <view class="header-tooltip">{{ col.tooltip }}</view>
- <view class="header-tooltip-arrow"></view>
- </view>
- </view>
- <rich-text v-else :nodes="titleNodes(col.title)" />
- </view>
- </view>
- <view v-if="!loading && list && list.length > 0" class="table-body">
- <template>
- <view class="row" v-for="(item, i) in list" :key="getUid()">
- <view
- v-for="(col, ci) in columnList"
- :key="getUid()"
- class="cell"
- :class="{
- underline: col.underline,
- striped: striped && (i + 1) % 2 === 0,
- }"
- :style="bodyCellStyle(ci, col)"
- @click="handleClick(item, col)"
- >{{ renderCell(item, col) }}</view
- >
- </view>
- <view class="row loading-row" v-if="hasmore">
- <view class="loading-wrapper">
- <image class="loading-icon" :src="loadingImg" />
- </view>
- </view>
- <view
- class="row"
- v-if="showSummary"
- :style="{
- position: 'sticky',
- bottom: '0',
- zIndex: 5,
- backgroundColor: '#fff',
- borderTop: '1rpx solid #eef0f4',
- color: summaryFontColor,
- }"
- >
- <view
- v-for="(col, ci) in columnList"
- :key="getUid()"
- class="cell"
- :style="{
- ...bodyCellStyle(ci, col),
- fontWeight: summaryBold ? 'bold' : 'normal',
- }"
- >{{ getSummary(col, ci) }}</view
- >
- </view>
- </template>
- </view>
- </view>
- <view
- v-if="loading"
- class="no-data-placeholder"
- :style="{ height: 'auto' }"
- >
- <view class="row loading-row">
- <view class="loading-wrapper">
- <image class="loading-icon" :src="loadingImg" />
- </view>
- </view>
- </view>
- <view
- v-if="!loading && (!list || list.length === 0)"
- class="no-data-placeholder"
- >
- <EmptyView />
- </view>
- </scroll-view>
- <view
- v-if="loading"
- class="no-data"
- :style="{ height: 'auto', top: cellHeight }"
- >
- <view class="row loading-row">
- <view class="loading-wrapper">
- <image class="loading-icon" :src="loadingImg" />
- </view>
- </view>
- </view>
- <view
- v-if="!loading && (!list || list.length === 0)"
- class="no-data"
- :style="{ top: cellHeight }"
- >
- <EmptyView />
- </view>
- </view>
- </view>
- </template>
- <script>
- import EmptyView from "../../../../wigets/empty.vue";
- import loadingImg from "../../../../static/images/loading.png";
- import { getUid } from "../../../../utils/utils.js";
- import request from "../../../../request/index.js";
- import Select from "../../../../wigets/select.vue";
- export default {
- name: "ScanRateTable",
- components: { EmptyView, Select },
- props: {
- params: {
- type: Object,
- default: null,
- },
- scanType: { type: String, default: "1" },
- api: {
- type: String,
- default: "",
- },
- tableType: { type: String, default: "customer" },
- title: { type: String, default: "客户扫码率" },
- showSelector: { type: Boolean, default: true },
- showHeader: { type: Boolean, default: true },
- dropdownDirection: { type: String, default: "bottom" },
- showSummary: { type: Boolean, default: true },
- striped: { type: Boolean, default: true },
- summaryStructure: {
- type: Array,
- default: () => [
- {
- key: "totalInRate",
- title: "入库扫码率",
- unit: "%",
- },
- {
- key: "totalOutRate",
- title: "出库扫码率",
- unit: "%",
- },
- {
- key: "totalSelfExaminationRate",
- title: "自验证率",
- unit: "%",
- },
- ],
- },
- summaryBold: { type: Boolean, default: false },
- summaryFontColor: {
- type: String,
- default: "#2c69ff",
- },
- initial: { type: Array, default: () => [] },
- products: { type: Array, default: () => [] },
- regions: { type: Array, default: () => [] },
- cellHeight: {
- type: String,
- default: "76rpx",
- },
- headerFontSize: {
- type: String,
- default: "32rpx",
- },
- headerBold: {
- type: Boolean,
- default: true,
- },
- bodyFontSize: {
- type: String,
- default: "32rpx",
- },
- bodyFontColor: {
- type: String,
- default: "",
- },
- //若需要横向滚动且左侧固定,则tableWidth需等于columns所有width之和(可以略小于)
- tableWidth: {
- type: String,
- default: "100%",
- },
- tableHeightAuto: {
- type: Boolean,
- default: false,
- },
- columns: {
- type: Array,
- default: () => [
- {
- key: "regionName",
- title: "区域",
- underline: true,
- fixed: true,
- width: "",
- },
- {
- key: "outScanRate",
- title: "出库扫码率",
- fixed: false,
- width: "",
- tooltip:
- "客户出库扫码量(与下游入库单中相同的追溯码)/下游企业入库扫码量",
- unit: "%",
- },
- {
- key: "inScanRate",
- title: "入库扫码率",
- fixed: false,
- width: "",
- tooltip:
- "客户入库扫码量(与上游出库单中相同的追溯码)/上游企业出库扫码量",
- unit: "%",
- },
- {
- key: "selfExaminationRate",
- title: "自验证率",
- fixed: false,
- width: "",
- tooltip: "客户出库扫码量(与入库单中相同的追溯码)/入库扫码量",
- unit: "%",
- },
- ],
- },
- },
- data() {
- return {
- dropdownOpen: false,
- dropdownRegionOpen: false,
- list: [],
- totalCount: 0,
- hasmore: true,
- loading: true,
- fetchLoading: false,
- loadingImg,
- product: null,
- region: null,
- tablePage: 1,
- tablePageSize: 10,
- summaryData: [],
- headerTooltip: {},
- regionSearchText: "",
- productSearchText: "",
- regionList: [],
- productList: [],
- };
- },
- computed: {
- filteredRegions() {
- if (!this.regionSearchText) return this.regions;
- const lower = this.regionSearchText.toLowerCase();
- return this.regions.filter(
- (r) =>
- (r.regionName || r.name || r || "")
- .toString()
- .toLowerCase()
- .indexOf(lower) > -1,
- );
- },
- filteredProducts() {
- if (!this.productSearchText) return this.products;
- const lower = this.productSearchText.toLowerCase();
- return this.products.filter(
- (p) => (p.physicName || "").toLowerCase().indexOf(lower) > -1,
- );
- },
- tableBodyHeight() {
- return 6 * 80;
- },
- columnList() {
- if (this.params) {
- const type = this.params?.type;
- if (type === "1" || type === "2")
- return this.columns.filter((i) => i.key !== "selfExaminationRate");
- }
- return this.columns;
- },
- },
- watch: {
- dropdownRegionOpen(val) {
- if (val) {
- this.regionSearchText = "";
- this.initRegionList();
- }
- },
- dropdownOpen(val) {
- if (val) {
- this.productSearchText = "";
- this.initProductList();
- }
- },
- product(val) {
- this.resetFetch();
- },
- region: {
- handler(val) {
- this.resetFetch();
- },
- deep: true,
- },
- params: {
- handler(newVal, oldVal) {
- if (
- newVal !== oldVal &&
- JSON.stringify(newVal) === JSON.stringify(oldVal)
- )
- return;
- this.resetFetch();
- },
- deep: true,
- },
- products: {
- handler(newVal, oldVal) {
- if (this.dropdownOpen) {
- this.initProductList();
- }
- },
- deep: true,
- },
- regions: {
- handler(newVal, oldVal) {
- if (this.dropdownRegionOpen) {
- this.initRegionList();
- }
- },
- deep: true,
- },
- },
- created() {
- // this.fetchLoading = false;
- // this.isLoading = false;
- // this.loading = false;
- // this.list =
- // this.initial && this.initial.length ? this.initial : this.genRows(7);
- // if (this.list.length > this.totalCount) {
- // this.list = this.list.slice(0, this.totalCount);
- // }
- // if (!this.showHeader) {
- // this.fetchList();
- // } else {
- // Promise.all([this.getProviceList(), this.getDrugInfoName()]).then(
- // () => { }
- // );
- // }
- this.fetchList();
- },
- methods: {
- renderCell(item, col) {
- if (!item[col.key]) return "--";
- const reg = /rate/i;
- if (reg.test(col.key))
- return Math.floor(Number(item[col.key])) + (col.unit || "");
- return item[col.key];
- },
- initRegionList() {
- this.regionList = this.filteredRegions.slice(0, 10);
- },
- loadMoreRegions(e) {
- if (this.regionList.length >= this.filteredRegions.length) return;
- const currentLen = this.regionList.length;
- const more = this.filteredRegions.slice(currentLen, currentLen + 10);
- this.regionList = this.regionList.concat(more);
- },
- onRegionSearch() {
- this.initRegionList();
- },
- initProductList() {
- this.productList = this.filteredProducts.slice(0, 10);
- },
- loadMoreProducts() {
- if (this.productList.length >= this.filteredProducts.length) return;
- const currentLen = this.productList.length;
- const more = this.filteredProducts.slice(currentLen, currentLen + 10);
- this.productList = this.productList.concat(more);
- },
- onProductSearch() {
- this.initProductList();
- },
- getUid,
- getSummary(col, ci) {
- if (ci == 0) return "合计";
- return Math.floor(Number(this.summaryData[ci])) + (col.unit || "");
- },
- closeAllTooltip() {
- this.headerTooltip = {};
- },
- toggleHeaderTooltip(i) {
- const value = !this.headerTooltip[i];
- this.headerTooltip = {};
- this.$set(this.headerTooltip, i, value);
- },
- // getUid(len = 16) {
- // const ts = Date.now().toString(36);
- // const rand = Math.random().toString(36).slice(2);
- // return (ts + rand).slice(0, len);
- // },
- // getProviceList() {
- // request('/common/getProviceList', {
- // path: 'customerScanningRate/wigets/ScanRateTable.vue',
- // }).then(res => {
- // if (res.code == 200) {
- // const _data = res.data;
- // this.regions = _data;
- // this.region = this.regions[0];
- // }
- // })
- // },
- // getDrugInfoName() {
- // request('/bills/getDrugInfoName', {
- // path: 'customerScanningRate/wigets/ScanRateTable.vue',
- // }).then(res => {
- // if (res.code == 200) {
- // const _data = res.data;
- // this.products = _data;
- // this.product = this.products[0];
- // }
- // })
- // },
- toggleDropdown() {
- if (this.fetchLoading) return;
- const next = !this.dropdownOpen;
- if (next) this.$emit("dropdown-open", this);
- this.dropdownOpen = next;
- },
- toggleDropdownRegion() {
- if (this.fetchLoading) return;
- const next = !this.dropdownRegionOpen;
- if (next) this.$emit("dropdown-open", this);
- this.dropdownRegionOpen = next;
- },
- selectProduct(type, p) {
- // this.$emit("change-product", p);
- if (type === "product") {
- this.product = p;
- this.dropdownOpen = false;
- } else if (type === "region") {
- this.region = p;
- this.dropdownRegionOpen = false;
- }
- },
- closeDropdown() {
- this.dropdownOpen = false;
- this.dropdownRegionOpen = false;
- },
- // genRows(n) {
- // const regions = ["广东", "广西", "湖南", "湖北", "四川", "浙江", "江苏"];
- // const res = [];
- // for (let i = 0; i < n; i++) {
- // const r = regions[i % regions.length];
- // res.push({
- // regionName: r,
- // outScanRate: `${(95 + (i % 5) * 0.5).toFixed(1)}%`,
- // inScanRate: `${(94 + (i % 5) * 0.6).toFixed(1)}%`,
- // });
- // }
- // return res;
- // },
- onScrollToLower(e) {
- if (e?.detail?.direction === "right") return;
- // if (!Array.isArray(this.list)) this.list = [];
- // if (this.list.length - 1 >= this.totalCount) return;
- // if (this.isLoading) return;
- // this.isLoading = true;
- // const remain = this.totalCount - this.list.length;
- // const toAdd = Math.min(7, remain);
- // setTimeout(() => {
- // if (this.list.length < this.totalCount) {
- // const more = this.genRows(toAdd);
- // this.list = this.list.concat(more);
- // }
- // this.isLoading = false;
- // }, 1000);
- this.fetchList();
- },
- resetFetch() {
- this.tablePage = 1;
- this.list = [];
- this.loading = true;
- this.hasmore = true;
- this.fetchList();
- },
- fetchList() {
- if (this._fetchDebounceTimer) clearTimeout(this._fetchDebounceTimer);
- const delay = 500;
- this._fetchDebounceTimer = setTimeout(() => {
- if (!this.hasmore) {
- setTimeout(() => {
- this.fetchLoading = false;
- this.loading = false;
- }, 500);
- return;
- }
- if (this.fetchLoading) return;
- this.fetchLoading = true;
- request(this.api, {
- drugEntBaseInfoId: this.product
- ? this.product?.drugEntBaseInfoId || ""
- : "",
- regionCode: this.region ? this.region?.regionCode || "" : "",
- pageNum: this.tablePage,
- pageSize: this.tablePageSize,
- path: "customerScanningRate/wigets/ScanRateTable.vue",
- ...(this.params || {}),
- }).then((res) => {
- if (res.code == 200) {
- const _data = res.data || {};
- let pageInfo = _data || {};
- if (this.tableType !== "variety") {
- this.summaryData = [];
- this.summaryData[0] = undefined;
- this.summaryStructure.forEach((item) => {
- this.summaryData.push(_data[item.key] || "--");
- });
- pageInfo = _data?.pageInfo || {};
- }
- const { list, total } = pageInfo;
- this.totalCount = total || 0;
- if (this.list.length >= this.totalCount) {
- this.fetchLoading = false;
- this.hasmore = false;
- this.loading = false;
- return;
- }
- this.list = Array.isArray(list)
- ? [...this.list, ...list]
- : [...this.list];
- if (this.list.length < this.totalCount) {
- this.hasmore = true;
- this.tablePage++;
- } else {
- this.hasmore = false;
- }
- // this.list.push(this.list[0]);
- // this.list.push(this.list[0]);
- // this.list.push(this.list[0]);
- // this.list.push(this.list[0]);
- // this.list.push(this.list[0]);
- // this.list.push(this.list[0]);
- // this.list.push(this.list[0]);
- // this.list.push(this.list[0]);
- // this.list.push(this.list[0]);
- // this.list.push(this.list[0]);
- // this.list.push(this.list[0]);
- }
- this.fetchLoading = false;
- this.loading = false;
- });
- }, delay);
- },
- headerCellStyle(ci, col) {
- const base = this.cellBaseStyle(ci, col);
- base.height = this.cellHeight;
- base.fontSize = this.headerFontSize;
- base.position = "sticky";
- base.zIndex = 2;
- base.top = "0rpx";
- base.background = "#eaf2ff";
- // base.display = 'flex';
- // base.alignItems = 'center';
- // base.justifyContent = 'center';
- if (ci === 0) {
- base.zIndex = 3;
- }
- if (col.fixed) {
- base.left = this.stickyLeft(ci);
- }
- return base;
- },
- bodyCellStyle(ci, col) {
- const base = this.cellBaseStyle(ci, col);
- // base.lineHeight = this.cellHeight;
- base.padding = "12rpx";
- base.fontSize = this.bodyFontSize;
- if (this.bodyFontColor) {
- base.color = this.bodyFontColor;
- }
- if (col.fixed) {
- base.position = "sticky";
- base.left = this.stickyLeft(ci);
- base.zIndex = 2;
- }
- return base;
- },
- cellBaseStyle(ci, col) {
- const style = {};
- // style.height = this.cellHeight;
- if (col && col.width) {
- style.width = col.width;
- style.flex = `0 0 ${col.width}`;
- } else {
- style.flex = 1;
- }
- return style;
- },
- stickyLeft(ci) {
- const parts = [];
- for (let i = 0; i < ci; i++) {
- const c = this.columns[i];
- if (c && c.fixed && c.width) parts.push(c.width);
- }
- if (!parts.length) return "0rpx";
- if (parts.length === 1) return parts[0];
- return `calc(${parts.join(" + ")})`;
- },
- isPlainTitle(t) {
- return typeof t === "string" ? t.indexOf("<") === -1 : true;
- },
- titleNodes(t) {
- if (typeof t !== "string") return t;
- let html = String(t);
- html = html
- .replace(/<\s*view/g, "<div")
- .replace(/<\/\s*view\s*>/g, "</div>");
- html = html.replace(
- /:style=\"\{\s*textAlign:\s*'center'\s*\}\"/g,
- 'style="text-align:center;"',
- );
- return html;
- },
- handleClick(data, col) {
- if (
- this.tableType === "variety" ||
- this.tableType === "customerDetail" ||
- col.key !== "regionName"
- )
- return;
- uni.navigateTo({
- url:
- "/traceCodePackages/traceabilityReport/pages/customerScanningRate/detail/index?regionCode=" +
- data.regionCode +
- "®ionName=" +
- encodeURIComponent(data.regionName) +
- "&drugEntBaseInfoId=" +
- (data.druGentBaseInfoId || "") +
- "&physicName=" +
- encodeURIComponent(data.name || "") +
- "&scanType=" +
- this.scanType +
- (this.params.type ? "&type=" + this.params.type : ""),
- });
- },
- },
- };
- </script>
- <style scoped>
- .section {
- margin-top: 24rpx;
- transform: translate3d(0, 0, 0);
- }
- .section-header {
- position: relative;
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 8rpx 8rpx;
- }
- .section-title {
- position: relative;
- font-size: 30rpx;
- font-weight: bold;
- color: #2c69ff;
- }
- .section-title::after {
- content: "";
- position: absolute;
- left: -20rpx;
- bottom: 13rpx;
- width: 8rpx;
- height: 50%;
- background: #2c69ff;
- border-radius: 10px;
- }
- .selector-wrap {
- position: relative;
- margin-right: 40rpx;
- }
- .selector {
- position: relative;
- display: flex;
- align-items: center;
- color: #2c69ff;
- padding-right: 30rpx;
- }
- .selector-text {
- font-size: 30rpx;
- max-width: 180rpx;
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- display: inline-block;
- }
- .selector-arrow {
- position: absolute;
- right: 0rpx;
- bottom: 14rpx;
- font-size: 30rpx;
- display: inline-block;
- width: 15rpx;
- height: 15rpx;
- border: 5rpx solid #2c69ff;
- border-top: none;
- border-left: none;
- transform-origin: 50% 50%;
- transform: rotate(45deg);
- transition: transform 0.2s;
- }
- .selector-arrow.open {
- bottom: 7rpx;
- transform: rotate(225deg);
- }
- .dropdown {
- position: absolute;
- right: 0rpx;
- top: 54rpx;
- width: 310rpx;
- max-height: 380rpx;
- background: #fff;
- border: 1rpx solid #eef0f4;
- border-radius: 12rpx;
- box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
- z-index: 93;
- overflow: hidden;
- }
- .dropdown-search-bar {
- padding: 10rpx;
- border-bottom: 1rpx solid #f0f2f5;
- background: #fff;
- z-index: 94;
- }
- .dropdown-search-input {
- width: 100%;
- height: 60rpx;
- background: #f5f7fa;
- border-radius: 8rpx;
- padding: 0 20rpx;
- font-size: 28rpx;
- box-sizing: border-box;
- }
- .dropdown-scroll-view {
- flex: 1;
- width: 100%;
- max-height: 260rpx;
- /* Adjusted height to fit search bar */
- overflow-y: auto;
- }
- .dropdown-item {
- padding: 16rpx 24rpx;
- font-size: 28rpx;
- color: #333;
- text-wrap: wrap;
- }
- .dropdown-item + .dropdown-item {
- border-top: 1rpx solid #f0f2f5;
- }
- .table-scroll-x {
- position: relative;
- margin-top: 12rpx;
- width: 100%;
- min-height: 120rpx;
- border-radius: 16rpx;
- overflow: visible;
- }
- .card {
- background: #fff;
- font-size: 32rpx;
- }
- .table-header {
- display: flex;
- background: #eaf2ff;
- font-weight: bold;
- color: #2c69ff;
- border-top-left-radius: 16rpx;
- border-top-right-radius: 16rpx;
- }
- /* .table-body {
- margin-top: 8rpx;
- } */
- .row {
- display: flex;
- align-items: stretch;
- border-bottom: 1rpx solid #eef0f4;
- }
- .row:last-child,
- .row:nth-last-child(2) {
- border-bottom: none;
- }
- .loading-row {
- justify-content: flex-start;
- }
- .loading-wrapper {
- width: calc(100vw - 60rpx);
- height: 76rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- position: sticky;
- top: 50%;
- left: 0;
- }
- .loading-icon {
- width: 40rpx;
- height: 40rpx;
- animation: spin 1s linear infinite;
- }
- @keyframes spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
- }
- .cell {
- flex: 1;
- box-sizing: border-box;
- width: 0;
- box-sizing: border-box;
- display: flex;
- align-items: center;
- justify-content: center;
- /* text-align: center; */
- word-break: break-all;
- }
- .table-body .cell {
- background-color: #fff;
- text-align: center;
- }
- .table-body .striped {
- background: #f7f7f7;
- }
- .underline {
- text-decoration: underline;
- color: #2c69ff;
- }
- /* hide scrollbars for H5/App while preserving scroll behavior */
- .no-scrollbar {
- position: relative;
- -ms-overflow-style: none;
- scrollbar-width: none;
- z-index: 2;
- }
- ::v-deep .no-scrollbar::-webkit-scrollbar {
- display: none !important;
- width: 0 !important;
- height: 0 !important;
- -webkit-appearance: none;
- background: transparent;
- }
- .header-tooltip-wrap {
- position: absolute;
- top: 60rpx;
- right: 0rpx;
- z-index: 93;
- }
- .header-tooltip {
- background: #000;
- color: #fff;
- border-radius: 8rpx;
- padding: 8rpx 12rpx;
- font-size: 24rpx;
- width: 270rpx;
- }
- .header-tooltip-arrow {
- position: absolute;
- top: -11rpx;
- right: 20rpx;
- width: 0;
- height: 0;
- border-left: 10rpx solid transparent;
- border-right: 10rpx solid transparent;
- border-bottom: 12rpx solid #000;
- margin: 0 auto;
- }
- .no-data-placeholder {
- opacity: 0;
- }
- .no-data {
- position: absolute;
- top: 76rpx;
- left: 0;
- width: 100%;
- z-index: 1;
- }
- </style>
|