index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. <template>
  2. <view class="detail-page">
  3. <!-- 顶部状态栏 -->
  4. <view class="header-section">
  5. <view class="header-content">
  6. <view class="title-group">
  7. <text class="main-title">黑名单企业监控</text>
  8. <text class="sub-title">监控异常经营企业</text>
  9. </view>
  10. <view class="stat-box">
  11. <text class="stat-num">{{ rows?.length || 0 }}</text>
  12. <text class="stat-unit">家</text>
  13. </view>
  14. </view>
  15. <view class="header-toolbar">
  16. <view class="filter-tabs">
  17. <view class="tab-item" v-for="(tab, index) in timeFilters" :key="index"
  18. :class="{ active: currentFilter === tab.value }" @click="switchFilter(tab.value)">
  19. {{ tab.label }}
  20. </view>
  21. </view>
  22. <view class="filter-wrap">
  23. <view class="selector" @click.stop="toggleProvinceDropdown">
  24. <text class="selector-text">{{
  25. selectedProvince || "全部省份"
  26. }}</text>
  27. <text class="selector-arrow" :class="{ open: dropdownProvinceOpen }"></text>
  28. </view>
  29. </view>
  30. </view>
  31. <!-- 背景装饰 -->
  32. <view class="header-circle circle-1"></view>
  33. <view class="header-circle circle-2"></view>
  34. </view>
  35. <scroll-view class="list-scroll" scroll-y="true" refresher-enabled :refresher-triggered="isRefreshing"
  36. @refresherrefresh="onRefresh">
  37. <view class="list-container">
  38. <view class="card-item" v-for="(item, index) in rows" :key="index" @click="toDetail(item)">
  39. <view class="card-header">
  40. <view class="header-left">
  41. <text class="index-num">{{ index + 1 }}</text>
  42. <text class="company-name">{{ item.queryCustomer }}</text>
  43. </view>
  44. <view class="header-right">
  45. <text class="status-tag">黑名单</text>
  46. </view>
  47. </view>
  48. <view class="card-body">
  49. <view class="code-row">
  50. <text class="label">信用代码:</text>
  51. <text class="value code-text">{{ item.socialCreditCode }}</text>
  52. </view>
  53. <view class="info-grid">
  54. <view class="info-item">
  55. <text class="label">省份</text>
  56. <text class="value">{{ item.province }}</text>
  57. </view>
  58. </view>
  59. </view>
  60. </view>
  61. <view v-if="!loading && rows.length === 0" class="empty-data">
  62. <EmptyView text="无相关数据" />
  63. </view>
  64. </view>
  65. </scroll-view>
  66. <view class="footer-btn-area">
  67. <!-- <button class="action-btn history-btn" @click="handleHistory">
  68. 历史记录
  69. </button> -->
  70. <button class="action-btn export-btn" @click="handleExport">
  71. 导出至邮箱
  72. </button>
  73. </view>
  74. <!-- 蒙层 -->
  75. <view class="report-export-create-modal-mask" v-if="emailModalOpen" @click="closeEmailModal"
  76. @touchmove.stop.prevent></view>
  77. <!-- 邮箱导出弹窗 -->
  78. <view class="report-export-create-modal report-export-create-email-modal"
  79. :class="{ 'report-export-create-modal--open': emailModalOpen }" v-if="emailModalOpen">
  80. <view class="report-export-create-modal-title">
  81. <text>发送至邮箱</text>
  82. <view class="report-export-create-modal-close" @click.stop="closeEmailModal">×</view>
  83. </view>
  84. <view class="report-export-create-modal-body" :style="{ padding: '40rpx' }">
  85. <up-input v-model="emailForm.email" border="none" :customStyle="{
  86. backgroundColor: '#ebf3fb',
  87. height: '80rpx',
  88. paddingLeft: '20rpx',
  89. }" placeholder="请填写邮箱" @input="emailError = false" disabled>
  90. <template #suffix>
  91. <view style="margin-right: 20rpx; color: #666">@999.com.cn</view>
  92. </template>
  93. </up-input>
  94. <text v-if="emailError" class="report-export-error-text">请输入邮箱</text>
  95. </view>
  96. <view class="report-export-create-modal-footer" :style="{
  97. padding: '20rpx 40rpx 40rpx',
  98. display: 'flex',
  99. 'justify-content': 'space-between',
  100. }">
  101. <view class="report-export-create-modal-btn cancel-btn" @click.stop="closeEmailModal">取消</view>
  102. <view class="report-export-create-modal-btn confirm-btn" @click.stop="handleSendEmail">发送</view>
  103. </view>
  104. </view>
  105. <!-- 独立的下拉菜单层 -->
  106. <view class="dropdown-layer" v-if="dropdownProvinceOpen" @click.stop>
  107. <view class="dropdown">
  108. <view class="dropdown-search-bar">
  109. <input class="dropdown-search-input" v-model="provinceSearchText" @input="onProvinceSearch"
  110. placeholder="搜索省份..." placeholder-style="color: #999" />
  111. </view>
  112. <scroll-view scroll-y="true" class="dropdown-scroll-view">
  113. <view class="dropdown-item" v-for="(p, i) in filteredProvinceList" :key="p || i" :class="{
  114. active: p === selectedProvince || (!selectedProvince && i === 0),
  115. }" @click.stop="selectProvince(p)">
  116. {{ p || "全部省份" }}
  117. <text v-if="p === selectedProvince || (!selectedProvince && i === 0)" class="check-mark">✓</text>
  118. </view>
  119. <view v-if="filteredProvinceList.length === 0" class="dropdown-empty">暂无数据</view>
  120. </scroll-view>
  121. </view>
  122. </view>
  123. </view>
  124. </template>
  125. <script>
  126. import EmptyView from "../../../wigets/empty.vue";
  127. import request from "../../../request/index.js";
  128. import { formatDate } from "../../../utils/utils.js";
  129. export default {
  130. components: {
  131. EmptyView,
  132. },
  133. data() {
  134. return {
  135. isRefreshing: false,
  136. loading: false,
  137. rows: [],
  138. allRows: [],
  139. dropdownProvinceOpen: false,
  140. provinceSearchText: "",
  141. provinceList: [""],
  142. selectedProvince: "",
  143. emailModalOpen: false,
  144. emailForm: {
  145. email: "",
  146. },
  147. emailError: false,
  148. currentFilter: "1",
  149. timeFilters: [
  150. { label: "昨日", value: "1" },
  151. { label: "近7天", value: "7" },
  152. { label: "近15天", value: "15" },
  153. { label: "近30天", value: "30" },
  154. ],
  155. };
  156. },
  157. created() {
  158. this.resetFetch();
  159. this.getProviceList();
  160. const userEmail = uni.getStorageSync('traceCode_useremail')
  161. this.emailForm.email = userEmail
  162. },
  163. methods: {
  164. formatDate,
  165. getProviceList() {
  166. request("/common/getProviceList", {
  167. path: "traceabilityReport/pages/blacklist/index.vue",
  168. }).then((res) => {
  169. if (res.code == 200) {
  170. const _data = res.data || [];
  171. this.provinceList = ["", ..._data.map((item) => item.regionName)];
  172. }
  173. });
  174. },
  175. switchFilter(value) {
  176. if (this.currentFilter === value) return;
  177. this.currentFilter = value;
  178. this.resetFetch();
  179. },
  180. fetchList() {
  181. if (this.loading) return;
  182. this.loading = true;
  183. const days = parseInt(this.currentFilter);
  184. const toDate = new Date();
  185. toDate.setDate(toDate.getDate() - 1);
  186. const fromDate = new Date(toDate);
  187. if (days > 1) {
  188. fromDate.setDate(toDate.getDate() - (days - 1));
  189. }
  190. const fromDateStr = this.formatDate(fromDate, "YYYY-MM-DD");
  191. const toDateStr = this.formatDate(toDate, "YYYY-MM-DD");
  192. request("/blacklist-report/get-export-company-data", {
  193. fromDate: fromDateStr,
  194. toDate: toDateStr,
  195. path: "traceabilityReport/pages/blacklist/index.vue",
  196. }).then((res) => {
  197. if (res.code == 200) {
  198. this.allRows = res.data || [];
  199. this.applyFilter();
  200. }
  201. this.loading = false;
  202. this.isRefreshing = false;
  203. });
  204. },
  205. async onRefresh() {
  206. this.isRefreshing = true;
  207. this.fetchList();
  208. },
  209. resetFetch() {
  210. this.rows = [];
  211. this.fetchList();
  212. },
  213. toDetail(item) {
  214. uni.navigateTo({
  215. url: `/traceCodePackages/traceabilityReport/pages/blacklist/detail/index?id=${item.socialCreditCode}&dateStr=${item.billTime}&name=${encodeURIComponent(item.queryCustomer)}`,
  216. });
  217. },
  218. handleHistory() {
  219. uni.navigateTo({
  220. url: "/traceCodePackages/traceabilityReport/pages/blacklist/history/index",
  221. });
  222. },
  223. handleExport() {
  224. if (this.rows?.length == 0) {
  225. uni.showToast({
  226. title: '暂无数据...',
  227. icon: 'none'
  228. })
  229. return
  230. }
  231. this.emailModalOpen = true;
  232. this.emailError = false;
  233. },
  234. closeEmailModal() {
  235. this.emailModalOpen = false;
  236. },
  237. handleSendEmail() {
  238. if (!this.emailForm.email) {
  239. this.emailError = true;
  240. return;
  241. }
  242. uni.showLoading({ title: "发送中..." });
  243. request("/report/sendemail", {
  244. taskId: this.rows[0]?.taskId,
  245. emailAddress: this.emailForm.email + "@999.com.cn",
  246. path: "traceabilityReport/pages/blacklist/index.vue",
  247. }).then((res) => {
  248. uni.hideLoading();
  249. if (res.code == 200) {
  250. uni.showToast({
  251. title: "发送成功",
  252. icon: "success",
  253. });
  254. this.closeEmailModal();
  255. } else {
  256. uni.showToast({
  257. title: res.msg || "发送失败",
  258. icon: "none",
  259. });
  260. }
  261. });
  262. },
  263. applyFilter() {
  264. if (!this.selectedProvince) {
  265. this.rows = [...this.allRows];
  266. } else {
  267. this.rows = this.allRows.filter(item => item.customerProvinceName === this.selectedProvince);
  268. }
  269. this.totalCount = this.rows.length;
  270. },
  271. toggleProvinceDropdown() {
  272. this.dropdownProvinceOpen = !this.dropdownProvinceOpen;
  273. },
  274. closeProvinceDropdown() {
  275. this.dropdownProvinceOpen = false;
  276. },
  277. selectProvince(province) {
  278. this.selectedProvince = province || "";
  279. this.dropdownProvinceOpen = false;
  280. this.applyFilter();
  281. },
  282. },
  283. computed: {
  284. filteredProvinceList() {
  285. if (!this.provinceSearchText) {
  286. return this.provinceList;
  287. }
  288. return this.provinceList.filter((p) =>
  289. p?.toLowerCase()?.includes(this.provinceSearchText.toLowerCase()),
  290. );
  291. },
  292. },
  293. };
  294. </script>
  295. <style scoped>
  296. .detail-page {
  297. display: flex;
  298. flex-direction: column;
  299. height: calc(100vh - 116rpx - env(safe-area-inset-bottom));
  300. box-sizing: border-box;
  301. background: #f5f7fa;
  302. }
  303. /* Header Section */
  304. .header-section {
  305. background: linear-gradient(135deg, #2b32b2 0%, #1488cc 100%);
  306. padding: 40rpx 40rpx 40rpx;
  307. /* Extra padding at bottom for overlap effect */
  308. position: relative;
  309. z-index: 20;
  310. color: #fff;
  311. border-bottom-left-radius: 40rpx;
  312. border-bottom-right-radius: 40rpx;
  313. overflow: hidden;
  314. box-shadow: 0 10rpx 30rpx rgba(20, 136, 204, 0.2);
  315. }
  316. .header-content {
  317. display: flex;
  318. justify-content: space-between;
  319. align-items: center;
  320. position: relative;
  321. z-index: 2;
  322. margin-bottom: 40rpx;
  323. }
  324. .title-group {
  325. display: flex;
  326. flex-direction: column;
  327. }
  328. .main-title {
  329. font-size: 40rpx;
  330. font-weight: bold;
  331. margin-bottom: 8rpx;
  332. letter-spacing: 2rpx;
  333. }
  334. .sub-title {
  335. font-size: 24rpx;
  336. opacity: 0.8;
  337. }
  338. .stat-box {
  339. display: flex;
  340. align-items: baseline;
  341. }
  342. .stat-num {
  343. font-size: 56rpx;
  344. font-weight: bold;
  345. margin-right: 8rpx;
  346. font-family: "DINAlternate-Bold", sans-serif;
  347. }
  348. .stat-unit {
  349. font-size: 24rpx;
  350. opacity: 0.8;
  351. }
  352. .header-toolbar {
  353. display: flex;
  354. justify-content: space-between;
  355. align-items: center;
  356. position: relative;
  357. z-index: 3;
  358. }
  359. .update-tip {
  360. display: inline-flex;
  361. align-items: center;
  362. background: rgba(255, 255, 255, 0.15);
  363. padding: 8rpx 20rpx;
  364. border-radius: 30rpx;
  365. font-size: 22rpx;
  366. backdrop-filter: blur(10px);
  367. }
  368. .tip-icon {
  369. margin-right: 8rpx;
  370. font-size: 20rpx;
  371. }
  372. /* Filter Tabs */
  373. .filter-tabs {
  374. display: flex;
  375. background: rgba(255, 255, 255, 0.2);
  376. border-radius: 30rpx;
  377. padding: 4rpx;
  378. margin-right: 20rpx;
  379. }
  380. .tab-item {
  381. padding: 8rpx 24rpx;
  382. font-size: 24rpx;
  383. color: rgba(255, 255, 255, 0.8);
  384. border-radius: 26rpx;
  385. transition: all 0.3s;
  386. }
  387. .tab-item.active {
  388. background: #fff;
  389. color: #1890ff;
  390. font-weight: 600;
  391. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
  392. }
  393. /* Filter Styles */
  394. .filter-wrap {
  395. position: relative;
  396. }
  397. .selector {
  398. display: flex;
  399. align-items: center;
  400. color: #fff;
  401. font-size: 26rpx;
  402. font-weight: 500;
  403. padding: 8rpx 20rpx;
  404. background: rgba(255, 255, 255, 0.2);
  405. border-radius: 30rpx;
  406. border: 1rpx solid rgba(255, 255, 255, 0.3);
  407. }
  408. .selector-text {
  409. max-width: 200rpx;
  410. overflow: hidden;
  411. white-space: nowrap;
  412. text-overflow: ellipsis;
  413. }
  414. .selector-arrow {
  415. margin-left: 10rpx;
  416. width: 0;
  417. height: 0;
  418. border-left: 8rpx solid transparent;
  419. border-right: 8rpx solid transparent;
  420. border-top: 10rpx solid #fff;
  421. transition: transform 0.3s;
  422. }
  423. .selector-arrow.open {
  424. transform: rotate(180deg);
  425. }
  426. /* Dropdown Layer (Absolute on top of everything) */
  427. .dropdown-layer {
  428. position: absolute;
  429. top: 300rpx;
  430. /* Adjust based on header layout */
  431. right: 40rpx;
  432. z-index: 999;
  433. }
  434. .dropdown {
  435. width: 360rpx;
  436. background: #fff;
  437. border-radius: 12rpx;
  438. box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.15);
  439. overflow: hidden;
  440. }
  441. .dropdown-search-bar {
  442. padding: 16rpx;
  443. border-bottom: 1rpx solid #f0f0f0;
  444. }
  445. .dropdown-search-input {
  446. background: #f5f7fa;
  447. height: 64rpx;
  448. border-radius: 32rpx;
  449. padding: 0 24rpx;
  450. font-size: 26rpx;
  451. }
  452. .dropdown-scroll-view {
  453. max-height: 400rpx;
  454. }
  455. .dropdown-item {
  456. padding: 20rpx 30rpx;
  457. font-size: 28rpx;
  458. color: #333;
  459. display: flex;
  460. justify-content: space-between;
  461. align-items: center;
  462. transition: background 0.2s;
  463. }
  464. .dropdown-item:active {
  465. background: #f5f7fa;
  466. }
  467. .dropdown-item.active {
  468. color: #1890ff;
  469. font-weight: 500;
  470. background: #e6f7ff;
  471. }
  472. .check-mark {
  473. font-size: 24rpx;
  474. }
  475. .dropdown-empty {
  476. padding: 40rpx;
  477. text-align: center;
  478. color: #999;
  479. font-size: 26rpx;
  480. }
  481. /* Header Decor Circles */
  482. .header-circle {
  483. position: absolute;
  484. border-radius: 50%;
  485. background: rgba(255, 255, 255, 0.05);
  486. }
  487. .circle-1 {
  488. width: 300rpx;
  489. height: 300rpx;
  490. top: -100rpx;
  491. right: -50rpx;
  492. }
  493. .circle-2 {
  494. width: 200rpx;
  495. height: 200rpx;
  496. bottom: -50rpx;
  497. left: -50rpx;
  498. }
  499. /* List Scroll */
  500. .list-scroll {
  501. flex: 1;
  502. height: 0;
  503. padding: 0 24rpx;
  504. /* Remove vertical padding from scroll container */
  505. box-sizing: border-box;
  506. margin-top: -20rpx;
  507. /* Negative margin to pull list up */
  508. position: relative;
  509. z-index: 21;
  510. }
  511. .list-container {
  512. padding-top: 10rpx;
  513. padding-bottom: calc(200rpx + env(safe-area-inset-bottom));
  514. }
  515. .card-item {
  516. background: #fff;
  517. border-radius: 20rpx;
  518. padding: 30rpx;
  519. margin-bottom: 24rpx;
  520. box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.05);
  521. transition: transform 0.2s;
  522. }
  523. .card-item:active {
  524. transform: scale(0.99);
  525. }
  526. .card-header {
  527. display: flex;
  528. justify-content: space-between;
  529. align-items: flex-start;
  530. margin-bottom: 24rpx;
  531. }
  532. .header-left {
  533. flex: 1;
  534. display: flex;
  535. align-items: center;
  536. margin-right: 20rpx;
  537. }
  538. .index-num {
  539. font-size: 24rpx;
  540. color: #999;
  541. margin-right: 12rpx;
  542. font-family: monospace;
  543. }
  544. .company-name {
  545. font-size: 32rpx;
  546. font-weight: 600;
  547. color: #096dd9;
  548. line-height: 1.4;
  549. text-decoration: underline;
  550. }
  551. .header-right {
  552. flex-shrink: 0;
  553. }
  554. .status-tag {
  555. font-size: 20rpx;
  556. padding: 6rpx 16rpx;
  557. border-radius: 20rpx;
  558. background: #fff1f0;
  559. color: #ff4d4f;
  560. font-weight: 600;
  561. border: 1rpx solid rgba(255, 77, 79, 0.2);
  562. }
  563. .card-body {
  564. background: #f9fbfd;
  565. border-radius: 12rpx;
  566. padding: 24rpx;
  567. }
  568. .code-row {
  569. display: flex;
  570. align-items: center;
  571. margin-bottom: 20rpx;
  572. padding-bottom: 20rpx;
  573. border-bottom: 1rpx solid #edf0f5;
  574. }
  575. .code-row:last-child {
  576. margin-bottom: 0;
  577. padding-bottom: 0;
  578. border-bottom: none;
  579. }
  580. .code-text {
  581. font-family: monospace;
  582. color: #333 !important;
  583. font-weight: 600 !important;
  584. letter-spacing: 1rpx;
  585. }
  586. .info-grid {
  587. display: flex;
  588. flex-wrap: wrap;
  589. gap: 24rpx;
  590. }
  591. .info-item {
  592. display: flex;
  593. align-items: center;
  594. width: 45%;
  595. }
  596. .info-item .label,
  597. .code-row .label {
  598. font-size: 24rpx;
  599. color: #999;
  600. margin-right: 12rpx;
  601. }
  602. .info-item .value,
  603. .code-row .value {
  604. font-size: 26rpx;
  605. color: #666;
  606. font-weight: 500;
  607. }
  608. /* Loading & Footer */
  609. .loading-more {
  610. display: flex;
  611. justify-content: center;
  612. align-items: center;
  613. padding: 30rpx 0;
  614. }
  615. .loading-text {
  616. font-size: 24rpx;
  617. color: #999;
  618. }
  619. .loading-icon {
  620. width: 32rpx;
  621. height: 32rpx;
  622. margin-right: 12rpx;
  623. animation: spin 1s linear infinite;
  624. }
  625. .empty-data {
  626. padding-top: 120rpx;
  627. }
  628. .no-more {
  629. text-align: center;
  630. color: #ccc;
  631. font-size: 24rpx;
  632. padding: 30rpx 0;
  633. }
  634. @keyframes spin {
  635. from {
  636. transform: rotate(0deg);
  637. }
  638. to {
  639. transform: rotate(360deg);
  640. }
  641. }
  642. .footer-btn-area {
  643. padding: 24rpx 32rpx calc(24rpx + env(safe-area-inset-bottom));
  644. background: #fff;
  645. box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08);
  646. position: fixed;
  647. z-index: 100;
  648. bottom: 0;
  649. width: 100%;
  650. box-sizing: border-box;
  651. display: flex;
  652. gap: 24rpx;
  653. }
  654. .action-btn {
  655. flex: 1;
  656. height: 88rpx;
  657. line-height: 88rpx;
  658. border-radius: 44rpx;
  659. font-size: 30rpx;
  660. font-weight: 600;
  661. text-align: center;
  662. border: none;
  663. transition: all 0.3s;
  664. }
  665. .action-btn::after {
  666. border: none;
  667. }
  668. .action-btn:active {
  669. transform: scale(0.96);
  670. }
  671. .history-btn {
  672. background: #fff;
  673. color: #1890ff;
  674. border: 2rpx solid #1890ff;
  675. box-shadow: 0 4rpx 12rpx rgba(24, 144, 255, 0.1);
  676. }
  677. .export-btn {
  678. background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
  679. color: #fff;
  680. box-shadow: 0 6rpx 16rpx rgba(24, 144, 255, 0.35);
  681. }
  682. /* 弹窗样式 */
  683. .report-export-create-modal-mask {
  684. position: fixed;
  685. top: 0;
  686. left: 0;
  687. right: 0;
  688. bottom: 0;
  689. background: rgba(0, 0, 0, 0.6);
  690. z-index: 999;
  691. backdrop-filter: blur(2px);
  692. }
  693. .report-export-create-modal {
  694. position: fixed;
  695. z-index: 1000;
  696. background: #fff;
  697. transition: all 0.3s ease;
  698. }
  699. .report-export-create-email-modal {
  700. top: 50%;
  701. left: 50%;
  702. transform: translate(-50%, -50%);
  703. width: 620rpx;
  704. border-radius: 24rpx;
  705. opacity: 0;
  706. visibility: hidden;
  707. overflow: hidden;
  708. }
  709. .report-export-create-email-modal.report-export-create-modal--open {
  710. opacity: 1;
  711. visibility: visible;
  712. }
  713. .report-export-create-modal-title {
  714. padding: 36rpx 32rpx;
  715. font-size: 36rpx;
  716. color: #333;
  717. text-align: center;
  718. font-weight: 600;
  719. border-bottom: 1rpx solid #f0f0f0;
  720. position: relative;
  721. }
  722. .report-export-create-modal-close {
  723. position: absolute;
  724. right: 32rpx;
  725. top: 50%;
  726. transform: translateY(-50%);
  727. font-size: 44rpx;
  728. color: #999;
  729. line-height: 1;
  730. padding: 10rpx;
  731. }
  732. .report-export-create-modal-body {
  733. padding: 48rpx 40rpx 32rpx;
  734. }
  735. .report-export-error-text {
  736. font-size: 24rpx;
  737. color: #ff4d4f;
  738. margin-top: 12rpx;
  739. display: block;
  740. }
  741. .report-export-create-modal-footer {
  742. padding: 0 40rpx 48rpx;
  743. display: flex;
  744. justify-content: space-between;
  745. gap: 24rpx;
  746. }
  747. .report-export-create-modal-btn {
  748. height: 88rpx;
  749. line-height: 88rpx;
  750. border-radius: 44rpx;
  751. text-align: center;
  752. font-size: 30rpx;
  753. font-weight: 600;
  754. flex: 1;
  755. margin: 0;
  756. }
  757. .cancel-btn {
  758. background: #f5f7fa;
  759. color: #666;
  760. border: 1rpx solid #e4e7ed;
  761. }
  762. .confirm-btn {
  763. background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%);
  764. color: #fff;
  765. box-shadow: 0 6rpx 16rpx rgba(24, 144, 255, 0.3);
  766. }
  767. </style>