1155 lines
25 KiB
Vue
1155 lines
25 KiB
Vue
<template>
|
||
<div class="sjsc-container fwsc-page portal-page-shell portal-market-figma-page">
|
||
<div class="portal-figma-scale-viewport">
|
||
<div class="portal-figma-scale-stage" ref="figmaStage">
|
||
<!-- 二级菜单 -->
|
||
<div class="secondary-nav">
|
||
<div class="secondary-nav-content">
|
||
<div class="nav-tabs">
|
||
<button v-for="tab in navTabs" :key="tab.path" :class="['nav-tab', { active: isActiveTab(tab.path) }]"
|
||
@click="goToTab(tab)">
|
||
{{ tab.label }}
|
||
</button>
|
||
</div>
|
||
<div class="nav-right">
|
||
<span class="list-count">共 {{ page.total }} 条数据</span>
|
||
<button class="publish-btn" @click="handlePublish">免费发布数据</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<main class="sjsc-main">
|
||
<div class="content-area">
|
||
<!-- 左侧卡片列表 -->
|
||
<div class="card-list">
|
||
<!-- 加载状态 -->
|
||
<div v-if="loading" class="loading-state">
|
||
<div class="loading-spinner"></div>
|
||
<p>加载中...</p>
|
||
</div>
|
||
|
||
<div class="service-grid" v-else>
|
||
<div v-for="card in cardList" :key="card.gxUuid" :data-gx-uuid="card.gxUuid" class="service-card">
|
||
<!-- 卡片头部 -->
|
||
<div class="card-header">
|
||
<div class="card-title-box">
|
||
<div class="card-title-text">
|
||
<div class="card-title-row">
|
||
<div class="card-title-main">{{ card.bt1 }}</div>
|
||
<!-- 收藏按钮 -->
|
||
<div class="card-collect" @click="handleCollect(card)">
|
||
<img v-if="card.scbz === 'Y'" src="../../assets/fwsc/ysc.svg" />
|
||
<img v-else src="../../assets/fwsc/wsc.svg" />
|
||
</div>
|
||
</div>
|
||
<div class="card-title-sub">
|
||
<div class="card-company">
|
||
<img src="../../assets/fwsc/city.svg" />
|
||
<span class="company-name">{{ card.qymc }}</span>
|
||
</div>
|
||
<div class="location" v-if="card.fwfw">
|
||
<img src="../../assets/fwsc/map.svg" />
|
||
<span class="company-name">{{ card.fwfw }}</span>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 卡片内容 -->
|
||
<div class="card-content">
|
||
<p class="card-desc">{{ card.fwnr }}</p>
|
||
<div class="card-tags">
|
||
<span v-for="(tag, i) in card.fwlxbqList" :key="i" class="tag">{{ tag }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 卡片底部 -->
|
||
<div class="card-footer">
|
||
<div class="card-price-info">
|
||
<span class="price-value">免费</span>
|
||
</div>
|
||
<div class="card-actions">
|
||
<span @click="handleContact(card)">立即咨询</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 空状态 -->
|
||
<div v-if="cardList.length === 0 && !loading" class="empty-state">
|
||
<p>暂无数据信息</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 右侧筛选栏 -->
|
||
<aside class="filter-sidebar">
|
||
<div class="filter-toggle" @click="filterCollapsed = !filterCollapsed">
|
||
<span class="toggle-text">筛选</span>
|
||
<span class="toggle-icon">{{ filterCollapsed ? '▼' : '▲' }}</span>
|
||
</div>
|
||
<div :class="['filter-sidebar-content', { collapsed: filterCollapsed }]">
|
||
<!-- 内容搜索 -->
|
||
<div class="filter-section">
|
||
<div class="filter-title">内容搜索</div>
|
||
<t-input v-model="filter.nr" placeholder="请输入关键词" @enter="onSearch">
|
||
<template #suffix-icon>
|
||
<SearchIcon />
|
||
</template>
|
||
</t-input>
|
||
</div>
|
||
|
||
<!-- 数据类型 -->
|
||
<div class="filter-section">
|
||
<div class="filter-title">数据类型</div>
|
||
<div class="filter-options">
|
||
<t-checkbox-group v-model="filter.fwlxjh" :options="sjlxOptions" @change="onSearch" />
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 服务地区 -->
|
||
<div class="filter-section">
|
||
<div class="filter-title">服务地区</div>
|
||
<t-select v-model="filter.dq" :options="fwfwOptions" placeholder="请选择" clearable style="width: 100%" @change="onSearch" />
|
||
</div>
|
||
|
||
<!-- 所属行业 -->
|
||
<div class="filter-section">
|
||
<div class="filter-title">所属行业</div>
|
||
<div class="filter-options">
|
||
<t-checkbox-group v-model="filter.sshy" :options="sshyDmOptions" @change="onSearch" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
|
||
<!-- 分页 -->
|
||
<div class="pagination-box" v-if="page.total > 0">
|
||
<div class="pagination-total">共 {{ page.total }} 条数据</div>
|
||
<t-pagination v-model="page.pageNo" :total="page.total" :page-size.sync="page.pageSize" :totalContent='false'
|
||
:page-size-options="[10, 20, 30, 50]" @change="onPageChange" align="center" />
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 发布数据抽屉 -->
|
||
<SjscPublish :visible.sync="publishVisible" @success="onPublishSuccess" />
|
||
|
||
<!-- 联系数据提供方弹窗 -->
|
||
<t-dialog :closeOnOverlayClick="false" header="联系数据提供方" :visible.sync="contactVisible" @confirm="onContactConfirm"
|
||
:onClose="onContactClose" class="global-dialog" attach="body">
|
||
<div class="dialog-line">
|
||
<div class="dialog-line-title">联系人:</div>
|
||
<div class="dialog-line-text">{{ contactData.lxr }}</div>
|
||
</div>
|
||
<div class="dialog-line">
|
||
<div class="dialog-line-title">联系电话:</div>
|
||
<div class="dialog-line-text">{{ contactData.lxdh }}</div>
|
||
</div>
|
||
<div class="dialog-line">
|
||
<div class="dialog-line-title">电子邮箱:</div>
|
||
<div class="dialog-line-text">{{ contactData.email }}</div>
|
||
</div>
|
||
</t-dialog>
|
||
|
||
<!-- 提示弹窗 -->
|
||
<t-dialog :closeOnOverlayClick="false" header="提示" body="请先进行企业入驻" :visible.sync="rzVisible" @confirm="onRzConfirm"
|
||
:onClose="onRzClose" :cancelBtn="null" class="global-dialog" />
|
||
|
||
<!-- 发布成功弹窗 -->
|
||
<t-dialog :closeOnOverlayClick="false" body="发布申请成功,请等待审核,是否继续发布?" :visible.sync="publishSuccessVisible"
|
||
@confirm="onPublishSuccessConfirm" @cancel="onPublishSuccessCancel" :onClose="onPublishSuccessClose"
|
||
cancelBtn="返回" confirmBtn="继续发布" class="global-dialog" />
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { LocationIcon, SearchIcon } from 'tdesign-icons-vue';
|
||
import NewNav from '@/pages/index/components/new-nav/index.vue';
|
||
import BreadcrumbNav from '@/pages/index/components/breadcrumb/index.vue';
|
||
import SjscPublish from './components/SjscPublish.vue';
|
||
import gxzxApi from '@/pages/index/api/gxzx/index.js';
|
||
import { hasLogin } from '@/pages/index/api/login';
|
||
import { scrollPortalContentToTop } from '@/pages/index/utils/portal-scroll-mode';
|
||
import portalFigmaScaleMixin from '@/pages/index/utils/portal-figma-scale-mixin';
|
||
import comingSoonMixin from '@/pages/index/utils/coming-soon-mixin';
|
||
|
||
export default {
|
||
name: 'SjscPage',
|
||
mixins: [portalFigmaScaleMixin, comingSoonMixin],
|
||
components: {
|
||
NewNav,
|
||
BreadcrumbNav,
|
||
SjscPublish,
|
||
LocationIcon,
|
||
SearchIcon,
|
||
},
|
||
data() {
|
||
return {
|
||
navTabs: [
|
||
{ label: '碳服务市场', path: '/tfwsc' },
|
||
{ label: '碳需求市场', path: '/txqsc' },
|
||
{ label: '碳数据市场', path: '/tsjsc' },
|
||
{ label: '碳金融市场', path: '/tjrsc', disable: true },
|
||
],
|
||
// 筛选条件
|
||
filter: {
|
||
fwlxjh: [],
|
||
sshy: [],
|
||
dq: '',
|
||
nr: '',
|
||
},
|
||
// 数据类型(前端硬编码,与 SjscPublish 保持一致)
|
||
sjlxOptions: [
|
||
{ value: 'public', label: '公共数据' },
|
||
{ value: 'factor', label: '因子库' },
|
||
{ value: 'social', label: '社会性数据' },
|
||
],
|
||
// 代码表选项
|
||
sshyDmOptions: [],
|
||
fwfwOptions: [],
|
||
// 卡片列表
|
||
cardList: [],
|
||
// 分页
|
||
page: {
|
||
pageNo: 1,
|
||
pageSize: 10,
|
||
total: 0,
|
||
},
|
||
// 加载状态
|
||
loading: false,
|
||
// 发布抽屉
|
||
publishVisible: false,
|
||
// 联系弹窗
|
||
contactVisible: false,
|
||
contactData: {},
|
||
// 入驻提示弹窗
|
||
rzVisible: false,
|
||
// 发布成功弹窗
|
||
publishSuccessVisible: false,
|
||
// 移动端筛选折叠状态
|
||
filterCollapsed: true,
|
||
};
|
||
},
|
||
mounted() {
|
||
this.loadDmList();
|
||
this.searchList();
|
||
// 检查是否需要直接打开发布面板
|
||
if (this.$route.query.publish === '1') {
|
||
this.handlePublish();
|
||
}
|
||
},
|
||
methods: {
|
||
// 加载代码表
|
||
loadDmList() {
|
||
this.sshyoptionsSearch();
|
||
this.fwfwoptionsSearch();
|
||
},
|
||
async sshyoptionsSearch() {
|
||
try {
|
||
const res = await gxzxApi.dms2mc('sshy', {});
|
||
this.sshyDmOptions = res.data || [];
|
||
} catch (error) {
|
||
this.sshyDmOptions = [];
|
||
}
|
||
},
|
||
async fwfwoptionsSearch() {
|
||
try {
|
||
const res = await gxzxApi.dms2mc('xzqh', {});
|
||
this.fwfwOptions = res.data || [];
|
||
} catch (error) {
|
||
this.fwfwOptions = [];
|
||
}
|
||
},
|
||
// 搜索列表
|
||
async searchList() {
|
||
this.loading = true;
|
||
this.cardList = [];
|
||
const targetId = this.$route.query.id || '';
|
||
try {
|
||
const prame = {
|
||
pageNo: this.page.pageNo,
|
||
pageSize: this.page.pageSize,
|
||
sjlxDm: this.filter.fwlxjh.length ? this.filter.fwlxjh.join(',') : '',
|
||
dq: this.filter.dq || '',
|
||
sshy: this.filter.sshy.length ? this.filter.sshy.join(',') : '',
|
||
nr: this.filter.nr || '',
|
||
};
|
||
// URL携带id:按id精确查询单条
|
||
if (targetId) {
|
||
prame.uuid = targetId;
|
||
}
|
||
const { data } = await gxzxApi.sjscList(prame);
|
||
const records = (data && data.records) || [];
|
||
records.map((item) => {
|
||
this.cardList.push({
|
||
id: item.uuid,
|
||
bt1: item.sjmc,
|
||
qymc: item.qymc || '',
|
||
fwnr: item.sjms,
|
||
fwfw: item.fwfw || '',
|
||
fwlxbqList: item.sjlxMc ? [item.sjlxMc] : [],
|
||
scbz: item.scbz || 'N',
|
||
lxr: item.lxr || '',
|
||
lxdh: item.lxdh || '',
|
||
email: item.email || '',
|
||
gxUuid: item.uuid,
|
||
});
|
||
});
|
||
this.page.total = Number((data && data.total) || 0);
|
||
// 数据渲染后定位到对应项
|
||
if (targetId) {
|
||
this.scrollToItem(targetId);
|
||
}
|
||
} catch (error) {
|
||
this.cardList = [];
|
||
this.page.total = 0;
|
||
console.error('获取数据列表失败', error);
|
||
} finally {
|
||
this.loading = false;
|
||
}
|
||
},
|
||
// 重置筛选
|
||
onReset() {
|
||
this.filter = {
|
||
fwlxjh: [],
|
||
sshy: [],
|
||
dq: '',
|
||
nr: '',
|
||
};
|
||
this.page.pageNo = 1;
|
||
this.searchList();
|
||
},
|
||
// 搜索
|
||
onSearch() {
|
||
this.page.pageNo = 1;
|
||
this.searchList();
|
||
},
|
||
onPageChange(pageInfo) {
|
||
this.page.pageNo = pageInfo.current;
|
||
this.page.pageSize = pageInfo.pageSize;
|
||
scrollPortalContentToTop();
|
||
this.searchList();
|
||
},
|
||
// 滚动到指定项并高亮
|
||
scrollToItem(gxUuid) {
|
||
this.$nextTick(() => {
|
||
const cardElement = document.querySelector(`[data-gx-uuid="${gxUuid}"]`);
|
||
if (cardElement) {
|
||
cardElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||
cardElement.classList.add('highlight-card');
|
||
setTimeout(() => {
|
||
cardElement.classList.remove('highlight-card');
|
||
}, 3000);
|
||
}
|
||
});
|
||
},
|
||
// 处理发布
|
||
handlePublish() {
|
||
const yhxx = window.sessionStorage.getItem('yhxx');
|
||
if (yhxx) {
|
||
const yhxxData = JSON.parse(yhxx);
|
||
if (yhxxData.gxdtRzbz === 'Y') {
|
||
this.publishVisible = true;
|
||
} else {
|
||
this.rzVisible = true;
|
||
}
|
||
} else {
|
||
this.rzVisible = true;
|
||
}
|
||
},
|
||
// 收藏/取消收藏
|
||
async handleCollect(card) {
|
||
try {
|
||
const type = card.scbz === 'Y' ? 'remove' : 'add';
|
||
await gxzxApi.gxsc({ gxUuid: card.gxUuid, type });
|
||
card.scbz = card.scbz === 'Y' ? 'N' : 'Y';
|
||
} catch (error) {
|
||
console.error('收藏失败', error);
|
||
}
|
||
},
|
||
// 联系数据提供方
|
||
handleContact(card) {
|
||
this.contactData = {
|
||
lxr: card.lxr || '',
|
||
lxdh: card.lxdh || '',
|
||
email: card.email || '',
|
||
};
|
||
this.contactVisible = true;
|
||
},
|
||
// 发布成功回调
|
||
onPublishSuccess() {
|
||
this.publishSuccessVisible = true;
|
||
},
|
||
// 导航相关
|
||
isActiveTab(path) {
|
||
return this.$route.path === path;
|
||
},
|
||
goToTab({ path, disable }) {
|
||
if (disable) {
|
||
this.showComingSoon();
|
||
return;
|
||
}
|
||
this.$router.push(path);
|
||
},
|
||
// 弹窗回调
|
||
onContactConfirm() {
|
||
this.contactVisible = false;
|
||
},
|
||
onContactClose() {
|
||
this.contactVisible = false;
|
||
},
|
||
onRzConfirm() {
|
||
this.rzVisible = false;
|
||
},
|
||
onRzClose() {
|
||
this.rzVisible = false;
|
||
},
|
||
onPublishSuccessConfirm() {
|
||
this.publishSuccessVisible = false;
|
||
this.publishVisible = true;
|
||
},
|
||
onPublishSuccessCancel() {
|
||
this.publishSuccessVisible = false;
|
||
this.$router.push('/tsjsc');
|
||
},
|
||
onPublishSuccessClose() {
|
||
this.publishSuccessVisible = false;
|
||
},
|
||
},
|
||
};
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
@import '../../styles/home-figma-variables.less';
|
||
|
||
.sjsc-container {
|
||
background: #F6F7FA;
|
||
.portal-figma-scale-page();
|
||
}
|
||
|
||
.sjsc-main {
|
||
width: 100%;
|
||
max-width: 1400px;
|
||
padding: 20px;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
// 二级菜单
|
||
.secondary-nav {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.secondary-nav-content {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
max-width: 1400px;
|
||
padding: 20px 20px 0;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.nav-tabs {
|
||
display: flex;
|
||
gap: 40px;
|
||
width: 596px;
|
||
height: 42px;
|
||
}
|
||
|
||
.nav-right {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20px;
|
||
}
|
||
|
||
.nav-tab {
|
||
position: relative;
|
||
min-width: max-content;
|
||
height: 42px;
|
||
padding: 8px 16px;
|
||
font-size: 18px;
|
||
font-weight: 500;
|
||
color: #003B1A;
|
||
cursor: pointer;
|
||
background: transparent;
|
||
border-radius: 32px;
|
||
transition: all 0.3s;
|
||
|
||
&:hover {
|
||
color: #009a29;
|
||
}
|
||
|
||
&.active {
|
||
background: #8CFFCE;
|
||
box-shadow: inset 0 0 0 1px #00B96B;
|
||
}
|
||
}
|
||
|
||
.publish-btn {
|
||
width: 220px;
|
||
height: 42px;
|
||
line-height: 26px;
|
||
padding: 8px 16px;
|
||
font-size: 18px;
|
||
font-weight: 400;
|
||
color: #fff;
|
||
cursor: pointer;
|
||
background: linear-gradient(135deg, #009a29 0%, #48C666 100%);
|
||
border: none;
|
||
border-radius: 6px;
|
||
box-shadow: 0 4px 12px rgba(0, 154, 41, 0.25);
|
||
transition: all 0.3s ease;
|
||
|
||
&:hover {
|
||
transform: translateY(-2px);
|
||
box-shadow: 0 6px 16px rgba(0, 154, 41, 0.35);
|
||
}
|
||
|
||
&:active {
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
.content-area {
|
||
display: flex;
|
||
gap: 20px;
|
||
align-items: stretch;
|
||
}
|
||
|
||
// 左侧筛选栏
|
||
.filter-sidebar {
|
||
position: sticky;
|
||
top: 104px;
|
||
width: 220px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
// 移动端筛选栏折叠
|
||
.filter-toggle {
|
||
display: none;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.filter-toggle {
|
||
display: flex;
|
||
padding: 12px;
|
||
margin-bottom: 8px;
|
||
cursor: pointer;
|
||
background: #fff;
|
||
border-radius: 8px;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.toggle-text {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
.toggle-icon {
|
||
font-size: 18px;
|
||
color: #666;
|
||
transition: transform 0.3s;
|
||
}
|
||
|
||
&.collapsed .toggle-icon {
|
||
transform: rotate(-90deg);
|
||
}
|
||
}
|
||
|
||
.filter-sidebar-content {
|
||
max-height: 1000px;
|
||
padding: 20px;
|
||
overflow: hidden;
|
||
transition: max-height 0.3s ease, padding 0.3s ease;
|
||
}
|
||
|
||
.filter-sidebar-content.collapsed {
|
||
max-height: 0;
|
||
padding-top: 0;
|
||
padding-bottom: 0;
|
||
}
|
||
}
|
||
|
||
.filter-sidebar-content {
|
||
padding: 20px;
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||
}
|
||
|
||
.filter-section {
|
||
// padding-bottom: 20px;
|
||
margin-bottom: 20px;
|
||
border-bottom: 1px dashed #e0e0e0;
|
||
|
||
&:last-child {
|
||
padding: 10px 0;
|
||
margin-bottom: 0;
|
||
border-bottom: none;
|
||
}
|
||
}
|
||
|
||
.filter-title {
|
||
display: flex;
|
||
margin-bottom: 12px;
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: #333;
|
||
align-items: center;
|
||
gap: 6px;
|
||
|
||
&::before {
|
||
width: 4px;
|
||
height: 14px;
|
||
background: linear-gradient(180deg, #009a29, #48C666);
|
||
border-radius: 2px;
|
||
content: '';
|
||
}
|
||
}
|
||
|
||
.filter-options {
|
||
/deep/.t-checkbox__label {
|
||
font-size: 14px;
|
||
color: #666;
|
||
}
|
||
|
||
&.enterprise-options {
|
||
max-height: 200px;
|
||
overflow-y: auto;
|
||
}
|
||
}
|
||
|
||
// 右侧卡片列表
|
||
.card-list {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.list-count {
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
color: #6B8575;
|
||
}
|
||
|
||
// 服务卡片网格
|
||
.service-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 24px;
|
||
}
|
||
|
||
.service-card {
|
||
position: relative;
|
||
display: flex;
|
||
flex-direction: column;
|
||
overflow: hidden;
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||
transition: all 0.3s ease;
|
||
|
||
&.highlight-card {
|
||
animation: highlight-pulse 3s ease-out;
|
||
}
|
||
}
|
||
|
||
.card-header {
|
||
position: relative;
|
||
padding: 16px;
|
||
height: 70px;
|
||
|
||
&::after {
|
||
position: absolute;
|
||
right: 16px;
|
||
bottom: -6px;
|
||
left: 16px;
|
||
height: 1px;
|
||
background: #E8F0EC;
|
||
content: '';
|
||
}
|
||
}
|
||
|
||
.card-title-box {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.card-title-text {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.card-title-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.card-title-main {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
line-height: 24px;
|
||
color: #003B1A;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.card-title-sub {
|
||
display: flex;
|
||
gap: 12px;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.card-company {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.card-collect {
|
||
display: flex;
|
||
width: 20px;
|
||
height: 20px;
|
||
cursor: pointer;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
img {
|
||
width: 18px;
|
||
height: 18px;
|
||
}
|
||
}
|
||
|
||
.location {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.company-name {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
font-size: 14px;
|
||
color: #6B8575;
|
||
font-weight: 400;
|
||
}
|
||
|
||
.card-content {
|
||
padding: 16px;
|
||
}
|
||
|
||
.card-tags {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
}
|
||
|
||
.tag {
|
||
padding: 2px 8px;
|
||
font-size: 13px;
|
||
font-weight: 400;
|
||
color: #00B96B;
|
||
background: #EEFAE2;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.card-desc {
|
||
display: block;
|
||
height: 70px;
|
||
overflow: hidden;
|
||
font-size: 14px;
|
||
line-height: 1.6;
|
||
color: #666;
|
||
text-overflow: ellipsis;
|
||
-webkit-line-clamp: 3;
|
||
}
|
||
|
||
.card-footer {
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 14px 16px;
|
||
height: 64px;
|
||
|
||
&::before {
|
||
position: absolute;
|
||
top: 0;
|
||
right: 16px;
|
||
left: 16px;
|
||
height: 1px;
|
||
background: #E8F0EC;
|
||
content: '';
|
||
}
|
||
}
|
||
|
||
.card-price-info {
|
||
display: flex;
|
||
align-items: baseline;
|
||
}
|
||
|
||
.price-value {
|
||
font-size: 20px;
|
||
font-weight: 600;
|
||
color: #2e7d32;
|
||
}
|
||
|
||
.card-actions {
|
||
display: flex;
|
||
height: 32px;
|
||
padding: 6px 12px;
|
||
border-radius: 4px;
|
||
border: 1px solid #00b96b;
|
||
color: #00b96b;
|
||
font-size: 14px;
|
||
font-weight: 400;
|
||
|
||
&:hover {
|
||
background: rgba(0, 154, 41, 0.1);
|
||
cursor: pointer;
|
||
}
|
||
}
|
||
|
||
// 空状态
|
||
.empty-state {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 100%;
|
||
min-height: 300px;
|
||
padding: 40px;
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
animation: fadeIn 0.5s ease;
|
||
|
||
.empty-icon {
|
||
margin-bottom: 16px;
|
||
font-size: 48px;
|
||
color: #d0d0d0;
|
||
}
|
||
|
||
p {
|
||
font-size: 14px;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
// 加载状态
|
||
.loading-state {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-height: 400px;
|
||
padding: 40px;
|
||
background: #fff;
|
||
border-radius: 12px;
|
||
|
||
.loading-spinner {
|
||
width: 48px;
|
||
height: 48px;
|
||
margin-bottom: 16px;
|
||
border: 4px solid #e8f5e9;
|
||
border-top-color: #009a29;
|
||
border-radius: 50%;
|
||
animation: spin 1s linear infinite;
|
||
}
|
||
|
||
p {
|
||
margin: 0;
|
||
font-size: 14px;
|
||
color: #999;
|
||
}
|
||
}
|
||
|
||
@keyframes spin {
|
||
to {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(10px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
@keyframes highlight-pulse {
|
||
0% {
|
||
box-shadow: 0 0 0 0 rgba(0, 154, 41, 0.4);
|
||
}
|
||
50% {
|
||
box-shadow: 0 0 20px 10px rgba(0, 154, 41, 0.2);
|
||
}
|
||
100% {
|
||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||
}
|
||
}
|
||
|
||
// 分页
|
||
.pagination-total {
|
||
font-size: 16px;
|
||
color: #666;
|
||
}
|
||
|
||
.pagination-box {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding-top: 32px;
|
||
gap: 16px;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
|
||
::v-deep .t-pagination {
|
||
display: flex !important;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: auto;
|
||
max-width: 100%;
|
||
gap: 12px 16px;
|
||
|
||
.t-input.t-is-readonly {
|
||
width: 110px;
|
||
}
|
||
|
||
.t-pagination__select {
|
||
margin-right: 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 弹窗样式
|
||
.dialog-line {
|
||
display: flex;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.dialog-line-title {
|
||
flex-shrink: 0;
|
||
width: 80px;
|
||
color: #333;
|
||
}
|
||
|
||
.dialog-line-text {
|
||
color: #666;
|
||
}
|
||
|
||
@media (max-width: 1200px) {
|
||
.service-card {
|
||
width: calc((100% - 20px) / 2);
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.sjsc-container {
|
||
overflow-x: hidden;
|
||
}
|
||
|
||
.sjsc-main {
|
||
padding: 12px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.secondary-nav-content {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
padding: 12px 16px;
|
||
gap: 12px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.nav-tabs {
|
||
display: flex;
|
||
flex-wrap: nowrap;
|
||
align-items: center;
|
||
width: 100%;
|
||
max-width: 100%;
|
||
height: auto;
|
||
min-height: 42px;
|
||
padding-bottom: 4px;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;
|
||
gap: 8px;
|
||
scrollbar-width: none;
|
||
-webkit-overflow-scrolling: touch;
|
||
|
||
&::-webkit-scrollbar {
|
||
display: none;
|
||
width: 0;
|
||
height: 0;
|
||
}
|
||
}
|
||
|
||
.nav-tab {
|
||
flex-shrink: 0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
height: auto;
|
||
min-height: 40px;
|
||
padding: 10px 12px;
|
||
font-size: 13px;
|
||
line-height: 1.2;
|
||
white-space: nowrap;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.nav-right {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
gap: 8px;
|
||
width: 100%;
|
||
}
|
||
|
||
.list-count {
|
||
width: 100%;
|
||
font-size: 14px;
|
||
line-height: 22px;
|
||
text-align: center;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.publish-btn {
|
||
width: 100%;
|
||
height: auto;
|
||
min-height: 44px;
|
||
padding: 10px 16px;
|
||
font-size: 15px;
|
||
line-height: 1.3;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.content-area {
|
||
flex-direction: column;
|
||
gap: 12px;
|
||
}
|
||
|
||
.filter-sidebar {
|
||
position: relative;
|
||
top: 0;
|
||
order: -1;
|
||
width: 100%;
|
||
}
|
||
|
||
.card-list {
|
||
order: 0;
|
||
width: 100%;
|
||
}
|
||
|
||
.service-grid {
|
||
grid-template-columns: 1fr;
|
||
gap: 12px;
|
||
}
|
||
|
||
.service-card {
|
||
width: 100%;
|
||
max-width: 100%;
|
||
}
|
||
|
||
.card-header {
|
||
height: auto;
|
||
min-height: 0;
|
||
padding: 12px 12px 14px;
|
||
}
|
||
|
||
.card-title-sub {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: 6px;
|
||
}
|
||
|
||
.card-content {
|
||
padding: 12px;
|
||
}
|
||
|
||
.card-desc {
|
||
height: auto;
|
||
min-height: 0;
|
||
max-height: none;
|
||
}
|
||
|
||
.card-footer {
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
height: auto;
|
||
min-height: 0;
|
||
padding: 12px;
|
||
gap: 12px;
|
||
}
|
||
|
||
.card-price-info {
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.card-actions {
|
||
flex-shrink: 0;
|
||
width: auto;
|
||
min-width: 96px;
|
||
height: 40px;
|
||
padding: 8px 14px;
|
||
box-sizing: border-box;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 480px) {
|
||
.sjsc-main {
|
||
padding: 8px;
|
||
}
|
||
|
||
.secondary-nav-content {
|
||
padding: 8px 12px;
|
||
}
|
||
|
||
.nav-tab {
|
||
padding: 8px 10px;
|
||
font-size: 12px;
|
||
}
|
||
|
||
.publish-btn {
|
||
padding: 8px;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.filter-sidebar-content {
|
||
padding: 12px;
|
||
}
|
||
|
||
.filter-title {
|
||
font-size: 13px;
|
||
}
|
||
|
||
.card-title-main {
|
||
font-size: 14px;
|
||
}
|
||
|
||
.card-desc {
|
||
font-size: 13px;
|
||
}
|
||
|
||
.price-value {
|
||
font-size: 18px;
|
||
}
|
||
}
|
||
</style>
|