feat: 新闻咨询由后台配置

This commit is contained in:
liulujian 2026-04-30 03:48:12 +08:00
parent f37f1051c0
commit cce8a1c57b
31 changed files with 1050025 additions and 168 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 KiB

View File

@ -200,12 +200,23 @@ export default {
data: JSON.stringify(params), data: JSON.stringify(params),
}); });
}, },
getSjlbb(params) { // 代码表查询tableName: fwlx/sshy/xzqh/bq/dw
dms2mc(tableName, params) {
return fetchSso({ return fetchSso({
url: `${basurl}/gxdt/getSjlbb`, url: `/yygl/cache/v1/list/${tableName}`,
method: 'get', method: 'post',
loading: true, loading: true,
params, data: JSON.stringify(params),
});
},
// 发布供需信息ywlxDm: '01'=供给, '02'=需求)
gxfb(params) {
return fetchSso({
url: `${basurl}/gxdt/gxfb`,
method: 'post',
loading: true,
data: JSON.stringify(params),
}); });
}, },
}; };

View File

@ -0,0 +1,30 @@
import { fetchSso } from '@/core/request';
const basurl = '/mhzc';
export default {
// 行业动态 - 按类型查询gjzc=国家政策、hyzx=行业资讯)
getHydtList(params) {
return fetchSso({
url: `${basurl}/sy/hydt/list`,
method: 'get',
params,
});
},
// 行业动态 - 按类型分组查询
getHydtGroupedList() {
return fetchSso({
url: `${basurl}/sy/hydt/groupedList`,
method: 'get',
});
},
// 平台公告列表
getPtggList() {
return fetchSso({
url: `${basurl}/sy/ptgg/list`,
method: 'get',
});
},
};

View File

@ -39,6 +39,9 @@
</t-form> </t-form>
<!-- <div class="py-4"><t-button theme="primary" @click="reactqyglxx()">新增</t-button></div> --> <!-- <div class="py-4"><t-button theme="primary" @click="reactqyglxx()">新增</t-button></div> -->
<div class="table-box" style="padding: 16px; background-color: #fff"> <div class="table-box" style="padding: 16px; background-color: #fff">
<div class="table-toolbar">
<t-button theme="primary" @click="handlePublish">发布服务</t-button>
</div>
<t-table <t-table
class="add-edit-table" class="add-edit-table"
ref="tableRef" ref="tableRef"
@ -68,6 +71,110 @@
</template> </template>
</t-table> </t-table>
</div> </div>
<!-- 发布服务弹窗 -->
<t-dialog
:visible.sync="publishVisible"
header="发布碳服务供给"
:closeOnOverlayClick="true"
:footer="false"
width="600px"
@close="onPublishClose"
class="global-dialog"
>
<div class="publish-form">
<t-form
:rules="publishRules"
:data="publishFormData"
ref="publishFormRef"
labelAlign="top"
>
<t-row :gutter="16">
<t-col :span="12">
<t-form-item label="服务标题" name="bt1">
<t-input v-model="publishFormData.bt1" placeholder="请输入服务标题" clearable />
</t-form-item>
</t-col>
<t-col :span="12">
<t-form-item label="服务类型" name="fwlxjh">
<t-select
v-model="publishFormData.fwlxjh"
:max="4"
:options="fwlxOptions"
placeholder="请选择服务类型"
multiple
clearable
/>
</t-form-item>
</t-col>
</t-row>
<t-row :gutter="16">
<t-col :span="12">
<t-form-item label="所属行业" name="sshy">
<t-select v-model="publishFormData.sshy" :options="sshyDmOptions" placeholder="请选择所属行业" clearable />
</t-form-item>
</t-col>
<t-col :span="12">
<t-form-item label="服务地区" name="fwfw">
<t-select v-model="publishFormData.fwfw" :options="fwfwOptions" placeholder="请选择服务地区" clearable />
</t-form-item>
</t-col>
</t-row>
<t-row :gutter="16">
<t-col :span="12">
<t-form-item label="价格" name="gjjg">
<t-input v-model="publishFormData.gjjg" :disabled="isMy" placeholder="请输入价格" clearable />
<t-radio style="width: 80px; margin-left: 8px" allowUncheck v-model="isMy" @click="isMyChange">面议</t-radio>
</t-form-item>
</t-col>
<t-col :span="12">
<t-form-item label="单位" name="gjdwDm">
<t-select v-model="publishFormData.gjdwDm" :disabled="isMy" :options="gjdwdmOptions" placeholder="请选择单位" clearable />
</t-form-item>
</t-col>
</t-row>
<t-form-item label="服务详细描述" name="fwnr">
<t-textarea v-model="publishFormData.fwnr" placeholder="请填写服务详细描述" :maxlength="100" />
</t-form-item>
<t-form-item label="标签" name="bqjh">
<t-select
v-model="publishFormData.bqjh"
:max="4"
:options="bqOptions"
placeholder="请选择标签"
multiple
clearable
/>
</t-form-item>
<t-row :gutter="16">
<t-col :span="8">
<t-form-item label="联系人" name="lxr">
<t-input v-model="publishFormData.lxr" placeholder="请输入联系人" />
</t-form-item>
</t-col>
<t-col :span="8">
<t-form-item label="联系电话" name="lxdh">
<t-input v-model="publishFormData.lxdh" placeholder="请输入联系电话" />
</t-form-item>
</t-col>
<t-col :span="8">
<t-form-item label="电子邮箱" name="email">
<t-input v-model="publishFormData.email" placeholder="请输入电子邮箱" />
</t-form-item>
</t-col>
</t-row>
</t-form>
<div class="form-actions">
<t-button theme="primary" type="button" @click="handlePublishSubmit">提交发布</t-button>
</div>
</div>
</t-dialog>
</div> </div>
</template> </template>
@ -83,6 +190,36 @@ export default {
return { return {
formData: { ywlxDm: '01' }, formData: { ywlxDm: '01' },
list: [], list: [],
//
publishVisible: false,
isMy: false,
publishFormData: {
bt1: '',
fwlxjh: '',
sshy: '',
gjjg: '',
gjdwDm: '',
fwfw: '',
fwnr: '',
bqjh: [],
lxr: '',
lxdh: '',
email: '',
},
publishRules: {
bt1: [{ required: true, message: '必填', type: 'error' }],
fwlxjh: [{ required: true, message: '必填', type: 'error' }],
sshy: [{ required: true, message: '必填', type: 'error' }],
fwfw: [{ required: true, message: '必填', type: 'error' }],
fwnr: [{ required: true, message: '必填', type: 'error' }],
lxr: [{ required: true, message: '必填', type: 'error' }],
lxdh: [{ required: true, message: '必填', type: 'error' }],
},
fwlxOptions: [],
sshyDmOptions: [],
fwfwOptions: [],
bqOptions: [],
gjdwdmOptions: [],
columns: [ columns: [
{ align: 'center', colKey: 'serial-number', width: '80px', title: '序号' }, { align: 'center', colKey: 'serial-number', width: '80px', title: '序号' },
{ align: 'left', width: '120px', colKey: 'bt1', title: '标题', ellipsis: true }, { align: 'left', width: '120px', colKey: 'bt1', title: '标题', ellipsis: true },
@ -152,13 +289,123 @@ export default {
this.onQuery(); this.onQuery();
} }
}, },
//
loadDmList() {
this.fwlxoptionsSearch();
this.sshyoptionsSearch();
this.fwfwoptionsSearch();
this.bqoptionsSearch();
this.gjdwdmoptionsSearch();
},
async fwlxoptionsSearch() {
try {
const res = await api.dms2mc('fwlx', {});
this.fwlxOptions = res.data || [];
} catch (error) {
this.fwlxOptions = [];
}
},
async sshyoptionsSearch() {
try {
const res = await api.dms2mc('sshy', {});
this.sshyDmOptions = res.data || [];
} catch (error) {
this.sshyDmOptions = [];
}
},
async fwfwoptionsSearch() {
try {
const res = await api.dms2mc('xzqh', {});
this.fwfwOptions = res.data || [];
} catch (error) {
this.fwfwOptions = [];
}
},
async bqoptionsSearch() {
try {
const res = await api.dms2mc('bq', {});
this.bqOptions = res.data || [];
} catch (error) {
this.bqOptions = [];
}
},
async gjdwdmoptionsSearch() {
try {
const res = await api.dms2mc('dw', {});
this.gjdwdmOptions = res.data || [];
} catch (error) {
this.gjdwdmOptions = [];
}
},
//
handlePublish() {
this.publishVisible = true;
this.loadDmList();
},
isMyChange() {
this.isMy = !this.isMy;
if (this.isMy) {
this.publishFormData.gjjg = '';
this.publishFormData.gjdwDm = '';
}
},
handlePublishSubmit() {
this.$refs.publishFormRef.validate().then((result) => {
if (result === true) {
this.submitGxfb();
} else {
this.$message.warning('请填写全部必填信息');
}
});
},
async submitGxfb() {
try {
let params = {
ywlxDm: '01',
...this.publishFormData,
};
if (params.bqjh && params.bqjh.length) {
params.bqjh = params.bqjh.toString();
}
if (params.fwlxjh && params.fwlxjh.length) {
params.fwlxjh = params.fwlxjh.toString();
}
await api.gxfb(params);
this.$message.success('发布成功,请等待审核');
this.publishVisible = false;
this.resetPublishForm();
this.onQuery();
} catch (error) {
console.error('发布失败', error);
}
},
resetPublishForm() {
this.publishFormData = {
bt1: '',
fwlxjh: '',
sshy: '',
gjjg: '',
gjdwDm: '',
fwfw: '',
fwnr: '',
bqjh: [],
lxr: '',
lxdh: '',
email: '',
};
this.isMy = false;
},
onPublishClose() {
this.publishVisible = false;
this.resetPublishForm();
},
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.container-body { .container-body {
height: 100%; height: calc(100vh - 64px);
padding: 40px 40px 0; padding: 24px;
background: #ecf1f9; background: #ecf1f9;
} }
/deep/ .t-table__header tr th{ /deep/ .t-table__header tr th{
@ -173,4 +420,19 @@ export default {
/deep/ .t-table__content{ /deep/ .t-table__content{
border: 1px solid #bdbdbd66; border: 1px solid #bdbdbd66;
} }
.table-toolbar {
margin-bottom: 16px;
}
.publish-form {
padding: 0 8px;
}
.form-actions {
display: flex;
justify-content: center;
margin-top: 30px;
.t-button {
width: 200px;
}
}
</style> </style>

View File

@ -39,6 +39,9 @@
</t-form> </t-form>
<!-- <div class="py-4"><t-button theme="primary" @click="reactqyglxx()">新增</t-button></div> --> <!-- <div class="py-4"><t-button theme="primary" @click="reactqyglxx()">新增</t-button></div> -->
<div class="table-box" style="padding: 16px; background-color: #fff"> <div class="table-box" style="padding: 16px; background-color: #fff">
<div class="table-toolbar">
<t-button theme="primary" @click="handlePublish">发布需求</t-button>
</div>
<t-table <t-table
class="add-edit-table" class="add-edit-table"
ref="tableRef" ref="tableRef"
@ -63,6 +66,107 @@
</template> </template>
</t-table> </t-table>
</div> </div>
<!-- 发布需求弹窗 -->
<t-dialog
:visible.sync="publishVisible"
header="发布碳服务需求"
:closeOnOverlayClick="true"
:footer="false"
width="600px"
@close="onPublishClose"
class="global-dialog"
>
<div class="publish-form">
<t-form
:rules="publishRules"
:data="publishFormData"
ref="publishFormRef"
labelAlign="top"
>
<t-row :gutter="16">
<t-col :span="12">
<t-form-item label="需求标题" name="bt1">
<t-input v-model="publishFormData.bt1" placeholder="请输入需求标题" clearable />
</t-form-item>
</t-col>
<t-col :span="12">
<t-form-item label="需求类型" name="fwlxjh">
<t-select v-model="publishFormData.fwlxjh" :options="xqlxOptions" placeholder="请选择需求类型" clearable />
</t-form-item>
</t-col>
</t-row>
<t-row :gutter="16">
<t-col :span="12">
<t-form-item label="所属行业" name="sshy">
<t-select v-model="publishFormData.sshy" :options="sshyDmOptions" placeholder="请选择所属行业" clearable />
</t-form-item>
</t-col>
<t-col :span="12">
<t-form-item label="预算范围" name="ysfwDm1">
<t-select v-model="publishFormData.ysfwDm1" :options="ysfwDm1Options" placeholder="请选择预算范围" clearable />
</t-form-item>
</t-col>
</t-row>
<t-row :gutter="16">
<t-col :span="12">
<t-form-item label="期望完成时间" name="qwwcsj">
<t-date-picker
v-model="publishFormData.qwwcsj"
placeholder="请选择期望完成时间"
style="width: 100%"
clearable
/>
</t-form-item>
</t-col>
<t-col :span="12">
<t-form-item label="服务地区" name="fwfw">
<t-select v-model="publishFormData.fwfw" :options="fwfwOptions" placeholder="请选择服务地区" clearable />
</t-form-item>
</t-col>
</t-row>
<t-form-item label="需求详细描述" name="fwnr">
<t-textarea v-model="publishFormData.fwnr" placeholder="请填写需求详细描述" :maxlength="100" />
</t-form-item>
<t-form-item label="标签" name="bqjh">
<t-select
v-model="publishFormData.bqjh"
:max="4"
:options="bqOptions"
placeholder="请选择标签"
multiple
clearable
/>
</t-form-item>
<t-row :gutter="16">
<t-col :span="8">
<t-form-item label="联系人" name="lxr">
<t-input v-model="publishFormData.lxr" placeholder="请输入联系人" />
</t-form-item>
</t-col>
<t-col :span="8">
<t-form-item label="联系电话" name="lxdh">
<t-input v-model="publishFormData.lxdh" placeholder="请输入联系电话" />
</t-form-item>
</t-col>
<t-col :span="8">
<t-form-item label="电子邮箱" name="email">
<t-input v-model="publishFormData.email" placeholder="请输入电子邮箱" />
</t-form-item>
</t-col>
</t-row>
</t-form>
<div class="form-actions">
<t-button theme="primary" type="button" @click="handlePublishSubmit">提交发布</t-button>
</div>
</div>
</t-dialog>
</div> </div>
</template> </template>
@ -78,6 +182,37 @@ export default {
return { return {
formData: { ywlxDm: '02' }, formData: { ywlxDm: '02' },
list: [], list: [],
//
publishVisible: false,
publishFormData: {
bt1: '',
fwlxjh: '',
sshy: '',
ysfwDm1: '',
qwwcsj: '',
fwfw: '',
fwnr: '',
bqjh: [],
lxr: '',
lxdh: '',
email: '',
},
publishRules: {
bt1: [{ required: true, message: '必填', type: 'error' }],
fwlxjh: [{ required: true, message: '必填', type: 'error' }],
sshy: [{ required: true, message: '必填', type: 'error' }],
ysfwDm1: [{ required: true, message: '必填', type: 'error' }],
qwwcsj: [{ required: true, message: '必填', type: 'error' }],
fwfw: [{ required: true, message: '必填', type: 'error' }],
fwnr: [{ required: true, message: '必填', type: 'error' }],
lxr: [{ required: true, message: '必填', type: 'error' }],
lxdh: [{ required: true, message: '必填', type: 'error' }],
},
xqlxOptions: [],
sshyDmOptions: [],
ysfwDm1Options: [],
fwfwOptions: [],
bqOptions: [],
columns: [ columns: [
{ align: 'center', colKey: 'serial-number', width: '80px', title: '序号' }, { align: 'center', colKey: 'serial-number', width: '80px', title: '序号' },
{ align: 'left', width: '120px', colKey: 'bt1', title: '标题', ellipsis: true }, { align: 'left', width: '120px', colKey: 'bt1', title: '标题', ellipsis: true },
@ -147,13 +282,112 @@ export default {
this.onQuery(); this.onQuery();
} }
}, },
//
loadDmList() {
this.xqlxoptionsSearch();
this.sshyoptionsSearch();
this.ysfwoptionsSearch();
this.fwfwoptionsSearch();
this.bqoptionsSearch();
},
async xqlxoptionsSearch() {
try {
const res = await api.dms2mc('xqlx', {});
this.xqlxOptions = res.data || [];
} catch (error) {
this.xqlxOptions = [];
}
},
async sshyoptionsSearch() {
try {
const res = await api.dms2mc('sshy', {});
this.sshyDmOptions = res.data || [];
} catch (error) {
this.sshyDmOptions = [];
}
},
async ysfwoptionsSearch() {
try {
const res = await api.dms2mc('ysfw', {});
this.ysfwDm1Options = res.data || [];
} catch (error) {
this.ysfwDm1Options = [];
}
},
async fwfwoptionsSearch() {
try {
const res = await api.dms2mc('xzqh', {});
this.fwfwOptions = res.data || [];
} catch (error) {
this.fwfwOptions = [];
}
},
async bqoptionsSearch() {
try {
const res = await api.dms2mc('bq', {});
this.bqOptions = res.data || [];
} catch (error) {
this.bqOptions = [];
}
},
//
handlePublish() {
this.publishVisible = true;
this.loadDmList();
},
handlePublishSubmit() {
this.$refs.publishFormRef.validate().then((result) => {
if (result === true) {
this.submitGxfb();
} else {
this.$message.warning('请填写全部必填信息');
}
});
},
async submitGxfb() {
try {
let params = {
ywlxDm: '02',
...this.publishFormData,
};
if (params.bqjh && params.bqjh.length) {
params.bqjh = params.bqjh.toString();
}
await api.gxfb(params);
this.$message.success('发布成功,请等待审核');
this.publishVisible = false;
this.resetPublishForm();
this.onQuery();
} catch (error) {
console.error('发布失败', error);
}
},
resetPublishForm() {
this.publishFormData = {
bt1: '',
fwlxjh: '',
sshy: '',
ysfwDm1: '',
qwwcsj: '',
fwfw: '',
fwnr: '',
bqjh: [],
lxr: '',
lxdh: '',
email: '',
};
},
onPublishClose() {
this.publishVisible = false;
this.resetPublishForm();
},
}, },
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.container-body { .container-body {
height: 100%; height: calc(100vh - 64px);
padding: 40px 40px 0; padding: 24px;
background: #ecf1f9; background: #ecf1f9;
} }
/deep/ .t-table__header tr th{ /deep/ .t-table__header tr th{
@ -168,4 +402,19 @@ export default {
/deep/ .t-table__content{ /deep/ .t-table__content{
border: 1px solid #bdbdbd66; border: 1px solid #bdbdbd66;
} }
.table-toolbar {
margin-bottom: 16px;
}
.publish-form {
padding: 0 8px;
}
.form-actions {
display: flex;
justify-content: center;
margin-top: 30px;
.t-button {
width: 200px;
}
}
</style> </style>

View File

@ -38,7 +38,7 @@ export default {
return { return {
shortcuts: [ shortcuts: [
{ label: '我的认证', icon: 'user', to: '/yhzx/qyrenzheng', bgColor: '#E6F8F0', color: '#344F3D' }, { label: '我的认证', icon: 'user', to: '/yhzx/qyrenzheng', bgColor: '#E6F8F0', color: '#344F3D' },
{ label: '账号编辑', icon: 'edit', to: '/yhzx/qyrenzheng', bgColor: '#E6F8F0', color: '#344F3D' }, // { label: '', icon: 'edit', to: '/yhzx/qyrenzheng', bgColor: '#E6F8F0', color: '#344F3D' },
{ label: '修改密码', icon: 'lock-on', to: '/yhzx/zhanghugl', bgColor: '#E6F8F0', color: '#344F3D' }, { label: '修改密码', icon: 'lock-on', to: '/yhzx/zhanghugl', bgColor: '#E6F8F0', color: '#344F3D' },
], ],
}; };
@ -62,7 +62,8 @@ export default {
.account-shortcuts { .account-shortcuts {
.shortcuts-row { .shortcuts-row {
display: flex; display: flex;
gap: 0; flex-wrap: wrap;
gap: 8px;
} }
} }
@ -77,7 +78,7 @@ export default {
border: none; border: none;
border-radius: 4px; border-radius: 4px;
transition: background 0.2s ease; transition: background 0.2s ease;
flex: 1; width: calc(33.33% - 6px);
min-width: 0; min-width: 0;
&:hover { &:hover {

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="panel-card carbon-service-table"> <div class="panel-card carbon-service-table">
<div class="table-wrapper"> <div class="table-wrapper">
<table class="data-table"> <table class="data-table" v-if="tableData.length > 0">
<thead> <thead>
<tr> <tr>
<th class="col-title">标题</th> <th class="col-title">标题</th>
@ -13,27 +13,42 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="item in tableData" :key="item.id"> <tr v-for="item in tableData" :key="item.gxUuid">
<td class="col-title">{{ item.title }}</td> <td class="col-title">{{ item.bt1 || item.bt }}</td>
<td class="col-industry">{{ item.industry }}</td> <td class="col-industry">{{ item.sshy }}</td>
<td class="col-scope">{{ item.scope }}</td> <td class="col-scope">{{ item.fwfw }}</td>
<td class="col-time">{{ item.createTime }}</td> <td class="col-time">{{ item.lrrq }}</td>
<td class="col-status"> <td class="col-status">
<span class="status-dot" :class="item.status === 'online' ? 'status--online' : 'status--offline'"></span> <span class="status-dot" :class="item.sjzt === 'Y' ? 'status--online' : 'status--offline'"></span>
{{ item.status === 'online' ? '已上线' : '未上线' }} {{ item.sjzt === 'Y' ? '已上线' : '未上线' }}
</td> </td>
<td class="col-action"> <td class="col-action">
<a class="action-link" @click="handleView(item)">查看</a> <a class="action-link" @click="handleView(item)">查看</a>
</td> </td>
</tr> </tr>
<tr class="more-row">
<td colspan="6">
<a class="more-link" @click="goToTfwgj">查看更多</a>
</td>
</tr>
</tbody> </tbody>
</table> </table>
<template v-else>
<div class="panel-header">
<h3 class="header-title">我的碳服务</h3>
</div>
<div class="empty-state">
<p class="empty-text">暂无服务</p>
<t-button theme="primary" size="small" @click="goToTfwgj">去发布</t-button>
</div>
</template>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { ListIcon } from 'tdesign-icons-vue'; import { ListIcon } from 'tdesign-icons-vue';
import api from '@/pages/index/api/gxzx/index';
export default { export default {
name: 'CarbonServiceTable', name: 'CarbonServiceTable',
@ -42,19 +57,32 @@ export default {
}, },
data() { data() {
return { return {
tableData: [ tableData: [],
{ id: 1, title: '碳服务供给信息', industry: '制造业', scope: '全国', createTime: '2026-04-20', status: 'online' },
{ id: 2, title: '碳服务供给信息', industry: '制造业', scope: '全国', createTime: '2026-04-18', status: 'online' },
{ id: 3, title: '碳服务供给信息', industry: '制造业', scope: '全国', createTime: '2026-04-15', status: 'offline' },
{ id: 4, title: '碳服务供给信息', industry: '制造业', scope: '全国', createTime: '2026-04-10', status: 'online' },
{ id: 5, title: '碳服务供给信息', industry: '制造业', scope: '全国', createTime: '2026-04-08', status: 'offline' },
],
}; };
}, },
created() {
this.fetchData();
},
methods: { methods: {
async fetchData() {
try {
const params = {
pageNumber: 1,
pageSize: 5,
};
const res = await api.gxxxListByYh(params);
this.tableData = res.data?.records || [];
} catch (error) {
console.error('获取服务列表失败', error);
this.tableData = [];
}
},
handleView(item) { handleView(item) {
console.log('查看详情', item); console.log('查看详情', item);
}, },
goToTfwgj() {
this.$router.push('/yhzx/tfwgj');
},
}, },
}; };
</script> </script>
@ -81,42 +109,24 @@ export default {
.panel-header { .panel-header {
display: flex; display: flex;
align-items: center; padding: 18px 20px;
gap: 14px;
padding: 18px 24px 16px;
background: linear-gradient(180deg, #FAFFFE 0%, @bg-card 100%); background: linear-gradient(180deg, #FAFFFE 0%, @bg-card 100%);
border-bottom: 1px solid @border-light; border-bottom: 1px solid @border-light;
align-items: center;
gap: 10px;
.header-icon { .header-title {
display: flex;
width: 40px;
height: 40px;
font-size: 20px;
color: #fff;
background: linear-gradient(135deg, @green-primary 0%, @green-dark 100%);
border-radius: 10px;
box-shadow: 0 4px 12px rgba(72, 198, 102, 0.3);
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.header-text {
flex: 1;
min-width: 0;
}
.panel-title {
margin: 0; margin: 0;
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
line-height: 1.4;
color: @text-dark; color: @text-dark;
flex: 1;
} }
} }
.table-wrapper { .table-wrapper {
overflow-x: auto; max-height: 320px;
overflow-y: auto;
} }
.data-table { .data-table {
@ -135,6 +145,9 @@ export default {
font-weight: 600; font-weight: 600;
color: @text-muted; color: @text-muted;
background: #FAFBFC; background: #FAFBFC;
position: sticky;
top: 0;
z-index: 1;
} }
td { td {
@ -206,5 +219,52 @@ export default {
color: @green-dark; color: @green-dark;
} }
} }
.more-row td {
text-align: center;
padding: 12px 16px;
border-bottom: none;
}
.more-link {
font-size: 13px;
font-weight: 500;
color: @green-primary;
cursor: pointer;
transition: color 0.2s ease;
&:hover {
color: @green-dark;
}
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 16px;
min-height: 200px;
.empty-icon {
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
margin-bottom: 16px;
font-size: 24px;
color: @text-light;
background: #F5F7FA;
border-radius: 50%;
}
.empty-text {
margin: 0 0 16px;
font-size: 14px;
color: @text-muted;
}
} }
</style> </style>

View File

@ -157,23 +157,36 @@
<div class="news-tabs"> <div class="news-tabs">
<div class="news-tab" :class="{ 'news-tab-active': activeTab === index }" v-for="(tab, index) in newsTabs" :key="index" @click="activeTab = index"> <div class="news-tab" :class="{ 'news-tab-active': activeTab === index }" v-for="(tab, index) in newsTabs" :key="index" @click="activeTab = index">
{{ tab }} {{ tab.name }}
</div> </div>
</div> </div>
<div class="news-list"> <!-- 骨架屏 -->
<div v-if="newsLoading" class="news-list">
<div class="news-item news-skeleton" v-for="i in 3" :key="i">
<div class="skeleton-pic"></div>
<div class="news-content">
<div class="skeleton-title"></div>
<div class="skeleton-meta"></div>
<div class="skeleton-desc"></div>
</div>
</div>
</div>
<!-- 新闻列表 -->
<div v-else class="news-list">
<div class="news-item" v-for="(item, index) in currentNewsList" :key="index" @click="handleNewsClick(item)"> <div class="news-item" v-for="(item, index) in currentNewsList" :key="index" @click="handleNewsClick(item)">
<img v-if="item.src" :src="item.pic" alt="" class="news-pic" /> <img :src="item.tp || getDefaultPic(newsTabs[activeTab].type)" alt="" class="news-pic" />
<div class="news-content"> <div class="news-content">
<div class="news-content-top"> <div class="news-content-top">
<div class="news-title">{{ item.title }}</div> <div class="news-title">{{ item.bt }}</div>
</div> </div>
<div class="news-content-middle"> <div class="news-content-middle">
<img src="@/pages/index/assets/alarm.png" class="news-alarm-icon" /> <img src="@/pages/index/assets/alarm.png" class="news-alarm-icon" />
<span class="news-date">{{ item.date }}</span> <span class="news-date">{{ item.fbsj }}</span>
<span v-if="item.remark" class="news-remark">{{ item.remark }}</span> <span v-if="item.lxr" class="news-remark">转载自 {{ item.lxr }}</span>
</div> </div>
<div v-if="item.content" class="news-content-bottom">{{ item.content }}</div> <div v-if="item.nr" class="news-content-bottom">{{ item.nr }}</div>
</div> </div>
</div> </div>
</div> </div>
@ -248,12 +261,19 @@
<script> <script>
import Footer from '@/pages/index/components/footer/index.vue'; import Footer from '@/pages/index/components/footer/index.vue';
import hydtApi from '@/pages/index/api/hydt';
export default { export default {
data() { data() {
return { return {
inputValue: '', inputValue: '',
activeTab: 0, activeTab: 0,
topBannerHeight: 820, topBannerHeight: 820,
newsLoading: true,
newsListByType: {
gjzc: [], //
hyzx: [], //
ptgg: [] //
},
topBannerImages: [ topBannerImages: [
require('@/pages/index/assets/home-top-bg1.jpg'), require('@/pages/index/assets/home-top-bg1.jpg'),
// require('@/pages/index/assets/home-top-bg2.jpg'), // require('@/pages/index/assets/home-top-bg2.jpg'),
@ -300,60 +320,11 @@ export default {
{ name: 'CBAM', btnName: "CBAM\n试算", desc: "欧盟对进口高碳产品按隐含排放征收碳关税。", icon: require('@/pages/index/assets/home-cbam-icon.png') }, { name: 'CBAM', btnName: "CBAM\n试算", desc: "欧盟对进口高碳产品按隐含排放征收碳关税。", icon: require('@/pages/index/assets/home-cbam-icon.png') },
{ name: '航运燃料', btnName: "申请服务", desc: "从化石油基向LNG、绿甲醇、绿氨等多元低碳方向加速转型。", icon: require('@/pages/index/assets/home-hyrl-icon.png') } { name: '航运燃料', btnName: "申请服务", desc: "从化石油基向LNG、绿甲醇、绿氨等多元低碳方向加速转型。", icon: require('@/pages/index/assets/home-hyrl-icon.png') }
], ],
// // tabs
newsTabs: ['国家政策', '行业资讯', '平台公告'], newsTabs: [
newsData: [ { name: '国家政策', type: 'gjzc' },
[ { name: '行业资讯', type: 'hyzx' },
{ title: '媒体报道 | “十五五”新图景:增绿降碳 加减之间再造万亿级新机遇', pic: require('@/pages/index/assets/news1.png'), date: '2026-03-31', remark: "转载自 中华人民共和国国家发展和改革委员会", content: "“十五五”规划纲要中提出加快经济社会发展全面绿色转型。当前一场增绿降碳的变革正在重塑我们的生产生活方式持续激发绿色发展动能。粤西海域离岸70公里外水深超50米一场绿色能源的接力正在加紧进行。一场绿色能源的接力正在加紧进行。一场绿色能源的接力正在加紧进行。总台央视记者 刘柏煊全球最大输送容量海上风电项目现在进入开春后的首个集中施工期8艘风机安装船在同步作业超过120米长的……", src: "https://www.ndrc.gov.cn/xwdt/spfg/mtjj/202603/t20260331_1404430.html" }, { name: '平台公告', type: 'ptgg' }
{ title: '2026年循环经济发展和资源综合利用专项扶持项目开始申报', pic: require('@/pages/index/assets/news2.png'), date: '2026-02-02', remark: "转载自 上海市发展和改革委员会", content: "根据《上海市循环经济发展和资源综合利用专项扶持办法2021版沪发改规范202113号以下简称《扶持办法》的要求结合上海市“免申即享”相关工作要求为做好2026年循环经济和资源综合利用项目申报工作上海市发展改革委近日发布《上海市发展改革委关于组织申报2026年循环经济发展和资源综合利用专项扶持项目的通知》", src: "https://fgw.sh.gov.cn/fgw_zyjyhhjbh/20260202/dbb80b9041b740da958411f9b3ea7e95.html" },
{ title: '商务部等9部门关于实施绿色消费推进行动的通知', pic: require('@/pages/index/assets/news3.png'), date: '2026-01-04', remark: "转载自 中华人民共和国中央人民政府", content: "各省、自治区、直辖市及计划单列市、新疆生产建设兵团商务、发展改革、工业和信息化、生态环境、住房城乡建设、农业农村、市场监管、金融监管部门,中国人民银行上海总部,各省、自治区、直辖市及计划单列市分行:为深入贯彻党的二十大和二十届历次全会精神,落实《中共中央 国务院关于加快经济社会发展全面绿色转型的意见》和中共中央办公厅、国务院办公厅印发的《提振消费专项行动方案》要求,加快发展方式和……", src: "https://www.gov.cn/zhengce/zhengceku/202601/content_7053876.htm" },
],
[
{
title: '全国首个红树林营造CCER项目完成登记 蓝碳生态价值实现路径获重要突破',
pic: require('@/pages/index/assets/news4.png'),
src: "https://www.cets.org.cn/xyyw/7348.jhtml",
date: '2026-03-22',
remark: "转载自 光明日报",
content: "3月20日全国首个红树林营造碳汇类国家温室气体自愿减排CCER项目“福建省霞浦县盐田乡和长春镇红树林植被修复项目”正式通过国家主管部门审核并完成登记注册。该项目由自然资源部第三海洋研究所作为项目业主申报实施中国质量认证中心CQC负责审定。项目的成功完成为海洋碳汇价值实现探索出可复制、可推广的实践路径是我国海洋生态系统保护修复领域的重要里程碑……"
},
{
title: '可再生能源电解水制氢等12项CCER方法学解读视频来了',
pic: require('@/pages/index/assets/news5.png'),
src: "https://www.cets.org.cn/xyyw/7347.jhtml",
date: '2026-03-20',
remark: "转载自 国家气候战略中心",
content: "可再生能源电解水制氢等12项CCER方法学解读视频来了"
},
{
title: '中碳登结算业务部获评2025年度全国巾帼文明岗',
pic: require('@/pages/index/assets/news6.png'),
src: "https://www.cets.org.cn/xyyw/7334.jhtml",
date: '2026-03-06',
remark: "转载自 中碳登",
content: "3月2日2025年度全国巾帼文明岗表彰名单正式揭晓碳排放权登记结算武汉有限责任公司以下简称“中碳登”结算业务部成功获评。这份全国巾帼建功领域的重磅荣誉是对中碳登“娘子军”专业实力、服务担当的高度认可更是对中碳登深耕全国碳市场基础设施建设、助力国家“双碳”战略落地成效的充分肯定..."
},
],
[
{
title: '关于碳信网接入全国温室气体排放因子数据库(第二版)的公告',
remark: "非真实公告,仅展示",
date: '2026-03-22',
content: "为进一步提升平台碳数据核算的准确性、权威性助力平台用户高效完成碳排放核算、碳信息报送工作碳信网已于2026年4月18日完成与国家温室气体排放因子数据库第二版的全面对接。本次对接后平台将同步更新576个全行业排放因子新增291个细分领域因子覆盖发电、钢铁、水泥、铝冶炼等重点控排行业可直接为用户提供合规、精准的因子查询、自动匹配及核算辅助服务。请各用户及时登录平台更新个人/企业碳数据核算模板确保数据符合最新监管要求如有操作疑问可通过平台在线客服或咨询热线400-XXXX-8899反馈……"
},
{
title: '2026年全国碳市场配额预分配相关信息提醒',
remark: "非真实公告,仅展示",
date: '2026-03-20',
content: "根据生态环境部《关于做好2026年全国碳排放权交易市场有关工作的通知》环办气候函202632号要求2026年全国碳市场配额预分配工作已正式启动。为帮助平台控排企业顺利完成配额认领、核对工作碳信网已开通配额预分配查询通道平台注册企业可登录“碳交易-配额管理”板块查询本企业预分配额度、行业基准值及相关政策说明。请钢铁、水泥、铝冶炼行业企业于4月30日前完成配额核对发电行业企业于6月20日前完成核对如有异议请在核对期限内提交书面说明逾期将视为无异议具体操作指南可在平台“政策中心”下载查阅"
},
{
title: '碳信网碳信息披露服务升级及上线通知',
date: '2026-03-06',
remark: "非真实公告,仅展示",
content: "为响应欧盟CBAM碳边境调节机制全面实施及国内上市公司ESG报告强制披露要求碳信网对碳信息披露服务进行全面升级新增碳足迹核算、ESG碳信息填报、报告生成及合规校验四大功能模块。本次升级后平台可支持企业快速完成全流程碳信息披露自动生成符合国内外标准的披露报告助力企业对接国际市场、满足监管要求。升级功能于2026年4月12日正式上线所有注册用户可免费体验基础版服务企业用户可申请升级专业版享受一对一咨询、定制化报告及合规审核服务详情可登录平台“碳信息-披露服务”板块了解..."
},
],
], ],
// //
partnerCount: '200+', partnerCount: '200+',
@ -400,6 +371,7 @@ export default {
mounted() { mounted() {
this.syncBannerHeight(); this.syncBannerHeight();
window.addEventListener('resize', this.syncBannerHeight); window.addEventListener('resize', this.syncBannerHeight);
this.fetchNewsData();
}, },
beforeDestroy() { beforeDestroy() {
window.removeEventListener('resize', this.syncBannerHeight); window.removeEventListener('resize', this.syncBannerHeight);
@ -469,20 +441,52 @@ export default {
}, },
// //
handleNewsClick(item) { handleNewsClick(item) {
if (item.src) { if (item.yyLj) {
window.open(item.src, '_blank'); window.open(item.yyLj, '_blank');
} else { } else {
console.log('点击新闻:', item.title); console.log('点击新闻:', item.bt);
this.$message.info(item.title); this.$message.info(item.bt);
} }
}, },
handleNewsMore() { handleNewsMore() {
this.$message.info('暂无更多动态'); this.$message.info('暂无更多动态');
}, },
async fetchNewsData() {
this.newsLoading = true;
try {
//
const [hydtRes, ptggRes] = await Promise.all([
hydtApi.getHydtGroupedList(),
hydtApi.getPtggList()
]);
if (hydtRes.data) {
this.newsListByType.gjzc = hydtRes.data.gjzc || [];
this.newsListByType.hyzx = hydtRes.data.hyzx || [];
}
if (ptggRes.data) {
this.newsListByType.ptgg = ptggRes.data || [];
}
} catch (e) {
console.error('获取新闻数据失败', e);
} finally {
this.newsLoading = false;
}
},
getDefaultPic(type) {
const defaultPics = {
gjzc: '/static_res/images/news/default-news.png',
hyzx: '/static_res/images/news/default-hydt.png',
ptgg: '/static_res/images/news/default-ptgg.png'
};
return defaultPics[type] || '/static_res/images/news/default-news.png';
},
}, },
computed: { computed: {
currentNewsList() { currentNewsList() {
return this.newsData[this.activeTab] || []; const type = this.newsTabs[this.activeTab]?.type;
const list = this.newsListByType[type] || [];
return list.slice(0, 3); // 3
}, },
partnerRow1() { partnerRow1() {
const row = this.partnerList.slice(0, 4); const row = this.partnerList.slice(0, 4);
@ -1502,6 +1506,57 @@ export default {
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
} }
/* 骨架屏样式 */
.news-skeleton {
pointer-events: none;
}
.skeleton-pic {
width: 200px;
height: 150px;
border-radius: 8px;
flex-shrink: 0;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: skeleton-loading 1.5s infinite;
}
.skeleton-title {
width: 80%;
height: 20px;
border-radius: 4px;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: skeleton-loading 1.5s infinite;
}
.skeleton-meta {
width: 50%;
height: 14px;
border-radius: 4px;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: skeleton-loading 1.5s infinite;
}
.skeleton-desc {
width: 95%;
height: 40px;
border-radius: 4px;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: skeleton-loading 1.5s infinite;
}
@keyframes skeleton-loading {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
/* ==================== 企业出海模块 ==================== */ /* ==================== 企业出海模块 ==================== */
.overseas-section { .overseas-section {
position: relative; position: relative;

View File

@ -1,54 +1,56 @@
<template> <template>
<div class="change-password-page"> <div class="change-password-page">
<div class="page-header"> <section class="left-panel">
<div class="page-title">修改密码</div> <div class="page-header">
</div> <div class="page-title">修改密码</div>
<div class="page-content"> </div>
<t-form <div class="page-content">
ref="formRef" <t-form
:data="formData" ref="formRef"
:rules="rules" :data="formData"
labelWidth="120" :rules="rules"
@submit="onSubmit" labelWidth="120"
class="password-form" @submit="onSubmit"
> class="password-form"
<t-form-item label="旧密码" name="oldPassword"> >
<t-input <t-form-item label="旧密码" name="oldPassword">
v-model="formData.oldPassword" <t-input
type="password" v-model="formData.oldPassword"
placeholder="请输入旧密码" type="password"
clearable placeholder="请输入旧密码"
showPassword clearable
/> showPassword
</t-form-item> />
</t-form-item>
<t-form-item label="新密码" name="newPassword"> <t-form-item label="新密码" name="newPassword">
<t-input <t-input
v-model="formData.newPassword" v-model="formData.newPassword"
type="password" type="password"
placeholder="请输入新密码" placeholder="请输入新密码"
clearable clearable
showPassword showPassword
/> />
<div class="password-tip">密码长度6-20需包含字母和数字</div> <div class="password-tip">密码长度6-20需包含字母和数字</div>
</t-form-item> </t-form-item>
<t-form-item label="确认密码" name="confirmPassword"> <t-form-item label="确认密码" name="confirmPassword">
<t-input <t-input
v-model="formData.confirmPassword" v-model="formData.confirmPassword"
type="password" type="password"
placeholder="请再次输入新密码" placeholder="请再次输入新密码"
clearable clearable
showPassword showPassword
/> />
</t-form-item> </t-form-item>
<t-form-item class="submit-item"> <t-form-item class="submit-item">
<t-button theme="primary" type="submit" :loading="submitLoading">确认修改</t-button> <t-button theme="primary" type="submit" :loading="submitLoading">确认修改</t-button>
<t-button theme="default" variant="outline" @click="onReset" style="margin-left: 12px">重置</t-button> <t-button theme="default" variant="outline" @click="onReset" style="margin-left: 12px">重置</t-button>
</t-form-item> </t-form-item>
</t-form> </t-form>
</div> </div>
</section>
</div> </div>
</template> </template>
@ -156,9 +158,17 @@ export default {
<style lang="less" scoped> <style lang="less" scoped>
.change-password-page { .change-password-page {
min-height: calc(100vh - 60px);
padding: 24px; padding: 24px;
background: #fff; background: #F5F7FA;
min-height: 100%; }
.left-panel {
padding: 20px;
background: #FFFFFF;
border-radius: 4px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
overflow: hidden;
} }
.page-header { .page-header {

View File

@ -0,0 +1,49 @@
-- 行业动态表(国家政策、行业资讯)
CREATE TABLE `txw_mhzc_hydtb` (
`uuid` VARCHAR(50) NOT NULL COMMENT 'UUID',
`bt` VARCHAR(500) NOT NULL COMMENT '标题',
`tp` VARCHAR(500) DEFAULT NULL COMMENT '图片',
`nr` TEXT COMMENT '内容',
`wx_nr` TEXT COMMENT '详细内容(富文本)',
`fbsj` DATETIME DEFAULT NULL COMMENT '发布时间',
`lx` VARCHAR(10) NOT NULL COMMENT '类型gjzc=国家政策、hyzx=行业资讯)',
`lx_mc` VARCHAR(50) DEFAULT NULL COMMENT '类型名称',
`lxr` VARCHAR(100) DEFAULT NULL COMMENT '来源',
`yy_lj` VARCHAR(500) DEFAULT NULL COMMENT '原文链接',
`zt` CHAR(1) DEFAULT '1' COMMENT '状态1=正常0=禁用)',
`llcs` INT DEFAULT 0 COMMENT '浏览次数',
`lrrq` DATETIME DEFAULT NULL COMMENT '录入日期',
`lrruuid` VARCHAR(50) DEFAULT NULL COMMENT '录入人UUID',
`xgrq` DATETIME DEFAULT NULL COMMENT '修改日期',
`xgruuid` VARCHAR(50) DEFAULT NULL COMMENT '修改人UUID',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='行业动态表';
-- 插入示例数据图片路径为public下的相对路径
INSERT INTO `txw_mhzc_hydtb` (`uuid`, `bt`, `tp`, `nr`, `fbsj`, `lx`, `lx_mc`, `lxr`, `yy_lj`) VALUES
('hydt_001', '媒体报道 | "十五五"新图景:增绿降碳 加减之间再造万亿级新机遇', '/static_res/images/news/news1.png', '"十五五"规划纲要中提出,加快经济社会发展全面绿色转型...', '2026-03-31 00:00:00', 'gjzc', '国家政策', '中华人民共和国国家发展和改革委员会', 'https://www.ndrc.gov.cn/xwdt/spfg/mtjj/202603/t20260331_1404430.html'),
('hydt_002', '2026年循环经济发展和资源综合利用专项扶持项目开始申报', '/static_res/images/news/news2.png', '根据《上海市循环经济发展和资源综合利用专项扶持办法2021版》...', '2026-02-02 00:00:00', 'gjzc', '国家政策', '上海市发展和改革委员会', 'https://fgw.sh.gov.cn/fgw_zyjyhhjbh/20260202/dbb80b9041b740da958411f9b3ea7e95.html'),
('hydt_003', '商务部等9部门关于实施绿色消费推进行动的通知', '/static_res/images/news/news3.png', '各省、自治区、直辖市及计划单列市、新疆生产建设兵团商务、发展改革、工业和信息化、生态环境、住房城乡建设、农业农村、市场监管、金融监管部门...', '2026-01-04 00:00:00', 'gjzc', '国家政策', '中华人民共和国中央人民政府', 'https://www.gov.cn/zhengce/zhengceku/202601/content_7053876.htm'),
('hydt_004', '全国首个红树林营造CCER项目完成登记 蓝碳生态价值实现路径获重要突破', '/static_res/images/news/news4.png', '3月20日全国首个红树林营造碳汇类国家温室气体自愿减排CCER项目...', '2026-03-22 00:00:00', 'hyzx', '行业资讯', '光明日报', 'https://www.cets.org.cn/xyyw/7348.jhtml'),
('hydt_005', '可再生能源电解水制氢等12项CCER方法学解读视频来了', '/static_res/images/news/news5.png', '可再生能源电解水制氢等12项CCER方法学解读视频来了', '2026-03-20 00:00:00', 'hyzx', '行业资讯', '国家气候战略中心', 'https://www.cets.org.cn/xyyw/7347.jhtml'),
('hydt_006', '中碳登结算业务部获评2025年度全国巾帼文明岗', '/static_res/images/news/news6.png', '3月2日2025年度全国巾帼文明岗表彰名单正式揭晓...', '2026-03-06 00:00:00', 'hyzx', '行业资讯', '中碳登', 'https://www.cets.org.cn/xyyw/7334.jhtml');
-- 平台公告表
CREATE TABLE `txw_mhzc_ptgg` (
`uuid` VARCHAR(50) NOT NULL COMMENT 'UUID',
`bt` VARCHAR(500) NOT NULL COMMENT '标题',
`nr` TEXT COMMENT '内容',
`fbsj` DATETIME DEFAULT NULL COMMENT '发布时间',
`zt` CHAR(1) DEFAULT '1' COMMENT '状态1=正常0=禁用)',
`lrrq` DATETIME DEFAULT NULL COMMENT '录入日期',
`lrruuid` VARCHAR(50) DEFAULT NULL COMMENT '录入人UUID',
`xgrq` DATETIME DEFAULT NULL COMMENT '修改日期',
`xgruuid` VARCHAR(50) DEFAULT NULL COMMENT '修改人UUID',
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='平台公告表';
-- 插入平台公告示例数据
INSERT INTO `txw_mhzc_ptgg` (`uuid`, `bt`, `nr`, `fbsj`) VALUES
('ptgg_001', '关于碳信网接入全国温室气体排放因子数据库(第二版)的公告', '为进一步提升平台碳数据核算的准确性、权威性助力平台用户高效完成碳排放核算、碳信息报送工作碳信网已于2026年4月18日完成与国家温室气体排放因子数据库第二版的全面对接...', '2026-03-22 00:00:00'),
('ptgg_002', '2026年全国碳市场配额预分配相关信息提醒', '根据生态环境部《关于做好2026年全国碳排放权交易市场有关工作的通知》要求2026年全国碳市场配额预分配工作已正式启动...', '2026-03-20 00:00:00'),
('ptgg_003', '碳信网碳信息披露服务升级及上线通知', '为响应欧盟CBAM碳边境调节机制全面实施及国内上市公司ESG报告强制披露要求碳信网对碳信息披露服务进行全面升级...', '2026-03-06 00:00:00');

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
package com.css.txw.mhzc.controller;
import com.css.ggzc.framework.common.pojo.CommonResult;
import com.css.txw.mhzc.pojo.vo.HydtbVO;
import com.css.txw.mhzc.service.TxwMhzcHydtbService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Tag(name = "行业动态接口")
@RestController
@RequestMapping("/sy/hydt")
@Validated
@Slf4j
public class HydtController {
@Resource
private TxwMhzcHydtbService hydtbService;
@GetMapping("/list")
@Operation(summary = "查询行业动态列表", description = "按类型查询行业动态,不传类型则查询全部")
public CommonResult<List<HydtbVO>> getList(@RequestParam(required = false) String lx) {
List<HydtbVO> list;
if (lx == null || lx.isEmpty()) {
list = hydtbService.getAll();
} else {
list = hydtbService.getByLx(lx);
}
return CommonResult.success(list);
}
@GetMapping("/groupedList")
@Operation(summary = "查询行业动态列表(按类型分组)", description = "返回按类型分组的行业动态")
public CommonResult<Map<String, List<HydtbVO>>> getGroupedList() {
Map<String, List<HydtbVO>> map = hydtbService.getGroupedByLx();
return CommonResult.success(map);
}
}

View File

@ -0,0 +1,32 @@
package com.css.txw.mhzc.controller;
import com.css.ggzc.framework.common.pojo.CommonResult;
import com.css.txw.mhzc.pojo.vo.PtggVO;
import com.css.txw.mhzc.service.TxwMhzcPtggService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Tag(name = "平台公告接口")
@RestController
@RequestMapping("/sy/ptgg")
@Validated
@Slf4j
public class PtggController {
@Resource
private TxwMhzcPtggService ptggService;
@GetMapping("/list")
@Operation(summary = "查询平台公告列表", description = "查询所有平台公告,按发布时间倒序")
public CommonResult<List<PtggVO>> getList() {
List<PtggVO> list = ptggService.getAll();
return CommonResult.success(list);
}
}

View File

@ -0,0 +1,40 @@
package com.css.txw.mhzc.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.css.txw.mhzc.pojo.domain.TxwMhzcHydtbDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author Claude
* @description 针对表txw_mhzc_hydtb(行业动态表)的数据库操作Mapper
* @createDate 2026-04-30
* @Entity com.css.txw.mhzc.pojo.domain.TxwMhzcHydtbDO
*/
public interface TxwMhzcHydtbMapper extends BaseMapper<TxwMhzcHydtbDO> {
/**
* 根据类型查询行业动态按发布时间倒序
*/
default List<TxwMhzcHydtbDO> getByLx(@Param("lx") String lx) {
QueryWrapper<TxwMhzcHydtbDO> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(TxwMhzcHydtbDO::getZt, "1");
if (lx != null && !lx.isEmpty()) {
wrapper.lambda().eq(TxwMhzcHydtbDO::getLx, lx);
}
wrapper.lambda().orderByDesc(TxwMhzcHydtbDO::getFbsj);
return selectList(wrapper);
}
/**
* 查询所有行业动态按发布时间倒序
*/
default List<TxwMhzcHydtbDO> getAllOrderByFbsj() {
QueryWrapper<TxwMhzcHydtbDO> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(TxwMhzcHydtbDO::getZt, "1");
wrapper.lambda().orderByDesc(TxwMhzcHydtbDO::getFbsj);
return selectList(wrapper);
}
}

View File

@ -0,0 +1,27 @@
package com.css.txw.mhzc.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.css.txw.mhzc.pojo.domain.TxwMhzcPtggDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author Claude
* @description 针对表txw_mhzc_ptgg(平台公告表)的数据库操作Mapper
* @createDate 2026-04-30
* @Entity com.css.txw.mhzc.pojo.domain.TxwMhzcPtggDO
*/
public interface TxwMhzcPtggMapper extends BaseMapper<TxwMhzcPtggDO> {
/**
* 查询所有平台公告按发布时间倒序
*/
default List<TxwMhzcPtggDO> getAllOrderByFbsj() {
QueryWrapper<TxwMhzcPtggDO> wrapper = new QueryWrapper<>();
wrapper.lambda().eq(TxwMhzcPtggDO::getZt, "1");
wrapper.lambda().orderByDesc(TxwMhzcPtggDO::getFbsj);
return selectList(wrapper);
}
}

View File

@ -0,0 +1,116 @@
package com.css.txw.mhzc.pojo.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
/**
* 行业动态表
* @TableName txw_mhzc_hydtb
*/
@TableName(value ="txw_mhzc_hydtb")
@Data
public class TxwMhzcHydtbDO implements Serializable {
/**
* UUID||uuid
*/
@TableId(value = "uuid")
private String uuid;
/**
* 标题
*/
@TableField(value = "bt")
private String bt;
/**
* 图片
*/
@TableField(value = "tp")
private String tp;
/**
* 内容
*/
@TableField(value = "nr")
private String nr;
/**
* 详细内容富文本
*/
@TableField(value = "wx_nr")
private String wxNr;
/**
* 发布时间
*/
@TableField(value = "fbsj")
private LocalDateTime fbsj;
/**
* 类型gjzc=国家政策hyzx=行业资讯ptgg=平台公告
*/
@TableField(value = "lx")
private String lx;
/**
* 类型名称
*/
@TableField(value = "lx_mc")
private String lxMc;
/**
* 来源
*/
@TableField(value = "lxr")
private String lxr;
/**
* 原文链接
*/
@TableField(value = "yy_lj")
private String yyLj;
/**
* 状态1=正常0=禁用
*/
@TableField(value = "zt")
private String zt;
/**
* 浏览次数
*/
@TableField(value = "llcs")
private Integer llcs;
/**
* 录入日期
*/
@TableField(value = "lrrq")
private LocalDateTime lrrq;
/**
* 录入人UUID
*/
@TableField(value = "lrruuid")
private String lrruuid;
/**
* 修改日期
*/
@TableField(value = "xgrq")
private LocalDateTime xgrq;
/**
* 修改人UUID
*/
@TableField(value = "xgruuid")
private String xgruuid;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,74 @@
package com.css.txw.mhzc.pojo.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Data;
/**
* 平台公告表
* @TableName txw_mhzc_ptgg
*/
@TableName(value ="txw_mhzc_ptgg")
@Data
public class TxwMhzcPtggDO implements Serializable {
/**
* UUID||uuid
*/
@TableId(value = "uuid")
private String uuid;
/**
* 标题
*/
@TableField(value = "bt")
private String bt;
/**
* 内容
*/
@TableField(value = "nr")
private String nr;
/**
* 发布时间
*/
@TableField(value = "fbsj")
private LocalDateTime fbsj;
/**
* 状态1=正常0=禁用
*/
@TableField(value = "zt")
private String zt;
/**
* 录入日期
*/
@TableField(value = "lrrq")
private LocalDateTime lrrq;
/**
* 录入人UUID
*/
@TableField(value = "lrruuid")
private String lrruuid;
/**
* 修改日期
*/
@TableField(value = "xgrq")
private LocalDateTime xgrq;
/**
* 修改人UUID
*/
@TableField(value = "xgruuid")
private String xgruuid;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,57 @@
package com.css.txw.mhzc.pojo.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class HydtbVO implements Serializable {
private String uuid;
/**
* 标题
*/
private String bt;
/**
* 图片
*/
private String tp;
/**
* 内容
*/
private String nr;
/**
* 详细内容富文本
*/
private String wxNr;
/**
* 发布时间
*/
private String fbsj;
/**
* 类型
*/
private String lx;
/**
* 类型名称
*/
private String lxMc;
/**
* 来源
*/
private String lxr;
/**
* 原文链接
*/
private String yyLj;
}

View File

@ -0,0 +1,27 @@
package com.css.txw.mhzc.pojo.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class PtggVO implements Serializable {
private String uuid;
/**
* 标题
*/
private String bt;
/**
* 内容
*/
private String nr;
/**
* 发布时间
*/
private String fbsj;
}

View File

@ -0,0 +1,33 @@
package com.css.txw.mhzc.service;
import com.css.txw.mhzc.pojo.domain.TxwMhzcHydtbDO;
import com.baomidou.mybatisplus.extension.service.IService;
import com.css.txw.mhzc.pojo.vo.HydtbVO;
import java.util.List;
import java.util.Map;
/**
* @author Claude
* @description 针对表txw_mhzc_hydtb(行业动态表)的数据库操作Service
* @createDate 2026-04-30
*/
public interface TxwMhzcHydtbService extends IService<TxwMhzcHydtbDO> {
/**
* 按类型查询行业动态列表
* @param lx 类型gjzc=国家政策hyzx=行业资讯ptgg=平台公告
*/
List<HydtbVO> getByLx(String lx);
/**
* 获取所有行业动态按发布时期倒序
*/
List<HydtbVO> getAll();
/**
* 获取所有行业动态按类型分组
*/
Map<String, List<HydtbVO>> getGroupedByLx();
}

View File

@ -0,0 +1,21 @@
package com.css.txw.mhzc.service;
import com.css.txw.mhzc.pojo.domain.TxwMhzcPtggDO;
import com.baomidou.mybatisplus.extension.service.IService;
import com.css.txw.mhzc.pojo.vo.PtggVO;
import java.util.List;
/**
* @author Claude
* @description 针对表txw_mhzc_ptgg(平台公告表)的数据库操作Service
* @createDate 2026-04-30
*/
public interface TxwMhzcPtggService extends IService<TxwMhzcPtggDO> {
/**
* 获取所有平台公告按发布时间倒序
*/
List<PtggVO> getAll();
}

View File

@ -0,0 +1,49 @@
package com.css.txw.mhzc.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.css.ggzc.framework.common.util.gy.GyUtils;
import com.css.ggzc.framework.common.util.object.BeanUtils;
import com.css.txw.mhzc.pojo.domain.TxwMhzcHydtbDO;
import com.css.txw.mhzc.pojo.vo.HydtbVO;
import com.css.txw.mhzc.mapper.TxwMhzcHydtbMapper;
import com.css.txw.mhzc.service.TxwMhzcHydtbService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author Claude
* @description 针对表txw_mhzc_hydtb(行业动态表)的数据库操作Service实现
* @createDate 2026-04-30
*/
@Service
public class TxwMhzcHydtbServiceImpl extends ServiceImpl<TxwMhzcHydtbMapper, TxwMhzcHydtbDO>
implements TxwMhzcHydtbService {
@Resource
private TxwMhzcHydtbMapper hydtbMapper;
@Override
public List<HydtbVO> getByLx(String lx) {
List<TxwMhzcHydtbDO> list = hydtbMapper.getByLx(lx);
if (GyUtils.isNull(list)) return null;
return BeanUtils.toBean(list, HydtbVO.class);
}
@Override
public List<HydtbVO> getAll() {
List<TxwMhzcHydtbDO> list = hydtbMapper.getAllOrderByFbsj();
if (GyUtils.isNull(list)) return null;
return BeanUtils.toBean(list, HydtbVO.class);
}
@Override
public Map<String, List<HydtbVO>> getGroupedByLx() {
List<HydtbVO> all = getAll();
if (GyUtils.isNull(all)) return null;
return all.stream().collect(Collectors.groupingBy(HydtbVO::getLx));
}
}

View File

@ -0,0 +1,33 @@
package com.css.txw.mhzc.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.css.ggzc.framework.common.util.gy.GyUtils;
import com.css.ggzc.framework.common.util.object.BeanUtils;
import com.css.txw.mhzc.pojo.domain.TxwMhzcPtggDO;
import com.css.txw.mhzc.pojo.vo.PtggVO;
import com.css.txw.mhzc.mapper.TxwMhzcPtggMapper;
import com.css.txw.mhzc.service.TxwMhzcPtggService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @author Claude
* @description 针对表txw_mhzc_ptgg(平台公告表)的数据库操作Service实现
* @createDate 2026-04-30
*/
@Service
public class TxwMhzcPtggServiceImpl extends ServiceImpl<TxwMhzcPtggMapper, TxwMhzcPtggDO>
implements TxwMhzcPtggService {
@Resource
private TxwMhzcPtggMapper ptggMapper;
@Override
public List<PtggVO> getAll() {
List<TxwMhzcPtggDO> list = ptggMapper.getAllOrderByFbsj();
if (GyUtils.isNull(list)) return null;
return BeanUtils.toBean(list, PtggVO.class);
}
}