<!--
 * @Author: ysh
 * @Date: 2026-04-09 09:18:44
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2026-04-20 10:54:20
-->
<template>
  <div class="app-container">
    <el-alert v-if="hasEnvBidcenterCredentials" title="已在环境变量中配置采招网账号：密码会打进前端包，切勿提交仓库；生产环境请改为后端登录，仅向前端下发 token。"
      type="warning" show-icon :closable="false" class="mb8" />
    <div class="toolbar-card mb8">
      <div class="bidcenter-auth-row">
        <span class="field-label">采招网会员</span>
        <el-tag :type="memberSearchActive ? 'success' : 'info'" size="small">{{ bidcenterAuthLabel }}</el-tag>
        <el-button v-if="hasEnvBidcenterCredentials" size="small" :loading="bidcenterLoginLoading"
          @click="handleBidcenterLoginFromEnv">环境变量登录</el-button>
        <el-button size="small" :loading="bidcenterLoginLoading" @click="openBidcenterLoginDialog">账号登录</el-button>
        <el-input v-model="manualTokenDraft" size="small" placeholder="手动粘贴搜索接口 token" show-password class="token-input"
          clearable />
        <el-button size="small" @click="applyManualBidcenterToken">应用 token</el-button>
        <el-button v-if="memberSearchActive" size="small" type="text" @click="clearBidcenterMemberToken">清除</el-button>
      </div>
      <!-- <div class="keyword-display-row">
        <span class="field-label">当前关键词</span>
        <el-tag type="primary" effect="plain" class="keyword-tag">{{ displayKeyword || '—' }}</el-tag>
      </div> -->
      <el-form :inline="true" size="small" class="remote-search-form" @submit.native.prevent>
        <el-form-item label="修改关键词">
          <el-input v-model="keywordText" placeholder="多个关键词用英文逗号分隔" clearable style="width: 620px"
            @keyup.enter.native="handleServerSearch" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" :loading="searchLoading"
            @click="handleServerSearch">检索</el-button>
        </el-form-item>
      </el-form>
      <div class="table-filter-row">
        <span class="field-label">表格筛选</span>
        <el-input v-model="tableFilter" placeholder="在当前页结果中过滤标题、类型、地区等" clearable prefix-icon="el-icon-search"
          style="width: 360px" />
        <span v-if="tableFilterTrimmed" class="filter-hint">
          本页匹配 {{ filteredTableData.length }} / {{ tableData.length }} 条
        </span>
      </div>
    </div>
    <el-alert type="warning" show-icon :closable="false" class="mb8" v-if="!memberSearchActive">
      <span>登录会员之后才能开启精准搜索</span>
    </el-alert>
    <el-alert v-if="searchWarning" :title="searchWarning" type="warning" show-icon :closable="false" class="mb8" />
    <div v-if="realInfoCount !== null && realInfoCount !== ''" class="search-summary mb8">
      约 <strong>{{ realInfoCount }}</strong> 条相关信息（分页每页 {{ pageSize }} 条）
    </div>
    <el-table v-loading="searchLoading" :data="filteredTableData" border stripe style="width: 100%"
      :empty-text="tableEmptyText">
      <el-table-column type="index" width="50" label="#" align="center" />
      <el-table-column prop="news_type_des" label="类型" width="100" show-overflow-tooltip />
      <el-table-column label="标题" min-width="300">
        <template slot-scope="scope">
          <a :href="scope.row.news_url" target="_blank" rel="noopener noreferrer" class="title-link">{{
            plainTitle(scope.row.news_title_show) }}</a>
          <span v-if="scope.row.contain_kwd_fujian" class="fujian-tag">含附件</span>
        </template>
      </el-table-column>
      <el-table-column label="金额/预算" width="130" show-overflow-tooltip>
        <template slot-scope="scope">{{ formatAmount(scope.row) }}</template>
      </el-table-column>
      <el-table-column label="采购方式/阶段" width="130" show-overflow-tooltip>
        <template slot-scope="scope">{{ formatCgfs(scope.row) }}</template>
      </el-table-column>
      <el-table-column label="截止时间/中标时间等" width="160" show-overflow-tooltip>
        <template slot-scope="scope">{{ formatTimeCol(scope.row) }}</template>
      </el-table-column>
      <el-table-column prop="news_diqustr" label="地区" width="120" show-overflow-tooltip />
      <el-table-column label="发布" width="120" show-overflow-tooltip>
        <template slot-scope="scope">{{ showText(scope.row.news_star_time_show) }}</template>
      </el-table-column>
    </el-table>
    <el-pagination v-if="pageTotal > 0" class="mt16" background :current-page="searchQuery.page" :page-size="pageSize"
      layout="total, prev, pager, next, jumper" :total="pageTotal" @current-change="handlePageChange" />

    <el-dialog :visible.sync="bidcenterLoginDialogVisible" custom-class="bidcenter-login-dialog" width="440px"
      append-to-body :close-on-click-modal="false" @open="onBidcenterDialogOpen">
      <template slot="title">
        <div class="bidcenter-login-dialog__title">
          <div class="bidcenter-login-dialog__brand" aria-hidden="true">
            <i class="el-icon-medal" />
          </div>
          <div class="bidcenter-login-dialog__title-text">
            <span class="bidcenter-login-dialog__title-main">采招网会员登录</span>
            <span class="bidcenter-login-dialog__title-sub">登录成功后，检索请求将按会员身份发起</span>
          </div>
        </div>
      </template>
      <div class="bidcenter-login-dialog__panel">
        <el-form class="bidcenter-login-dialog__form" label-position="top" size="medium" @submit.native.prevent>
          <el-form-item label="用户名 / 手机号">
            <el-input v-model="bidcenterLoginForm.username" autocomplete="username" clearable placeholder="请输入采招网账号"
              prefix-icon="el-icon-user" />
          </el-form-item>
          <el-form-item label="密码">
            <el-input v-model="bidcenterLoginForm.password" type="password" show-password
              autocomplete="current-password" clearable placeholder="请输入密码" prefix-icon="el-icon-lock"
              @keyup.enter.native="handleBidcenterLoginFromForm" />
          </el-form-item>
        </el-form>
        <p class="bidcenter-login-dialog__hint">
          <i class="el-icon-info" />
          凭账号校验后可能仅写入 Cookie；若检索权限异常，可在页面使用「应用 token」。
        </p>
      </div>
      <div slot="footer" class="bidcenter-login-dialog__footer">
        <el-button size="medium" @click="bidcenterLoginDialogVisible = false">取消</el-button>
        <el-button type="primary" size="medium" :loading="bidcenterLoginLoading" @click="handleBidcenterLoginFromForm">
          登录
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import axios from 'axios'
import CryptoJS from 'crypto-js'
import { Message, Loading } from 'element-ui'
import { listBid } from '@/api/oa/bid/bid'
import {
  loginBidcenterMemberJsonp,
  pickTokenFromLoginResponse,
  pickNextTokenFromLoginResponse,
  getStoredBidcenterToken,
  setStoredBidcenterToken,
  clearStoredBidcenterToken,
  setBidcenterJsonpMemberSession,
  getBidcenterJsonpMemberSession
} from '@/utils/bidcenterMemberLogin'

const SEARCH_PRO_URL = 'https://interface.bidcenter.com.cn/search/GetSearchProHandler.ashx'
const BIDCENTER_GUID = 'cad034bd-ad01-4dce-a4ca-1a1252f0dbf1'

// 与 searchv16.js 中 variate.key / variate.aceIV 一致（采招网接口 AES）
const bidcenterAes = {
  key: CryptoJS.lib.WordArray.create(
    [863652730, 2036741733, 1164342596, 1782662963],
    16
  ),
  iv: CryptoJS.lib.WordArray.create(
    [1719227713, 1314533489, 1397643880, 1749959510],
    16
  )
}

/** 与 jq_search POST 一致：keywords 已为 encodeURIComponent 结果，不再二次编码；token 允许空串也提交 */
function serializeSearchParams(data) {
  const parts = []
  for (const key of Object.keys(data)) {
    const v = data[key]
    if (v === undefined || v === null) continue
    if (v === '' && key !== 'token' && key !== 'next_token') continue
    if (key === 'keywords') {
      parts.push(`keywords=${v}`)
    } else {
      parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(v))}`)
    }
  }
  return parts.join('&')
}

export default {
  name: 'Bid',
  data() {
    return {
      bidList: [],
      tableData: [],
      pageTotal: 0,
      pageSize: 40,
      realInfoCount: null,
      searchWarning: '',
      emptyText: '暂无数据',
      searchLoading: false,
      /** 接口每次返回的 next_token（searchv16：20 页后靠此续页） */
      storedNextTokenFromApi: '',
      /** 仅用于下一次 POST 的 next_token，发出后清空 */
      pendingNextToken: '',
      /** 检索输入框与接口关键词（明文） */
      keywordText: '控制网,库容复核,测量技术,地形测量,安全监测,基准网复测,测量中心,土地测绘',
      /** 接口返回或上次成功检索后的展示文案 */
      displayKeyword: '控制网,库容复核,测量技术,地形测量,安全监测,基准网复测,测量中心,土地测绘',
      /** 仅筛选当前页表格，不发请求 */
      tableFilter: '',
      searchQuery: {
        time: 90,
        type: 1,
        mod: 0,
        page: 1
      },
      /** 采招网搜索接口 token（与 searchv16 中 token 一致） */
      bidcenterMemberToken: '',
      /** JSONP 登录成功但未返回 token 时，与 sessionStorage 同步：用采招网 cookie + withCredentials 调搜索 */
      bidcenterCookieMember: false,
      bidcenterLoginLoading: false,
      manualTokenDraft: '',
      bidcenterLoginDialogVisible: false,
      bidcenterLoginForm: {
        username: '',
        password: ''
      }
    }
  },
  computed: {
    bidcenterAuthLabel() {
      if ((this.bidcenterMemberToken || '').trim()) return '已登录（请求已携带 token）'
      if (this.bidcenterCookieMember) return '已登录（采招网 Cookie，无 token 字段）'
      return '未登录（匿名）'
    },
    memberSearchActive() {
      return !!(this.bidcenterMemberToken || '').trim() || this.bidcenterCookieMember
    },
    hasEnvBidcenterCredentials() {
      const u = process.env.VUE_APP_BIDCENTER_USERNAME
      const p = process.env.VUE_APP_BIDCENTER_PASSWORD
      return !!(u && String(u).trim() && p && String(p).trim())
    },
    tableFilterTrimmed() {
      return (this.tableFilter || '').trim()
    },
    filteredTableData() {
      const q = this.tableFilterTrimmed.toLowerCase()
      if (!q) return this.tableData
      return this.tableData.filter((row) => {
        const title = this.plainTitle(row.news_title_show).toLowerCase()
        const type = String(row.news_type_des || '').toLowerCase()
        const area = String(row.news_diqustr || '').toLowerCase()
        const amount = this.formatAmount(row).toLowerCase()
        const cgfs = this.formatCgfs(row).toLowerCase()
        const timeCol = this.formatTimeCol(row).toLowerCase()
        return (
          title.includes(q) ||
          type.includes(q) ||
          area.includes(q) ||
          amount.includes(q) ||
          cgfs.includes(q) ||
          timeCol.includes(q)
        )
      })
    },
    tableEmptyText() {
      if (this.tableFilterTrimmed && this.tableData.length && this.filteredTableData.length === 0) {
        return '当前页无匹配项，请调整筛选词'
      }
      return this.emptyText
    }
  },
  async created() {
    this.restoreBidcenterTokenFromStorage()
    await this.tryAutoLoginBidcenterFromEnv()
    await this.getList()
  },
  methods: {
    restoreBidcenterTokenFromStorage() {
      this.bidcenterMemberToken = getStoredBidcenterToken()
      this.bidcenterCookieMember = getBidcenterJsonpMemberSession()
      if (this.memberSearchActive && Number(this.searchQuery.mod) === 0) {
        this.searchQuery.mod = 1
      }
    },
    async tryAutoLoginBidcenterFromEnv() {
      if (!this.hasEnvBidcenterCredentials) return
      if (this.memberSearchActive) return
      const u = String(process.env.VUE_APP_BIDCENTER_USERNAME || '').trim()
      const p = String(process.env.VUE_APP_BIDCENTER_PASSWORD || '').trim()
      await this.runBidcenterMemberLogin(u, p, { silent: true })
    },
    onBidcenterDialogOpen() {
      const u = String(process.env.VUE_APP_BIDCENTER_USERNAME || '').trim()
      const p = String(process.env.VUE_APP_BIDCENTER_PASSWORD || '').trim()
      if (!this.bidcenterLoginForm.username && u) this.bidcenterLoginForm.username = u
      if (!this.bidcenterLoginForm.password && p) this.bidcenterLoginForm.password = p
    },
    openBidcenterLoginDialog() {
      this.bidcenterLoginDialogVisible = true
    },
    async handleBidcenterLoginFromEnv() {
      const u = String(process.env.VUE_APP_BIDCENTER_USERNAME || '').trim()
      const p = String(process.env.VUE_APP_BIDCENTER_PASSWORD || '').trim()
      await this.runBidcenterMemberLogin(u, p, { silent: false })
    },
    async handleBidcenterLoginFromForm() {
      const u = (this.bidcenterLoginForm.username || '').trim()
      const p = (this.bidcenterLoginForm.password || '').trim()
      const ok = await this.runBidcenterMemberLogin(u, p, { silent: false })
      if (ok) this.bidcenterLoginDialogVisible = false
    },
    /**
     * @returns {Promise<boolean>} 是否拿到 token
     */
    async runBidcenterMemberLogin(username, password, { silent }) {
      this.bidcenterLoginLoading = true
      try {
        const r = await loginBidcenterMemberJsonp(username, password)
        const ok = r.status === 'true' || r.status === true
        if (!ok) {
          let brief = '登录失败'
          if (r.brief != null) {
            try {
              brief = decodeURIComponent(String(r.brief))
            } catch (e) {
              brief = String(r.brief)
            }
          }
          Message.error(brief)
          return false
        }
        const tok = pickTokenFromLoginResponse(r)
        if (tok) {
          setBidcenterJsonpMemberSession(false)
          this.bidcenterCookieMember = false
          this.bidcenterMemberToken = tok
          setStoredBidcenterToken(tok)
          this.searchQuery.mod = 1
          const nt = pickNextTokenFromLoginResponse(r)
          this.storedNextTokenFromApi = nt || ''
          if (!silent) {
            Message.success('采招网会员登录成功')
            this.fetchBidcenterSearch()
          }
          return true
        }
        // 与采招网原页一致：登录接口常只写 cookie、不返回搜索 token；凭 cookie 请求搜索接口
        setBidcenterJsonpMemberSession(true)
        this.bidcenterCookieMember = true
        this.bidcenterMemberToken = ''
        this.searchQuery.mod = 1
        this.storedNextTokenFromApi = ''
        this.pendingNextToken = ''
        if (!silent) {
          Message.success('采招网账号已校验；将携带采招网 Cookie 请求检索（若仍非会员数据，请从采招网页复制 token 后「应用 token」）')
          this.fetchBidcenterSearch()
        } else {
          Message({
            message:
              '采招网环境账号已登录（Cookie 会话）。若检索权限异常，请在页面使用「应用 token」或检查浏览器是否拦截第三方 Cookie。',
            type: 'warning',
            duration: 8000
          })
        }
        return true
      } catch (e) {
        Message.error(e.message || '采招网登录失败')
        return false
      } finally {
        this.bidcenterLoginLoading = false
      }
    },
    applyManualBidcenterToken() {
      const t = (this.manualTokenDraft || '').trim()
      if (!t) {
        Message.warning('请先粘贴 token')
        return
      }
      setBidcenterJsonpMemberSession(false)
      this.bidcenterCookieMember = false
      this.bidcenterMemberToken = t
      setStoredBidcenterToken(t)
      this.searchQuery.mod = 1
      this.storedNextTokenFromApi = ''
      this.pendingNextToken = ''
      this.manualTokenDraft = ''
      Message.success('已保存 token，正在按会员身份重新检索')
      this.fetchBidcenterSearch()
    },
    clearBidcenterMemberToken() {
      clearStoredBidcenterToken()
      setBidcenterJsonpMemberSession(false)
      this.bidcenterCookieMember = false
      this.bidcenterMemberToken = ''
      this.searchQuery.mod = 0
      this.storedNextTokenFromApi = ''
      this.pendingNextToken = ''
      Message.success('已清除采招网 token')
      this.fetchBidcenterSearch()
    },
    async getList() {
      const queryParams = {
        url:
          'https://search.bidcenter.com.cn/search?keywords=%e6%8e%a7%e5%88%b6%e7%bd%91%2c%e5%ba%93%e5%ae%b9%e5%a4%8d%e6%a0%b8%2c%e6%b5%8b%e9%87%8f%e6%8a%80%e6%9c%af%2c%e5%9c%b0%e5%bd%a2%e6%b5%8b%e9%87%8f%2c%e5%ae%89%e5%85%a8%e7%9b%91%e6%b5%8b%2c%e5%9f%ba%e5%87%86%e7%bd%91%e5%a4%8d%e6%b5%8b%2c%e6%b5%8b%e9%87%8f%e4%b8%ad%e5%bf%83%2c%e5%9c%9f%e5%9c%b0%e6%b5%8b%e7%bb%98&time=90&type=1&mod=0&page=2'
      }
      await listBid(queryParams)
      await this.fetchBidcenterSearch()
    },
    handleServerSearch() {
      const t = (this.keywordText || '').trim()
      if (!t) {
        Message.warning('请输入关键词')
        return
      }
      this.keywordText = t
      this.searchQuery.page = 1
      this.storedNextTokenFromApi = ''
      this.pendingNextToken = ''
      this.tableFilter = ''
      if (this.memberSearchActive) {
        this.searchQuery.mod = 1
      }
      this.fetchBidcenterSearch()
    },
    buildSearchPostBody() {
      const token = (this.bidcenterMemberToken || '').trim()
      const isMember = this.memberSearchActive
      const modNum = Number(this.searchQuery.mod)
      const body = {
        from: 6137,
        guid: BIDCENTER_GUID,
        location: 6138,
        token,
        keywords: encodeURIComponent((this.keywordText || '').trim()),
        time: this.searchQuery.time,
        type: this.searchQuery.type,
        mod: isMember ? (modNum >= 1 ? modNum : 1) : this.searchQuery.mod,
        page: this.searchQuery.page
      }
      let nextTok = ''
      if (this.pendingNextToken) {
        nextTok = this.pendingNextToken
      } else if (isMember && this.storedNextTokenFromApi) {
        nextTok = this.storedNextTokenFromApi
      }
      if (nextTok) {
        body.next_token = nextTok
      }
      return body
    },
    async fetchBidcenterSearch() {
      let loadingInstance = null
      try {
        loadingInstance = Loading.service({
          lock: true,
          text: '加载中',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.1)'
        })
      } catch (e) { /* ignore */ }
      this.searchLoading = true
      const postData = this.buildSearchPostBody()
      this.pendingNextToken = ''
      const useCookieMember =
        this.bidcenterCookieMember && !(this.bidcenterMemberToken || '').trim()
      try {
        const res = await axios({
          url: SEARCH_PRO_URL,
          method: 'post',
          timeout: 20000,
          responseType: 'text',
          withCredentials: useCookieMember,
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
          },
          transformRequest: [(data) => serializeSearchParams(data)],
          data: postData
        })
        this.bindSearchData(res.data)
      } catch (e) {
        if (useCookieMember && e && e.message === 'Network Error') {
          Message({
            message:
              '携带采招网 Cookie 的请求被浏览器或 CORS 拦截。请关闭第三方 Cookie 限制，或从采招网搜索页复制 token 后使用「应用 token」。',
            type: 'error',
            duration: 10000
          })
        } else {
          Message({ message: '网络错误，请重试', type: 'error' })
        }
        this.tableData = []
      } finally {
        this.searchLoading = false
        if (loadingInstance) {
          loadingInstance.close()
        }
      }
    },
    /**
     * 对齐 searchv16.js method.bindSearchData：解密后取 data.other2.listData 等
     */
    bindSearchData(resText) {
      this.searchWarning = ''
      const data = this.AESDecrypt(resText)
      if (!data) {
        Message.error('解密失败或响应为空')
        this.tableData = []
        this.emptyText = '解密失败'
        return
      }
      if (Number(data.retbs) === 1) {
        this.searchWarning =
          '您查询的信息中可能含有敏感内容，因政策监管原因，部分信息会做屏蔽处理，如需查询更多详情，请联系客服专员。'
      }
      if (data.ret) {
        if (!data.other2) {
          this.tableData = []
          this.pageTotal = 0
          this.realInfoCount = 0
          return
        }
        const resultData = data.other2
        this.applyPageSearchJson(resultData.pageSearchJson)
        this.storedNextTokenFromApi =
          resultData.next_token != null && resultData.next_token !== ''
            ? String(resultData.next_token)
            : ''
        const list = resultData.listData
        this.tableData = Array.isArray(list) ? list : []
        this.pageTotal = Number(resultData.showInfoCount) || 0
        let total = resultData.realInfoCount
        if (
          resultData.optimize &&
          Array.isArray(resultData.optimize) &&
          resultData.optimize.indexOf('totalcount') > -1
        ) {
          total = `约${resultData.realInfoCount}`
        }
        this.realInfoCount = total != null ? total : this.pageTotal
        this.emptyText = this.tableData.length ? '暂无数据' : '未查询到相关信息'
      } else {
        this.storedNextTokenFromApi = ''
        if (data.msg) {
          Message.warning(data.msg)
        }
        if (data.other2 && data.other2.pageSearchJson) {
          this.applyPageSearchJson(data.other2.pageSearchJson)
        }
        this.tableData = []
        this.emptyText = '未查询到相关信息'
      }
    },
    applyPageSearchJson(pageSearchJson) {
      if (!pageSearchJson) {
        const k = (this.keywordText || '').trim()
        if (k) this.displayKeyword = k
        return
      }
      try {
        const jq = JSON.parse(pageSearchJson)
        if (jq.zbje_min && jq.zbje_min > 0) {
          jq.zbje_min = jq.zbje_min / 10000
        }
        if (jq.zbje_max && jq.zbje_max > 0 && jq.zbje_max < 999999999999) {
          jq.zbje_max = jq.zbje_max / 10000
        } else if (jq) {
          jq.zbje_max = 0
        }
        if (jq.page != null) {
          this.searchQuery.page = jq.page
        }
        if (jq.mod != null && jq.mod !== '') {
          const m = parseInt(jq.mod, 10)
          if (!Number.isNaN(m)) {
            this.searchQuery.mod = m
          }
        }
        if (jq.keywords != null && String(jq.keywords).trim() !== '') {
          this.displayKeyword = String(jq.keywords).trim()
        } else {
          const k = (this.keywordText || '').trim()
          if (k) this.displayKeyword = k
        }
      } catch (e) {
        const k = (this.keywordText || '').trim()
        if (k) this.displayKeyword = k
      }
    },
    /**
     * 匿名：仅第 20→21 页用 pending 带 next_token（与 searchv16 layui-last 一致）。
     * 会员：翻页时在 buildSearchPostBody 中自动带上一响应的 storedNextTokenFromApi；跳页/回退则清空游标。
     */
    handlePageChange(page) {
      const oldPage = this.searchQuery.page
      this.pendingNextToken = ''
      const hasMember = this.memberSearchActive
      if (!hasMember && page === oldPage + 1 && oldPage >= 20 && this.storedNextTokenFromApi) {
        this.pendingNextToken = this.storedNextTokenFromApi
      }
      if (page < oldPage || page > oldPage + 1) {
        this.storedNextTokenFromApi = ''
      }
      this.searchQuery.page = page
      this.fetchBidcenterSearch()
    },
    plainTitle(html) {
      if (html == null || html === '') return '—'
      return String(html).replace(/<[^>]+>/g, '')
    },
    showText(val) {
      if (val == null || val === '' || val === '--') return '—'
      return String(val)
    },
    formatAmount(row) {
      if (row.news_type === 4) return this.showText(row.news_zhongbiaojine_show)
      if (row.is_xiangmu) return this.showText(row.news_gczj_show)
      return this.showText(row.news_zbje_show)
    },
    formatCgfs(row) {
      if (row.is_xiangmu) return this.showText(row.news_jieduan_show)
      return this.showText(row.news_cgfs)
    },
    formatTimeCol(row) {
      const t = row.news_type
      if (t === 4 || t === 6 || row.is_xiangmu) return this.showText(row.news_star_time_show)
      if (t === 2) return this.showText(row.news_end_time_show)
      return this.showText(row.news_end_time_show)
    },
    AESDecrypt(str) {
      if (str == null || str === '') {
        return null
      }
      var nContent = CryptoJS.AES.decrypt(str, bidcenterAes.key, {
        iv: bidcenterAes.iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.ZeroPadding
      })
      if (nContent && nContent != null) {
        try {
          var constr = CryptoJS.enc.Utf8.stringify(nContent)
          if (constr !== '') {
            var data = JSON.parse(constr)
            return data
          }
          return null
        } catch (err) {
          return null
        }
      }
      return null
    }
  }
}
</script>

<style lang="scss" scoped>
.mb8 {
  margin-bottom: 8px;
}

.toolbar-card {
  padding: 16px 16px 8px;
  background: #fff;
  border-radius: 4px;
  border: 1px solid #ebeef5;
}

.keyword-display-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.field-label {
  font-size: 14px;
  color: #606266;
  font-weight: 500;
  flex-shrink: 0;
}

.keyword-tag {
  max-width: 100%;
  white-space: normal;
  height: auto;
  line-height: 1.5;
  padding: 6px 12px;
}

.remote-search-form {
  margin-bottom: 8px;
}

.bidcenter-auth-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px dashed #ebeef5;
}

.token-input {
  width: 200px;
}

.table-filter-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  padding-top: 8px;
  border-top: 1px dashed #ebeef5;
}

.filter-hint {
  font-size: 13px;
  color: #909399;
}

.mt16 {
  margin-top: 16px;
}

.search-summary {
  font-size: 14px;
  color: #606266;
}

.title-link {
  color: #409eff;
  text-decoration: none;

  &:hover {
    text-decoration: underline;
  }
}

.fujian-tag {
  margin-left: 6px;
  font-size: 12px;
  color: #e6a23c;
}
</style>

<!-- append-to-body 时对话框在 body 下，需非 scoped 样式 + custom-class -->
<style lang="scss">
.bidcenter-login-dialog {
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 22px 55px rgba(15, 52, 96, 0.14), 0 0 1px rgba(15, 52, 96, 0.06);

  .el-dialog__header {
    padding: 0;
    margin: 0;
    border: none;
  }

  .el-dialog__headerbtn {
    top: 18px;
    right: 18px;
    font-size: 16px;

    .el-dialog__close {
      color: rgba(255, 255, 255, 0.88);
    }

    &:hover .el-dialog__close,
    &:focus .el-dialog__close {
      color: #fff;
    }
  }

  .el-dialog__body {
    padding: 0 24px 8px;
    background: linear-gradient(180deg, #f7fafc 0%, #fff 48%);
  }

  .el-dialog__footer {
    padding: 12px 24px 20px;
    border-top: 1px solid #eef2f6;
    background: #fff;
  }
}

.bidcenter-login-dialog__title {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 22px 48px 18px 24px;
  background: linear-gradient(135deg, #1a5fb4 0%, #409eff 55%, #66b1ff 100%);
  color: #fff;
}

.bidcenter-login-dialog__brand {
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.18);
  backdrop-filter: blur(6px);
  font-size: 24px;
}

.bidcenter-login-dialog__title-text {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.bidcenter-login-dialog__title-main {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1.3;
}

.bidcenter-login-dialog__title-sub {
  font-size: 12px;
  opacity: 0.92;
  line-height: 1.45;
}

.bidcenter-login-dialog__panel {
  padding-top: 20px;
}

.bidcenter-login-dialog__form {
  .el-form-item {
    margin-bottom: 18px;
  }

  .el-form-item__label {
    padding: 0 0 6px;
    line-height: 1.4;
    color: #606266;
    font-weight: 500;
  }

  .el-input__inner {
    border-radius: 8px;
    height: 40px;
    line-height: 40px;
  }
}

.bidcenter-login-dialog__hint {
  margin: 4px 0 0;
  padding: 10px 12px;
  font-size: 12px;
  line-height: 1.55;
  color: #909399;
  background: #f4f7fb;
  border-radius: 8px;
  border: 1px solid #e8eef5;

  .el-icon-info {
    margin-right: 6px;
    color: #409eff;
  }
}

.bidcenter-login-dialog__footer {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 12px;

  .el-button {
    min-width: 96px;
    border-radius: 8px;
  }

  .el-button--primary {
    box-shadow: 0 4px 12px rgba(64, 158, 255, 0.35);
  }
}
</style>
