Commit 1ad60607 authored by jiaxu.yan's avatar jiaxu.yan

feat: 已购课程

parent a58188f6
.el-aside{
@import './learnCenter.scss';
.el-aside {
overflow: visible;
}
.el-main {
padding: 0 20px;
}
.el-pagination {
.number {
width: 32px;
height: 28px;
border: 1px solid #d9d9d9;
border-radius: 2px;
margin: 0 5px;
font-weight: normal;
background-color: #ffffff;
color: #6F6F6F;
}
button {
border: 1px solid #d9d9d9;
border-radius: 2px;
margin: 0 5px;
font-weight: normal;
color: #606266;
padding: 6px;
}
}
.el-pagination .btn-next {
padding-left: 6px;
}
.el-pagination .btn-prev {
padding-right: 6px;
}
.el-pager li.active + li {
border-left: 1px solid #d9d9d9 !important;
}
.el-pager li.active {
color: #ffffff;
// background-color: #ffffff;
background-color:#3684FC;
}
\ No newline at end of file
.page-main {
position: relative;
background: #ffffff;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.05);
padding: 1.3rem 2rem;
.page-header {
font-size: 1.3rem;
font-weight: bold;
padding-bottom: 2.3rem;
}
}
<template>
<img
:src="imagePath"
:style="{ width: width, height: height }"
alt="Dynamic Image"
/>
</template>
<script>
export default {
name: 'PngIcon',
props: {
iconClass: {
type: String,
required: true
},
width: {
type: String,
default: '1em'
},
height: {
type: String,
default: '1em'
},
},
computed: {
imagePath() {
console.log(`@/assets/icons/${this.iconClass}.png`)
// 根据图片名称动态生成图片路径
const path = require(`@/assets/icons/${this.iconClass}.png`)
return path
}
}
}
</script>
<template>
<div class="classes-box">
<div class="left-image">
<img
src="https://img2.baidu.com/it/u=536065398,4128871835&fm=253&fmt=auto&app=138&f=JPEG?w=667&h=500"
alt=""
/>
<div class="level">初级</div>
</div>
<div class="right-content">
<div class="classes-tltle">
visual C++案例教程visual C++案例教程教visual C++案visual
C++案例教程visual C++案例教程教visual C++案visual C++案例教程visual
C++案例教程教visual C++案visual C++案例教程visual C++案例教程教visual
C++案
</div>
<div class="classes-content">
<div class="classes-itme">
<div class="classes-name">100课时</div>
</div>
<div class="line"></div>
<div class="classes-itme">
<div class="classes-name">有效期: 2024-03-01 至 2024-03-01</div>
</div>
<div class="line"></div>
<div class="classes-itme">
<div class="classes-name">
有效期还剩: <span class="red">14天</span>
</div>
</div>
</div>
<div class="classes-itme">
<div class="classes-name">学习角色:</div>
<div class="classes-value">管理员、超级管理员</div>
<div class="classes-btn">
<png-icon iconClass="xuexi_shezhi" height="16px"> </png-icon>
<span class="btn-name">设置</span>
</div>
</div>
<div class="classes-itme">
<div class="classes-name">技术分类:</div>
<div class="classes-value">环境感知技术、智能决策技术</div>
<div class="classes-btn">
<png-icon iconClass="xuexi_yonghu" height="16px"> </png-icon>
<span class="btn-name">100</span>
</div>
</div>
</div>
</div>
</template>
<script></script>
<style lang="scss">
.classes-box {
width: 100%;
height: 163px;
background: #ffffff;
border: 1px solid #e1edff;
border-radius: 8px;
padding: 10px;
margin: 8px 0;
display: flex;
position: relative;
}
.left-image {
width: 254px;
height: 143px;
border-radius: 4px;
position: relative;
img {
width: 100%;
height: 100%;
}
.level {
width: 48px;
height: 28px;
line-height: 28px;
background: #5fc72e;
border-radius: 4px;
position: absolute;
top: 10px;
right: 10px;
color: white;
text-align: center;
}
}
.right-content {
flex: 1;
padding: 0 16px;
flex-flow: column;
display: flex;
justify-content: space-between;
.classes-tltle {
width: 800px;
font-size: 18px;
font-weight: 700;
color: #000000;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
}
.classes-content {
display: flex;
align-items: center;
justify-content: flex-start;
.classes-itme {
margin: 0;
}
.line {
width: 1px;
background-color: #e4e4e4;
height: 15px;
margin: 0 16px;
}
}
.classes-itme {
color: #6f6f6f;
display: flex;
align-items: center;
justify-content: flex-start;
margin-right: 30px;
font-size: 14px;
}
.classes-btn {
color: #3683fc;
margin-left: 16px;
cursor: pointer;
display: flex;
align-items: flex-end;
justify-content: space-between;
.btn-name {
margin-left: 10px;
}
}
}
</style>
<template>
<div class="page-main">
<div class="page-header"> {{ $route.meta.title }}</div>
<slot>
</slot>
</div>
</template>
<script>
export default {
}
</script>
<style></style>
<template>
<div class="screen-box">
<div class="screen-title" v-if="title">{{ title }}:</div>
<ul class="screen-list">
<div style="width: 100px;">
<li
class="screen-item"
:class="value == undefined ? 'is-active' : ''"
@click="selectValue(undefined)"
>
全部
</li>
</div>
<div style="flex: 1;">
<li
class="screen-item"
:class="value == item.value ? 'is-active' : ''"
@click="selectValue(item.value)"
v-for="item in filteredItems"
:key="item.value"
>
{{ item.label }}
</li>
</div>
</ul>
</div>
</template>
<script>
export default {
props: {
items: {
type: Array
},
value: {
type: String
},
title: {
type: String,
default: ''
}
},
data() {
return {}
},
computed: {
filteredItems() {
return this.items
}
},
methods: {
selectValue(value) {
console.log(value)
this.$emit('input', value)
}
}
}
</script>
<style>
.screen-box {
display: flex;
margin: 30px 0;
}
.screen-title {
font-size: 18px;
font-weight: 500;
color: #292929;
line-height: 21px;
width: 120px;
}
.screen-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex: 1;
margin-top:-15px;
}
.screen-item {
float: left;
cursor: pointer;
font-size: 18px;
color: #292929;
line-height: 21px;
padding: 5px 16px;
margin: 10px 0;
margin-right: 20px;
}
.is-active {
background: rgba(55, 136, 252, 0.15);
border-radius: 30px;
color: #3789fc;
}
</style>
......@@ -75,6 +75,7 @@ Vue.prototype.$parseDate = (value, format) => {
}
return moment(value).format(format || 'YYYY-MM-DD HH:mm:ss')
}
// 如果想要中文版 element-ui,按如下方式声明
// Vue.use(ElementUI)
// Vue.use(drective)
......@@ -82,28 +83,19 @@ Vue.config.productionTip = false
// 全局组件挂载
Vue.component('Pagination', Pagination)
import pageLayout from '@/components/pageLayout'
Vue.component('pageLayout', pageLayout)
import Screen from '@/components/screen'
Vue.component('screen', Screen)
import classesItem from '@/components/classesItem'
Vue.component('classesItem', classesItem)
import PngIcon from '@/components/PngIcon'
Vue.component('PngIcon', PngIcon)
Vue.use(permission)
import ModelDataSource from './utils/ModelDataSource'
Vue.use(ModelDataSource)
// 检查权限后动态导航的函数
function checkAuthAndNavigate(to, from, next) {
const hasAccess = false; // 假设这是一个检查权限的逻辑
console.log(to);
if(to.name == 'learningCenter'){
next('/learningCenter/purchased')
}else{
next()
}
}
// 在全局前置守卫中使用
router.beforeEach((to, from, next) => {
// 如果要对所有路由检查权限,可以在这里调用 checkAuthAndNavigate
checkAuthAndNavigate(to, from, next);
});
new Vue({
el: '#app',
router,
......
import request from '@/utils/request'
export default {
data() {
return {
listUrl: '',
queryParams: {
pageNum: 1,
pageSize: 10
},
tableId: false,
loading: false,
// 显示搜索条件
showSearch: true,
// 重新渲染表格状态
refreshTable: true,
tableData: [],
total: 0
}
},
mounted() {
this.loadData()
},
methods: {
/** 展开/折叠操作 */
toggleExpandAll() {
this.refreshTable = false
this.isExpandAll = !this.isExpandAll
this.$nextTick(() => {
this.refreshTable = true
})
},
resetQuery() {
// this.refs.queryForm.restForm() this.resetForm("queryForm");
this.queryParams = {
pageNum: this.queryParams.pageNum,
pageSize: this.queryParams.pageSize
}
this.handleQuery()
},
handleQuery() {
this.queryParams.pageNum = 1
this.loadData()
},
loadData() {
this.loading = true
request({
url: this.listUrl,
method: 'post',
data: this.queryParams
})
.then(res => {
if (res.code === 200) {
this.tableData = res.rows
this.total = res.total
}
this.loading = false
})
.catch(error => {
if (error.msg) {
this.$message.error(error.msg)
}
this.loading = false
})
}
}
}
export default {
// beforeRouteEnter(to, from, next) {
// next(vm => {
// console.log(vm.formPath)
// vm.formPath.push(from.path)
// console.log(vm.formPath);
// })
// },
data() {
return {
formPath: []
}
},
methods: {
/**
* 返回上一页
*/
goBack() {
// if (this.formPath) {
// this.$router.push({
// path: this.formPath[0]
// })
// } else {
this.$router.back()
// }
}
}
}
/**
* Model 数据源
* 用于 单条记录的增删查改
*/
import _ from 'lodash'
import request from '@/utils/request'
function ModelDataSource(vm, settings) {
this.vm = vm
this.settings = settings
this.errors = {}
this.debug = true
// this.dataKey = settings.
// this.defaultAttributes = settings.attributes;
this.init()
}
ModelDataSource.prototype = {
vm: null,
settings: null,
uuid: 0,
init: function () {
let self = this
_.assign(self, self.settings.attributes)
_.assignInWith(self.errors, self.settings.attributes, () => {
return ''
})
},
/**
* Fetch
*
* @param id
* @param successCallback
* @param failedCallback
*/
fetch: function (
uuid = 0,
params = {},
successCallback = function () {},
failedCallback = function () {}
) {
let self = this
let url = self.settings.url
self.uuid = uuid
if (uuid == 0 || uuid == null) {
self.reset()
} else {
params.id = uuid
request({
url: url + '/getById',
method: 'post',
data: params
})
.then(function (response) {
if (response.data) {
for (let key in response.data) {
self[key] = response.data[key]
}
} else {
for (let key in response.data) {
self[key] = response.data[key]
}
}
successCallback()
})
.catch(function (error) {
failedCallback()
})
}
},
/**
* 保存model
* @param successCallback
* @param failedCallback
*/
save: function (
successCallback = function () {},
failedCallback = function () {}
) {
let self = this
let url = ''
if (self.uuid == 0) {
url = self.settings.url + '/add'
delete self.id
} else {
url = self.settings.url + '/edit'
}
request({
url,
method: 'post',
data: _.omit(self, ['vm', 'settings', 'errors', 'debug'])
})
.then(function (response) {
if (response.data) {
for (let key in response.data) {
self[key] = response.data[key]
}
} else {
for (let key in response.data) {
self[key] = response.data[key]
}
}
successCallback(response)
})
.catch(function (error) {
// if (error.response) {
// _.forEach(error.response.data, function (value, key) {
// typeof value === 'object' && self.vm.$set(self.vm[self.settings.dataKey].errors, key, value[0]);
// typeof value === 'string' && self.vm.$set(self.vm[self.settings.dataKey].errors, key, value);
// });
// } else {
// // Something happened in setting up the request that triggered an Error
// self.debug && console.log(error);
// }
failedCallback(error)
})
},
/**
* 删除model
* @param id
*/
/**
*
* @param successCallback
* @param failedCallback
*/
destroy: function (
successCallback = function () {},
failedCallback = function () {}
) {
let self = this
request({
url: self.settings.url + '/remove',
method: 'post',
data: {
ids: [self.uuid]
}
})
.then(function (response) {
successCallback()
})
.catch(function (error) {
// Something happened in setting up the request that triggered an Error
self.debug && console.log('Error', error.message)
failedCallback(error)
})
},
/**
* 重置model 为默认值
* @param id
*/
reset: function () {
let self = this
_.assign(self, self.settings.attributes)
_.assignInWith(self.errors, self.settings.attributes, () => {
return ''
})
}
}
/**
* Vue Plugin
*/
ModelDataSource.install = function (Vue) {
Vue.prototype.$modelDataSource = function (options) {
return new ModelDataSource(this, options)
}
}
export default ModelDataSource
<template>
<div>
<div class="learningPlatform-content">
小组管理
</div>
</div>
</template>
<script>
export default {
<page-layout> </page-layout>
</template>
<script>
export default {
name: 'Index',
components: {
},
components: {},
data() {
return {
}
return {}
},
computed: {
}
}
</script>
<style scoped lang="scss">
.learningPlatform-content{
height: 400px;
}
</style>
\ No newline at end of file
computed: {}
}
</script>
<template>
<div>
<div class="learningPlatform-content">
我的课程
</div>
</div>
</template>
<script>
export default {
<page-layout> </page-layout>
</template>
<script>
export default {
name: 'Index',
components: {
},
components: {},
data() {
return {
}
return {}
},
computed: {
}
}
</script>
<style scoped lang="scss">
.learningPlatform-content{
height: 400px;
}
</style>
\ No newline at end of file
computed: {}
}
</script>
<template>
<div>
<div class="learningPlatform-content">
我的小组
</div>
</div>
</template>
<script>
export default {
<page-layout> </page-layout>
</template>
<script>
export default {
name: 'Index',
components: {
},
components: {},
data() {
return {
}
return {}
},
computed: {
}
}
</script>
<style scoped lang="scss">
.learningPlatform-content{
height: 400px;
}
</style>
\ No newline at end of file
computed: {}
}
</script>
<template>
<div>
<div class="learningPlatform-content">
学员管理
</div>
</div>
</template>
<script>
export default {
<page-layout> </page-layout>
</template>
<script>
export default {
name: 'Index',
components: {
},
components: {},
data() {
return {
}
return {}
},
computed: {
}
}
</script>
<style scoped lang="scss">
.learningPlatform-content{
height: 400px;
}
</style>
\ No newline at end of file
computed: {}
}
</script>
<template>
<div>
<div class="learningPlatform-content">
已购课程
<page-layout>
<div class="">
<screen
title="技术分类"
v-model="queryParams.technology"
:items="technologyOptions"
></screen>
<screen
title="难度等级"
v-model="queryParams.difficulty"
:items="difficultyOptions"
></screen>
<el-checkbox v-model="queryParams.model" size="medium"
>只看付费</el-checkbox
>
<el-checkbox v-model="queryParams.checked" size="medium"
>只看试用</el-checkbox
>
<classesItem v-for="i in 10" :key="i"> </classesItem>
<div style="display: flex;justify-content: center;">
<pagination
:total="100"
:background="false"
layout="prev, pager, next"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="loadData"
/>
</div>
</div>
</template>
<script>
export default {
</page-layout>
</template>
<script>
import page from '@/mixins/page'
export default {
name: 'Index',
components: {
},
mixins: [page],
data() {
return {
}
technologyOptions: [
{
label: '环境感知技术',
value: '1'
},
computed: {
{
label: '智能决策技术',
value: '2'
},
{
label: '控制执行技术',
value: '3'
},
{
label: '系统设计技术',
value: '4'
},
{
label: '大数据云控基础平台技术',
value: '5'
},
{
label: '车路协同技术',
value: '6'
},
{
label: '安全技术',
value: '7'
},
{
label: '智能决策技术',
value: '8'
},
{
label: '专用通信与网络技术',
value: '9'
},
{
label: '测试评价技术',
value: '10'
}
],
difficultyOptions: [
{
label: '初级',
value: '1'
},
{
label: '中级',
value: '2'
},
{
label: '高级',
value: '3'
}
</script>
<style scoped lang="scss">
.learningPlatform-content{
height: 400px;
]
}
</style>
\ No newline at end of file
},
computed: {}
}
</script>
<template>
<div>
<div class="learningPlatform-content">
角色管理
</div>
</div>
</template>
<script>
export default {
<page-layout> </page-layout>
</template>
<script>
export default {
name: 'Index',
components: {
},
components: {},
data() {
return {
}
return {}
},
computed: {
}
}
</script>
<style scoped lang="scss">
.learningPlatform-content{
height: 400px;
}
</style>
\ No newline at end of file
computed: {}
}
</script>
<template>
<div>
<div class="learningPlatform-content">
数据统计
</div>
</div>
</template>
<script>
export default {
<page-layout> </page-layout>
</template>
<script>
export default {
name: 'Index',
components: {
},
components: {},
data() {
return {
}
return {}
},
computed: {
}
}
</script>
<style scoped lang="scss">
.learningPlatform-content{
height: 400px;
}
</style>
\ No newline at end of file
computed: {}
}
</script>
......@@ -5,16 +5,13 @@
<router-view v-if="!$route.meta.link" :key="key" />
</keep-alive>
</transition>
<iframe-toggle />
</section>
</template>
<script>
import iframeToggle from './IframeToggle/index'
export default {
name: 'AppMain',
components: { iframeToggle },
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews
......
......@@ -5,11 +5,12 @@
:default-active="activeMenu"
:collapse="false"
background-color="#fff"
text-color="#333"
text-color="#292929"
:unique-opened="true"
active-text-color="rgb(64, 158, 255)"
active-text-color="#3685FC"
:collapse-transition="false"
mode="vertical"
class="user-menu"
>
<el-menu-item index="purchased" @click.native="goPage('purchased')">
<span slot="title">已购课程</span>
......@@ -26,10 +27,10 @@
<el-menu-item index="statistics" @click.native="goPage('statistics')">
<span slot="title">数据统计</span>
</el-menu-item>
<el-menu-item index="statistics" @click.native="goPage('my')">
<el-menu-item index="my" @click.native="goPage('my')">
<span slot="title">我的课程</span>
</el-menu-item>
<el-menu-item index="statistics" @click.native="goPage('myGroup')">
<el-menu-item index="myGroup" @click.native="goPage('myGroup')">
<span slot="title">我的小组</span>
</el-menu-item>
</el-menu>
......@@ -42,8 +43,6 @@ import userCard from './userCard.vue'
export default {
components: { userCard },
computed: {
...mapState(['settings']),
...mapGetters(['sidebarRouters', 'sidebar']),
activeMenu() {
const route = this.$route
const { meta, path } = route
......@@ -55,9 +54,33 @@ export default {
}
},
methods: {
goPage(name){
goPage(name) {
this.$router.push({ path: `/learningCenter/${name}` })
}
}
}
</script>
<style lang="scss">
.user-menu {
.el-menu-item {
margin: 9px 11px;
height: 60px;
font-size: 16px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.el-menu-item.is-active {
background: #f6f9ff !important;
span {
border-bottom :1px solid #3685FC;
line-height: 18px;
}
}
.el-menu-item:hover {
background: #f6f9ff !important;
}
}
</style>
......@@ -2,7 +2,7 @@
<div class="user-card">
<div class="card-box">
<div class="user-info">
<el-avatar :size="150" :src="avatar" class="user-avatar"></el-avatar>
<el-avatar :size="164" :src="avatar" class="user-avatar"></el-avatar>
<div class="user-name">某大学管理</div>
<div class="user-dept">天津南开大学</div>
</div>
......@@ -31,8 +31,7 @@ export default {
</script>
<style lang="scss">
.card-box {
background-color: #fff;
width: 400px;
width: 100%;
text-align: center;
.user-info {
display: flex;
......@@ -40,16 +39,45 @@ export default {
align-items: center;
justify-content: center;
.user-avatar {
margin-top: -40px;
margin-top: -32px;
}
.user-name {
color: #292929;
margin-top: 18px;
margin-bottom: 9px;
font-size: 20px;
font-weight: bold;
}
.user-dept {
color: #6f6f6f;
font-size: 16px;
}
}
.item-list {
display: flex;
flex-wrap: wrap;
border-top: 1px solid #dfdfdf;
border-bottom: 1px solid #dfdfdf;
margin-top: 24px ;
margin-bottom: 32px ;
.item {
width: 50%;
height: 100px;
padding: 23px;
.item-num {
font-size: 30px;
font-weight: 700;
text-align: center;
color: #338ffc;
line-height: 35px;
}
.item-name {
font-size: 16px;
text-align: center;
color: #292929;
line-height: 19px;
margin-top: 6px;
}
}
}
}
......
......@@ -3,7 +3,7 @@
<nav-list :list="navList" :current-menu="'/learningCenter/index'" />
<!-- <HomeSearch /> -->
<el-container class="learningCenter_module">
<el-aside width="400px" style="background-color: rgb(238, 241, 246)">
<el-aside width="320px" class="page-left" >
<sidebar />
</el-aside>
<el-main>
......@@ -55,5 +55,9 @@ export default {
// position: relative;
padding: 50px 30px;
}
.page-left{
background: #ffffff;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.05);
}
</style>
......@@ -465,7 +465,47 @@ export default {
{
dictLabel: '停用',
dictValue: '0'
}
},
{
dictLabel: '启用',
dictValue: '1'
},
{
dictLabel: '停用',
dictValue: '0'
},
{
dictLabel: '启用',
dictValue: '1'
},
{
dictLabel: '停用',
dictValue: '0'
},
{
dictLabel: '启用',
dictValue: '1'
},
{
dictLabel: '停用',
dictValue: '0'
},
{
dictLabel: '启用',
dictValue: '1'
},
{
dictLabel: '停用',
dictValue: '0'
},
{
dictLabel: '启用',
dictValue: '1'
},
{
dictLabel: '停用',
dictValue: '0'
},
],
// 性别状态字典
sexOptions: [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment