cms功能 添加 5。8

master
zhc077 2 years ago
parent 644d924e63
commit e3f6118c44
  1. 16
      ant-design-vue-jeecg/src/config/router.config.js
  2. 3
      ant-design-vue-jeecg/src/permission.js
  3. 209
      ant-design-vue-jeecg/src/views/cms/admin/CmsArticleList.vue
  4. 379
      ant-design-vue-jeecg/src/views/cms/admin/CmsColumnList.vue
  5. 132
      ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleForm.vue
  6. 60
      ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleModal.vue
  7. 84
      ant-design-vue-jeecg/src/views/cms/admin/modules/CmsArticleModal__Style#Drawer.vue
  8. 165
      ant-design-vue-jeecg/src/views/cms/admin/modules/CmsColumnModal.vue
  9. BIN
      ant-design-vue-jeecg/src/views/cms/assets/Group01.png
  10. BIN
      ant-design-vue-jeecg/src/views/cms/assets/Group02.png
  11. BIN
      ant-design-vue-jeecg/src/views/cms/assets/Group03.png
  12. BIN
      ant-design-vue-jeecg/src/views/cms/assets/Group04.png
  13. BIN
      ant-design-vue-jeecg/src/views/cms/assets/bg02.png
  14. BIN
      ant-design-vue-jeecg/src/views/cms/assets/logo.png
  15. BIN
      ant-design-vue-jeecg/src/views/cms/assets/logo5.png
  16. 64
      ant-design-vue-jeecg/src/views/cms/assets/reset.css
  17. 53
      ant-design-vue-jeecg/src/views/cms/components/FooterView.vue
  18. 108
      ant-design-vue-jeecg/src/views/cms/components/HeaderView.vue
  19. 195
      ant-design-vue-jeecg/src/views/cms/home.vue
  20. 268
      ant-design-vue-jeecg/src/views/cms/pages/Detail/DetailView.vue
  21. 290
      ant-design-vue-jeecg/src/views/cms/pages/Major/MajorView.vue
  22. 41
      jeecg-boot/jeecg-boot-module-cms/pom.xml
  23. 190
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/controller/CmsArticleController.java
  24. 260
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/controller/CmsColumnController.java
  25. 111
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/entity/CmsArticle.java
  26. 96
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/entity/CmsColumn.java
  27. 15
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/mapper/CmsArticleMapper.java
  28. 23
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/mapper/CmsColumnMapper.java
  29. 15
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/ICmsArticleService.java
  30. 54
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/ICmsColumnService.java
  31. 20
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/impl/CmsArticleServiceImpl.java
  32. 192
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/admin/service/impl/CmsColumnServiceImpl.java
  33. 70
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/front/CmsHomePageController.java
  34. 67
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/controller/NewsWebMagicController.java
  35. 93
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/service/NewsPageProcessor.java
  36. 59
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/service/NewsPipeline.java
  37. 53
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/NewsAsyncJob.java
  38. 71
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/NewsWebMagicTask.java
  39. 22
      jeecg-boot/jeecg-boot-module-cms/src/main/java/org/jeecg/modules/cms/webmagic/task/SampleJobTest.java
  40. 12
      jeecg-boot/jeecg-boot-module-system/pom.xml
  41. 2
      jeecg-boot/jeecg-boot-module-system/src/main/resources/logback-spring.xml
  42. 71
      jeecg-boot/pom.xml

@ -553,5 +553,21 @@ export const constantRouterMap = [
// component: () => import(/* webpackChunkName: "fail" */ '@/views/seknowgroup/SeKnowAtlasList'),
},
//cms首页,免登录,单独访问页面
// #/protal/home
//需要在新窗口打开的页面路径
{
path: '/cms/home',//这里是你需要设置新窗口打开的页面的路径
component: () => import('@/views/cms/home'),
},
{
path: '/cms/major',//这里是你需要设置新窗口打开的页面的路径
component: () => import('@/views/cms/pages/Major/MajorView'),
},
{
path: '/cms/detail',//这里是你需要设置新窗口打开的页面的路径
component: () => import('@/views/cms/pages/Detail/DetailView'),
},
]

