feat: 添加Tailwind CSS支持并修复URL拼接问题
添加Tailwind CSS及相关配置 修复多个爬虫服务中的URL拼接问题,避免双斜杠 调整前端导航菜单项顺序
This commit is contained in:
@@ -17,9 +17,13 @@
|
|||||||
"vue": "^3.5.24"
|
"vue": "^3.5.24"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@tailwindcss/postcss": "^4.1.18",
|
||||||
"@types/node": "^24.10.1",
|
"@types/node": "^24.10.1",
|
||||||
"@vitejs/plugin-vue": "^6.0.1",
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
"@vue/tsconfig": "^0.8.1",
|
"@vue/tsconfig": "^0.8.1",
|
||||||
|
"autoprefixer": "^10.4.23",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
|
"tailwindcss": "^4.1.18",
|
||||||
"typescript": "~5.9.3",
|
"typescript": "~5.9.3",
|
||||||
"vite": "^7.2.4",
|
"vite": "^7.2.4",
|
||||||
"vue-tsc": "^3.1.4"
|
"vue-tsc": "^3.1.4"
|
||||||
|
|||||||
6
frontend/postcss.config.js
Normal file
6
frontend/postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
'@tailwindcss/postcss': {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -4,18 +4,19 @@
|
|||||||
<div class="logo">投标信息一览</div>
|
<div class="logo">投标信息一览</div>
|
||||||
<el-menu active-text-color="#ffd04b" background-color="#545c64" class="el-menu-vertical-demo" default-active="1"
|
<el-menu active-text-color="#ffd04b" background-color="#545c64" class="el-menu-vertical-demo" default-active="1"
|
||||||
text-color="#fff" @select="handleSelect">
|
text-color="#fff" @select="handleSelect">
|
||||||
|
|
||||||
<el-menu-item index="1">
|
<el-menu-item index="1">
|
||||||
<el-icon>
|
|
||||||
<DataBoard />
|
|
||||||
</el-icon>
|
|
||||||
<span>Dashboard</span>
|
|
||||||
</el-menu-item>
|
|
||||||
<el-menu-item index="2">
|
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<MagicStick />
|
<MagicStick />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
<span>Dashboard AI</span>
|
<span>Dashboard AI</span>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
<el-menu-item index="2">
|
||||||
|
<el-icon>
|
||||||
|
<DataBoard />
|
||||||
|
</el-icon>
|
||||||
|
<span>Dashboard</span>
|
||||||
|
</el-menu-item>
|
||||||
<el-menu-item index="3">
|
<el-menu-item index="3">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Document />
|
<Document />
|
||||||
@@ -43,8 +44,8 @@
|
|||||||
</el-header>
|
</el-header>
|
||||||
|
|
||||||
<el-main>
|
<el-main>
|
||||||
<DashboardAI v-if="activeIndex === '2'" :bids="bids" :high-priority-bids="highPriorityBids" />
|
<DashboardAI v-if="activeIndex === '1'" :bids="bids" :high-priority-bids="highPriorityBids" />
|
||||||
<Dashboard v-if="activeIndex === '1'" :today-bids="todayBids" :high-priority-bids="highPriorityBids"
|
<Dashboard v-if="activeIndex === '2'" :today-bids="todayBids" :high-priority-bids="highPriorityBids"
|
||||||
:keywords="keywords" :loading="loading" :is-crawling="isCrawling" @refresh="fetchData"
|
:keywords="keywords" :loading="loading" :is-crawling="isCrawling" @refresh="fetchData"
|
||||||
@update-bids="updateBidsByDateRange" />
|
@update-bids="updateBidsByDateRange" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export interface CdtResult {
|
|||||||
export const CdtCrawler = {
|
export const CdtCrawler = {
|
||||||
name: '中国大唐集团电子商务平台',
|
name: '中国大唐集团电子商务平台',
|
||||||
url: 'https://tang.cdt-ec.com/home/index.html',
|
url: 'https://tang.cdt-ec.com/home/index.html',
|
||||||
baseUrl: 'https://tang.cdt-ec.com/',
|
baseUrl: 'https://tang.cdt-ec.com',
|
||||||
|
|
||||||
async crawl(browser: puppeteer.Browser): Promise<CdtResult[]> {
|
async crawl(browser: puppeteer.Browser): Promise<CdtResult[]> {
|
||||||
const logger = new Logger('CdtCrawler');
|
const logger = new Logger('CdtCrawler');
|
||||||
@@ -252,10 +252,11 @@ export const CdtCrawler = {
|
|||||||
const dateStr = match[3]?.trim();
|
const dateStr = match[3]?.trim();
|
||||||
|
|
||||||
if (title && url) {
|
if (title && url) {
|
||||||
|
const fullUrl = url.startsWith('http') ? url : this.baseUrl + url;
|
||||||
results.push({
|
results.push({
|
||||||
title,
|
title,
|
||||||
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
||||||
url: url.startsWith('http') ? url : this.baseUrl + url
|
url: fullUrl.replace(/\/\//g, '/')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ export const CeicCrawler = {
|
|||||||
allResults.push(...pageResults.map(r => ({
|
allResults.push(...pageResults.map(r => ({
|
||||||
title: r.title,
|
title: r.title,
|
||||||
publishDate: r.dateStr ? new Date(r.dateStr) : new Date(),
|
publishDate: r.dateStr ? new Date(r.dateStr) : new Date(),
|
||||||
url: r.url
|
url: r.url.replace(/\/\//g, '/')
|
||||||
})));
|
})));
|
||||||
|
|
||||||
logger.log(`Extracted ${pageResults.length} items.`);
|
logger.log(`Extracted ${pageResults.length} items.`);
|
||||||
|
|||||||
@@ -190,10 +190,11 @@ export const CgnpcCrawler = {
|
|||||||
const dateStr = match[3]?.trim();
|
const dateStr = match[3]?.trim();
|
||||||
|
|
||||||
if (title && url) {
|
if (title && url) {
|
||||||
|
const fullUrl = url.startsWith('http') ? url : this.baseUrl + url;
|
||||||
results.push({
|
results.push({
|
||||||
title,
|
title,
|
||||||
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
||||||
url: url.startsWith('http') ? url : this.baseUrl + url
|
url: fullUrl.replace(/\/\//g, '/')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,10 +105,11 @@ export const ChdtpCrawler = {
|
|||||||
const dateStr = match[5]?.trim();
|
const dateStr = match[5]?.trim();
|
||||||
|
|
||||||
if (title && urlSuffix) {
|
if (title && urlSuffix) {
|
||||||
|
const fullUrl = this.baseUrl + urlSuffix;
|
||||||
results.push({
|
results.push({
|
||||||
title,
|
title,
|
||||||
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
||||||
url: this.baseUrl + urlSuffix
|
url: fullUrl.replace(/\/\//g, '/')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ export const ChngCrawler = {
|
|||||||
allResults.push(...pageResults.map(r => ({
|
allResults.push(...pageResults.map(r => ({
|
||||||
title: r!.title,
|
title: r!.title,
|
||||||
publishDate: new Date(r!.dateStr),
|
publishDate: new Date(r!.dateStr),
|
||||||
url: r!.url
|
url: r!.url.replace(/\/\//g, '/')
|
||||||
})));
|
})));
|
||||||
|
|
||||||
logger.log(`Extracted ${pageResults.length} items.`);
|
logger.log(`Extracted ${pageResults.length} items.`);
|
||||||
|
|||||||
@@ -181,10 +181,11 @@ export const CnncecpCrawler = {
|
|||||||
const title = match[3]?.trim();
|
const title = match[3]?.trim();
|
||||||
|
|
||||||
if (title && url) {
|
if (title && url) {
|
||||||
|
const fullUrl = url.startsWith('http') ? url : this.baseUrl + url;
|
||||||
results.push({
|
results.push({
|
||||||
title,
|
title,
|
||||||
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
||||||
url: url.startsWith('http') ? url : this.baseUrl + url
|
url: fullUrl.replace(/\/\//g, '/')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,10 +182,11 @@ export const CnoocCrawler = {
|
|||||||
const dateStr = match[3]?.trim();
|
const dateStr = match[3]?.trim();
|
||||||
|
|
||||||
if (title && url) {
|
if (title && url) {
|
||||||
|
const fullUrl = url.startsWith('http') ? url : this.baseUrl + url;
|
||||||
results.push({
|
results.push({
|
||||||
title,
|
title,
|
||||||
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
||||||
url: url.startsWith('http') ? url : this.baseUrl + url
|
url: fullUrl.replace(/\/\//g, '/')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,10 +188,11 @@ export const EpsCrawler = {
|
|||||||
const dateStr = match[3]?.trim();
|
const dateStr = match[3]?.trim();
|
||||||
|
|
||||||
if (title && url) {
|
if (title && url) {
|
||||||
|
const fullUrl = url.startsWith('http') ? url : this.baseUrl + url;
|
||||||
results.push({
|
results.push({
|
||||||
title,
|
title,
|
||||||
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
||||||
url: url.startsWith('http') ? url : this.baseUrl + url
|
url: fullUrl.replace(/\/\//g, '/')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -234,10 +234,11 @@ export const EspicCrawler = {
|
|||||||
const dateStr = match[3]?.trim();
|
const dateStr = match[3]?.trim();
|
||||||
|
|
||||||
if (title && url) {
|
if (title && url) {
|
||||||
|
const fullUrl = url.startsWith('http') ? url : this.baseUrl + url;
|
||||||
results.push({
|
results.push({
|
||||||
title,
|
title,
|
||||||
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
||||||
url: url.startsWith('http') ? url : this.baseUrl + url
|
url: fullUrl.replace(/\/\//g, '/')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,10 +185,11 @@ export const PowerbeijingCrawler = {
|
|||||||
const dateStr = match[3]?.trim();
|
const dateStr = match[3]?.trim();
|
||||||
|
|
||||||
if (title && url) {
|
if (title && url) {
|
||||||
|
const fullUrl = url.startsWith('http') ? url : this.baseUrl + url;
|
||||||
results.push({
|
results.push({
|
||||||
title,
|
title,
|
||||||
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
||||||
url: url.startsWith('http') ? url : this.baseUrl + url
|
url: fullUrl.replace(/\/\//g, '/')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,10 +190,11 @@ export const SdiccCrawler = {
|
|||||||
const dateStr = match[4]?.trim();
|
const dateStr = match[4]?.trim();
|
||||||
|
|
||||||
if (title && ggGuid && gcGuid) {
|
if (title && ggGuid && gcGuid) {
|
||||||
|
const fullUrl = `${this.baseUrl}/cgxx/ggDetail?gcGuid=${gcGuid}&ggGuid=${ggGuid}`;
|
||||||
results.push({
|
results.push({
|
||||||
title,
|
title,
|
||||||
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
publishDate: dateStr ? new Date(dateStr) : new Date(),
|
||||||
url: `${this.baseUrl}/cgxx/ggDetail?gcGuid=${gcGuid}&ggGuid=${ggGuid}`
|
url: fullUrl.replace(/\/\//g, '/')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export const SzecpCrawler = {
|
|||||||
allResults.push(...pageResults.map(r => ({
|
allResults.push(...pageResults.map(r => ({
|
||||||
title: r!.title,
|
title: r!.title,
|
||||||
publishDate: new Date(r!.dateStr),
|
publishDate: new Date(r!.dateStr),
|
||||||
url: r!.url
|
url: r!.url.replace(/\/\//g, '/')
|
||||||
})));
|
})));
|
||||||
|
|
||||||
logger.log(`Extracted ${pageResults.length} items.`);
|
logger.log(`Extracted ${pageResults.length} items.`);
|
||||||
|
|||||||
Reference in New Issue
Block a user