产品课程

master
yujialong 5 months ago
parent c1b1a1e6a8
commit 5d997905c9
  1. 20
      src/api/index.js
  2. BIN
      src/assets/images/style/78.png
  3. BIN
      src/assets/images/style/79.png
  4. BIN
      src/assets/images/style/80.png
  5. BIN
      src/assets/images/style/81.png
  6. 18
      src/const/modules.js
  7. 10
      src/pages/article/add/index.vue
  8. 991
      src/pages/article/add/product.vue
  9. 19
      src/pages/article/list/index.vue
  10. 244
      src/pages/column/page/member.vue
  11. 4
      src/plugins/requests/index.js
  12. 46
      src/router/modules/article.js
  13. 2
      src/setting.js

@ -1,10 +1,13 @@
import Setting from '@/setting'
const host = Setting.apiBaseURL
const { huoranApi, apiBaseURL: host } = Setting
export default {
logins: `/iasf/sys/user/login`,
verification: `${host}/iasf/sys/getVerify`,
upload: `${host}/iasf/sysFiles/upload`,
courseDiscipline: `${huoranApi}/nakadai/nakadai/subject/courseDiscipline`,
courseProfessionalClass: `${huoranApi}/nakadai/nakadai/subject/courseProfessionalClass`,
courseProfessional: `${huoranApi}/nakadai/nakadai/subject/courseProfessional`,
listByPage: `/iasf/sysFiles/listByPage`,
delFile: `/iasf/sysFiles/delete`,
updateFile: `/iasf/sysFiles/update`,
@ -15,12 +18,12 @@ export default {
user: `/iasf/sys/user`,
sendPhoneOrEmailCode: `/iasf/sys/sendPhoneOrEmailCode`,
updatePhoneOrEmail: `/iasf/sys/updatePhoneOrEmail`,
updateUserAvatars: `${host}/iasf/sys/updateUserAvatars`,
staffTemplate: `http://139.159.254.212/用户导入模板.xlsx`,
checkJobNumber: `/iasf/sys/checkJobNumber`,
checkUsername: `/iasf/sys/checkUsername`,
resetPwd: `/iasf/sys/resetPwd`,
pwd: `/iasf/sys/user/pwd`,
updateUserAvatars: `${host}/iasf/sys/updateUserAvatars`,
exportFailure: `${host}/iasf/sys/exportFailure`,
importStaff: `${host}/iasf/sys/importStaff`,
roles: `/iasf/sys/roles`,
@ -88,6 +91,7 @@ export default {
delSeo: `/iasf/seo/delete`,
seoList: `/iasf/seo/list`,
updateSeo: `/iasf/seo/update`,
batchDeletionFloating: `/iasf/SysFloatingColumnSchemeService/SysFloatingColumnScheme/batchDeletion`,
findFloating: `/iasf/SysFloatingColumnSchemeService/SysFloatingColumnScheme/findById`,
listFloating: `/iasf/SysFloatingColumnSchemeService/SysFloatingColumnScheme/floatingBarList`,
@ -102,4 +106,16 @@ export default {
saveFooter: `/iasf/SysFooterSetupService/SysFooterSetup/saveOrUpdate`,
checkEnableOrDisableFooter: `/iasf/SysFooterSetupService/SysFooterSetup/checkEnableOrDisable`,
enableOrDisableSchemeFooter: `/iasf/SysFooterSetupService/SysFooterSetup/enableOrDisableScheme`,
categoryDel: `/iasf/categoryService/Category/batchDelete`,
categoryFind: `/iasf/categoryService/Category/findById`,
categoryList: `/iasf/categoryService/Category/list`,
categorySave: `/iasf/categoryService/Category/saveOrUpdate`,
productDetailsSave: `/iasf/productDetails/saveOrUpdate`,
productDetailsFind: `/iasf/productDetails/findById`,
productDetailsDel: `/iasf/productDetails/batchDelete`,
productDetailsEnable: `/iasf/productDetails/articleEnableOrDisable`,
productDetailsTop: `/iasf/productDetails/courseProductTopOperation`,
productDetailsCheck: `/iasf/productDetails/checkIfTheTitleIsRepeat`,
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 KiB

@ -113,7 +113,7 @@ export default {
},
list: [
{
pic: 'https://www.occupationlab.com/images/index/1.png',
pic: 'https://occupationlab.com/images/index/1.png',
title: '职站',
link: {
linkName: '无',
@ -130,7 +130,7 @@ export default {
isEnable: 1
},
{
pic: 'https://www.occupationlab.com/images/index/2.png',
pic: 'https://occupationlab.com/images/index/2.png',
title: 'Dataforward数据前瞻',
link: {
linkName: '无',
@ -147,7 +147,7 @@ export default {
isEnable: 1
},
{
pic: 'https://www.occupationlab.com/images/index/3.png',
pic: 'https://occupationlab.com/images/index/3.png',
title: '大赛平台',
link: {
linkName: '无',
@ -244,37 +244,37 @@ export default {
},
list: [
{
pic: 'https://www.occupationlab.com/images/member/icon1.png',
pic: 'https://occupationlab.com/images/member/icon1.png',
title: '采购降本',
des: '优选高品质低价格产品',
isEnable: 1
},
{
pic: 'https://www.occupationlab.com/images/member/icon2.png',
pic: 'https://occupationlab.com/images/member/icon2.png',
title: '精准匹配',
des: '体系化产品方案匹配满足不同学科需求',
isEnable: 1
},
{
pic: 'https://www.occupationlab.com/images/member/icon3.png',
pic: 'https://occupationlab.com/images/member/icon3.png',
title: '本地服务',
des: '提供项目全流程售前售后支持服务',
isEnable: 1
},
{
pic: 'https://www.occupationlab.com/images/member/icon4.png',
pic: 'https://occupationlab.com/images/member/icon4.png',
title: '移动办公',
des: '查看产品、参数,下单,方案生成,手机上即可完成',
isEnable: 1
},
{
pic: 'https://www.occupationlab.com/images/member/icon5.png',
pic: 'https://occupationlab.com/images/member/icon5.png',
title: '免息账期',
des: '先发货后付款,支持背靠背支付',
isEnable: 1
},
{
pic: 'https://www.occupationlab.com/images/member/icon6.png',
pic: 'https://occupationlab.com/images/member/icon6.png',
title: '智能方案',
des: '内置有实验室配置方案模板只需3分钟即可生成方案',
isEnable: 1

@ -159,16 +159,6 @@
</div>
<template v-if="form.articleTemplate === 25">
<div class="item-line">
<!-- <el-form-item prop="classificationId" label="所属分类">
<el-select style="width: 234px;" v-model="getModelData" clearable>
<template v-for="item in classifications">
<el-option v-if="item.classificationName" :key="item.id" :label="item.classificationName"
:value="item.id">
</el-option>
</template>
</el-select>
<el-button class="set-btn" type="primary" @click="setClass">设置</el-button>
</el-form-item> -->
<el-form-item prop="offlineLocation" label="线下地点">
<el-input placeholder="请输入线下地点" v-model="form.offlineLocation" clearable maxlength="100"></el-input>
</el-form-item>

@ -0,0 +1,991 @@
<template>
<div class="page">
<p class="page-name mb">文章详情</p>
<el-form :model="form" :rules="rules" class="input-form model" label-width="140px">
<el-form-item class="lg" prop="articleTemplate" label="独立文章模板">
<el-popover placement="top-start" trigger="hover" content="默认使用栏目中设置的文章样式,如果需要为该篇文章指定专门的模板样式,可以设置此项">
<img slot="reference" class="info" src="@/assets/images/ques.png" alt="">
</el-popover>
<div style="width: 940px;text-align: right;">
<el-switch v-model="form.templateStatus" :active-value="1" :inactive-value="0">
</el-switch>
</div>
<ul v-if="form.templateStatus" class="styles">
<template v-for="(item, i) in detailStyle">
<li v-if="item.id !== column.detailStyle" :key="i" @click="styleChange(item.id)">
<div class="review">
<img :class="{ 'is-link': item.id == 24 }" :src="require('@/assets/images/style/' + item.id + '.png')"
alt="">
</div>
<el-radio v-model="form.articleTemplate" :label="item.id">{{ item.style }}</el-radio>
</li>
</template>
</ul>
</el-form-item>
<el-form-item prop="name" label="名称">
<el-input id="articleTitle" style="width: 940px" placeholder="请输入名称" v-model="form.name" clearable
maxlength="100" @change="nameChange"></el-input>
</el-form-item>
<div class="item-line">
<el-form-item label="分类">
<el-select style="width: 234px;" v-model="getModelData" clearable>
<template v-for="item in classifications">
<el-option v-if="item.categoryId" :key="item.categoryId" :label="item.name" :value="item.categoryId">
</el-option>
</template>
</el-select>
<el-button class="set-btn" type="primary" @click="setClass">设置</el-button>
</el-form-item>
<el-form-item prop="author" label="类型">
<el-select style="width: 234px;" v-model="form.categoryId" multiple>
<template v-for="item in categories">
<el-option v-if="item.categoryId" :key="item.categoryId" :label="item.name" :value="item.categoryId">
</el-option>
</template>
</el-select>
<el-button class="set-btn" type="primary" @click="setLabel">设置</el-button>
</el-form-item>
</div>
<el-form-item prop="subjectSpecialtyList" label="适用学科专业">
<div class="subject-wrap">
<div class="subject">
<div v-for="(item, i) in form.subjectSpecialtyList" :key="i" class="subject-line">
<el-form-item label="学科类别">
<el-select v-model="item.subjectCategoryId" @change="getProfessionalClass(item)">
<el-option v-for="(item, i) in subjectList" :key="i" :label="item.disciplineName"
:value="item.disciplineId"></el-option>
</el-select>
</el-form-item>
<el-form-item label="专业类">
<el-select v-model="item.professionalCategoryId" :disabled="item.subjectCategoryId ? false : true"
@change="getProfessional(item)">
<el-option v-for="(item, i) in item.professionalClassList" :key="i"
:label="item.professionalClassName" :value="item.professionalClassId"></el-option>
</el-select>
</el-form-item>
<el-form-item label="专业">
<el-select v-model="item.majorId" :disabled="item.professionalCategoryId ? false : true">
<el-option v-for="(item, i) in item.professionalList" :key="i" :label="item.professionalName"
:value="item.majorId"></el-option>
</el-select>
</el-form-item>
<i v-if="i" class="del el-icon-delete" @click="form.subjectSpecialtyList.splice(i, 1)"></i>
</div>
</div>
<div class="subject-plus" @click="addSubject">
<i class="el-icon-circle-plus-outline"></i>
</div>
</div>
</el-form-item>
<template v-if="form.articleTemplate === 78">
<div class="item-line">
<el-form-item label="匹配课程" prop="matchedCourses">
<el-input placeholder="请输入匹配课程" v-model="form.matchedCourses" maxlength="30"></el-input>
</el-form-item>
<el-form-item label="预计课时" prop="estimatedHours">
<el-select v-model="form.estimatedHours" clearable placeholder="请选择预计课时">
<el-option label="32课时" value="32课时"></el-option>
<el-option label="64课时" value="64课时"></el-option>
</el-select>
</el-form-item>
</div>
<el-form-item label="适用场景" prop="applicableScenarios">
<el-input style="width: 940px;" placeholder="请输入适用场景" v-model="form.applicableScenarios"
maxlength="50"></el-input>
</el-form-item>
</template>
<el-form-item prop="coverImageUrl" label="封面图">
<el-upload class="avatar-uploader" accept=".jpg,.png,.jpeg,.gif" :on-change="file => changeFile(file, 0)"
:show-file-list="false" :action="this.api.upload" :auto-upload="false">
<img v-if="form.coverImageUrl" :src="form.coverImageUrl" class="avatar">
<div class="uploader-default" v-else>
<img class="plus" src="@/assets/images/plus.png" alt="">
<p>点击上传</p>
</div>
</el-upload>
</el-form-item>
<div class="item-line">
<el-form-item label="来源" prop="source" style="margin-right: 40px;">
<el-input placeholder="请输入来源" v-model="form.source" maxlength="50"></el-input>
</el-form-item>
<el-form-item label="按钮跳转链接">
<el-input class="m-r-10" style="width: 150px;" placeholder="请设置按钮名称" v-model="form.jumpButtonName"
maxlength="10"></el-input>
<el-input placeholder="请设置跳转链接" v-model="form.jumpLinkUrl"></el-input>
</el-form-item>
</div>
<el-form-item label="简介" prop="introduction">
<el-input style="width: 940px;" v-model="form.introduction" type="textarea" maxlength="200"></el-input>
</el-form-item>
<el-form-item prop="detailedDescription" label="详情">
<Editor api-key='rnk6zw9v267xqz7pf98twt1vmrvltmd436je7a642pckltda' v-model="form.detailedDescription"
:init="editorConfig" />
</el-form-item>
</el-form>
<div class="btns">
<el-button type="primary" @click="submit(1)">发布</el-button>
<el-button v-if="$route.query.id" @click="preview">预览</el-button>
<el-button @click="submit(0)">保存草稿</el-button>
<el-button @click="back">取消</el-button>
</div>
<!-- 剪裁组件弹窗 -->
<el-dialog title="图片裁剪" append-to-body :visible.sync="cropperModel" width="1100px" :close-on-click-modal="false">
<Cropper ref="cropper" :img-file.sync="file" :is-upload="isUpload" :fixed="true" :fixedNumber.sync="fixedNumber"
@upload="customUpload" />
</el-dialog>
<el-dialog title="分类设置" :visible.sync="classVisible" width="500px" :close-on-click-modal="false" class="manage-dia"
:before-close="closeClass">
<div class="plus">
<i class="el-icon-circle-plus-outline" @click="addClass"></i>
</div>
<el-table :data="classifications" ref="table" header-align="center" row-key="id">
<el-table-column type="index" width="60" label="序号" align="center"></el-table-column>
<el-table-column prop="name" label="分类名称" align="center" min-width="130">
<template slot-scope="scope">
<el-input v-if="scope.row.edit" placeholder="请输入分类名称" v-model="scope.row.name" clearable
maxlength="30"></el-input>
<span v-else>{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column prop="updateTime1" label="是否引用" align="center" min-width="60"></el-table-column>
<el-table-column label="操作" align="center" min-width="60">
<template slot-scope="scope">
<i v-if="scope.row.edit" class="el-icon-check edit" @click="submitClass(scope.row)"></i>
<i v-else class="el-icon-edit edit" @click="editClass(scope.row)"></i>
<i class="el-icon-delete del" @click="delClass(scope.row, scope.$index)"></i>
</template>
</el-table-column>
</el-table>
<span slot="footer">
<el-button @click="closeClass">返回</el-button>
</span>
</el-dialog>
<el-dialog title="类型设置" :visible.sync="labelVisible" width="500px" :close-on-click-modal="false" class="manage-dia"
:before-close="closeLabel">
<div class="plus">
<i class="el-icon-circle-plus-outline" @click="addLabel"></i>
</div>
<el-table :data="categories" ref="table" header-align="center" row-key="id">
<el-table-column type="index" width="60" label="序号" align="center"></el-table-column>
<el-table-column prop="name" label="类型" align="center" min-width="130">
<template slot-scope="scope">
<el-input v-if="scope.row.edit" placeholder="请输入类型" v-model="scope.row.name" clearable
maxlength="30"></el-input>
<span v-else>{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column prop="updateTime1" label="是否引用" align="center" min-width="60"></el-table-column>
<el-table-column label="操作" align="center" min-width="60">
<template slot-scope="scope">
<i v-if="scope.row.edit" class="el-icon-check edit" @click="submitLabel(scope.row)"></i>
<i v-else class="el-icon-edit edit" @click="editLabel(scope.row)"></i>
<i class="el-icon-delete del" @click="delLabel(scope.row, scope.$index)"></i>
</template>
</el-table-column>
</el-table>
<span slot="footer">
<el-button @click="closeLabel">返回</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Setting from '@/setting'
import Util from '@/libs/util'
import { mapState } from 'vuex'
import Editor from '@tinymce/tinymce-vue'
import editorConfig from './editor'
import Cropper from '@/components/img-upload/Cropper'
import Axios from 'axios'
export default {
data () {
return {
site: this.$store.state.content.site,
userId: this.$store.state.user.userId,
headers: {
token: Util.local.get(Setting.tokenKey)
},
nameRepeat: false,
categories: [],
detailStyle: [
{
id: 78,
style: '产品详情'
},
{
id: 72,
style: '富文本'
},
{
id: 24,
style: '链接'
},
{
id: 79,
style: '课程详情'
},
],
subjectList: [], //
form: {
siteId: this.$store.state.content.site.id,
id: this.$route.query.id || '',
founderId: this.$store.state.user.userId,
templateStatus: 0,
articleTemplate: '',
applicableScenarios: '',
categoryId: '',
classificationTagId: '',
estimatedHours: '',
introduction: '',
jumpButtonName: '',
jumpLinkUrl: '',
matchedCourses: '',
name: '',
columnId: +this.$route.query.columnId,
publishStatus: 0,
detailedDescription: '',
source: '平台官方',
coverImageUrl: '',
subjectSpecialtyList: [
{
professionalClassList: [],
professionalList: [],
subjectCategoryId: 1,
professionalCategoryId: 1,
majorId: 1,
}
],
},
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' }
],
subjectSpecialtyList: [
{ required: true, message: '请选择学科专业', trigger: 'change' }
],
source: [
{ required: true, message: '请输入来源', trigger: 'blur' }
],
coverImageUrl: [
{ required: true, message: '请上传封面图', trigger: 'change' }
],
detailedDescription: [
{ required: true, message: '请输入正文', trigger: 'blur' }
],
},
columnInfo: {},
editorConfig,
submiting: false, //
pass: false,
uploading: 0,
updateTime: 0,
cropperModel: false,
isUpload: false,
fixedNumber: [1.76, 1],
file: {}, //
isBanner: 0,
classifications: [],
classVisible: false,
categories: [],
labelVisible: false,
originalName: '',
originColumnId: ''
};
},
computed: {
...mapState('user', [
'userName'
]),
...mapState('content', [
'column'
]),
getModelData: {
get () {
const data = this.classifications.find(item => item.id === this.form.classificationTagId)
return data ? data.id : ''
},
set (newVal) {
this.form.classificationTagId = newVal
}
},
},
components: {
Editor,
Cropper
},
watch: {
// ,
form: {
handler (val) {
this.updateTime++
},
deep: true
}
},
//
beforeRouteLeave (to, from, next) {
if (this.submiting) {
next()
} else if (!this.pass) {
//
if (this.updateTime > 1) {
this.$confirm(`所填写内容暂未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.submit(this.form.publishStatus, next)
}).catch(() => {
next()
})
} else {
next()
}
} else {
next()
}
},
mounted () {
this.$store.commit('user/setCrumbs', [
{
name: '站点管理',
route: '/site'
},
{
name: '内容管理'
},
{
name: '文章管理',
route: '/article'
},
{
name: this.$route.query.columnName,
route: '/article'
},
{
name: this.$route.query.id ? '编辑' : '新增'
}
])
this.form.id ? this.getData() : this.getColumn()
this.getSubject()
this.getLabel()
// this.getTemplate()
},
methods: {
//
getData () {
this.$post(`${this.api.productDetailsFind}?id=${this.form.id}`).then(({ data }) => {
data.categoryId = data.categoryId ? data.categoryId.split(',').map(e => +e) : []
this.originalName = data.name
let lableData = []
data.categoryId.forEach(item => {
this.categories.forEach(options => {
if (item == options.id) {
lableData.push(item)
}
})
})
data.categoryId = lableData
this.form = data
}).catch(err => { })
},
//
getColumn () {
this.$post(`${this.api.findColumn}?id=${this.$route.query.columnId}`).then(({ data }) => {
this.columnInfo = data
const { form } = this
// /78
if (!form.templateStatus) {
form.articleTemplate = (data.typeId === 1 || data.typeId === 4) ? data.detailStyleId : 78
}
this.getClassification()
this.$nextTick(() => {
this.updateTime = 0
})
}).catch(err => { })
},
//
styleChange (id) {
this.form.articleTemplate = id
},
//
addSubject () {
const e = {
professionalClassList: [],
professionalList: [],
subjectCategoryId: 1,
professionalCategoryId: 1,
majorId: 1,
}
this.form.subjectSpecialtyList.push(e)
this.getProfessionalClassData(e)
},
//
async getSubject () {
const { list } = await this.$get(this.api.courseDiscipline)
this.subjectList = list
this.form.subjectSpecialtyList.forEach(e => {
e.subjectCategoryId === 1 && this.getProfessionalClass(e)
})
},
//
clearClass (item) {
item.professionalCategoryId = item.subjectCategoryId === 1 ? 1 : ''
item.majorId = item.subjectCategoryId === 1 ? 1 : ''
},
//
getProfessionalClass (item) {
this.clearClass(item)
this.getProfessionalClassData(item)
},
async getProfessionalClassData (item) {
const { list } = await this.$get(this.api.courseProfessionalClass, {
disciplineId: item.subjectCategoryId
})
item.professionalClassList = list
this.form.subjectSpecialtyList.forEach(e => {
e.professionalCategoryId === 1 && this.getProfessional(e)
})
},
//
clearProfess (item) {
item.majorId = item.professionalCategoryId === 1 ? 1 : ''
},
//
getProfessional (item) {
this.clearProfess(item)
this.getProfessionalData(item)
},
async getProfessionalData (item) {
const { list } = await this.$get(this.api.courseProfessional, {
professionalClassId: item.professionalCategoryId
})
item.professionalList = list
},
//
getTemplate () {
this.$post(this.api.individualTemplateDetailsStyle).then(({ data }) => {
const result = []
data.map(e => {
result.find(n => n.style === e.style) || result.push(e)
})
this.detailStyle = result
}).catch(err => { })
},
//
getClassification () {
this.$post(`${this.api.categoryList}?siteId=${this.site.id}&type=0`).then(({ data }) => {
this.classifications = data
}).catch(err => { })
},
//
setClass () {
this.classVisible = true
},
//
addClass () {
this.classifications.push({
edit: true,
categoryId: '',
name: ''
})
},
//
editClass (row) {
this.$set(row, 'edit', 1)
},
//
delClass (row, i) {
if (row.categoryId) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
}).then(() => {
this.$post(this.api.categoryDel, [row.categoryId]).then(res => {
Util.successMsg('删除成功')
this.getClassification()
}).catch(res => { })
}).catch(() => { })
} else {
this.classifications.splice(i, 1)
}
},
//
submitClass (row, showMsg = 1) {
if (!row.name) return Util.errorMsg('请输入分类')
// this.$post(`${this.api.checkClassif}?name=${row.name}&siteId=${this.site.id}&classificationTagId=${row.id}`).then(res => {
this.$post(this.api.categorySave, {
type: 0,
name: row.name,
categoryId: row.categoryId,
siteId: this.site.id,
editorId: this.userId,
founderId: this.userId
}).then(res => {
showMsg && Util.successMsg((row.categoryId ? '修改' : '新增') + '成功')
this.getClassification()
}).catch(res => { })
// }).catch(res => { })
},
//
closeClass () {
const list = this.classifications
if (list.find(e => e.edit && e.name)) {
this.$confirm('所填写内容暂未保存,是否保存?', '提示', {
type: 'warning'
}).then(() => {
list.map(e => {
e.edit && e.name && this.submitClass(e, 0)
})
this.classVisible = false
}).catch(() => {
this.classVisible = false
})
} else {
this.classVisible = false
}
},
//
getLabel () {
this.$post(`${this.api.categoryList}?siteId=${this.site.id}&type=1`).then(({ data }) => {
this.categories = data
}).catch(err => { })
},
//
setLabel () {
this.labelVisible = true
},
//
addLabel () {
this.categories.push({
edit: true,
id: '',
name: ''
})
},
//
editLabel (row) {
this.$set(row, 'edit', 1)
},
//
delLabel (row, i) {
if (row.categoryId) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
}).then(() => {
this.$post(this.api.categoryDel, [row.categoryId]).then(res => {
Util.successMsg('删除成功')
this.getLabel()
}).catch(res => { })
}).catch(() => { })
} else {
this.categories.splice(i, 1)
}
},
//
submitLabel (row, showMsg = 1) {
if (!row.name) return Util.errorMsg('请输入类型')
// this.$post(`${this.api.checkLabel}?name=${row.name}&siteId=${this.site.id}&labelId=${row.id}`).then(res => {
this.$post(this.api.categorySave, {
type: 1,
name: row.name,
categoryId: row.categoryId,
siteId: this.site.id,
editorId: this.userId,
founderId: this.userId
}).then(res => {
showMsg && Util.successMsg((row.categoryId ? '修改' : '新增') + '成功')
this.getLabel()
}).catch(res => { })
// }).catch(res => { })
},
//
closeLabel () {
const list = this.categories
if (list.find(e => e.edit && e.name)) {
this.$confirm('所填写内容暂未保存,是否保存?', '提示', {
type: 'warning'
}).then(() => {
list.map(e => {
e.edit && e.name && this.submitLabel(e, 0)
})
this.labelVisible = false
}).catch(() => {
this.labelVisible = false
})
} else {
this.labelVisible = false
}
},
//
nameChange () {
const { name, id } = this.form
if (name && name !== this.originalName) {
this.$post(this.api.productDetailsCheck, {
siteId: this.site.id,
name,
id: id || ''
}).then(res => {
this.nameRepeat = false
}).catch(res => {
this.nameRepeat = true
})
} else {
this.nameRepeat = false
}
},
//
customUpload (data) {
const formData = new FormData()
formData.append('file', data, this.file.name)
formData.append('quote', this.form.name)
formData.append('site', this.site.siteName)
formData.append('uploader', this.userName)
this.imgUpload(formData)
},
//
compress (img) {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
// let initSize = img.src.length;
const width = img.width
const height = img.height
canvas.width = width
canvas.height = height
//
ctx.fillStyle = '#fff'
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(img, 0, 0, width, height)
//
const ndata = canvas.toDataURL('image/jpeg', 0.8)
return ndata
},
// base64bolb
dataURItoBlob (base64Data) {
let byteString
if (base64Data.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(base64Data.split(',')[1])
} else {
byteString = unescape(base64Data.split(',')[1])
}
const mimeString = base64Data
.split(',')[0]
.split(':')[1]
.split(';')[0]
const ia = new Uint8Array(byteString.length)
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i)
}
return new Blob([ia], {
type: mimeString
})
},
//
imgUpload (formData) {
this.isUpload = true
Axios({
method: 'post',
url: this.api.upload,
data: formData,
headers: {
'Content-Type': 'multipart/form-data',
token: Util.local.get(Setting.tokenKey)
},
}).then(({ data }) => {
if (data.code === 401) {
Util.errorMsg(data.msg)
setTimeout(() => {
this.$store.dispatch('user/logout')
}, 1000)
return false
}
let url = this.form.coverImageUrl
url && this.$del(this.api.delFile, [url.split('/').pop()]).then(res => { }).catch(e => { }) //
this.form.coverImageUrl = data.url
}).catch(res => { })
this.$refs.cropper.isDisabled = false
this.isUpload = false
this.cropperModel = false
},
//
changeFile (file, isBanner) {
this.isBanner = isBanner
const { size, name } = file
const ext = name.substring(name.lastIndexOf('.') + 1)
if (!Util.isImg(ext)) {
this.$message.error('请上传图片!')
return false
}
// if (size / 1024 / 1024 > 5) {
// this.$message.error('5M')
// return false
// }
this.file = file
this.cropperModel = true
this.$nextTick(() => {
this.$refs.cropper.updateImg({
url: window.URL.createObjectURL(file.raw),
size: file.size
})
})
},
//
preview () {
window.open((Setting.isDev ? `http://${location.hostname}:8095` : this.$store.state.content.site.domainName) + `#/article?articleId=${this.form.id}&siteId=${this.form.siteId}&id=${this.form.columnId}`)
},
//
back () {
this.pass = true
const { updateTime } = this
//
if (updateTime > 1) {
this.$confirm(`所填写内容暂未保存,是否保存?`, '提示', {
type: 'warning'
}).then(() => {
this.submit(this.form.publishStatus)
}).catch(() => {
this.$router.back()
})
} else {
this.$router.back()
}
},
//
updateFile (files, form, quoteId) {
files.map(e => {
this.$post(this.api.updateFile, {
id: e,
publishStatus: form.publishStatus,
quote: form.name,
quoteId
}).then(res => { }).catch(err => { })
})
},
//
submit (publishStatus, next) {
if (this.submiting) return false
const form = JSON.parse(JSON.stringify(this.form))
if (!form.name) return Util.errorMsg('请填写名称')
if (this.nameRepeat) return Util.errorMsg('该名称已重复!')
//
if (publishStatus) {
if (!form.coverImageUrl) return Util.errorMsg('请上传封面')
if (!form.coverImageUrl) return Util.errorMsg('请上传封面')
if (!form.source) return Util.errorMsg('请输入来源')
}
if (this.uploading) return Util.errorMsg('文件正在上传,请上传完成后再发布')
const { coverImageUrl } = form
const fileId = []
// idurlid
if (coverImageUrl) fileId.push(coverImageUrl.substr(coverImageUrl.lastIndexOf('/') + 1))
form.categoryId = form.categoryId.join(',')
form.subjectSpecialtyList.map(e => {
delete e.professionalClassList
delete e.professionalList
})
form.publishStatus = publishStatus
this.submiting = true
form.editorId = +this.$store.state.user.userId
this.$post(this.api.productDetailsSave, form).then(res => {
this.updateFile(fileId, form, form.id || res.data)
Util.successMsg(form.id ? '修改成功' : '创建成功')
next ? next() : this.$router.back()
}).catch(err => {
this.submiting = false
})
},
}
};
</script>
<style lang="scss" scoped>
$upload-width: 220px;
$upload-height: 102px;
$upload-lg-height: 102px;
/deep/ .avatar-uploader {
.el-upload {
position: relative;
width: $upload-width;
height: $upload-height;
border: 1px solid #dcdee0;
border-radius: 2px;
cursor: pointer;
overflow: hidden;
.uploader-default {
display: flex;
height: $upload-height;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
background: #fafafa;
p {
margin-top: 10px;
font-size: 14px;
color: #333;
line-height: 20px;
}
}
}
&.avatar-uploader-lg {
.el-upload {
width: 100%;
max-width: 820px;
height: $upload-lg-height;
.uploader-default {
height: $upload-lg-height;
}
}
}
.avatar {
display: block;
width: $upload-width;
height: $upload-height;
}
.avatar-lg {
display: block;
width: 100%;
height: $upload-lg-height;
}
.el-upload__tip {
margin-top: 0;
p {
font-size: 12px;
color: #333;
}
}
}
.styles {
display: flex;
flex-wrap: wrap;
width: 955px;
// height: 320px;
margin-top: 20px;
overflow: auto;
li {
margin: 0 20px 10px 0;
text-align: center;
cursor: pointer;
&:hover .review {
border-color: #2962ff;
}
}
.review {
display: flex;
justify-content: center;
align-items: center;
width: 170px;
height: 112px;
margin-bottom: 10px;
border: 1px solid #dcdee0;
border-radius: 2px;
img {
width: 80px;
}
.is-link {
width: 50px;
}
}
}
.info {
position: absolute;
top: 8px;
left: -32px;
cursor: pointer;
}
.plus {
margin-bottom: 10px;
font-size: 18px;
color: #2962ff;
text-align: right;
cursor: pointer;
}
.set-btn {
margin-left: 10px !important;
}
.manage-dia {
.edit,
.del {
font-size: 14px;
cursor: pointer;
}
.edit {
margin-right: 10px;
}
}
.subject-wrap {
width: 940px;
.subject {
padding: 10px;
border: 1px dashed #ccc;
.subject-line {
position: relative;
display: flex;
padding-right: 50px;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
}
.el-form-item {
margin-bottom: 0;
}
.el-select {
width: auto;
}
.del {
position: absolute;
top: 11px;
right: 20px;
cursor: pointer;
}
}
.subject-plus {
margin-top: 5px;
text-align: center;
font-size: 18px;
color: #5481ff;
cursor: pointer;
}
}
</style>

@ -211,7 +211,8 @@ export default {
show: true
}
],
originList: []
originList: [],
isCourseProduct: 0
};
},
watch: {
@ -286,6 +287,7 @@ export default {
this.list = data.records
const total = +data.total
this.total = total
this.isCourseProduct = this.list.length ? this.list[0].isCourseProduct : 0
if (this.last) {
let page = parseInt(total / 10)
total % 10 && page++
@ -355,7 +357,7 @@ export default {
list.map(e => {
data.push('ids=' + e.id)
})
this.$post(`${this.api.deleteArticle}?${data.join('&')}`).then(res => {
this.$post(`${this.api[this.isCourseProduct ? 'productDetailsDel' : 'deleteArticle']}?${data.join('&')}`).then(res => {
this.$refs.table.clearSelection()
util.successMsg("删除成功")
this.getData()
@ -370,7 +372,7 @@ export default {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
}).then(() => {
this.$post(`${this.api.deleteArticle}?ids=${row.id}`).then(res => {
this.$post(`${this.api[this.isCourseProduct ? 'productDetailsDel' : 'deleteArticle']}?ids=${row.id}`).then(res => {
util.successMsg('删除成功')
this.getData()
}).catch(res => { })
@ -378,13 +380,14 @@ export default {
},
//
switchOff (val, row) {
this.$post(`${this.api.articleEnableOrDisable}?id=${row.id}&isDisable=${val}`).then(res => { }).catch((res) => { })
this.$post(`${this.api[this.isCourseProduct ? 'productDetailsEnable' : 'articleEnableOrDisable']}?id=${row.id}&isDisable=${val}`).then(res => { }).catch((res) => { })
},
//
add () {
if (!this.columns.length) return util.errorMsg('请添加栏目')
this.setColumn(this.$refs.column.getCurrentNode())
this.$router.push(`add?columnId=${this.$refs.column.getCurrentKey()}&columnName=${this.$refs.column.getCurrentNode().columnName}`)
const node = this.$refs.column.getCurrentNode()
this.setColumn(node)
this.$router.push(`${this.isCourseProduct ? 'addProduct' : 'add'}?columnId=${this.$refs.column.getCurrentKey()}&columnName=${this.$refs.column.getCurrentNode().columnName}`)
},
//
sortChange (column) {
@ -417,7 +420,7 @@ export default {
},
//
sticky (row) {
this.$post(`${this.api.articleTopOperation}?articleId=${row.id}&isTop=${row.isTop ? 0 : 1}`).then(res => {
this.$post(`${this.api[this.isCourseProduct ? 'productDetailsTop' : 'articleTopOperation']}?articleId=${row.id}&isTop=${row.isTop ? 0 : 1}`).then(res => {
this.initData()
}).catch(res => { })
},
@ -427,7 +430,7 @@ export default {
},
//
edit (row) {
this.$router.push(`add?id=${row.id}&columnId=${this.$refs.column.getCurrentKey()}&columnName=${this.$refs.column.getCurrentNode().columnName}`)
this.$router.push(`${this.isCourseProduct ? 'addProduct' : 'add'}?id=${row.id}&columnId=${this.$refs.column.getCurrentKey()}&columnName=${this.$refs.column.getCurrentNode().columnName}`)
},
}
};

@ -3,11 +3,9 @@
<div class="actions">
<p class="page-name">页面设置/会员中心</p>
<div>
<el-button type="primary"
@click="preview">预览</el-button>
<el-button type="primary" @click="preview">预览</el-button>
<el-button @click="save(0)">保存为草稿</el-button>
<el-button type="primary"
@click="save(1)">发布</el-button>
<el-button type="primary" @click="save(1)">发布</el-button>
<el-button @click="back">放弃编辑</el-button>
</div>
</div>
@ -15,9 +13,7 @@
<div class="modules">
<div class="reg">
<div class="equity-wrap">
<img class="logo"
src="@/assets/images/logo1.png"
alt="">
<img class="logo" src="@/assets/images/logo1.png" alt="">
<div class="equity">
<h6>
会员<em>专享权益</em>
@ -25,31 +21,24 @@
<div class="c-wrap">
<ul class="step">
<template v-for="(item, i) in modules[0].list">
<li v-if="item.isEnable"
:key="i">{{ item.title }}</li>
<li v-if="item.isEnable" :key="i">{{ item.title }}</li>
</template>
</ul>
<div class="cover"
@click="toSet(0)">点击更改标题</div>
<div class="cover" @click="toSet(0)">点击更改标题</div>
</div>
<div class="c-wrap m-b-20">
<div class="member-des"
v-html="modules[1].form.des"></div>
<div class="cover"
@click="toSet(1)">点击更改描述</div>
<div class="member-des" v-html="modules[1].form.des"></div>
<div class="cover" @click="toSet(1)">点击更改描述</div>
</div>
<div class="c-wrap">
<ul class="param">
<li v-for="(item, i) in modules[2].list"
:key="i">
<img :src="item.pic"
alt="">
<li v-for="(item, i) in modules[2].list" :key="i">
<img :src="item.pic" alt="">
<p class="name">{{ item.title }}</p>
<p class="des">{{ item.des }}</p>
</li>
</ul>
<div class="cover"
@click="toSet(2)">点击更改图片标题与描述</div>
<div class="cover" @click="toSet(2)">点击更改图片标题与描述</div>
</div>
<div class="btn">立即注册 | 0元成会员</div>
</div>
@ -57,10 +46,7 @@
</div>
</div>
<Module ref="module"
:data.sync="curData"
:visible.sync="diaVisible"
@moduleSubmit="moduleSubmit" />
<Module ref="module" :data.sync="curData" :visible.sync="diaVisible" @moduleSubmit="moduleSubmit" />
</div>
</template>
@ -101,107 +87,123 @@ export default {
<style lang="scss" scoped>
@import '../../../styles/page/page.scss';
.reg {
padding-bottom: 50px;
background: url(https://www.occupationlab.com/images/member/1.jpg) 0 0/100% 605px no-repeat;
.equity-wrap {
width: 1190px;
padding-top: 20px;
margin: 0 auto;
}
.logo {
width: 150px;
}
.equity {
min-height: 614px;
margin-top: 20px;
background: url(https://www.occupationlab.com/images/member/2.jpg) 0 0/100% 100% no-repeat;
background-color: #111d42;
border-radius: 24px 18px 18px 18px;
box-shadow: 0 0 20px 4px rgba(0, 16, 42, 0.3);
overflow: hidden;
padding-bottom: 50px;
background: url(https://occupationlab.com/images/member/1.jpg) 0 0/100% 605px no-repeat;
.equity-wrap {
width: 1190px;
padding-top: 20px;
margin: 0 auto;
}
.logo {
width: 150px;
}
.equity {
min-height: 614px;
margin-top: 20px;
background: url(https://occupationlab.com/images/member/2.jpg) 0 0/100% 100% no-repeat;
background-color: #111d42;
border-radius: 24px 18px 18px 18px;
box-shadow: 0 0 20px 4px rgba(0, 16, 42, 0.3);
overflow: hidden;
}
h6 {
position: relative;
margin: 60px 0 39px;
font-size: 2rem;
font-weight: 600;
text-align: center;
color: #fff;
em {
font-style: normal;
color: #e3b871;
}
h6 {
position: relative;
margin: 60px 0 39px;
font-size: 2rem;
font-weight: 600;
text-align: center;
color: #fff;
em {
font-style: normal;
color: #e3b871;
}
&:after {
content: 'VIP';
position: absolute;
top: -37px;
left: 0;
width: 100%;
text-align: center;
font-size: 6rem;
font-weight: 700;
color: hsla(0, 0%, 100%, 0.05);
}
&:after {
content: 'VIP';
position: absolute;
top: -37px;
left: 0;
width: 100%;
text-align: center;
font-size: 6rem;
font-weight: 700;
color: hsla(0, 0%, 100%, 0.05);
}
.step {
display: flex;
justify-content: space-between;
padding: 0 60px 0 100px;
li {
position: relative;
font-size: 1.4rem;
color: #fff;
&:before {
content: '';
position: absolute;
top: 5px;
left: -34px;
width: 24px;
height: 24px;
background: url(https://www.occupationlab.com/images/member/3.png) 0 0/100% 100% no-repeat;
}
}
}
.step {
display: flex;
justify-content: space-between;
padding: 0 60px 0 100px;
li {
position: relative;
font-size: 1.4rem;
color: #fff;
&:before {
content: '';
position: absolute;
top: 5px;
left: -34px;
width: 24px;
height: 24px;
background: url(https://occupationlab.com/images/member/3.png) 0 0/100% 100% no-repeat;
}
}
.member-des {
margin-top: 25px;
font-size: 1rem;
text-align: center;
}
.member-des {
margin-top: 25px;
font-size: 1rem;
text-align: center;
color: #fff;
}
.param {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 0 120px;
li {
width: 33.33%;
padding: 20px 30px;
text-align: center;
.name {
margin: 10px 0 10px;
font-size: 1.1rem;
color: #fff;
}
.des {
font-size: 0.9rem;
line-height: 1.6;
color: hsla(0, 0%, 100%, 0.7);
}
}
.param {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding: 0 120px;
li {
width: 33.33%;
padding: 20px 30px;
text-align: center;
.name {
margin: 10px 0 10px;
font-size: 1.1rem;
color: #fff;
}
.des {
font-size: 0.9rem;
line-height: 1.6;
color: hsla(0, 0%, 100%, 0.7);
}
}
}
.btn {
width: 400px;
height: 72px;
margin: 30px auto;
font-size: 24px;
color: #13192e;
font-weight: 600;
line-height: 72px;
text-align: center;
background-color: #e3b871;
background-image: linear-gradient(233.36deg, #e8ce8c, #f3c169);
border-radius: 38px;
}
}
.btn {
width: 400px;
height: 72px;
margin: 30px auto;
font-size: 24px;
color: #13192e;
font-weight: 600;
line-height: 72px;
text-align: center;
background-color: #e3b871;
background-image: linear-gradient(233.36deg, #e8ce8c, #f3c169);
border-radius: 38px;
}
}
</style>

@ -30,8 +30,8 @@ service.interceptors.request.use(config => {
service.interceptors.response.use(
response => {
const res = response.data
const { code } = res
if (code == 200) {
const { code, status } = res
if (code == 200 || status === 200) {
return Promise.resolve(res).catch(e => { });
} else if (code === 401) {
Util.errorMsg(res.msg)

@ -5,25 +5,31 @@ const meta = {}
const pre = 'article-'
export default {
path: '/article',
name: 'article',
redirect: {
name: `${pre}list`
path: '/article',
name: 'article',
redirect: {
name: `${pre}list`
},
meta,
component: BasicLayout,
children: [
{
name: `${pre}list`,
path: `list`,
component: () => import('@/pages/article/list'),
meta: { title: '文章管理' }
},
meta,
component: BasicLayout,
children: [
{
name: `${pre}list`,
path: `list`,
component: () => import('@/pages/article/list'),
meta: { title: '文章管理' }
},
{
name: `${pre}add`,
path: `add`,
component: () => import('@/pages/article/add'),
meta: { title: '添加文章' }
}
]
{
name: `${pre}add`,
path: `add`,
component: () => import('@/pages/article/add'),
meta: { title: '添加文章' }
},
{
name: `${pre}addProduct`,
path: `addProduct`,
component: () => import('@/pages/article/add/product'),
meta: { title: '添加文章' }
}
]
}

@ -16,6 +16,8 @@ const Setting = {
routerMode: "hash", // 路由模式,可选值为 history 或 hash
showProgressBar: true, // 页面切换时,是否显示模拟的进度条
apiBaseURL: host, // 接口请求地址
// huoranApi: `https://occupationlab.com`,
huoranApi: `http://121.37.12.51`,
autoLogoutTime: 1000 * 60 * 60 * 3, // 长时间未操作,自动退出登录时间
modalDuration: 3, // 接口请求返回错误时,弹窗的持续时间,单位:秒
errorModalType: "Message", // 接口请求返回错误时,弹窗的类型,可选值为 Message 或 Notice

Loading…
Cancel
Save