@ -26,6 +26,9 @@ const whiteList = [
'/user/register',
'/user/register-result',
'/user/alteration',
'/cms/home',
'/cms/major',
'/cms/detail',
] // no redirect whitelist
router.beforeEach((to, from, next) => {

@ -0,0 +1,209 @@
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="栏目">
<!-- <j-select-depart placeholder="请选择车间" v-model="queryParam.name"/>-->
<j-dict-select-tag type="list" v-model="queryParam.columnId"
dictCode="cms_column,name,id"/>
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="标题">
<!-- <j-dict-select-tag type="radio" v-model="queryParam.speedUp" dictCode="sfjj" placeholder="请选择是否加急"/>-->
<a-input placeholder="请输入标题" v-model="queryParam.title"></a-input>
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="是否发布">
<!-- <j-dict-select-tag type="radio" v-model="queryParam.speedUp" dictCode="sfjj" placeholder="请选择是否加急"/>-->
<j-dict-select-tag type="list" v-model="queryParam.status" dictCode="isShow"
placeholder="请选择是否发布"/>
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
<a-button type="primary" @click="searchReset" icon="reload"
style="margin-left: 8px">重置</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
<a-button type="primary" icon="download" @click="handleExportXls('文章管理')">导出</a-button>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a
style="font-weight: 600">{{ selectedRowKeys.length }}</a>
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
:scroll="{x:true}"
bordered
rowKey="id"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
class="j-table-force-nowrap"
@change="handleTableChange">
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical"/>
<a v-if="record.status==0" @click="operationStatus(record,'1')">发布</a>
<a v-if="record.status==1" @click="operationStatus(record,'0')">取消发布</a>
<a-divider type="vertical"/>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
<a>删除</a>
</a-popconfirm>
</span>
</a-table>
</div>
<cms-article-modal ref="modalForm" @ok="modalFormOk"></cms-article-modal>
</a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import {mixinDevice} from '@/utils/mixin'
import {JeecgListMixin} from '@/mixins/JeecgListMixin'
import CmsArticleModal from './modules/CmsArticleModal'
import {postAction} from "@api/manage";
export default {
name: 'CmsArticleList',
mixins: [JeecgListMixin, mixinDevice],
components: {
CmsArticleModal
},
data() {
return {
description: '文章管理管理页面',
//
columns: [
// {
// title: '#',
// dataIndex: '',
// key: 'rowIndex',
// width: 60,
// align: "center",
// customRender: function (t, r, index) {
// return parseInt(index) + 1;
// }
// },
{
title: '所属栏目',
align: "center",
dataIndex: 'columnName'
},
{
title: '文章标题',
align: "center",
dataIndex: 'title'
},
{
title: '作者',
align: "center",
dataIndex: 'createBy_dictText'
},
{
title: '来源',
align: "center",
dataIndex: 'source'
},
{
title: '是否发布',
align: "center",
dataIndex: 'status_dictText'
},
{
title: '发布时间',
align: "center",
dataIndex: 'publishTime'
},
{
title: '操作',
dataIndex: 'action',
align: "center",
fixed: "right",
width: 147,
scopedSlots: {customRender: 'action'}
}
],
url: {
list: "/cms/cmsArticle/list",
delete: "/cms/cmsArticle/delete",
deleteBatch: "/cms/cmsArticle/deleteBatch",
exportXlsUrl: "/cms/cmsArticle/exportXls",
operationStatus: "cms/cmsArticle/operationStatus",
},
dictOptions: {},
superFieldList: [],
}
},
// created() {
// this.loadData();
// },
computed: {
importExcelUrl: function () {
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
},
},
methods: {
operationStatus(record, status) {
let parma = {
"id": record.id,
"status": status,
}
postAction(this.url.operationStatus, parma).then((res) => {
if (res.success) {
this.$message.success("操作成功");
this.loadData();
} else {
this.$message.warning(res.message)
}
}).finally(() => {
this.loading = false
this.loadData();
})
},
initDictConfig() {
},
getSuperFieldList() {
let fieldList = [];
fieldList.push({type: 'string', value: 'title', text: '文章标题', dictCode: ''})
fieldList.push({type: 'string', value: 'status', text: '状态', dictCode: ''})
fieldList.push({type: 'string', value: 'columnId', text: '所属栏目', dictCode: ''})
fieldList.push({type: 'string', value: 'columnName', text: '栏目', dictCode: ''})
fieldList.push({type: 'string', value: 'source', text: '来源', dictCode: ''})
this.superFieldList = fieldList
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>

@ -0,0 +1,379 @@
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="栏目名称">
<!-- <j-select-depart placeholder="请选择车间" v-model="queryParam.name"/>-->
<j-dict-select-tag type="list" v-model="queryParam.name"
dictCode="cms_column,name,name"/>
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<a-form-item label="是否显示">
<!-- <j-dict-select-tag type="radio" v-model="queryParam.speedUp" dictCode="sfjj" placeholder="请选择是否加急"/>-->
<j-dict-select-tag type="list" v-model="queryParam.isShow" dictCode="isShow"
placeholder="请选择是否显示"/>
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
<a-button type="primary" @click="searchReset" icon="reload"
style="margin-left: 8px">重置</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<!-- 查询区域-END -->
<!-- 操作按钮区域 -->
<div class="table-operator">
<!-- <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>-->
<!-- <a-button @click="handleAddChild" type="primary" icon="plus">新增2</a-button>-->
<a-button type="primary" icon="download" @click="handleExportXls('文章栏目')">导出</a-button>
<!-- <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">-->
<!-- <a-button type="primary" icon="import">导入</a-button>-->
<!-- </a-upload>-->
<!-- 高级查询区域 -->
<!-- <j-super-query :fieldList="superFieldList" ref="superQueryModal" @handleSuperQuery="handleSuperQuery"></j-super-query>-->
<!-- <a-dropdown v-if="selectedRowKeys.length > 0">-->
<!-- <a-menu slot="overlay">-->
<!-- <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>-->
<!-- </a-menu>-->
<!-- <a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>-->
<!-- </a-dropdown>-->
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i> 已选择 <a
style="font-weight: 600">{{ selectedRowKeys.length }}</a>
<a style="margin-left: 24px" @click="onClearSelected">清空</a>
</div>
<a-table
ref="table"
size="middle"
rowKey="id"
class="j-table-force-nowrap"
:scroll="{x:true}"
:columns="columns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
:expandedRowKeys="expandedRowKeys"
@change="handleTableChange"
@expand="handleExpand"
bordered
v-bind="tableProps">
<span slot="action" slot-scope="text, record">
<a @click="handleEdit(record)">编辑</a>
<a-divider type="vertical"/>
<a-popconfirm title="确定删除吗?" @confirm="() => handleDeleteNode(record.id)" placement="topLeft">
<a>删除</a>
</a-popconfirm>
<a-divider type="vertical"/>
<a @click="handleAddChild(record)">添加下级</a>
</span>
</a-table>
</div>
<cmsColumn-modal ref="modalForm" @ok="modalFormOk"></cmsColumn-modal>
</a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import {deleteAction, getAction} from '@/api/manage'
import {JeecgListMixin} from '@/mixins/JeecgListMixin'
import CmsColumnModal from './modules/CmsColumnModal'
import {filterObj} from '@/utils/util';
export default {
name: "CmsColumnList",
mixins: [JeecgListMixin],
components: {
CmsColumnModal
},
data() {
return {
description: '文章栏目管理页面',
//
columns: [
// {
// title: '#',
// dataIndex: '',
// key: 'rowIndex',
// width: 60,
// align: "center",
// customRender: function (t, r, index) {
// return parseInt(index) + 1;
// }
// },
{
title: '名称',
align: "center",
dataIndex: 'name',
width: 380,
},
{
title: '显示',
align: "center",
dataIndex: 'isShow_dictText',
},
{
title: '排序',
align: "center",
dataIndex: 'sort',
},
{
title: '创建人',
align: "center",
dataIndex: 'createBy_dictText',
},
{
title: '创建时间',
align: "center",
dataIndex: 'createTime',
},
{
title: '操作',
dataIndex: 'action',
align: "center",
fixed: "right",
width: 280,
scopedSlots: {customRender: 'action'}
}
],
url: {
list: "/cms/cmsColumn/rootList",
childList: "/cms/cmsColumn/childList",
getChildListBatch: "/cms/cmsColumn/getChildListBatch",
delete: "/cms/cmsColumn/delete",
deleteBatch: "/cms/cmsColumn/deleteBatch",
exportXlsUrl: "/cms/cmsColumn/exportXls",
importExcelUrl: "cms/cmsColumn/importExcel",
},
expandedRowKeys: [],
hasChildrenField: "hasChild",
pidField: "pid",
dictOptions: {},
loadParent: false,
superFieldList: [],
}
},
created() {
this.getSuperFieldList();
},
computed: {
importExcelUrl() {
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
},
tableProps() {
let _this = this
return {
//
rowSelection: {
selectedRowKeys: _this.selectedRowKeys,
onChange: (selectedRowKeys) => _this.selectedRowKeys = selectedRowKeys
}
}
}
},
methods: {
loadData(arg) {
if (arg == 1) {
this.ipagination.current = 1
}
this.loading = true
let params = this.getQueryParams()
params.hasQuery = 'true'
getAction(this.url.list, params).then(res => {
if (res.success) {
let result = res.result
if (Number(result.total) > 0) {
this.ipagination.total = Number(result.total)
this.dataSource = this.getDataByResult(res.result.records)
return this.loadDataByExpandedRows(this.dataSource)
} else {
this.ipagination.total = 0
this.dataSource = []
}
} else {
this.$message.warning(res.message)
}
}).finally(() => {
this.loading = false
})
},
//
loadDataByExpandedRows(dataList) {
if (this.expandedRowKeys.length > 0) {
return getAction(this.url.getChildListBatch, {parentIds: this.expandedRowKeys.join(',')}).then(res => {
if (res.success && res.result.records.length > 0) {
//
let records = res.result.records
const listMap = new Map();
for (let item of records) {
let pid = item[this.pidField];
if (this.expandedRowKeys.join(',').includes(pid)) {
let mapList = listMap.get(pid);
if (mapList == null) {
mapList = [];
}
mapList.push(item);
listMap.set(pid, mapList);
}
}
let childrenMap = listMap;
let fn = (list) => {
if (list) {
list.forEach(data => {
if (this.expandedRowKeys.includes(data.id)) {
data.children = this.getDataByResult(childrenMap.get(data.id))
fn(data.children)
}
})
}
}
fn(dataList)
}
})
} else {
return Promise.resolve()
}
},
getQueryParams(arg) {
//
let sqp = {}
let param = {}
if (this.superQueryParams) {
sqp['superQueryParams'] = encodeURI(this.superQueryParams)
sqp['superQueryMatchType'] = this.superQueryMatchType
}
if (arg) {
param = Object.assign(sqp, this.isorter, this.filters);
} else {
param = Object.assign(sqp, this.queryParam, this.isorter, this.filters);
}
if (JSON.stringify(this.queryParam) === "{}" || arg) {
param.hasQuery = 'false'
} else {
param.hasQuery = 'true'
}
param.field = this.getQueryField();
param.pageNo = this.ipagination.current;
param.pageSize = this.ipagination.pageSize;
return filterObj(param);
},
searchReset() {
//
this.expandedRowKeys = []
this.queryParam = {}
this.loadData(1);
},
getDataByResult(result) {
if (result) {
return result.map(item => {
//
if (item[this.hasChildrenField] == '1') {
let loadChild = {id: item.id + '_loadChild', name: 'loading...', isLoading: true}
item.children = [loadChild]
}
return item
})
}
},
handleExpand(expanded, record) {
//
if (expanded) {
this.expandedRowKeys.push(record.id)
if (record.children.length > 0 && record.children[0].isLoading === true) {
let params = this.getQueryParams(1);//
params[this.pidField] = record.id
params.hasQuery = 'false'
params.superQueryParams = ""
getAction(this.url.childList, params).then((res) => {
if (res.success) {
if (res.result.records) {
record.children = this.getDataByResult(res.result.records)
this.dataSource = [...this.dataSource]
} else {
record.children = ''
record.hasChildrenField = '0'
}
} else {
this.$message.warning(res.message)
}
})
}
} else {
let keyIndex = this.expandedRowKeys.indexOf(record.id)
if (keyIndex >= 0) {
this.expandedRowKeys.splice(keyIndex, 1);
}
}
},
handleAddChild(record) {
this.loadParent = true
// console.log("handleAddChild()"+JSON.stringify(record))
let obj = {}
obj[this.pidField] = record['id']
this.$refs.modalForm.add(obj);
},
handleDeleteNode(id) {
if (!this.url.delete) {
this.$message.error("请设置url.delete属性!")
return
}
var that = this;
deleteAction(that.url.delete, {id: id}).then((res) => {
if (res.success) {
that.loadData(1)
} else {
that.$message.warning(res.message);
}
});
},
batchDel() {
if (this.selectedRowKeys.length <= 0) {
this.$message.warning('请选择一条记录!');
return false;
} else {
let ids = "";
let that = this;
that.selectedRowKeys.forEach(function (val) {
ids += val + ",";
});
that.$confirm({
title: "确认删除",
content: "是否删除选中数据?",
onOk: function () {
that.handleDeleteNode(ids)
that.onClearSelected();
}
});
}
},
getSuperFieldList() {
let fieldList = [];
fieldList.push({type: 'string', value: 'isShow', text: '显示', dictCode: ''})
fieldList.push({type: 'string', value: 'name', text: '名称', dictCode: ''})
fieldList.push({type: 'string', value: 'pid', text: '父级节点', dictCode: ''})
this.superFieldList = fieldList
}
}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>

@ -0,0 +1,132 @@
<template>
<a-spin :spinning="confirmLoading">
<j-form-container :disabled="formDisabled">
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<a-col :span="24">
<a-form-model-item label="文章标题" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="title">
<a-input v-model="model.title" placeholder="请输入文章标题"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="是否发布" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="status">
<j-dict-select-tag type="radio" v-model="model.status" dictCode="isShow" placeholder="请选择是否发布"/>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="所属栏目" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="columnId">
<j-dict-select-tag type="list" v-model="model.columnId" dictCode="cms_column,name,id"
placeholder="请选择所属栏目"/>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="来源" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="source">
<a-input v-model="model.source" placeholder="请输入来源"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="内容" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="content">
<j-editor style="width: 100%" v-model="model.content" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
</a-spin>
</template>
<script>
import {httpAction} from '@/api/manage'
export default {
name: 'CmsArticleForm',
components: {},
props: {
//
disabled: {
type: Boolean,
default: false,
required: false
}
},
data() {
return {
model: {
status: 1,
},
labelCol: {
xs: {span: 24},
sm: {span: 5},
},
wrapperCol: {
xs: {span: 24},
sm: {span: 16},
},
confirmLoading: false,
validatorRules: {
title: [
{required: true, message: "标题不能为空"},
],
columnId: [
{required: true, message: "栏目不能为空"},
// {pattern: /^[0-9]{0,100}$/, message: ''}
],
},
url: {
add: "/cms/cmsArticle/add",
edit: "/cms/cmsArticle/edit",
queryById: "/cms/cmsArticle/queryById"
}
}
},
computed: {
formDisabled() {
return this.disabled
},
},
created() {
//model
this.modelDefault = JSON.parse(JSON.stringify(this.model));
},
methods: {
add() {
this.edit(this.modelDefault);
},
edit(record) {
this.model = Object.assign({}, record);
this.visible = true;
},
submitForm() {
const that = this;
//
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if (!this.model.id) {
httpurl += this.url.add;
method = 'post';
} else {
httpurl += this.url.edit;
method = 'put';
}
httpAction(httpurl, this.model, method).then((res) => {
if (res.success) {
that.$message.success(res.message);
that.$emit('ok');
} else {
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
}
}
</script>

@ -0,0 +1,60 @@
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel"
cancelText="关闭">
<cms-article-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></cms-article-form>
</j-modal>
</template>
<script>
import CmsArticleForm from './CmsArticleForm'
export default {
name: 'CmsArticleModal',
components: {
CmsArticleForm
},
data () {
return {
title:'',
width:900,
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>

@ -0,0 +1,84 @@
<template>
<a-drawer
:title="title"
:width="width"
placement="right"
:closable="false"
@close="close"
destroyOnClose
:visible="visible">
<cms-article-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit" normal></cms-article-form>
<div class="drawer-footer">
<a-button @click="handleCancel" style="margin-bottom: 0;">关闭</a-button>
<a-button v-if="!disableSubmit" @click="handleOk" type="primary" style="margin-bottom: 0;">提交</a-button>
</div>
</a-drawer>
</template>
<script>
import CmsArticleForm from './CmsArticleForm'
export default {
name: 'CmsArticleModal',
components: {
CmsArticleForm
},
data () {
return {
title:"操作",
width:800,
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
});
},
close () {
this.$emit('close');
this.visible = false;
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
handleCancel () {
this.close()
}
}
}
</script>
<style lang="less" scoped>
/** Button按钮间距 */
.ant-btn {
margin-left: 30px;
margin-bottom: 30px;
float: right;
}
.drawer-footer{
position: absolute;
bottom: -8px;
width: 100%;
border-top: 1px solid #e8e8e8;
padding: 10px 16px;
text-align: right;
left: 0;
background: #fff;
border-radius: 0 0 2px 2px;
}
</style>

@ -0,0 +1,165 @@
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
:confirmLoading="confirmLoading"
switchFullscreen
@ok="handleOk"
@cancel="handleCancel"
cancelText="关闭">
<a-spin :spinning="confirmLoading">
<a-form-model ref="form" :model="model" :rules="validatorRules">
<a-form-model-item label="名称" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="name">
<a-input v-model="model.name" placeholder="请输入名称" ></a-input>
</a-form-model-item>
<a-form-model-item label="显示" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="isShow">
<j-dict-select-tag type="radio" v-model="model.isShow" dictCode="isShow" placeholder="请选择显示" />
</a-form-model-item>
<a-form-model-item label="栏目" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="pid">
<j-tree-select
ref="treeSelect"
placeholder="请选择父级节点"
v-model="model.pid"
dict="cms_column,name,id"
pidField="pid"
>
</j-tree-select>
</a-form-model-item>
<a-form-model-item label="排序" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="sort">
<a-input v-model="model.sort" placeholder="请输入名称"></a-input>
</a-form-model-item>
</a-form-model>
</a-spin>
</j-modal>
</template>
<script>
import { httpAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
export default {
name: "CmsColumnModal",
components: {
},
data () {
return {
title:"操作",
width:800,
visible: false,
model:{
isShow:1,
},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules: {
name: [
{required: true, message: "栏目名称不能为空"},
],
sort: [
{required: true, message: "栏目排序不能为空"},
{pattern: /^[0-9]{0,100}$/, message: '栏目排序不能为空且长度为正整数'}
],
},
url: {
add: "/cms/cmsColumn/add",
edit: "/cms/cmsColumn/edit",
},
expandedRowKeys:[],
pidField:"pid"
}
},
created () {
//model
this.modelDefault = JSON.parse(JSON.stringify(this.model));
},
methods: {
add (obj) {
this.modelDefault.pid=''
this.edit(Object.assign(this.modelDefault , obj));
},
edit (record) {
this.model = Object.assign({}, record);
this.visible = true;
},
close () {
this.$emit('close');
this.visible = false;
this.$refs.form.clearValidate()
},
handleOk () {
const that = this;
//
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
if(this.model.id && this.model.id === this.model[this.pidField]){
that.$message.warning("父级节点不能选择自己");
that.confirmLoading = false;
return;
}
httpAction(httpurl,this.model,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
this.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
that.close();
})
}else{
return false
}
})
},
handleCancel () {
this.close()
},
submitSuccess(formData,flag){
if(!formData.id){
let treeData = this.$refs.treeSelect.getCurrTreeData()
this.expandedRowKeys=[]
this.getExpandKeysByPid(formData[this.pidField],treeData,treeData)
this.$emit('ok',formData,this.expandedRowKeys.reverse());
}else{
this.$emit('ok',formData,flag);
}
},
getExpandKeysByPid(pid,arr,all){
if(pid && arr && arr.length>0){
for(let i=0;i<arr.length;i++){
if(arr[i].key==pid){
this.expandedRowKeys.push(arr[i].key)
this.getExpandKeysByPid(arr[i]['parentId'],all,all)
}else{
this.getExpandKeysByPid(pid,arr[i].children,all)
}
}
}
}
}
}
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

@ -0,0 +1,64 @@
* {
margin: 0;
padding: 0
}
em,
i {
font-style: normal
}
li {
list-style: none
}
img {
border: 0;
vertical-align: middle
}
button {
cursor: pointer
}
a {
color: #666;
text-decoration: none
}
a:hover {
color: #c81623
}
button,
input {
font-family: Microsoft YaHei, tahoma, arial, Hiragino Sans GB, \\5b8b\4f53, sans-serif
}
body {
-webkit-font-smoothing: antialiased;
background-color: #fff;
font: 12px/1.5 Microsoft YaHei, tahoma, arial, Hiragino Sans GB, \\5b8b\4f53, sans-serif;
color: #666
}
.hide,
.none {
display: none
}
.clearfix:after {
visibility: hidden;
clear: both;
display: block;
content: ".";
height: 0
}
.clearfix {
*zoom: 1
}
.d-flex{
display: flex;
justify-content: space-between;align-items: center;
}

@ -0,0 +1,53 @@
<template>
<div class="footer">
<p class="first">软件工程专业</p>
<p class="second">教学一体化平台</p>
<p class="third">关于我们<span>|</span>联系我们<span>|</span>服务协议</p>
<p class="fourth">黄淮学院版权所有@2023 湘豫CP备 19005950-1</p>
<p class="fifth">
违法和不良信息举报 举报电话0xxx-8xxxxxxx 举报邮箱xxxxxxxxx@qq.com
</p>
</div>
</template>
<script>
export default {
name: "FooterView",
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
.footer {
height: 310px;
background: #212640;
text-align: center;
color: #7f9eed;
padding-top: 50px;
p {
margin-bottom: 6px;
}
.first {
font-size: 14px;
font-style: italic;
}
.second {
font-size: 28px;
font-style: italic;
margin-bottom: 20px;
}
.third {
color: #95b7ff;
margin-bottom: 25px;
span {
margin-left: 20px;
margin-right: 20px;
}
}
.fourth,
.fifth {
font-size: 14px;
color: #95b7ff;
}
}
</style>

@ -0,0 +1,108 @@
<template>
<div class="header">
<div class="navBox d-flex">
<img src="../assets/logo.png" />
<nav class="d-flex">
<a v-for="(item,index) in trendsList" :key="index" v-if="index != 0" @click="goToMajor(item.id)">
{{item.name}}
</a>
<!-- <router-link to="/cms/home">学院首页</router-link>-->
<!-- <router-link to="/cms/major">专业概况</router-link>-->
<!-- <router-link to="/cms/major">教学改革</router-link>-->
<!-- <router-link to="/cms/major">科学研就</router-link>-->
<!-- <router-link to="/cms/major">人才培养</router-link>-->
<!-- <router-link to="/cms/major">成果展示</router-link>-->
<!-- <router-link to="/cms/major">产教融合</router-link>-->
<!-- <router-link to="/cms/major">日常教学</router-link>-->
<!-- <router-link to="/cms/major">优秀学生</router-link>-->
</nav>
</div>
<nav class="topNav d-flex">
<router-link to="/cms/home">企业入口</router-link>
<a>|</a>
<router-link to="/cms/home">教师入口</router-link>
<a>|</a>
<router-link to="/cms/home">学生入口</router-link>
<a>|</a>
<router-link to="/cms/home">毕业生入口</router-link>
</nav>
<!-- <router-view /> -->
</div>
</template>
<script>
import {getAction} from "../../../api/manage";
export default {
name: "HeaderView",
data(){
return{
trendsList:[],
url:{
list:"/cms/front/getColumnList"
}
}
},
mounted() {
getAction(this.url.list).then((res) => {
this.trendsList = res.result
}
)
},
methods:{
goToMajor(majorId){
if(majorId == "1640260091386368001"){
this.$router.push({
path: "/cms/home",
query: { id: majorId},
});
}else{
this.$router.push({
path: "/cms/major",
query: { id: majorId},
});
}
}
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
.header {
width: 1920px;
height: 365px;
// background: #2080f7;
position: relative;
.navBox {
height: 118px;
width: 1620px;
margin: 0 auto;
img {
/*width: 200px;*/
/*height: 59px;*/
}
.d-flex {
width: 1080px;
align-items: center;
font-size: 20px;
a {
color: #fff;
}
}
}
.topNav {
position: absolute;
top: 2%;
right: 5%;
width: 250px;
align-items: center;
a {
color: #fff;
font-size: 12px;
}
}
}
</style>

@ -0,0 +1,195 @@
<template>
<div class="home">
<Header></Header>
<div class="main d-flex">
<div class="img">
<video id="videoPlayer" src="./assets/01.mp4" style="width: 90%" controls loop></video>
</div>
<div class="lanmu">
<div class="title d-flex">
<div class="l">{{obj.name}}</div>
<router-link to="/cms/major" class="r">MORE</router-link>
</div>
<div class="itemList">
<div
class="item d-flex"
v-for="(item, index) in trendsList"
v-if="index<9"
:key="index"
@click="goToDetail(item)"
>
<div class="name">{{ item.title }}</div>
<div class="time">{{ item.publishTime === undefined ? "" :item.publishTime.substr(0,10)}}</div>
</div>
</div>
</div>
</div>
<div class="title">
<p class="title1">课程体系</p>
<p class="title2">全面落实立德树人根本任务CDIO工程教育理念</p>
</div>
<img src="./assets/Group01.png" />
<div class="title">
<p class="title1">专业目标</p>
<p class="title2">全面落实立德树人根本任务CDIO工程教育理念</p>
</div>
<img src="./assets/Group04.png" />
<div class="title">
<p class="title1">毕业要求</p>
<p class="title2">适应产业与社会变革的国际化应用型人才应具备的能力</p>
</div>
<img src="./assets/Group03.png" />
<Footer></Footer>
</div>
</template>
<script>
import Header from "./components/HeaderView";
import Footer from "./components/FooterView.vue";
import {getAction} from "../../api/manage";
export default {
name: "home",
components: { Header, Footer },
data() {
return {
trendsList: [
{
id: "1",
title: "首页新闻标题未选中",
date: "2023.01.11",
},
{
id: "2",
title: "首页新闻标题未选中",
date: "2023.01.11",
},
{
id: "3",
title: "首页新闻标题未选中",
date: "2023.01.11",
},
],
obj:{},
url:{
list:"/cms/front/getColumnList",
detail:"/cms/front/getArticleListByColumn"
}
};
},
mounted() {
getAction(this.url.list).then((res) => {
this.obj =res.result[0]
getAction(this.url.detail,{columnId:this.obj.id}).then((res) => {
this.trendsList = res.result.records
}
)
}
),
this.playBySeconds(6)//
},
methods: {
//
playBySeconds (num) {
if (num && document.getElementById ('videoPlayer')) {
let myVideo = document.getElementById ('videoPlayer');
myVideo.currentTime = num;
}
},
goToDetail(item) {
this.$router.push({
path: "/cms/detail",
query: {
item: item,
},
});
},
},
// filters:{
// changeDate: function(value) {
// return value
// }
// }
};
</script>
<style scoped lang="less">
@import "./assets/reset.css";
.home {
text-align: center;
}
.header {
background: #2080f7;
}
.main {
width: 1620px;
margin: 0 auto;
margin-top: -250px;
z-index: 99;
position: relative;
.img {
width: 1073px;
height: 547px;
/*background: #d9d9d9;*/
}
.lanmu {
width: 519px;
height: 547px;
box-sizing: border-box;
background: #ffffff;
box-shadow: 0px 0px 32px 0px rgba(0, 0, 0, 0.08);
border-radius: 4px 4px 4px 4px;
padding: 50px;
.title {
border-bottom: 1px solid #d9d9d9;
.l {
font-size: 18px;
padding: 20px 0;
color: #000000;
border-bottom: 4px solid #000;
}
.r {
font-size: 16px;
padding: 20px 0;
color: #0052ff;
cursor: pointer;
}
}
.itemList {
padding: 20px 0;
.item {
padding: 6px;
cursor: pointer;
.name {
width: 70%;
color: #555555;
font-size: 16px;
overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}
.time {
width: 30%;
color: #cccccc;
font-size: 16px;
}
}
}
}
}
.title {
margin-top: 20px;
.title1 {
font-size: 42px;
font-weight: 500;
color: #333333;
margin-bottom: 20px;
}
.title2 {
font-size: 20px;
font-weight: 400;
color: #777777;
}
}
</style>

@ -0,0 +1,268 @@
<template>
<div class="detail">
<Header></Header>
<div class="main">
<p class="title">成果展示</p>
<div class="card">
首页<span>·</span>成果展示<span>·</span>教师获奖成果
</div>
<div class="mainDiv clearfix">
<div class="itemList">
<div class="articalTitle">{{ this.$route.query.item.title }}</div>
<div class="info">
<div class="t">
<span>{{this.$route.query.item.createTime}}</span><span>信息来源国际教育学院</span>
</div>
<div class="b">责编{{this.$route.query.item.createBy_dictText}}</div>
</div>
<div class="acticalCont" v-html="this.$route.query.item.content"></div>
</div>
<div class="trends">
<div class="title">
<div class="name">最新动态</div>
</div>
<div v-for="(item, index) in trendsList" :key="index">
<div class="article d-flex" v-if="index < 7">
<div class="l d-flex">
<div class="t">{{ item.date }}</div>
<div class="b">{{ item.month }}</div>
</div>
<div class="line"></div>
<div class="r d-flex">
<p>
{{ item.cont }}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- <Footer></Footer>-->
</div>
</template>
<script>
import Header from "../../components/HeaderView.vue";
import Footer from "../../components/FooterView.vue";
export default {
name: "DetailView",
components: { Header, Footer },
data() {
return {
current: 1,
artical: {
title:
"标题标题标题标题标题标题标题标题标题标题标题标题标题,标题标题标题标题标题标题标题标题标题标题标题",
date: "2022-03-23",
source: "国际教育学院",
adit: "张三",
cont: "文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本",
},
//
trendsList: [
{
id: "1",
month: "2",
date: "03",
cont: "李斯同学获得国际比赛奖,标题可以很长很长.哈哈哈哈哈哈哈哈简李斯同学获得国际比赛奖,标题可以很长很长.哈哈哈哈哈哈哈哈简",
},
{
id: "2",
month: "2",
date: "02",
cont: "李斯同学获得国际比赛奖,标题可以很长很长.哈哈哈哈哈哈哈哈简..",
},
{
id: "3",
month: "2",
date: "02",
cont: "李斯同学获得国际比赛奖,标题可以很长很长.哈哈哈哈哈哈哈哈简..",
},
{
id: "4",
month: "2",
date: "01",
cont: "李斯同学获得国际比赛奖,标题可以很长很长.哈哈哈哈哈哈哈哈简..",
},
{
id: "5",
month: "2",
date: "01",
cont: "李斯同学获得国际比赛奖,标题可以很长很长.哈哈哈哈哈哈哈哈简..",
},
],
};
},
mounted() {
console.log("---")
console.log(this.$route.query.item)
},
methods: {
onSearch(value) {
console.log(value);
},
goToDetail(id) {
this.$router.push("/detail");
},
},
};
</script>
<style>
.clearfix::before,.clearfix::after{
content:"";
display:table;
clear: both;
}
</style>
<style scoped lang="less">
@import "../../assets/reset.css";
#components-pagination-demo-mini {
margin-top: 30px;
}
.detail .header {
background-image: url("../../assets/bg02.png");
}
.main {
margin-top: -220px;
z-index: 99;
padding-bottom: 220px;
position: relative;
p {
text-align: center;
font-size: 30px;
font-weight: 500;
color: #ffffff;
margin-bottom: 130px;
}
.card {
width: 950px;
height: 70px;
margin-bottom: 47px;
line-height: 70px;
color: #ffffff;
font-size: 16px;
padding-left: 150px;
background: linear-gradient(90deg, #0052ff 0%, #00c2ff 100%);
clip-path: polygon(0 0, 920px 0, 100% 100%, 0 100%);
span {
margin-left: 20px;
margin-right: 20px;
}
}
.mainDiv {
padding-left: 150px;
padding-right: 150px;
/*overflow: scroll;*/
.itemList {
float: left;
width: 1050px;
height: 300px;
/*overflow: auto;*/
.articalTitle {
font-size: 26px;
font-weight: 400;
color: #333;
margin-bottom: 30px;
}
.info {
height: 70px;
border-left: 1px solid #cccccc;
padding-left: 38px;
margin-bottom: 50px;
.t {
height: 35px;
line-height: 35px;
span {
font-size: 14px;
font-weight: 400;
color: #777777;
margin-right: 28px;
}
}
.b {
font-size: 14px;
font-weight: 400;
color: #777777;
}
}
.acticalCont {
font-size: 18px;
font-weight: 400;
color: #333333;
line-height: 40px;
text-indent: 2em;
}
}
.trends {
float: right;
height: 300px;
width: 400px;
.title {
height: 45px;
line-height: 45px;
background: linear-gradient(90deg, #0052ff 0%, #00c2ff 100%);
text-align: center;
margin-bottom: 20px;
.name {
font-size: 18px;
font-weight: 500;
color: #ffffff;
}
}
.article {
height: 86px;
padding: 21px 12px;
box-sizing: border-box;
align-items: center;
justify-content: space-between;
.l {
width: 50px;
color: #0052ff;
text-align: center;
height: 86px;
flex-direction: column;
justify-content: center;
.t {
font-size: 34px;
font-weight: 600;
padding-bottom: 0;
}
.b {
font-size: 14px;
font-weight: 500;
}
}
.line {
height: 100%;
width: 1px;
background: #ccc;
}
.r {
height: 86px;
align-items: center;
width: 292px;
p {
text-align: left;
margin-bottom: 0px;
font-size: 16px;
font-weight: 400;
color: #333333;
overflow: hidden;
display: -webkit-box;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
white-space: normal;
}
}
}
}
}
}
</style>

@ -0,0 +1,290 @@
<template>
<div class="major">
<Header></Header>
<div class="main">
<p class="title">教师获奖成果</p>
<div class="card">
首页<span>·</span>成果展示<span>·</span>教师获奖成果
</div>
<div class="mainDiv d-flex">
<div class="itemList">
<div
class="item"
v-for="(item, index) in originalList"
:key="index"
@click="goToDetail(item)"
>
<div class="t d-flex">
<span class="date">{{ item.date }}</span>
<span class="title">{{ item.title }}</span>
</div>
<div class="b">{{ item.month }}</div>
</div>
<div id="components-pagination-demo-mini">
<a-pagination
:total="50"
show-size-changer
show-quick-jumper
:show-total="(total) => `共 ${originalList.length} 项数据`"
/>
</div>
</div>
<div class="trends">
<div class="inputDiv">
<a-input-search
placeholder="输入搜索内容"
enter-button
@search="onSearch"
/>
</div>
<div class="title d-flex">
<div class="icon"><a-icon type="clock-circle" /></div>
<div class="name">最新动态</div>
</div>
<a-steps progress-dot :current="current" direction="vertical">
<template v-for="(item, index) in trendsList">
<a-step
v-if="index < 10"
:key="index"
:title="item.date"
:description="item.cont"
/>
</template>
</a-steps>
</div>
</div>
</div>
</div>
</template>
<script>
import Header from "../../components/HeaderView";
import {getAction} from "../../../../api/manage";
export default {
name: "MajorView",
components: { Header },
data() {
return {
//
newList: [
{
id: "1",
title: "中国分析测试协会高校分析测试分会举办“测论”系列学术论坛",
date: "03",
month: "2023.02",
},
{
id: "2",
title:
"中国分析测试协会高校分析测试分会举办“测论”系列学术论坛:“又抢回一个可以团圆的春节”",
date: "02",
month: "2023.02",
},
{
id: "3",
title:
"中国分析测试协会高校分析测试分会举办“测论”系列学术论坛“疫”中一路“肠”通",
date: "01",
month: "2023.02",
},
{
id: "4",
title: "学生领导力“唐仲英计划”实践支队赴河南兰考开展社会实践",
date: "31",
month: "2023.01",
},
{
id: "5",
title:
"DeepMind研究科学dsfsdfsgdrgzrgvzewf方便地方v地方“AlphaCode:编程竞赛级的程序自动生成”",
date: "30",
month: "2023.01",
},
],
originalList:[],
current: 1,
majorId:"",
//
trendsList: [
{
id: "1",
date: "02.03",
cont: "文本文本文本文本文本文本文本",
},
{
id: "2",
date: "02.02",
cont: "文本文本文本文本文本文本文本",
},
{
id: "3",
date: "02.01",
cont: "文本文本文本文本文本文本文本",
},
{
id: "4",
date: "01.30",
cont: "文本文本文本文本文本文本文本",
},
{
id: "5",
date: "01.29",
cont: "文本文本文本文本文本文本文本",
},
{
id: "6",
date: "01.28",
cont: "文本文本文本文本文本文本文本",
},
{
id: "7",
date: "01.27",
cont: "文本文本文本文本文本文本文本",
},
{
id: "8",
date: "01.26",
cont: "文本文本文本文本文本文本文本",
},
],
url:{
detail:"/cms/front/getArticleListByColumn"
},
};
},
created() {
this.getList()
},
methods: {
onSearch(value) {
console.log(value);
},
getList(){
getAction(this.url.detail,{columnId:this.$route.query.id}).then((res) => {
this.originalList = res.result.records
this.originalList.forEach(function(item,index,array){
item.date = item.publishTime.slice(8,10)
item.month = item.publishTime.slice(0,7)
})
}
)
},
goToDetail(item) {
this.$router.push({
path: "/cms/detail",
query: {
item: item,
},
});
},
},
};
</script>
<style scoped lang="less">
@import "../../assets/reset.css";
#components-pagination-demo-mini {
margin-top: 30px;
}
.major .header {
background-image: url("../../assets/bg02.png");
}
.main {
margin-top: -220px;
z-index: 99;
position: relative;
p {
text-align: center;
font-size: 30px;
font-weight: 500;
color: #ffffff;
margin-bottom: 130px;
}
.card {
width: 950px;
height: 70px;
margin-bottom: 47px;
line-height: 70px;
color: #ffffff;
font-size: 16px;
padding-left: 150px;
background: linear-gradient(90deg, #0052ff 0%, #00c2ff 100%);
clip-path: polygon(0 0, 920px 0, 100% 100%, 0 100%);
span {
margin-left: 20px;
margin-right: 20px;
}
}
.mainDiv {
padding-left: 150px;
padding-right: 150px;
.itemList {
width: 1050px;
height: 300px;
.item {
border-bottom: 1px solid #dcdcdc;
height: 106px;
box-sizing: border-box;
padding: 33px 17px;
cursor: pointer;
.t {
justify-content: start;
align-items: center;
.date {
width: 70px;
text-align: center;
font-weight: 500;
color: #0052ff;
font-size: 30px;
margin-right: 12px;
}
.title {
font-size: 18px;
font-weight: 500;
color: #000000;
}
}
.b {
width: 70px;
text-align: center;
font-size: 12px;
font-weight: 400;
color: #0052ff;
}
}
}
.trends {
height: 300px;
width: 400px;
.title {
padding-bottom: 22px;
padding-top: 38px;
border-bottom: 2px solid #d6d6d6;
justify-content: flex-start;
margin-bottom: 20px;
.icon {
width: 36px;
height: 36px;
line-height: 36px;
text-align: center;
color: #fff;
font-size: 18px;
background: #0052ff;
margin-right: 18px;
border-radius: 2px;
}
.name {
font-size: 18px;
font-weight: 500;
color: #0052ff;
}
}
}
}
}
</style>

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>2.4.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-module-cms</artifactId>
<dependencies>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base-core</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base-core</artifactId>
</dependency>
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-core</artifactId>
<version>0.7.3</version>
</dependency>
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-extension</artifactId>
<version>0.7.3</version>
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>org.slf4j</groupId>-->
<!-- <artifactId>slf4j-log4j12</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
</dependency>
</dependencies>
</project>

@ -0,0 +1,190 @@
package org.jeecg.modules.cms.admin.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.cms.admin.entity.CmsArticle;
import org.jeecg.modules.cms.admin.entity.CmsColumn;
import org.jeecg.modules.cms.admin.service.ICmsArticleService;
import org.jeecg.modules.cms.admin.service.ICmsColumnService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Null;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
/**
* @Description: 文章管理
* @Author: jeecg-boot
* @Date: 2023-03-27
* @Version: V1.0
*/
@Api(tags = "文章管理")
@RestController
@RequestMapping("/cms/cmsArticle")
@Slf4j
public class CmsArticleController extends JeecgController<CmsArticle, ICmsArticleService> {
@Autowired
private ICmsArticleService cmsArticleService;
@Autowired
private ICmsColumnService cmsColumnService;
/**
* 分页列表查询
*
* @param cmsArticle
* @param pageNo
* @param pageSize
* @param req
* @return
*/
// @AutoLog(value = "文章管理-分页列表查询")
@ApiOperation(value = "文章管理-分页列表查询", notes = "文章管理-分页列表查询")
@GetMapping(value = "/list")
public Result<?> queryPageList(CmsArticle cmsArticle,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<CmsArticle> queryWrapper = QueryGenerator.initQueryWrapper(cmsArticle, req.getParameterMap());
Page<CmsArticle> page = new Page<CmsArticle>(pageNo, pageSize);
IPage<CmsArticle> pageList = cmsArticleService.page(page, queryWrapper);
return Result.OK(pageList);
}
/**
* 添加
*
* @param cmsArticle
* @return
*/
// @AutoLog(value = "文章管理-添加")
@ApiOperation(value = "文章管理-添加", notes = "文章管理-添加")
@PostMapping(value = "/add")
public Result<?> add(@RequestBody CmsArticle cmsArticle) {
LoginUser principal = (LoginUser) SecurityUtils.getSubject().getPrincipal();
cmsArticle.setCreateBy(principal.getUsername());
CmsColumn cmsColumn = cmsColumnService.getById(cmsArticle.getColumnId());
cmsArticle.setColumnName(cmsColumn.getName());
if (StringUtils.equals("1", cmsArticle.getStatus())) {
cmsArticle.setPublishTime(new Date());
}
cmsArticleService.save(cmsArticle);
return Result.OK("添加成功!");
}
@ApiOperation(value = "文章管理-发布/取消发布", notes = "文章管理-发布/取消发布")
@PostMapping(value = "/operationStatus")
public Result<?> operationStatus(@RequestBody CmsArticle cmsArticle) {
if (StringUtils.equals("1", cmsArticle.getStatus())) {
cmsArticle.setPublishTime(new Date());
}
cmsArticleService.updateById(cmsArticle);
return Result.OK("操作成功!");
}
/**
* 编辑
*
* @param cmsArticle
* @return
*/
// @AutoLog(value = "文章管理-编辑")
@ApiOperation(value = "文章管理-编辑", notes = "文章管理-编辑")
@PutMapping(value = "/edit")
public Result<?> edit(@RequestBody CmsArticle cmsArticle) {
if (StringUtils.equals("1", cmsArticle.getStatus())) {
cmsArticle.setPublishTime(new Date());
} else {
cmsArticle.setPublishTime(null);
}
cmsArticleService.updateById(cmsArticle);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
// @AutoLog(value = "文章管理-通过id删除")
@ApiOperation(value = "文章管理-通过id删除", notes = "文章管理-通过id删除")
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
cmsArticleService.removeById(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
// @AutoLog(value = "文章管理-批量删除")
@ApiOperation(value = "文章管理-批量删除", notes = "文章管理-批量删除")
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.cmsArticleService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
// @AutoLog(value = "文章管理-通过id查询")
@ApiOperation(value = "文章管理-通过id查询", notes = "文章管理-通过id查询")
@GetMapping(value = "/queryById")
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
CmsArticle cmsArticle = cmsArticleService.getById(id);
if (cmsArticle == null) {
return Result.error("未找到对应数据");
}
return Result.OK(cmsArticle);
}
/**
* 导出excel
*
* @param request
* @param cmsArticle
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, CmsArticle cmsArticle) {
return super.exportXls(request, cmsArticle, CmsArticle.class, "文章管理");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, CmsArticle.class);
}
}

@ -0,0 +1,260 @@
package org.jeecg.modules.cms.admin.controller;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.cms.admin.entity.CmsColumn;
import org.jeecg.modules.cms.admin.service.ICmsColumnService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @Description: 文章栏目
* @Author: jeecg-boot
* @Date: 2023-03-27
* @Version: V1.0
*/
@Api(tags = "文章栏目")
@RestController
@RequestMapping("/cms/cmsColumn")
@Slf4j
public class CmsColumnController extends JeecgController<CmsColumn, ICmsColumnService> {
@Autowired
private ICmsColumnService cmsColumnService;
@ApiOperation(value = "文章栏目-获取栏目树型列表", notes = "文章栏目-获取栏目树型列表")
@GetMapping(value = "/getColumnTree")
public Result<?> getColumnTree(HttpServletRequest req) {
//1.配置树节点信息,指定key,可直接使用默认的key
//2.查询数据
List<CmsColumn> list = cmsColumnService.list(new LambdaQueryWrapper<CmsColumn>().orderByAsc(CmsColumn::getSort));
//3.转为树结构,其中rootId参数代表根节点的父级id值
TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
treeNodeConfig.setParentIdKey("pid");
//转换器
List<Tree<String>> treeNodes = TreeUtil.build(list, "0", treeNodeConfig,
(treeNode, tree) -> {
tree.setId(treeNode.getId().toString());
tree.setName(treeNode.getName());
// 扩展属性 ...
tree.putExtra("isShow", treeNode.getIsShow());
tree.putExtra("pid", treeNode.getPid());
});
return Result.OK(treeNodes);
}
/**
* 分页列表查询
*
* @param cmsColumn
* @param pageNo
* @param pageSize
* @param req
* @return
*/
// @AutoLog(value = "文章栏目-分页列表查询")
@ApiOperation(value = "文章栏目-分页列表查询", notes = "文章栏目-分页列表查询")
@GetMapping(value = "/rootList")
public Result<?> queryPageList(CmsColumn cmsColumn,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
String hasQuery = req.getParameter("hasQuery");
if (hasQuery != null && "true".equals(hasQuery)) {
QueryWrapper<CmsColumn> queryWrapper = QueryGenerator.initQueryWrapper(cmsColumn, req.getParameterMap());
List<CmsColumn> list = cmsColumnService.queryTreeListNoPage(queryWrapper);
IPage<CmsColumn> pageList = new Page<>(1, 10, list.size());
pageList.setRecords(list);
List<CmsColumn> records = pageList.getRecords();
Collections.sort(records, Comparator.comparingInt(CmsColumn::getSort));
return Result.OK(pageList);
} else {
String parentId = cmsColumn.getPid();
if (oConvertUtils.isEmpty(parentId)) {
parentId = "0";
}
cmsColumn.setPid(null);
QueryWrapper<CmsColumn> queryWrapper = QueryGenerator.initQueryWrapper(cmsColumn, req.getParameterMap());
// 使用 eq 防止模糊查询
queryWrapper.eq("pid", parentId);
queryWrapper.last("order by sort");
Page<CmsColumn> page = new Page<CmsColumn>(pageNo, pageSize);
IPage<CmsColumn> pageList = cmsColumnService.page(page, queryWrapper);
List<CmsColumn> records = pageList.getRecords();
// records.sort(Comparator.comparing(CmsColumn::getSort));
Collections.sort(records, Comparator.comparingInt(CmsColumn::getSort));
return Result.OK(pageList);
}
}
/**
* 获取子数据
*
* @param cmsColumn
* @param req
* @return
*/
// @AutoLog(value = "文章栏目-获取子数据")
@ApiOperation(value = "文章栏目-获取子数据", notes = "文章栏目-获取子数据")
@GetMapping(value = "/childList")
public Result<?> queryPageList(CmsColumn cmsColumn, HttpServletRequest req) {
QueryWrapper<CmsColumn> queryWrapper = QueryGenerator.initQueryWrapper(cmsColumn, req.getParameterMap());
List<CmsColumn> list = cmsColumnService.list(queryWrapper);
IPage<CmsColumn> pageList = new Page<>(1, 10, list.size());
pageList.setRecords(list);
return Result.OK(pageList);
}
/**
* 批量查询子节点
*
* @param parentIds 父ID多个采用半角逗号分割
* @param parentIds
* @return 返回 IPage
* @return
*/
// @AutoLog(value = "文章栏目-批量获取子数据")
@ApiOperation(value = "文章栏目-批量获取子数据", notes = "文章栏目-批量获取子数据")
@GetMapping("/getChildListBatch")
public Result getChildListBatch(@RequestParam("parentIds") String parentIds) {
try {
QueryWrapper<CmsColumn> queryWrapper = new QueryWrapper<>();
List<String> parentIdList = Arrays.asList(parentIds.split(","));
queryWrapper.in("pid", parentIdList);
List<CmsColumn> list = cmsColumnService.list(queryWrapper);
IPage<CmsColumn> pageList = new Page<>(1, 10, list.size());
pageList.setRecords(list);
return Result.OK(pageList);
} catch (Exception e) {
log.error(e.getMessage(), e);
return Result.error("批量查询子节点失败:" + e.getMessage());
}
}
/**
* 添加
*
* @param cmsColumn
* @return
*/
// @AutoLog(value = "文章栏目-添加")
@ApiOperation(value = "文章栏目-添加", notes = "文章栏目-添加")
@PostMapping(value = "/add")
public Result<?> add(@RequestBody CmsColumn cmsColumn) {
LoginUser principal = (LoginUser) SecurityUtils.getSubject().getPrincipal();
cmsColumn.setCreateBy(principal.getUsername());
cmsColumnService.addCmsColumn(cmsColumn);
return Result.OK("添加成功!");
}
/**
* 编辑
*
* @param cmsColumn
* @return
*/
// @AutoLog(value = "文章栏目-编辑")
@ApiOperation(value = "文章栏目-编辑", notes = "文章栏目-编辑")
@PutMapping(value = "/edit")
public Result<?> edit(@RequestBody CmsColumn cmsColumn) {
cmsColumnService.updateCmsColumn(cmsColumn);
return Result.OK("编辑成功!");
}
/**
* 通过id删除
*
* @param id
* @return
*/
@ApiOperation(value = "文章栏目-通过id删除", notes = "文章栏目-通过id删除")
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
CmsColumn cmsColumn = cmsColumnService.getById(id);
if (StringUtils.equals("99", cmsColumn.getId())) throw new JeecgBootException("文章总栏目不可删除");
int count = cmsColumnService.count(new LambdaQueryWrapper<CmsColumn>().eq(CmsColumn::getPid, cmsColumn.getId()));
if (count > 0) throw new JeecgBootException("存在子栏目暂不可删除");
cmsColumnService.deleteCmsColumn(id);
return Result.OK("删除成功!");
}
/**
* 批量删除
*
* @param ids
* @return
*/
@AutoLog(value = "文章栏目-批量删除")
@ApiOperation(value = "文章栏目-批量删除", notes = "文章栏目-批量删除")
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.cmsColumnService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
}
/**
* 通过id查询
*
* @param id
* @return
*/
@AutoLog(value = "文章栏目-通过id查询")
@ApiOperation(value = "文章栏目-通过id查询", notes = "文章栏目-通过id查询")
@GetMapping(value = "/queryById")
public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
CmsColumn cmsColumn = cmsColumnService.getById(id);
if (cmsColumn == null) {
return Result.error("未找到对应数据");
}
return Result.OK(cmsColumn);
}
/**
* 导出excel
*
* @param request
* @param cmsColumn
*/
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(HttpServletRequest request, CmsColumn cmsColumn) {
return super.exportXls(request, cmsColumn, CmsColumn.class, "文章栏目");
}
/**
* 通过excel导入数据
*
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
return super.importExcel(request, response, CmsColumn.class);
}
}

@ -0,0 +1,111 @@
package org.jeecg.modules.cms.admin.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecg.common.aspect.annotation.Dict;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 文章管理
* @Author: jeecg-boot
* @Date: 2023-03-27
* @Version: V1.0
*/
@Data
@TableName("cms_article")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "cms_article对象", description = "文章管理")
public class CmsArticle implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private String id;
/**
* 创建人
*/
@ApiModelProperty(value = "创建人")
@Dict(dictTable = "sys_user", dicCode = "username", dicText = "realname")
private String createBy;
/**
* 创建日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建日期")
private Date createTime;
/**
* 更新人
*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**
* 更新日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新日期")
private Date updateTime;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "发布时间")
private Date publishTime;
/**
* 文章标题
*/
@Excel(name = "文章标题", width = 15)
@ApiModelProperty(value = "文章标题")
private String title;
/**
* 内容
*/
@Excel(name = "内容", width = 15)
@ApiModelProperty(value = "内容")
private String content;
/**
* 状态
*/
@Excel(name = "状态", width = 15)
@ApiModelProperty(value = "状态 0:未发布,1:已发布")
@Dict(dicCode = "isShow")
private String status;
/**
* 所属栏目
*/
@Excel(name = "所属栏目", width = 15)
@ApiModelProperty(value = "所属栏目")
private String columnId;
/**
* 栏目
*/
@Excel(name = "栏目", width = 15)
@ApiModelProperty(value = "栏目")
private String columnName;
/**
* 来源
*/
@Excel(name = "来源", width = 15)
@ApiModelProperty(value = "来源")
private String source;
@ApiModelProperty(value = "源url")
private String originUrl;
}

@ -0,0 +1,96 @@
package org.jeecg.modules.cms.admin.entity;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.UnsupportedEncodingException;
/**
* @Description: 文章栏目
* @Author: jeecg-boot
* @Date: 2023-03-27
* @Version: V1.0
*/
@Data
@TableName("cms_column")
@ApiModel(value = "cms_column对象", description = "文章栏目")
public class CmsColumn implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "主键")
private String id;
/**
* 创建人
*/
@ApiModelProperty(value = "创建人")
@Dict(dictTable = "sys_user",dicCode = "username",dicText = "realname")
private String createBy;
/**
* 创建日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建日期")
private Date createTime;
/**
* 更新人
*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**
* 更新日期
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ApiModelProperty(value = "更新日期")
private Date updateTime;
/**
* 显示
*/
@Excel(name = "显示", width = 15)
@ApiModelProperty(value = "显示")
@Dict(dicCode = "isShow")
private String isShow;
/**
* 排序
*/
@Excel(name = "排序", width = 15)
@ApiModelProperty(value = "排序")
private Integer sort;
/**
* 名称
*/
@Excel(name = "名称", width = 15)
@ApiModelProperty(value = "名称")
private String name;
/**
* 父级节点
*/
@Excel(name = "父级节点", width = 15)
@ApiModelProperty(value = "父级节点")
private String pid;
/**
* 是否有子节点
*/
@Excel(name = "是否有子节点", width = 15, dicCode = "yn")
@Dict(dicCode = "yn")
@ApiModelProperty(value = "是否有子节点")
private String hasChild;
}

@ -0,0 +1,15 @@
package org.jeecg.modules.cms.admin.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.cms.admin.entity.CmsArticle;
/**
* @Description: 文章管理
* @Author: jeecg-boot
* @Date: 2023-03-27
* @Version: V1.0
*/
public interface CmsArticleMapper extends BaseMapper<CmsArticle> {
}

@ -0,0 +1,23 @@
package org.jeecg.modules.cms.admin.mapper;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.jeecg.modules.cms.admin.entity.CmsColumn;
/**
* @Description: 文章栏目
* @Author: jeecg-boot
* @Date: 2023-03-27
* @Version: V1.0
*/
public interface CmsColumnMapper extends BaseMapper<CmsColumn> {
/**
* 编辑节点状态
* @param id
* @param status
*/
void updateTreeNodeStatus(@Param("id") String id,@Param("status") String status);
}

@ -0,0 +1,15 @@
package org.jeecg.modules.cms.admin.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.cms.admin.entity.CmsArticle;
/**
* @Description: 文章管理
* @Author: jeecg-boot
* @Date: 2023-03-27
* @Version: V1.0
*/
public interface ICmsArticleService extends IService<CmsArticle> {
}

@ -0,0 +1,54 @@
package org.jeecg.modules.cms.admin.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.cms.admin.entity.CmsColumn;
import java.util.List;
/**
* @Description: 文章栏目
* @Author: jeecg-boot
* @Date: 2023-03-27
* @Version: V1.0
*/
public interface ICmsColumnService extends IService<CmsColumn> {
/**
* 根节点父ID的值
*/
public static final String ROOT_PID_VALUE = "0";
/**
* 树节点有子节点状态值
*/
public static final String HASCHILD = "1";
/**
* 树节点无子节点状态值
*/
public static final String NOCHILD = "0";
/**
* 新增节点
*/
void addCmsColumn(CmsColumn cmsColumn);
/**
* 修改节点
*/
void updateCmsColumn(CmsColumn cmsColumn) throws JeecgBootException;
/**
* 删除节点
*/
void deleteCmsColumn(String id) throws JeecgBootException;
/**
* 查询所有数据无分页
*/
List<CmsColumn> queryTreeListNoPage(QueryWrapper<CmsColumn> queryWrapper);
}

@ -0,0 +1,20 @@
package org.jeecg.modules.cms.admin.service.impl;
import org.jeecg.modules.cms.admin.entity.CmsArticle;
import org.jeecg.modules.cms.admin.mapper.CmsArticleMapper;
import org.jeecg.modules.cms.admin.service.ICmsArticleService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: 文章管理
* @Author: jeecg-boot
* @Date: 2023-03-27
* @Version: V1.0
*/
@Service
public class CmsArticleServiceImpl extends ServiceImpl<CmsArticleMapper, CmsArticle> implements ICmsArticleService {
}

@ -0,0 +1,192 @@
package org.jeecg.modules.cms.admin.service.impl;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.cms.admin.entity.CmsColumn;
import org.jeecg.modules.cms.admin.mapper.CmsColumnMapper;
import org.jeecg.modules.cms.admin.service.ICmsColumnService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
/**
* @Description: 文章栏目
* @Author: jeecg-boot
* @Date: 2023-03-27
* @Version: V1.0
*/
@Service
public class CmsColumnServiceImpl extends ServiceImpl<CmsColumnMapper, CmsColumn> implements ICmsColumnService {
@Override
public void addCmsColumn(CmsColumn cmsColumn) {
//新增时设置hasChild为0
cmsColumn.setHasChild(ICmsColumnService.NOCHILD);
if(oConvertUtils.isEmpty(cmsColumn.getPid())){
cmsColumn.setPid(ICmsColumnService.ROOT_PID_VALUE);
}else{
//如果当前节点父ID不为空 则设置父节点的hasChildren 为1
CmsColumn parent = baseMapper.selectById(cmsColumn.getPid());
if(parent!=null && !"1".equals(parent.getHasChild())){
parent.setHasChild("1");
baseMapper.updateById(parent);
}
}
baseMapper.insert(cmsColumn);
}
@Override
public void updateCmsColumn(CmsColumn cmsColumn) {
CmsColumn entity = this.getById(cmsColumn.getId());
if(entity==null) {
throw new JeecgBootException("未找到对应实体");
}
String old_pid = entity.getPid();
String new_pid = cmsColumn.getPid();
if(!old_pid.equals(new_pid)) {
updateOldParentNode(old_pid);
if(oConvertUtils.isEmpty(new_pid)){
cmsColumn.setPid(ICmsColumnService.ROOT_PID_VALUE);
}
if(!ICmsColumnService.ROOT_PID_VALUE.equals(cmsColumn.getPid())) {
baseMapper.updateTreeNodeStatus(cmsColumn.getPid(), ICmsColumnService.HASCHILD);
}
}
baseMapper.updateById(cmsColumn);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteCmsColumn(String id) throws JeecgBootException {
//查询选中节点下所有子节点一并删除
id = this.queryTreeChildIds(id);
if(id.indexOf(",")>0) {
StringBuffer sb = new StringBuffer();
String[] idArr = id.split(",");
for (String idVal : idArr) {
if(idVal != null){
CmsColumn cmsColumn = this.getById(idVal);
String pidVal = cmsColumn.getPid();
//查询此节点上一级是否还有其他子节点
List<CmsColumn> dataList = baseMapper.selectList(new QueryWrapper<CmsColumn>().eq("pid", pidVal).notIn("id",Arrays.asList(idArr)));
if((dataList == null || dataList.size()==0) && !Arrays.asList(idArr).contains(pidVal)
&& !sb.toString().contains(pidVal)){
//如果当前节点原本有子节点 现在木有了,更新状态
sb.append(pidVal).append(",");
}
}
}
//批量删除节点
baseMapper.deleteBatchIds(Arrays.asList(idArr));
//修改已无子节点的标识
String[] pidArr = sb.toString().split(",");
for(String pid : pidArr){
this.updateOldParentNode(pid);
}
}else{
CmsColumn cmsColumn = this.getById(id);
if(cmsColumn==null) {
throw new JeecgBootException("未找到对应实体");
}
updateOldParentNode(cmsColumn.getPid());
baseMapper.deleteById(id);
}
}
@Override
public List<CmsColumn> queryTreeListNoPage(QueryWrapper<CmsColumn> queryWrapper) {
List<CmsColumn> dataList = baseMapper.selectList(queryWrapper);
List<CmsColumn> mapList = new ArrayList<>();
for(CmsColumn data : dataList){
String pidVal = data.getPid();
//递归查询子节点的根节点
if(pidVal != null && !"0".equals(pidVal)){
CmsColumn rootVal = this.getTreeRoot(pidVal);
if(rootVal != null && !mapList.contains(rootVal)){
mapList.add(rootVal);
}
}else{
if(!mapList.contains(data)){
mapList.add(data);
}
}
}
return mapList;
}
/**
* 根据所传pid查询旧的父级节点的子节点并修改相应状态值
* @param pid
*/
private void updateOldParentNode(String pid) {
if(!ICmsColumnService.ROOT_PID_VALUE.equals(pid)) {
Integer count = baseMapper.selectCount(new QueryWrapper<CmsColumn>().eq("pid", pid));
if(count==null || count<=1) {
baseMapper.updateTreeNodeStatus(pid, ICmsColumnService.NOCHILD);
}
}
}
/**
* 递归查询节点的根节点
* @param pidVal
* @return
*/
private CmsColumn getTreeRoot(String pidVal){
CmsColumn data = baseMapper.selectById(pidVal);
if(data != null && !"0".equals(data.getPid())){
return this.getTreeRoot(data.getPid());
}else{
return data;
}
}
/**
* 根据id查询所有子节点id
* @param ids
* @return
*/
private String queryTreeChildIds(String ids) {
//获取id数组
String[] idArr = ids.split(",");
StringBuffer sb = new StringBuffer();
for (String pidVal : idArr) {
if(pidVal != null){
if(!sb.toString().contains(pidVal)){
if(sb.toString().length() > 0){
sb.append(",");
}
sb.append(pidVal);
this.getTreeChildIds(pidVal,sb);
}
}
}
return sb.toString();
}
/**
* 递归查询所有子节点
* @param pidVal
* @param sb
* @return
*/
private StringBuffer getTreeChildIds(String pidVal,StringBuffer sb){
List<CmsColumn> dataList = baseMapper.selectList(new QueryWrapper<CmsColumn>().eq("pid", pidVal));
if(dataList != null && dataList.size()>0){
for(CmsColumn tree : dataList) {
if(!sb.toString().contains(tree.getId())){
sb.append(",").append(tree.getId());
}
this.getTreeChildIds(tree.getId(),sb);
}
}
return sb;
}
}

@ -0,0 +1,70 @@
package org.jeecg.modules.cms.front;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.modules.cms.admin.entity.CmsArticle;
import org.jeecg.modules.cms.admin.entity.CmsColumn;
import org.jeecg.modules.cms.admin.service.ICmsArticleService;
import org.jeecg.modules.cms.admin.service.ICmsColumnService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@Api(tags = "cms首页")
@RestController
@RequestMapping("/cms/front")
@Slf4j
public class CmsHomePageController /*extends JeecgController<CmsColumn, ICmsColumnService>*/ {
@Autowired
private ICmsColumnService cmsColumnService;
@Autowired
private ICmsArticleService cmsArticleService;
@ApiOperation(value = "文章栏目-列表", notes = "文章栏目-列表")
@GetMapping(value = "/getColumnList")
public Result<?> getColumnList(HttpServletRequest req) {
List<CmsColumn> list = cmsColumnService.list(new LambdaQueryWrapper<CmsColumn>()
.eq(CmsColumn::getIsShow, "1")
.orderByAsc(CmsColumn::getSort));
return Result.OK(list);
}
@ApiOperation(value = "通过栏目类型获取文章列表", notes = "通过栏目类型获取文章列表")
@GetMapping(value = "/getArticleListByColumn")
public Result<?> getArticleListByColumn(CmsArticle cmsArticle,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
HttpServletRequest req) {
QueryWrapper<CmsArticle> queryWrapper = QueryGenerator.initQueryWrapper(cmsArticle, req.getParameterMap());
queryWrapper.eq("status", "1");
queryWrapper.eq("column_id", cmsArticle.getColumnId());
queryWrapper.last("order by publish_time desc");
Page<CmsArticle> page = new Page<CmsArticle>(pageNo, pageSize);
IPage<CmsArticle> pageList = cmsArticleService.page(page, queryWrapper);
return Result.OK(pageList);
}
@ApiOperation(value = "通过文单标题查询", notes = "通过文单标题查询")
@GetMapping(value = "/getByArticleTitle")
public Result<?> getByArticleTitle(CmsArticle cmsArticle, HttpServletRequest req) {
List<CmsArticle> list = cmsArticleService.list(new LambdaQueryWrapper<CmsArticle>()
.eq(CmsArticle::getStatus, "1")
.eq(CmsArticle::getTitle, cmsArticle.getTitle())
.orderByDesc(CmsArticle::getPublishTime));
return Result.OK(list);
}
}

@ -0,0 +1,67 @@
package org.jeecg.modules.cms.webmagic.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor;
import org.jeecg.modules.cms.webmagic.service.NewsPipeline;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import us.codecraft.webmagic.Spider;
@Api(tags = "国际学院-新闻联动态爬虫")
@RestController
@RequestMapping("/cms/newWebMagic")
@Slf4j
public class NewsWebMagicController {
@Autowired
private NewsPipeline pipeline;
@Autowired
private NewsPageProcessor pageProcessor;
@ApiOperation(value = "国际学院-新联动态爬虫", notes = "国际学院-新联动态爬虫")
@GetMapping(value = "/crawl")
public void crawl() {
String page1 = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml";
String pageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-";
String url = "";
try {
Spider.create(pageProcessor)
.addUrl(page1)
// 抓取到的数据存数据库
.addPipeline(pipeline)
// 开启2个线程抓取
.thread(1)
// 异步启动爬虫
.start();
} catch (Exception ex) {
log.error("数据抓取异常:", ex.getMessage());
log.error("定时抓取数据线程执行异常", ex);
}
// for (int i = 60; i <= 65; i++) {
// if (i == 1) {
// url = page1;
// } else {
// url = pageOther + (i + 1) + ".html";
// }
// log.info("the page {} url:{}", i, url);
// try {
// Spider.create(pageProcessor)
// .addUrl(url)
// // 抓取到的数据存数据库
// .addPipeline(pipeline)
// // 开启2个线程抓取
// .thread(3)
// // 异步启动爬虫
// .start();
// } catch (Exception ex) {
// log.error("第[{}]页数据抓取异常:", i, ex.getMessage());
// log.error("定时抓取数据线程执行异常", ex);
// }
// }
}
}

@ -0,0 +1,93 @@
package org.jeecg.modules.cms.webmagic.service;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.util.DateUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Component;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.processor.PageProcessor;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
@Component
@Slf4j
public class NewsPageProcessor implements PageProcessor {
private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);
@Override
public void process(Page page) {
log.info("the page.url ****** = " + page.getUrl());
// log.info("page= " + page.getHtml().toString());
/**
* <div class="position">
* <a href="http://sie.huanghuai.edu.cn">首页</a> &gt;&gt;
* <a href="http://sie.huanghuai.edu.cn/index.php/item-list-category-12805.html">走进学院</a> &gt;&gt;
* <a href="http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.html">学院新闻</a> &gt;&gt;
* <a>详细内容</a>
*
* 该div包含<a>详细内容</a> 说明是文章详情页面,需求处理,其它页面不处理
*/
page.putField("flag", page.getHtml().xpath("//div[@class='position']/a[4]/html()").toString());
if (StringUtils.isBlank(page.getResultItems().get("flag"))) {
//文章日期
// List<String> dateList = page.getHtml().xpath("//ul[@class='label_ul_b']/li/span[@class='label_datatime']/html()").all();
// List<String> urlList = page.getHtml().xpath("//ul[@class='label_ul_b']/li/a/html()").all();
List<String> liNodes = page.getHtml().xpath("//ul[@class='label_ul_b']/li/html()").all();
String currentDate = DateUtils.date2Str(new SimpleDateFormat("yyyy-MM-dd"));
Optional.ofNullable(liNodes).orElse(new LinkedList<>()).forEach(li -> {
if (StringUtils.isNotEmpty(li)) {
Element body = Jsoup.parse(li).body();
Elements allElements = body.getAllElements();
String date = allElements.get(1).text();
String dateStr = date.substring(1, date.length() - 1);
// log.info("dateStr = " + dateStr);
String href = allElements.get(2).attr("href");
// log.info("url = " + href);
//只抓取当前日期发布的文章
if (StringUtils.equals(currentDate, dateStr)) {
page.addTargetRequest(href);
}
}
});
//要抓取的文章url
// List<Request> requestList = page.getTargetRequests();
// requestList.forEach(e -> {
// log.info("当前页,文章列表:{}", e.getUrl());
// });
// 如果是列表页,跳过此页,pipeline不进行后续处理
//不处理列表的页面,只处理详情页数据
page.setSkip(true);
} else { //文章信息
//文章标题
page.putField("title", page.getHtml().xpath("//div[@class='layout_txtcontent_title']/html()").toString());
//文章内容
page.putField("content", page.getHtml().xpath("//div[@class='layout_txtcontent_content']/html()").toString());
// 日期:2023-04-03 00:00:00
String publishTimeHtml = page.getHtml().xpath("//div[@class='layout_txtcontent_info']/text()").toString();
String publishTime = publishTimeHtml.substring(4, 23);
//发布时间
page.putField("publishTime", publishTime);
// log.info("publishTime2-------------:{}", publishTime);
}
}
@Override
public Site getSite() {
return site;
}
}

@ -0,0 +1,59 @@
package org.jeecg.modules.cms.webmagic.service;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.cms.admin.entity.CmsArticle;
import org.jeecg.modules.cms.admin.entity.CmsColumn;
import org.jeecg.modules.cms.admin.service.ICmsArticleService;
import org.jeecg.modules.cms.admin.service.ICmsColumnService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
@Slf4j
public class NewsPipeline implements Pipeline {
@Autowired
private ICmsArticleService iCmsArticleService;
@Autowired
private ICmsColumnService iCmsColumnService;
public void process(ResultItems resultItems, Task task) {
// log.info("the url:{}", resultItems.getRequest().getUrl());
// log.info("the title:{}", resultItems.get("title").toString());
// log.info("the content:{}", resultItems.get("content").toString());
String publishTime = resultItems.get("publishTime").toString();
CmsArticle cmsArticle = new CmsArticle();
cmsArticle.setSource("国际学院");
cmsArticle.setStatus("1");
Date date = DateUtils.str2Date(publishTime, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
cmsArticle.setPublishTime(date);
cmsArticle.setCreateTime(date);
cmsArticle.setTitle(resultItems.get("title").toString());
cmsArticle.setContent(resultItems.get("content").toString());
cmsArticle.setCreateBy("admin");
cmsArticle.setOriginUrl(resultItems.getRequest().getUrl());
CmsColumn cmsColumn = iCmsColumnService.getOne(new LambdaQueryWrapper<CmsColumn>()
.eq(CmsColumn::getName, "专业动态"));
if (!ObjectUtils.isEmpty(cmsColumn)) {
cmsArticle.setColumnId(cmsColumn.getId());
cmsArticle.setColumnName(cmsColumn.getName());
}
try {
iCmsArticleService.save(cmsArticle);
log.info("保存文章成功:{}", resultItems.get("title").toString());
} catch (Exception e) {
log.error("保存文章失败", e.getMessage());
}
}
}

@ -0,0 +1,53 @@
package org.jeecg.modules.cms.webmagic.task;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor;
import org.jeecg.modules.cms.webmagic.service.NewsPipeline;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import us.codecraft.webmagic.Spider;
/**
* @Description: 同步定时任务
* <p>
* 此处的同步是指 当定时任务的执行时间大于任务的时间间隔时
* 会等待第一个任务执行完成才会走第二个任务
* @author: taoyan
* @date: 2020年06月19日
*/
@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Slf4j
public class NewsAsyncJob implements Job {
@Autowired
private NewsPipeline pipeline;
@Autowired
private NewsPageProcessor pageProcessor;
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(" NewsAsyncJob Execution key:" + jobExecutionContext.getJobDetail().getKey());
log.info(String.format("NewsAsyncJob-开始时间:" + DateUtils.getTimestamp()));
String urlPage1 = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml";
// String urlPageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-";
// String url = "";
try {
Spider.create(pageProcessor)
.addUrl(urlPage1)
// 抓取到的数据存数据库
.addPipeline(pipeline)
// 开启2个线程抓取
.thread(1)
// 异步启动爬虫
.start();
} catch (Exception ex) {
log.error("数据抓取异常:", ex.getMessage());
log.error("定时抓取数据线程执行异常", ex);
}
}
}

@ -0,0 +1,71 @@
//package org.jeecg.modules.cms.webmagic.task;
//
//import lombok.extern.slf4j.Slf4j;
//import org.jeecg.modules.cms.webmagic.service.NewsPageProcessor;
//import org.jeecg.modules.cms.webmagic.service.NewsPipeline;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.scheduling.annotation.Scheduled;
//import org.springframework.stereotype.Component;
//import us.codecraft.webmagic.Spider;
//
//@Slf4j
//@Component
//public class NewsWebMagicTask {
//
// @Autowired
// private NewsPipeline pipeline;
//
// @Autowired
// private NewsPageProcessor pageProcessor;
//
// // 每天23点执行一次
//// @Scheduled(cron = "0 0 23 * * ?")
// //@Scheduled(cron = "0 40 15 * * ?")
// // 每隔1分钟执行一次
//// @Scheduled(cron = "0 */3 * * * ?")
// public void crawl() {
// //第1页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml
// //第2页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-2.html
// //第3页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-3.html
// // ......
// //第65页 http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-65.html
//
// String urlPage1 = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151.shtml";
// String urlPageOther = "http://sie.huanghuai.edu.cn/index.php/item-list-category-13151-page-";
// String url = "";
// try {
// Spider.create(pageProcessor)
// .addUrl(urlPage1)
// // 抓取到的数据存数据库
// .addPipeline(pipeline)
// // 开启2个线程抓取
// .thread(1)
// // 异步启动爬虫
// .start();
// } catch (Exception ex) {
// log.error("数据抓取异常:", ex.getMessage());
// log.error("定时抓取数据线程执行异常", ex);
// }
//// for (int i = 1; i <= 9; i++) {
//// if (i == 1) {
//// url = urlPage1;
//// } else {
//// url = urlPageOther + (i + 1) + ".html";
//// }
//// log.info("the page {} url:{}", i, url);
//// try {
//// Spider.create(pageProcessor)
//// .addUrl(url)
//// // 抓取到的数据存数据库
//// .addPipeline(pipeline)
//// // 开启2个线程抓取
//// .thread(3)
//// // 异步启动爬虫
//// .start();
//// } catch (Exception ex) {
//// log.error("第[{}]页数据抓取异常:", i, ex.getMessage());
//// log.error("定时抓取数据线程执行异常", ex);
//// }
//// }
// }
//}

@ -0,0 +1,22 @@
package org.jeecg.modules.cms.webmagic.task;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.DateUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
* 示例不带参定时任务
*
* @Author Scott
*/
@Slf4j
public class SampleJobTest implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(" >>>>>>>>SampleJobTest Execution key:"+jobExecutionContext.getJobDetail().getKey());
log.info(String.format(" 普通定时任务 SampleJobTest,时间:" + DateUtils.getTimestamp()));
}
}

@ -110,6 +110,18 @@
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-module-cms</artifactId>
<version>${jeecgboot.version}</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 -->
<property name="LOG_HOME" value="../logs" />
<property name="LOG_HOME" value="./logs" />
<!--<property name="COLOR_PATTERN" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta( %replace(%caller{1}){'\t|Caller.{1}0|\r\n', ''})- %gray(%msg%xEx%n)" />-->
<!-- 控制台输出 -->

@ -51,6 +51,7 @@
<modules>
<module>jeecg-boot-base</module>
<module>jeecg-boot-module-system</module>
<module>jeecg-boot-module-cms</module>
<!-- 需要微服务,请打开注释
<module>jeecg-boot-starter</module>
<module>jeecg-cloud-module</module>-->
@ -169,40 +170,40 @@
<version>${jeecgboot.version}</version>
</dependency>-->
<!--xxl-job定时任务-->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-starter-job</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
<!-- &lt;!&ndash;xxl-job定时任务&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.jeecgframework.boot</groupId>-->
<!-- <artifactId>jeecg-boot-starter-job</artifactId>-->
<!-- <version>${jeecgboot.version}</version>-->
<!-- </dependency>-->
<!--redis分布式锁-->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-starter-lock</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
<!-- &lt;!&ndash;redis分布式锁&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.jeecgframework.boot</groupId>-->
<!-- <artifactId>jeecg-boot-starter-lock</artifactId>-->
<!-- <version>${jeecgboot.version}</version>-->
<!-- </dependency>-->
<!--rabbitmq消息队列-->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-starter-rabbitmq</artifactId>
<version>${jeecgboot.version}</version>
</dependency>
<!-- &lt;!&ndash;rabbitmq消息队列&ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>org.jeecgframework.boot</groupId>-->
<!-- <artifactId>jeecg-boot-starter-rabbitmq</artifactId>-->
<!-- <version>${jeecgboot.version}</version>-->
<!-- </dependency>-->
<!-- 七牛云SDK -->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>${qiniu-java-sdk.version}</version>
<exclusions>
<exclusion>
<artifactId>okhttp</artifactId>
<groupId>com.squareup.okhttp3</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- &lt;!&ndash; 七牛云SDK &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.qiniu</groupId>-->
<!-- <artifactId>qiniu-java-sdk</artifactId>-->
<!-- <version>${qiniu-java-sdk.version}</version>-->
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <artifactId>okhttp</artifactId>-->
<!-- <groupId>com.squareup.okhttp3</groupId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
<!-- </dependency>-->
<!-- dom4j -->
@ -212,11 +213,11 @@
<version>${dom4j.version}</version>
</dependency>
<!-- redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>${redisson.version}</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.redisson</groupId>-->
<!-- <artifactId>redisson</artifactId>-->
<!-- <version>${redisson.version}</version>-->
<!-- </dependency>-->
<!-- guava工具类 -->
<dependency>

Loading…
Cancel
Save