|
@@ -0,0 +1,1093 @@
|
|
|
+<template>
|
|
|
+ <div class="content">
|
|
|
+ <a-card :bordered="false" :body-style="{padding:0}">
|
|
|
+ <div class="step1" v-if="flag">
|
|
|
+ <a-divider>SEO月报生成及下载</a-divider>
|
|
|
+ <a-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="formState"
|
|
|
+ :rules="rules"
|
|
|
+ :label-col="labelCol"
|
|
|
+ :wrapper-col="wrapperCol"
|
|
|
+ style="width: 80%"
|
|
|
+ >
|
|
|
+ <a-button type="primary" @click="handleEdit" preIcon="ant-design:edit-outlined"
|
|
|
+ class="btn3">修改话术
|
|
|
+ </a-button>
|
|
|
+ <SeoPdfExportModal @register="registerModal" @success="handleSuccess"></SeoPdfExportModal>
|
|
|
+ <a-form-item label="站点名称" name="siteName">
|
|
|
+ <a-select
|
|
|
+ label-in-value
|
|
|
+ v-model:value="formState.siteName"
|
|
|
+ placeholder="请选择站点"
|
|
|
+ showSearch
|
|
|
+ style="width: 100%"
|
|
|
+ :options="siteOptions"
|
|
|
+ :filter-option="filterOption"
|
|
|
+ @change="handleChange"
|
|
|
+ :field-names="{ label: 'name', value: 'code' }"
|
|
|
+ ></a-select>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="客户名称" name="customerName">
|
|
|
+ <a-input placeholder="请输入客户名称" v-model:value="formState.customerName"
|
|
|
+ allowClear></a-input>
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item label="查询时间" name="range">
|
|
|
+ <a-date-picker v-model:value="formState.range"
|
|
|
+ :disabled-date="disabledDate"
|
|
|
+ placeholder="请选择月份"
|
|
|
+ style="width: 100%;"
|
|
|
+ format="YYYY-MM"
|
|
|
+ picker="month" />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item style="text-align: center" :wrapper-col="{ span: 20, offset: 4 }">
|
|
|
+ <a-button @click="onSubmit" type="primary" preIcon="ant-design:search-outlined">查询
|
|
|
+ </a-button>
|
|
|
+ <a-button @click="resetForm" type="default" preIcon="ant-design:reload-outlined"
|
|
|
+ style="margin-left: 8px">
|
|
|
+ 重置
|
|
|
+ </a-button>
|
|
|
+ </a-form-item>
|
|
|
+ </a-form>
|
|
|
+ </div>
|
|
|
+ <div class="step2" v-if="!flag">
|
|
|
+ <a-spin :spinning="infoLoading">
|
|
|
+ <section class="top">
|
|
|
+ <h1>{{ formState.customerName }} - SEO月度报告
|
|
|
+ <a-button type="default" @click="handleEdit" preIcon="ant-design:edit-outlined"
|
|
|
+ class="btn6">修改话术
|
|
|
+ </a-button>
|
|
|
+ <a-button type="primary" preIcon="ant-design:file-pdf" @click="exportPDF"
|
|
|
+ class="btn1">导出pdf
|
|
|
+ </a-button>
|
|
|
+ <a-button type="default" preIcon="ant-design:reload" @click="goBack" class="btn2">
|
|
|
+ 返回
|
|
|
+ </a-button>
|
|
|
+ </h1>
|
|
|
+ <p style='margin-top: 15px'>
|
|
|
+ 生成周期:{{ moment(formState.range.format("YYYY-MM")).startOf("month").format("YYYY-MM-DD")
|
|
|
+ }}至{{ moment(formState.range.format("YYYY-MM")).endOf("month").format("YYYY-MM-DD")
|
|
|
+ }}</p>
|
|
|
+ </section>
|
|
|
+ <section class="s1">
|
|
|
+ <p class="p1" style="font-size: 15px;margin-top: 15px">
|
|
|
+ 尊敬的【{{ formState.siteName.label
|
|
|
+ }}】:</p>
|
|
|
+ <p class="p1" style="text-indent: 28px">
|
|
|
+ 我非常高兴向您呈上{{ moment(formState.range).format("YYYY-MM")
|
|
|
+ }}月的SEO月报,为您提供网站在SEO中的详尽数据和分析。作为您的SEO团队,一直努力追求卓越的结果,以确保您的在线业务能够获得更大的曝光度和持续增长.</p>
|
|
|
+ <p class="p1" style="text-indent: 28px">
|
|
|
+ 在过去的一个月里,我们积极地致力于提升您的网站的可见性和排名,并进行了一系列优化策略的实施。具体细节请参考以下报告细节。</p>
|
|
|
+ <h2 class="title mb">当月优化总结<span class="red">*</span></h2>
|
|
|
+ <p class="tips" style="margin: -10px 0 10px;">
|
|
|
+ 在过去的1个月里,我们致力于为您的网站进行全面的SEO优化工作。通过对关键词排名、网站结构、内容优化以及用户体验等方面的深入分析和优化,以下是我们的SEO优化总结:</p>
|
|
|
+ <div class="num-suffix">
|
|
|
+ <a-textarea :style="detailInfo.thisMonth.length > 1000 ? 'border-color:red':''"
|
|
|
+ auto-size placeholder="请输入"
|
|
|
+ v-model:value="detailInfo.thisMonth"></a-textarea>
|
|
|
+ <span :style="detailInfo.thisMonth.length > 1000 ? 'color:red':''"
|
|
|
+ class="suffix-self">
|
|
|
+ {{ detailInfo.thisMonth.length }}/1000
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <h2 class="title mb">下月优化计划<span class="red">*</span></h2>
|
|
|
+ <p class="tips" style="margin: -10px 0 10px;">
|
|
|
+ 感谢您对我们的SEO优化工作的信任。在下个月,我们计划继续改进和优化您的网站,以进一步提升其在搜索引擎中的表现。以下是我们的下月优化计划:</p>
|
|
|
+ <div class="num-suffix">
|
|
|
+ <a-textarea :style="detailInfo.nextMonth.length > 1000 ? 'border-color:red':''"
|
|
|
+ auto-size placeholder="请输入"
|
|
|
+ v-model:value="detailInfo.nextMonth"></a-textarea>
|
|
|
+ <span :style="detailInfo.nextMonth.length > 1000 ? 'color:red':''"
|
|
|
+ class="suffix-self">
|
|
|
+ {{ detailInfo.nextMonth.length }}/1000
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <p class="tips" style="margin: 10px 0 10px;">
|
|
|
+ 我们将按照以上优化计划,不断努力提升您的网站在搜索引擎中的表现。如果您有任何疑问或需要进一步讨论,请随时与我们联系。感谢您的合作,我们期待着实现更大的SEO成功!</p>
|
|
|
+ </section>
|
|
|
+ <section class="s2">
|
|
|
+ <h2 class="title mb">网站流量</h2>
|
|
|
+ <p class="tips" style="margin: -5px 0 5px;">
|
|
|
+ 在本月的SEO月报中,我们会向您展示关于网站流量数据及其他相关的数据,如页面浏览量、跳出率、平均访问时长等,以帮助您更全面地了解网站流量情况和用户行为。这些数据将以图表、表格或其他可视化方式呈现,以便您更直观地理解和分析。</p>
|
|
|
+ <p class="tips">以下是一些关键的流量指标和相应的数据展示:</p>
|
|
|
+ <a-row class="r5-1">
|
|
|
+ <a-col :span="24">
|
|
|
+ <div class="fr" v-if="coreDataChart.x.length > 0">
|
|
|
+ <span><i style="background: #544BEB;"></i>访客数(UV)</span>
|
|
|
+ <span><i style="background: #F0B358;"></i>浏览量(PV)</span>
|
|
|
+ <span><i style="background: #58CCA8;"></i>询盘数</span>
|
|
|
+ </div>
|
|
|
+ <area-chart v-if="coreDataChart.x.length > 0"
|
|
|
+ :dataSource="coreDataChart"></area-chart>
|
|
|
+ <a-empty v-else style="float: right;width: 100%;margin-top: 110px;"></a-empty>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="24">
|
|
|
+ <div class="item">
|
|
|
+ <p><img src="@/assets/pdfExport/uvicon.svg" />访客数(UV)</p>
|
|
|
+ <p>{{ statistics.averageVisit }}</p>
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <p><img src="@/assets/pdfExport/pvicon.svg" />浏览量(PV)</p>
|
|
|
+ <p>{{ 0 }}</p>
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <p><img src="@/assets/pdfExport/unReadEnquiryNum.svg" />日均访问量</p>
|
|
|
+ <p>{{ statistics.averageVisit }}</p>
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <p><img src="@/assets/pdfExport/keywordsrank3.svg" />平均访问时长</p>
|
|
|
+ <p>{{ statistics.averageVisitDuration }}</p>
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <p><img src="@/assets/pdfExport/conversionRate.svg" />平均访问页面数</p>
|
|
|
+ <p>{{ statistics.averageVisitPage }}</p>
|
|
|
+ </div>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <h2 class="title mb">最多访问TOP10</h2>
|
|
|
+ <a-row>
|
|
|
+ <a-col :span="24">
|
|
|
+ <a-table
|
|
|
+ :columns="mostAccessColumns"
|
|
|
+ :data-source="mostAccessDatasource"
|
|
|
+ size="middle"
|
|
|
+ :pagination="false">
|
|
|
+ <template #bodyCell="{ column, text }">
|
|
|
+ <template v-if="column.key ==='pagePathSlot' ">
|
|
|
+ <a-popover>
|
|
|
+ <template slot="content">
|
|
|
+ {{ text }}
|
|
|
+ </template>
|
|
|
+ <a :href="text" target="_blank">
|
|
|
+ <div
|
|
|
+ style="width: 700px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis">
|
|
|
+ {{ text }}
|
|
|
+ </div>
|
|
|
+ </a>
|
|
|
+ </a-popover>
|
|
|
+ </template>
|
|
|
+ <template v-if="column.key ==='centerSlot' ">
|
|
|
+ <span style="margin-left: 20px;">{{ text }}</span>
|
|
|
+ </template>
|
|
|
+ <template v-if="column.key ==='avgTimeOnPageSlot' ">
|
|
|
+ <span style="margin-left: 30px;">{{ text }} s</span>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </a-table>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ </section>
|
|
|
+ <section class="s3">
|
|
|
+ <h2 class="title mb">网站排名</h2>
|
|
|
+ <p class="tips" style="margin: -5px 0 5px;">
|
|
|
+ 在本月的SEO月报中,我们向您展示关于您网站排名的部分数据。因关键词排名数据量较大且实时变化,这边仅展示前50个关键词排名细节,您可登录后台查看全部数据。以下是一些的排名指标和相应的数据展示:</p>
|
|
|
+ <a-row
|
|
|
+ v-if="appointKeywordNum == null && longTailKeywordNum == null">
|
|
|
+ <a-col>
|
|
|
+ <a-empty style="padding-top: 50px" />
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-row type="flex">
|
|
|
+ <a-col :span="3" v-if="appointKeywordNum">
|
|
|
+ <div class="item">
|
|
|
+ <img src="@/assets/pdfExport/zhidingci.svg" />
|
|
|
+ <p>指定词</p>
|
|
|
+ <p>{{ appointKeywordNum }}</p>
|
|
|
+ </div>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="longTailKeywordNum ? 9 : 21"
|
|
|
+ v-if="appointKeywordNum">
|
|
|
+ <div class="wrap">
|
|
|
+ <p class="t1">指定词排名</p>
|
|
|
+ <div class="content">
|
|
|
+ <div class="d1"><img src="@/assets/pdfExport/NO1.svg" />1-10位</div>
|
|
|
+ <div class="d2">{{ rankInfo.appointKeyword.firstNum }}个
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div class="d1"><img src="@/assets/pdfExport/NO2.svg" />11-30位</div>
|
|
|
+ <div class="d2">{{ rankInfo.appointKeyword.secondNum }}个
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div class="d1"><img src="@/assets/pdfExport/NO3.svg" />31-100位</div>
|
|
|
+ <div class="d2">{{ rankInfo.appointKeyword.thirdType }}个
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="3" v-if="longTailKeywordNum">
|
|
|
+ <div class="item">
|
|
|
+ <img src="@/assets/pdfExport/changweici.svg" />
|
|
|
+ <p>关键词</p>
|
|
|
+ <p>{{ longTailKeywordNum }}</p>
|
|
|
+ </div>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="appointKeywordNum ? 9 : 21" v-if="rankInfo.longTailKeyword">
|
|
|
+ <div class="wrap">
|
|
|
+ <p class="t1">关键词排名</p>
|
|
|
+ <div class="content">
|
|
|
+ <div class="d1"><img src="../../../assets/seo/NO1.svg" />1-10位</div>
|
|
|
+ <div class="d2">{{ rankInfo.longTailKeyword.firstNum }}个
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div class="d1"><img src="@/assets/pdfExport/NO2.svg" />11-30位</div>
|
|
|
+ <div class="d2">{{ rankInfo.longTailKeyword.secondNum }}个
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="content">
|
|
|
+ <div class="d1"><img src="@/assets/pdfExport/NO3.svg" />31-100位</div>
|
|
|
+ <div class="d2">{{ rankInfo.longTailKeyword.thirdType }}个
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="24" v-if="appointKeywordsList.length > 0">
|
|
|
+ <h2 class="title mb">指定词排名列表</h2>
|
|
|
+ <a-table
|
|
|
+ ref="table"
|
|
|
+ size="middle"
|
|
|
+ :scroll="{x:true}"
|
|
|
+ :columns="appointKeywordPageListColumns"
|
|
|
+ :pagination="ipagination"
|
|
|
+ :dataSource="appointKeywordsList"
|
|
|
+ >
|
|
|
+ <template #bodyCell="{ column, record, index, text }">
|
|
|
+ <template v-if="column.key === 'rowIndex'">
|
|
|
+ {{ index + 1 }}
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template class="tag" v-if="column.key === 'lastRank'">
|
|
|
+ {{ record.lastRank }}
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-if="column.key === 'positionUrl'">
|
|
|
+ <a :href="text" target="_blank">{{ text }}</a>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </a-table>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="24" v-if="longTailKeywordsList.length > 0">
|
|
|
+ <h2 class="title mb">关键词排名列表</h2>
|
|
|
+ <a-table
|
|
|
+ ref="table"
|
|
|
+ size="middle"
|
|
|
+ :scroll="{x:true}"
|
|
|
+ :columns="longTailPageListColumns"
|
|
|
+ :pagination="ipagination"
|
|
|
+ :dataSource="longTailKeywordsList"
|
|
|
+ >
|
|
|
+ <template #bodyCell="{ column, record, index, text }">
|
|
|
+ <template v-if="column.key ==='rowIndex'">
|
|
|
+ {{ index + 1 }}
|
|
|
+ </template>
|
|
|
+ <template class="tag" v-if="column.key ==='lastRank'">
|
|
|
+ {{ record.lastRank }}
|
|
|
+ </template>
|
|
|
+ <template v-if="column.key ==='positionUrl'">
|
|
|
+ <a :href="text" target="_blank">{{ text }}</a>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </a-table>
|
|
|
+ </a-col>
|
|
|
+
|
|
|
+ </a-row>
|
|
|
+ </section>
|
|
|
+ <section class="s4">
|
|
|
+ <h2 class="title mb">网站外链</h2>
|
|
|
+ <a-row>
|
|
|
+ <a-col :span="24">
|
|
|
+ <div class="item">
|
|
|
+ <p>外链总数</p>
|
|
|
+ <a-input placeholder="请输入" v-model="detailInfo.outlink1" />
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <p>外链域</p>
|
|
|
+ <a-input placeholder="请输入" v-model="detailInfo.outlink2" />
|
|
|
+ </div>
|
|
|
+ <div class="item">
|
|
|
+ <p>外链发布数</p>
|
|
|
+ <a-input placeholder="请输入" v-model="detailInfo.outlink3" />
|
|
|
+ </div>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+
|
|
|
+ <a-row :gutter="12">
|
|
|
+ <a-col :span="12">
|
|
|
+ <p class="sub-title">外链总数趋势</p>
|
|
|
+ <a-col :span="24" style="margin: 10px 0px">
|
|
|
+ <j-upload bizPath="seopdf/image" :multiple="false" :returnUrl="false" v-model:file-list="detailInfo.outLinkImg"/>
|
|
|
+ </a-col>
|
|
|
+ <div class="img-wrap">
|
|
|
+ <template v-if="detailInfo.outLinkImg.length > 0">
|
|
|
+ <img class="img" :src="detailInfo.outLinkImg[0].url "/>
|
|
|
+ </template>
|
|
|
+ <a-empty v-else>
|
|
|
+ <span slot="description">请上传图片</span>
|
|
|
+ </a-empty>
|
|
|
+ </div>
|
|
|
+ <div v-if="detailInfo.outLinkImg.length > 0">
|
|
|
+ <a-textarea
|
|
|
+ :style="detailInfo.outLinkImgDetail1.length > 1000 ? 'border-color:red':''"
|
|
|
+ auto-size placeholder="请输入"
|
|
|
+ v-model="detailInfo.outLinkImgDetail1"></a-textarea>
|
|
|
+ <span :style="detailInfo.outLinkImgDetail1.length > 1000 ? 'color:red':''"
|
|
|
+ class="suffix-self">
|
|
|
+ {{ detailInfo.outLinkImgDetail1.length }}/1000
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="12">
|
|
|
+ <p class="sub-title">外链变化趋势</p>
|
|
|
+ <a-col :span="24" style="margin: 10px 0px">
|
|
|
+ <j-upload bizPath="seopdf/image" :returnUrl="true" :multiple="false" v-model:file-list="detailInfo.outLinkImg2"/>
|
|
|
+ </a-col>
|
|
|
+ <div class="img-wrap">
|
|
|
+ <template v-if="detailInfo.outLinkImg2.length > 0">
|
|
|
+ <img class="img" :src="detailInfo.outLinkImg2[0].url" />
|
|
|
+ </template>
|
|
|
+ <a-empty v-else>
|
|
|
+ <span slot="description">请上传图片</span>
|
|
|
+ </a-empty>
|
|
|
+ </div>
|
|
|
+ <div v-if="detailInfo.outLinkImg2.length > 0">
|
|
|
+ <a-textarea
|
|
|
+ :style="detailInfo.outLinkImgDetail2.length > 1000 ? 'border-color:red':''"
|
|
|
+ auto-size placeholder="请输入"
|
|
|
+ v-model="detailInfo.outLinkImgDetail2"></a-textarea>
|
|
|
+ <span :style="detailInfo.outLinkImgDetail2.length > 1000 ? 'color:red':''"
|
|
|
+ class="suffix-self">
|
|
|
+ {{ detailInfo.outLinkImgDetail2.length }}/1000
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section class="s5">
|
|
|
+ <h2 class="title mb">结语</h2>
|
|
|
+ <p style="text-indent: 28px">
|
|
|
+ 我们深知SEO是一个持续的过程,需要不断地监测、调整和改进。通过本月报告,我们与您分享我们的工作成果,并提供专业的建议和策略,以进一步提升您的网站在搜索引擎中的表现。</p>
|
|
|
+ <p style="text-indent: 28px">
|
|
|
+ 我们期待帮助您更好地理解和利用SEO对您的业务带来的巨大潜力。如果您对报告中的任何内容有疑问或需要进一步的解释,我们将随时为您提供支持和指导。</p>
|
|
|
+ <p style="text-indent: 28px">
|
|
|
+ 感谢您对我们的信任和合作。我们将继续竭尽全力,为您的网站取得更大的成功。</p>
|
|
|
+ <p style="text-indent: 28px">祝您生意兴隆!</p>
|
|
|
+ <p class="right">诚挚的问候</p>
|
|
|
+ <p class="right">SEO团队</p>
|
|
|
+ <p class="tips">
|
|
|
+ 注:本次报告的SEO数据仅反映一段时间内的网站表现,但要注意数据的可变性和动态性,建议结合长期趋势和综合指标来评估网站SEO的整体表现。</p>
|
|
|
+ </section>
|
|
|
+ </a-spin>
|
|
|
+ </div>
|
|
|
+ </a-card>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script setup lang="ts">
|
|
|
+
|
|
|
+import { onMounted, reactive, ref } from "vue";
|
|
|
+import { getAction, postAction } from "/@/api/manage/manage";
|
|
|
+import moment from "moment";
|
|
|
+import SeoPdfExportModal from "@/views/adweb/seo/components/SeoPdfExportModal.vue";
|
|
|
+import { useModal } from "@/components/Modal";
|
|
|
+//注册model
|
|
|
+const [registerModal, { openModal }] = useModal();
|
|
|
+import { useMessage } from "@/hooks/web/useMessage";
|
|
|
+import AreaChart from "@/views/adweb/data/chart/areaChart.vue";
|
|
|
+import { JUpload } from "@/components/Form/src/jeecg/components/JUpload";
|
|
|
+import { PageEnum } from "@/enums/pageEnum";
|
|
|
+import { router } from "@/router";
|
|
|
+
|
|
|
+const fileList = ref([]);
|
|
|
+const appointKeywordPageListColumns = ref([
|
|
|
+ {
|
|
|
+ title: "序号",
|
|
|
+ dataIndex: "rowIndex",
|
|
|
+ key: "rowIndex",
|
|
|
+ width: 100,
|
|
|
+ align: "center",
|
|
|
+ fixed: "left",
|
|
|
+
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "关键词",
|
|
|
+ dataIndex: "keywords",
|
|
|
+ key: "keywords",
|
|
|
+ fixed: "left",
|
|
|
+ width: 300
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "网址",
|
|
|
+ dataIndex: "positionUrl",
|
|
|
+ key: "positionUrl",
|
|
|
+ fixed: "left",
|
|
|
+ width: 600
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "排名",
|
|
|
+ dataIndex: "lastRank",
|
|
|
+ key: "lastRank",
|
|
|
+ width: 100,
|
|
|
+ }
|
|
|
+]);
|
|
|
+const longTailPageListColumns = ref([
|
|
|
+ {
|
|
|
+ title: "序号",
|
|
|
+ dataIndex: "rowIndex",
|
|
|
+ key: "rowIndex",
|
|
|
+ width: 100,
|
|
|
+ align: "center",
|
|
|
+ fixed: "left",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "关键词",
|
|
|
+ dataIndex: "keywords",
|
|
|
+ key: "keywords",
|
|
|
+ fixed: "left",
|
|
|
+ width: 300
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "网址",
|
|
|
+ dataIndex: "positionUrl",
|
|
|
+ key: "positionUrl",
|
|
|
+ fixed: "left",
|
|
|
+ width: 600
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "排名",
|
|
|
+ dataIndex: "lastRank",
|
|
|
+ key: "lastRank",
|
|
|
+ width: 100,
|
|
|
+ }
|
|
|
+]);
|
|
|
+
|
|
|
+const { createMessage } = useMessage();
|
|
|
+
|
|
|
+/**
|
|
|
+ * 编辑事件
|
|
|
+ */
|
|
|
+function handleEdit(record: Recordable) {
|
|
|
+ openModal(true, {
|
|
|
+ record,
|
|
|
+ isUpdate: true,
|
|
|
+ showFooter: true
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 成功回调
|
|
|
+ */
|
|
|
+function handleSuccess() {
|
|
|
+}
|
|
|
+
|
|
|
+const formState = reactive({
|
|
|
+ siteName: ref(undefined),
|
|
|
+ customerName: ref(undefined),
|
|
|
+ range: ref(undefined)
|
|
|
+});
|
|
|
+const formRef = ref();
|
|
|
+const rules = ref({
|
|
|
+ siteName: [
|
|
|
+ { required: true, message: "请选择站点", trigger: "change" }
|
|
|
+ ],
|
|
|
+ customerName: [
|
|
|
+ { required: true, message: "请输入客户名称", trigger: "blur" }
|
|
|
+ ],
|
|
|
+ range: [
|
|
|
+ { required: true, message: "请选择查询时间范围", trigger: "change" }
|
|
|
+ ]
|
|
|
+});
|
|
|
+const labelCol = ref({ span: 6 });
|
|
|
+const wrapperCol = ref({ span: 18 });
|
|
|
+const flag = ref(true);
|
|
|
+const siteOptions = ref([]);
|
|
|
+
|
|
|
+const handleChange = (value: string) => {
|
|
|
+ formState.customerName = value.label;
|
|
|
+};
|
|
|
+
|
|
|
+const filterOption = (input: string, option: any) => {
|
|
|
+ return option.name.toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
|
|
+};
|
|
|
+
|
|
|
+const getSiteOption = () => {
|
|
|
+ getAction("/adweb/adwebSite/getSiteListByUid", {}).then(function(res) {
|
|
|
+ if (res.code == 200) {
|
|
|
+ siteOptions.value = res.result;
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+const disabledDate = (current) => {
|
|
|
+ return current > moment().subtract(1, "months");
|
|
|
+};
|
|
|
+const onSubmit = () => {
|
|
|
+ formRef.value.validate().then(() => {
|
|
|
+ flag.value = false;
|
|
|
+ getInfo();
|
|
|
+ getMostAccessList();
|
|
|
+ getComprehenInfo();
|
|
|
+ getRankInfo();
|
|
|
+ getSeoMonthPlanContent();
|
|
|
+ }).catch(error => {
|
|
|
+ return false;
|
|
|
+ });
|
|
|
+};
|
|
|
+const infoLoading = ref(false);
|
|
|
+const coreDataChart = ref({
|
|
|
+ x: [],
|
|
|
+ pv: [],
|
|
|
+ uv: [],
|
|
|
+ enquiry: []
|
|
|
+});
|
|
|
+const statistics = ref({
|
|
|
+ uv: 0,
|
|
|
+ pv: 0,
|
|
|
+ averageVisit: 0,
|
|
|
+ averageVisitDuration: 0,
|
|
|
+ averageVisitPage: 0,
|
|
|
+ bounceRate: "0%",
|
|
|
+ conversionRate: "0%"
|
|
|
+});
|
|
|
+const mostAccessDatasource = ref([]);
|
|
|
+const appointKeywordsList = ref([]);
|
|
|
+const longTailKeywordsList = ref([]);
|
|
|
+const ipagination = ref({
|
|
|
+ pageSize: 50
|
|
|
+});
|
|
|
+const getInfo = () => {
|
|
|
+ let queryParam = {
|
|
|
+ siteCode: formState.siteName.value,
|
|
|
+ start: moment(formState.range.format("YYYY-MM")).startOf("month").format("YYYY-MM-DD"),
|
|
|
+ end: moment(formState.range.format("YYYY-MM")).endOf("month").format("YYYY-MM-DD")
|
|
|
+ };
|
|
|
+ infoLoading.value = true;
|
|
|
+ try {
|
|
|
+ getAction("/dmp-data/site-overview/stats", queryParam).then(function(res) {
|
|
|
+ if (!res.result) {
|
|
|
+ coreDataChart.value = {
|
|
|
+ x: [],
|
|
|
+ uv: [],
|
|
|
+ pv: [],
|
|
|
+ enquiry: []
|
|
|
+ };
|
|
|
+ statistics.value = {
|
|
|
+ uv: 0,
|
|
|
+ pv: 0,
|
|
|
+ averageVisit: 0,
|
|
|
+ averageVisitDuration: 0,
|
|
|
+ averageVisitPage: 0,
|
|
|
+ bounceRate: "0%",
|
|
|
+ conversionRate: "0%"
|
|
|
+ };
|
|
|
+ infoLoading.value = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const r = res.result.dailyStats;
|
|
|
+ const x = [], pv = [], uv = [], enquiry = [];
|
|
|
+ if (r != null && r.length > 0) {
|
|
|
+ for (let item of r) {
|
|
|
+ x.push(item.date);
|
|
|
+ pv.push(item.pageViews);
|
|
|
+ uv.push(item.totalUsers);
|
|
|
+ enquiry.push(item.enquires);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ coreDataChart.value.x = x;
|
|
|
+ coreDataChart.value.pv = pv;
|
|
|
+ coreDataChart.value.uv = uv;
|
|
|
+ coreDataChart.value.enquiry = enquiry;
|
|
|
+
|
|
|
+ statistics.value.uv = res.result.totalUsers;
|
|
|
+ statistics.value.pv = res.result.pageViews;
|
|
|
+ statistics.value.averageVisit = res.result.dailyTotalUsers;
|
|
|
+ statistics.value.averageVisitDuration = res.result.avgTimeOnPage;
|
|
|
+ statistics.value.averageVisitPage = res.result.pageViewsPerSession;
|
|
|
+ statistics.value.bounceRate = res.result.bounceRate;
|
|
|
+ statistics.value.conversionRate = res.result.enquiryConversionRate;
|
|
|
+ infoLoading.value = false;
|
|
|
+ });
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 最多访问TOP10列表
|
|
|
+const mostAccessColumns = ref([
|
|
|
+ {
|
|
|
+ title: "来源",
|
|
|
+ dataIndex: "pagePath",
|
|
|
+ scopedSlots: {
|
|
|
+ customRender: "pagePathSlot"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "浏览量(PV)",
|
|
|
+ dataIndex: "pageViews",
|
|
|
+ defaultSortOrder: "descend",
|
|
|
+ sorter: (a, b) => a.pageViews - b.pageViews,
|
|
|
+ width: 160,
|
|
|
+ scopedSlots: {
|
|
|
+ customRender: "centerSlot"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: "浏览量占比",
|
|
|
+ dataIndex: "pvProportion",
|
|
|
+ width: 160,
|
|
|
+ scopedSlots: {
|
|
|
+ customRender: "centerSlot"
|
|
|
+ }
|
|
|
+ }
|
|
|
+]);
|
|
|
+const getMostAccessList = async () => {
|
|
|
+ try {
|
|
|
+ let queryParam = {
|
|
|
+ siteCode: formState.siteName.value,
|
|
|
+ limit: 10,
|
|
|
+ start: moment(formState.range.format("YYYY-MM")).startOf("month").format("YYYY-MM-DD"),
|
|
|
+ end: moment(formState.range.format("YYYY-MM")).endOf("month").format("YYYY-MM-DD")
|
|
|
+ };
|
|
|
+ const res = await getAction("/dmp-data/page-path/stats", queryParam);
|
|
|
+ if (res.code == 200) {
|
|
|
+ mostAccessDatasource.value = res.result;
|
|
|
+ } else {
|
|
|
+ mostAccessDatasource.value = [];
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ }
|
|
|
+};
|
|
|
+const appointKeywordNum = ref(null);
|
|
|
+const longTailKeywordNum = ref(null);
|
|
|
+const getComprehenInfo = async () => {
|
|
|
+ let d = {
|
|
|
+ siteCode: formState.siteName.value
|
|
|
+ };
|
|
|
+ await getAction("/seo/seoKeywordsRank/comprehensiveInfo", d).then(res => {
|
|
|
+ if (res.code == 200) {
|
|
|
+ appointKeywordNum.value = res.result.appointKeywordNum;
|
|
|
+ longTailKeywordNum.value = res.result.longTailKeywordNum;
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+const detailInfo = ref({
|
|
|
+ thisMonth: "",
|
|
|
+ nextMonth: "",
|
|
|
+ outlink1: "",
|
|
|
+ outlink2: "",
|
|
|
+ outlink3: "",
|
|
|
+ outLinkImg: [],
|
|
|
+ outLinkImg2: [],
|
|
|
+ outLinkImgDetail1: "",
|
|
|
+ outLinkImgDetail2: ""
|
|
|
+});
|
|
|
+const rankInfo = ref({
|
|
|
+ appointKeyword: ref({}),
|
|
|
+ longTailKeyword: ref({})
|
|
|
+});
|
|
|
+//获取三个list的数据
|
|
|
+const getRankInfo = () => {
|
|
|
+ let d = {
|
|
|
+ siteCode: formState.siteName.value
|
|
|
+ };
|
|
|
+ getAction("/seo/seoKeywordsRank/getRankInfo", d).then(res => {
|
|
|
+ if (res.code == 200) {
|
|
|
+ rankInfo.value.appointKeyword = res.result.appointKeyword;
|
|
|
+ rankInfo.value.longTailKeyword = res.result.longTailKeyword;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ let d2 = {
|
|
|
+ siteCode: formState.siteName.value,
|
|
|
+ exportMonth: formState.range.format("YYYY-MM")
|
|
|
+ };
|
|
|
+ getAction("seo/seoMonthPdf/getSeoKeywordsRank", d2).then(res => {
|
|
|
+ if (res.code == 200) {
|
|
|
+ appointKeywordsList.value = res.result.appointKeywordsInfoList;
|
|
|
+ longTailKeywordsList.value = res.result.longTailKeywordsInfoList;
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+const getSeoMonthPlanContent = () => {
|
|
|
+ getAction("/seo/seoMonthPdf/getSeoMonthPlanContent", {}).then(function(res) {
|
|
|
+ detailInfo.value.thisMonth = res.result.currentMonthPlan;
|
|
|
+ detailInfo.value.nextMonth = res.result.nextMonthPlan;
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+function exportPDF() {
|
|
|
+ // 假设你有一个生成 PDF 的 URL
|
|
|
+ const pdfUrl = "/pdf";
|
|
|
+
|
|
|
+ // 使用 window.open 打开新窗口
|
|
|
+ window.open(pdfUrl, '_blank');
|
|
|
+}
|
|
|
+
|
|
|
+function goBack() {
|
|
|
+ flag.value = true;
|
|
|
+ coreDataChart.value.x = [];
|
|
|
+ coreDataChart.value.pv = [];
|
|
|
+ coreDataChart.value.uv = [];
|
|
|
+ detailInfo.value.thisMonth = '';
|
|
|
+ detailInfo.value.nextMonth = '';
|
|
|
+ detailInfo.value.outlink1 = '';
|
|
|
+ detailInfo.value.outlink2 = '';
|
|
|
+ detailInfo.value.outlink3 = '';
|
|
|
+ detailInfo.value.outLinkImg = [];
|
|
|
+ detailInfo.value.outLinkImg2 = [];
|
|
|
+ detailInfo.value.outLinkImgDetail1 = '';
|
|
|
+ detailInfo.value.outLinkImgDetail2 = '';
|
|
|
+ formState.siteName = undefined;
|
|
|
+ formState.customerName = '';
|
|
|
+ appointKeywordsList.value = [];
|
|
|
+ longTailKeywordsList.value = [];
|
|
|
+ formState.range = moment().subtract(1, "months");
|
|
|
+}
|
|
|
+
|
|
|
+const resetForm = () => {
|
|
|
+ formRef.value.resetFields();
|
|
|
+};
|
|
|
+onMounted(() => {
|
|
|
+ getSiteOption();
|
|
|
+});
|
|
|
+</script>
|
|
|
+<style scoped lang="less">
|
|
|
+.content {
|
|
|
+ /deep/ .ant-table-pagination.ant-pagination {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tip {
|
|
|
+ color: #666;
|
|
|
+ }
|
|
|
+
|
|
|
+ .ant-card {
|
|
|
+ /deep/ .ant-card-body {
|
|
|
+
|
|
|
+ .step1 {
|
|
|
+ min-height: 90vh;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ width: 720px;
|
|
|
+ margin: 0 auto;
|
|
|
+ flex-direction: column;
|
|
|
+
|
|
|
+ .ant-form-item {
|
|
|
+ margin-bottom: 15px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn3 {
|
|
|
+ position: fixed;
|
|
|
+ right: 100px;
|
|
|
+ top: 180px;
|
|
|
+ z-index: 999;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step2 {
|
|
|
+ padding: 24px;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .top {
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ h1 {
|
|
|
+ font-size: 27px;
|
|
|
+ font-weight: 500;
|
|
|
+ line-height: 1;
|
|
|
+ margin: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ p {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn1 {
|
|
|
+ position: fixed;
|
|
|
+ right: 150px;
|
|
|
+ top: 180px;
|
|
|
+ z-index: 999;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn2 {
|
|
|
+ position: fixed;
|
|
|
+ right: 50px;
|
|
|
+ top: 180px;
|
|
|
+ z-index: 999;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn4 {
|
|
|
+ position: fixed;
|
|
|
+ right: 265px;
|
|
|
+ top: 180px;
|
|
|
+ z-index: 999;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn6 {
|
|
|
+ position: fixed;
|
|
|
+ right: 265px;
|
|
|
+ top: 180px;
|
|
|
+ z-index: 999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .title {
|
|
|
+ border-left: 4px solid #544beb;
|
|
|
+ line-height: 1;
|
|
|
+ padding-left: 5px;
|
|
|
+ margin: 40px 0 0;
|
|
|
+
|
|
|
+ &.mb {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .red {
|
|
|
+ color: red;
|
|
|
+ position: relative;
|
|
|
+ top: 4px;
|
|
|
+ left: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .s1 {
|
|
|
+ .p1 {
|
|
|
+ color: #333;
|
|
|
+ font-size: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ textarea {
|
|
|
+ min-height: 170px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .num-suffix {
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ .suffix-self {
|
|
|
+ position: absolute;
|
|
|
+ right: 10px;
|
|
|
+ bottom: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .s2 {
|
|
|
+ .r5-1 {
|
|
|
+ .item {
|
|
|
+ width: 18%;
|
|
|
+ margin: 40px 1% 0;
|
|
|
+ float: left;
|
|
|
+ padding: 20px;
|
|
|
+ box-shadow: 3px 2px 10px -6px #544beb;
|
|
|
+ border-radius: 10px;
|
|
|
+
|
|
|
+ p {
|
|
|
+ text-align: center;
|
|
|
+ font-size: 15px;
|
|
|
+
|
|
|
+ &:nth-child(2) {
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 20px;
|
|
|
+ margin-top: -5px;
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .fr {
|
|
|
+ float: right;
|
|
|
+ line-height: 2;
|
|
|
+
|
|
|
+ span {
|
|
|
+ margin-right: 30px;
|
|
|
+
|
|
|
+ i {
|
|
|
+ display: inline-block;
|
|
|
+ width: 25px;
|
|
|
+ height: 3px;
|
|
|
+ background: #544BEB;
|
|
|
+ position: relative;
|
|
|
+ top: -4px;
|
|
|
+ margin-right: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:last-child i {
|
|
|
+ background: #F0B358;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .s3 {
|
|
|
+ .item {
|
|
|
+ padding: 20px;
|
|
|
+ height: 100%;
|
|
|
+ border-radius: 10px;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 80px;
|
|
|
+ margin: 20px auto;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ p {
|
|
|
+ text-align: center;
|
|
|
+ font-size: 15px;
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .wrap {
|
|
|
+ padding: 20px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 10px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+
|
|
|
+ .t1 {
|
|
|
+ color: #000;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .content {
|
|
|
+ display: block;
|
|
|
+ overflow: hidden;
|
|
|
+ line-height: 1;
|
|
|
+ border-bottom: 1px solid #ddd;
|
|
|
+ padding: 20px 0;
|
|
|
+
|
|
|
+ &:last-child {
|
|
|
+ border-bottom: none;
|
|
|
+ padding-bottom: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .d1 {
|
|
|
+ float: left;
|
|
|
+ width: 50%;
|
|
|
+ line-height: 25px;
|
|
|
+ color: #000;
|
|
|
+
|
|
|
+ img {
|
|
|
+ width: 15px;
|
|
|
+ margin: -4px 5px 0 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .d2 {
|
|
|
+ float: right;
|
|
|
+ width: 50%;
|
|
|
+ text-align: right;
|
|
|
+
|
|
|
+ &.d3 {
|
|
|
+ span {
|
|
|
+ color: #000;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ a {
|
|
|
+ font-size: 25px;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .s4 {
|
|
|
+ .item {
|
|
|
+ width: 32.33%;
|
|
|
+ margin: 0 0.5%;
|
|
|
+ border: 1px solid #e6e6e6;
|
|
|
+ float: left;
|
|
|
+ padding: 10px;
|
|
|
+ border-radius: 10px;
|
|
|
+
|
|
|
+ p {
|
|
|
+ font-weight: 600;
|
|
|
+ font-size: 15px;
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ input {
|
|
|
+ border: none;
|
|
|
+ border-bottom: 1px solid #d9d9d9;
|
|
|
+ border-radius: 0;
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ &:focus {
|
|
|
+ box-shadow: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .sub-title {
|
|
|
+ font-size: 19px;
|
|
|
+ color: #333;
|
|
|
+ padding: 0 0 0 10px;
|
|
|
+ border-left: 4px solid #544beb;
|
|
|
+ line-height: 1;
|
|
|
+ padding-left: 5px;
|
|
|
+ margin: 20px 0 5px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .img-wrap {
|
|
|
+ height: 340px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ border: 1px solid #d9d9d9;
|
|
|
+ border-radius: 5px;
|
|
|
+
|
|
|
+ .img {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ object-fit: contain;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ textarea.ant-input {
|
|
|
+ margin: 10px 0 0;
|
|
|
+ min-height: 80px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .suffix-self {
|
|
|
+ position: absolute;
|
|
|
+ right: 10px;
|
|
|
+ bottom: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ .s5 {
|
|
|
+ p {
|
|
|
+ font-size: 15px;
|
|
|
+ color: #333;
|
|
|
+
|
|
|
+ &.right {
|
|
|
+ text-align: right;
|
|
|
+ padding-right: 50px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.tips {
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+</style>
|
|
|
+
|