develoop
ww 4 months ago
parent a570de2a2f
commit db33196725
  1. 4
      .env.development
  2. 26
      src/api/courseChaptersApi.ts
  3. 12
      src/api/user/user.js
  4. BIN
      src/assets/images/default.png
  5. BIN
      src/assets/images/fe.jpg
  6. 32
      src/layout/tabbar/setting/index.vue
  7. 2
      src/router/routers.ts
  8. 3
      src/setting.ts
  9. 6
      src/store/index.ts
  10. 222
      src/store/modules/user.ts
  11. 3
      src/views/course/CourseObjectives.vue
  12. 354
      src/views/course/components/KnowledgeGraphUi/AddOrEdit copy.vue
  13. 261
      src/views/course/components/KnowledgeGraphUi/FoldAdd.vue
  14. 245
      src/views/course/components/KnowledgeGraphUi/FoldEdit.vue
  15. 356
      src/views/course/courseChapters.vue
  16. 17
      src/views/home/components/ConHeader.vue
  17. 138
      src/views/home/components/Info.vue
  18. 84
      src/views/home/components/Lessonlist.vue
  19. 165
      src/views/home/components/Status.vue
  20. 27
      src/views/home/components/Student1.vue
  21. 189
      src/views/home/components/Welcome.vue
  22. 424
      src/views/home/index.vue
  23. 21
      src/views/login/index.vue
  24. 29
      src/views/student/index.vue
  25. 68
      src/views/student/login.vue

@ -1,5 +1,5 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 # 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development' NODE_ENV = 'development'
VITE_APP_TITLE = '无糖运营平台' VITE_APP_TITLE = '无糖运营平台'
# VITE_APP_BASE_API = 'http://127.0.0.1:8008' VITE_APP_BASE_API = 'http://127.0.0.1:8080'
VITE_APP_BASE_API = 'http://39.106.16.162:8080' # VITE_APP_BASE_API = 'http://39.106.16.162:8080'

@ -96,20 +96,20 @@ export const deleteCourse = (params: any) => {
// 获取详情 // 获取详情
export const getCourseInfo = (params: any) => { export const getCourseInfo = (params: any) => {
return request({ return request({
// <<<<<<< HEAD // <<<<<<< HEAD
url: '/objective_contents/' + params.id, url: '/objective_contents/' + params.id,
method: 'get', method: 'get',
// // params // // params
// ======= // =======
// <<<<<<< HEAD // <<<<<<< HEAD
// url: '/api/objective_contents/' + params.id, // url: '/api/objective_contents/' + params.id,
// method: 'get', // method: 'get',
// params, // params,
// ======= // =======
// url: '/objective_contents/' + params.id, // url: '/objective_contents/' + params.id,
// method: "get", // method: "get",
// // params // // params
// >>>>>>> 1a620e19de970965f426e07348b1dbc4be900eaf // >>>>>>> 1a620e19de970965f426e07348b1dbc4be900eaf
// >>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a // >>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a
}) })
} }

@ -25,6 +25,7 @@ export const userPhoneRegisterService = (jsonData) => {
export const userCodeRegisterService = (phoness) => { export const userCodeRegisterService = (phoness) => {
return request.post('/api/user/code?phone=' + phoness) return request.post('/api/user/code?phone=' + phoness)
} }
//用户信息接口 //用户信息接口
export const userGetInfoService = (token) => export const userGetInfoService = (token) =>
request.get('/api/user/info', { request.get('/api/user/info', {
@ -46,3 +47,14 @@ export const userIdenChangeService = (dataToSend) => {
headers: { 'Content-Type': 'application/json;charset=UTF-8' }, headers: { 'Content-Type': 'application/json;charset=UTF-8' },
}) })
} }
//修改密码
export const userChangePasswordService = (dataToSend) => {
return request.post('/api/user/updatePassword', dataToSend)
}
//获取排名靠前的课程
export const userToplessonService = () => request.get('#')
//获取最新收藏的课程
export const userNewLikeService = (id) => {
return request.post('/api/course_favour/newCollect?userId=' + id)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

@ -12,11 +12,22 @@
<el-button size="small" icon="refresh" circle @click="refresh" /> <el-button size="small" icon="refresh" circle @click="refresh" />
<el-button size="small" icon="FullScreen" circle @click="fullScreen" /> <el-button size="small" icon="FullScreen" circle @click="fullScreen" />
<el-button size="small" icon="Setting" circle /> <el-button size="small" icon="Setting" circle />
<el-button
size="small"
icon="Link"
circle
@click="openWeb('http://www.baidu.com/', 'baidu')"
/>
<img <img
src="" :src="userStore.data.icon || defImg"
alt="" alt=""
style="width: 24px; height: 24px; margin: 0 10px; border-radius: 50%" style="width: 24px; height: 24px; margin: 0 10px; border-radius: 50%"
/> />
<!-- <img
src="@/assets/images/default.jpg
alt=""
style="width: 24px; height: 24px; margin: 0 10px; border-radius: 50%"
/> -->
<!-- 退出登录 --> <!-- 退出登录 -->
<el-dropdown @command="handleCommand"> <el-dropdown @command="handleCommand">
<span class="el-dropdown-link"> <span class="el-dropdown-link">
@ -37,12 +48,16 @@
// import { useDark, useToggle } from '@vueuse/core' // import { useDark, useToggle } from '@vueuse/core'
import useLayoutSettingStoe from '@/store/modules/setting' import useLayoutSettingStoe from '@/store/modules/setting'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
// import default from '@/assets/images/default.jpg'
import defImg from '@/assets/images/default.png'
// import { Moon, Sunny } from '@element-plus/icons-vue' // import { Moon, Sunny } from '@element-plus/icons-vue'
const useStore = useLayoutSettingStoe() const useStore = useLayoutSettingStoe()
const userStore = useUserStore() const userStore = useUserStore()
const $router = useRouter() const $router = useRouter()
const $route = useRoute() const $route = useRoute()
// //
const fullScreen = () => { const fullScreen = () => {
let full = document.fullscreenElement let full = document.fullscreenElement
@ -56,7 +71,6 @@ const fullScreen = () => {
const refresh = () => { const refresh = () => {
useStore.refresh = !useStore.refresh useStore.refresh = !useStore.refresh
} }
// //
const handleCommand = (command: string) => { const handleCommand = (command: string) => {
switch (command) { switch (command) {
@ -65,18 +79,28 @@ const handleCommand = (command: string) => {
break break
} }
} }
//
const openWeb = (url, name) => {
window.open(url, name, '_blank')
}
//
onMounted(() => {
userStore.getUserInfo()
console.log(userStore.data.icon, 'icon')
})
const logout = () => { const logout = () => {
console.log($route) console.log($route)
userStore.logout() userStore.logout()
$router.push({ $router.push({
path: '/login', path: '/login',
query: { redirect: $route.path }, query: { redirect: $route.path },
}) })
} }
// import IconEpSunny from '~icons/ep/sunny'; // import IconEpSunny from '~icons/ep/sunny';
// import IconEpMoon from '~icons/ep/moon'; // import IconEpMoon from '~icons/ep/moon';
// const isDark = useDark() // const isDark = useDark()
// const toggleDark = () => useToggle(isDark) // const toggleDark = () => useToggle(isDark)
</script> </script>

@ -308,5 +308,5 @@ export const constantRoute: any = [
hidden: true, hidden: true,
icon: 'Notebook', icon: 'Notebook',
}, },
} },
] ]

@ -3,4 +3,7 @@ export default {
title: '教学一体化后台', //项目标题 title: '教学一体化后台', //项目标题
logo: '/public/vite.svg', //项目logo logo: '/public/vite.svg', //项目logo
logoHidden: true, // logo隐藏设置 logoHidden: true, // logo隐藏设置
'files.associations': {
'*.vue': 'html',
},
} }

@ -1,9 +1,9 @@
// 引入仓库 // 引入仓库
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate' // import persist from 'pinia-plugin-persistedstate'
// 创建仓库 // 创建仓库
const pinia = createPinia() const pinia = createPinia()
// 暴露仓库 // 暴露仓库
pinia.use(persist) // pinia.use(persist)
export default pinia export default pinia
export * from './modules/user' // export * from './modules/user'

@ -1,7 +1,5 @@
// 创建用户相关的仓库 // 创建用户相关的仓库
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
// 引入登录接口
// import { reqLogin, getUserInfo } from '@/api/user/index'
// 引入登录参数类型 // 引入登录参数类型
import { loginType } from '@/api/user/types' import { loginType } from '@/api/user/types'
// 引入ElementPlus通知插件 // 引入ElementPlus通知插件
@ -21,136 +19,108 @@ import {
userIdenService, userIdenService,
} from '@/api/user/user.js' } from '@/api/user/user.js'
const useUserStore = defineStore( const useUserStore = defineStore('User', {
'User', // @ts-expect-error
{ state: (): LoginStoreType => {
// @ts-expect-error return {
token: GET_TKOEN('TOKEN') || '',
state: (): LoginStoreType => { menuRoutes: constantRoute, //存储生成菜单路由数据
return { userName: '', // 用户姓名
token: GET_TKOEN('TOKEN') || '', avatar: '', // 用户头像
menuRoutes: constantRoute, //存储生成菜单路由数据 routes: '',
userName: '', // 用户姓名 phone: '',
avatar: '', // 用户头像 userInfo: {}, // 当前用户相关信息
routes: '', data: {},
phone: '', }
userInfo: {}, // 当前用户相关信息 },
data: {}, actions: {
// 登录事件
async userLogin(data: any) {
// console.log(data, 'pinia')
const res: any = await userLoginService(data).catch((error) => {
ElMessage.error(error.response.data.message)
// console.log(error, 'error')
})
if (res.code === 200) {
this.token = res.data.token as string
SET_TKOEN('TOKEN', this.token)
// localStorage.setItem('TOKEN', this.token)
ElNotification({
type: 'success',
message: '登录成功!',
title: `Hi ${getTime()}!`,
})
return 'ok'
} else {
// ElNotification({
// // type: 'error',
// message: res.message,
// })
ElMessage.error(res.message)
return Promise.reject(new Error(res.data.message))
} }
}, },
actions: { //手机号登录
// 登录事件 async userPhoneLogin(data: loginType) {
async userLogin(data: any) { const res: any = await userPhoneLoginService(data)
// console.log(data, 'pinia') // console.log(res, 11111)
const res: any = await userLoginService(data).catch((error) => { if (res.code === 200) {
ElMessage.error(error.response.data.message) this.token = res.data.token as string //接收返回的token
console.log(error, 'error') // @ts-expect-error
SET_TKOEN('TOKEN', this.token)
// localStorage.setItem('TOKEN', this.token)
ElNotification({
type: 'success',
message: '登录成功!',
title: `Hi ${getTime()}!`,
}) })
return 'ok'
if (res.code === 200) { } else {
// @ts-expect-error ElNotification({
this.token = res.data.token as string type: 'error',
// @ts-expect-error message: res.message,
})
SET_TKOEN('TOKEN', this.token) return Promise.reject(new Error(res.data.message))
// localStorage.setItem('TOKEN', this.token) }
ElNotification({ },
type: 'success', // 获取用户信息
message: '登录成功!', async getUserInfo() {
title: `Hi ${getTime()}!`, const result: any = await userGetInfoService(GET_TKOEN('TOKEN'))
}) if (result.code === 200) {
return 'ok' console.log(result, 'result')
} else { const res = await userIdenService(result.data.id)
// ElNotification({ // console.log(res, 'res')
// // type: 'error', this.userInfo = res.data
// message: res.message, // console.log(this.userInfo, 'this.userInfo')
// }) this.data = result.data
ElMessage.error(res.message) // console.log(result, '123')
return Promise.reject(new Error(res.data.message)) this.userName = result.data.username
} // this.avatar = result.data.checkUser.avatar
}, this.routes = result.data.permissions
//手机号登录 return {
async userPhoneLogin(data: loginType) { result,
const res: any = await userPhoneLoginService(data)
console.log(res, 11111)
if (res.code === 200) {
// @ts-expect-error
this.token = res.data.token as string //接收返回的token
// @ts-expect-error
SET_TKOEN('TOKEN', this.token)
// localStorage.setItem('TOKEN', this.token)
ElNotification({
type: 'success',
message: '登录成功!',
title: `Hi ${getTime()}!`,
})
return 'ok'
} else {
ElNotification({
type: 'error',
message: res.message,
})
return Promise.reject(new Error(res.data.message))
}
},
// 获取用户信息事件
async getUserInfo() {
const result: any = await userGetInfoService(GET_TKOEN('TOKEN'))
if (result.code === 200) {
const res = await userIdenService(result.data.id)
console.log(res, 'huonghu')
// @ts-expect-error
this.userInfo = res.data
// console.log(this.userInfo, 'this.userInfo')
// @ts-expect-error
this.data = result.data
console.log(result, '123')
// @ts-expect-error
this.userName = result.data.username
// this.avatar = result.data.checkUser.avatar
// @ts-expect-error
this.routes = result.data.permissions
return {
result,
}
} else {
return Promise.reject('登录过期')
} }
}, } else {
// 退出登录事件 return Promise.reject('登录过期')
logout() { }
const usePermissionStore = permissionStore() },
console.log(usePermissionStore) // 退出登录事件
// 清除token logout() {
REMOVE_TOKEN('TOKEN'), const usePermissionStore = permissionStore()
// ;(this.userName = ''), (this.avatar = '') // console.log(usePermissionStore)
// @ts-expect-error // 清除token
REMOVE_TOKEN('TOKEN'),
(this.userName = ''), // ;(this.userName = ''), (this.avatar = '')
// @ts-expect-error
(this.avatar = '')
// @ts-expect-error // @ts-expect-error
(this.userName = ''),
this.token = ''
// @ts-expect-error // @ts-expect-error
(this.avatar = '')
this.routes = '' this.token = ''
usePermissionStore.removeRouter() this.routes = ''
location.reload() usePermissionStore.removeRouter()
}, location.reload()
}, },
getters: {},
},
{
persist: true, // 持久化
}, },
) getters: {},
})
export default useUserStore export default useUserStore

@ -18,7 +18,6 @@ const route = useRoute()
const router = useRouter() const router = useRouter()
// id id // id id
// targetId // targetId
const targetList = ref([ const targetList = ref([
{ {
label: '课程目标一', label: '课程目标一',
@ -114,7 +113,7 @@ const filterTarger = (target) => {
return res.label return res.label
} }
const editdata = ref({ id: '', objectiveId:'' }) const editdata = ref({ id: '', objectiveId: '' })
// //
const flog = ref(false) const flog = ref(false)
const editBook = async (obj) => { const editBook = async (obj) => {

@ -1,213 +1,253 @@
<template> <template>
<div class="add-or-edit"> <div class="add-or-edit">
<el-drawer v-model="isDrawer" title="新增章节" direction="rtl" size="50%"> <el-drawer v-model="isDrawer" title="新增章节" direction="rtl" size="50%">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto" <el-form
class="demo-ruleForm" :size="formSize" status-icon> ref="ruleFormRef"
<el-form-item label="章节" prop="pid"> style="max-width: 600px"
<el-cascader v-model="activePidArr" :options="options" :props="CascaderProps" :model="ruleForm"
:show-all-levels="false" clearable /> :rules="rules"
</el-form-item> label-width="auto"
<el-form-item label="章节名" prop="name"> class="demo-ruleForm"
<el-input v-model="ruleForm.name" style="width: 240px" :placeholder="placeholder" /> :size="formSize"
</el-form-item> status-icon
<el-form-item label="总学时" prop="totalclasshours"> >
<el-input v-model="ruleForm.totalclasshours" style="width: 240px" placeholder="请输入总学时" /> <el-form-item label="章节" prop="pid">
</el-form-item> <el-cascader
<el-form-item> v-model="activePidArr"
<el-button type="primary" :loading="loading" @click="submitForm(ruleFormRef)"> :options="options"
Create :props="CascaderProps"
</el-button> :show-all-levels="false"
<el-button @click="resetForm(ruleFormRef)">Reset</el-button> clearable
</el-form-item> />
</el-form> </el-form-item>
</el-drawer> <el-form-item label="章节名" prop="name">
</div> <el-input
v-model="ruleForm.name"
style="width: 240px"
:placeholder="placeholder"
/>
</el-form-item>
<el-form-item label="总学时" prop="totalclasshours">
<el-input
v-model="ruleForm.totalclasshours"
style="width: 240px"
placeholder="请输入总学时"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
:loading="loading"
@click="submitForm(ruleFormRef)"
>
Create
</el-button>
<el-button @click="resetForm(ruleFormRef)">Reset</el-button>
</el-form-item>
</el-form>
</el-drawer>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
function comNum(n: number | undefined) { function comNum(n: number | undefined) {
if (n === undefined) return 1 if (n === undefined) return 1
return n + 1 return n + 1
} }
import { ref, reactive, watch, computed, nextTick } from 'vue' import { ref, reactive, watch, computed, nextTick } from 'vue'
const props = defineProps(['isD', 'data', 'loading']) const props = defineProps(['isD', 'data', 'loading'])
const emits = defineEmits(['update:isD', 'submit']) const emits = defineEmits(['update:isD', 'submit'])
const isDrawer = ref(props.isD) const isDrawer = ref(props.isD)
watch(() => props.isD, newVal => isDrawer.value = newVal) watch(
watch(() => isDrawer.value, newVal => emits('update:isD', newVal)) () => props.isD,
(newVal) => (isDrawer.value = newVal),
)
watch(
() => isDrawer.value,
(newVal) => emits('update:isD', newVal),
)
const type = false const type = false
const options = computed(() => { const options = computed(() => {
if (type) { if (type) {
const arr = props.data.map((item: any, i: number) => { const arr = props.data.map((item: any, i: number) => {
const obj = { ...item } const obj = { ...item }
if (item.chapterSection) obj.chapterSection = item.chapterSection.map((chap: any) => ({ ...chap, disabled: true })) if (item.chapterSection)
else obj.chapterSection = [] obj.chapterSection = item.chapterSection.map((chap: any) => ({
obj.chapterSection.push({ name: `${i + 1}章第${comNum(item.chapterSection?.length)}`, pid: item.id }) ...chap,
return obj disabled: true,
}) }))
arr.push({ name: `${arr.length + 1}`, pid: '' }) else obj.chapterSection = []
return arr obj.chapterSection.push({
} name: `${i + 1}章第${comNum(item.chapterSection?.length)}`,
return props.data pid: item.id,
})
return obj
})
arr.push({ name: `${arr.length + 1}`, pid: '' })
return arr
}
return props.data
}) })
const CascaderProps = { const CascaderProps = {
checkStrictly: !type, checkStrictly: !type,
label: 'name', label: 'name',
value: type ? 'pid' : 'id', value: type ? 'pid' : 'id',
children: 'chapterSection' children: 'chapterSection',
} }
import type { ComponentSize, FormInstance, FormRules } from 'element-plus' import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
interface RuleForm { interface RuleForm {
content: string content: string
courseid: string courseid: string
courseobjectivesid: string courseobjectivesid: string
createBy: string createBy: string
createTime: string createTime: string
id: string id: string
name: string name: string
num: number num: number
numshow: string numshow: string
onlinclasshours: string onlinclasshours: string
pid: string | undefined pid: string | undefined
requirement: string requirement: string
sysOrgCode: string sysOrgCode: string
totalclasshours: string totalclasshours: string
updateBy: string updateBy: string
updateTime: string updateTime: string
zc: string zc: string
ziyuan: string ziyuan: string
zywj: string zywj: string
} }
const formSize = ref<ComponentSize>('default') const formSize = ref<ComponentSize>('default')
const ruleFormRef = ref<FormInstance>() const ruleFormRef = ref<FormInstance>()
let o let o
if (type) { if (type) {
o = { o = {
"content": "", content: '',
"courseid": "", courseid: '',
"courseobjectivesid": "", courseobjectivesid: '',
"createBy": "", createBy: '',
"createTime": "", createTime: '',
"id": "", id: '',
"name": "", name: '',
"num": 0, num: 0,
"numshow": "", numshow: '',
"onlinclasshours": "", onlinclasshours: '',
"pid": undefined, pid: undefined,
"requirement": "", requirement: '',
"sysOrgCode": "", sysOrgCode: '',
"totalclasshours": "", totalclasshours: '',
"updateBy": "", updateBy: '',
"updateTime": "", updateTime: '',
"zc": "", zc: '',
"ziyuan": "", ziyuan: '',
"zywj": "" zywj: '',
} }
}else{ } else {
o = { o = {
"content": "", content: '',
"courseid": "", courseid: '',
"courseobjectivesid": "", courseobjectivesid: '',
"createBy": "", createBy: '',
"createTime": "", createTime: '',
"id": undefined, id: undefined,
"name": "111", name: '111',
"num": 0, num: 0,
"numshow": "", numshow: '',
"onlinclasshours": "", onlinclasshours: '',
"pid": "", pid: '',
"requirement": "", requirement: '',
"sysOrgCode": "", sysOrgCode: '',
"totalclasshours": "", totalclasshours: '',
"updateBy": "", updateBy: '',
"updateTime": "", updateTime: '',
"zc": "", zc: '',
"ziyuan": "", ziyuan: '',
"zywj": "" zywj: '',
} }
} }
let pxObj let pxObj
if (type) pxObj = o if (type) pxObj = o
else { else {
pxObj = new Proxy(o, { pxObj = new Proxy(o, {
get(target, key) { get(target, key) {
if (key === 'pid') return target.id if (key === 'pid') return target.id
// @ts-ignore // @ts-ignore
return target[key]; return target[key]
}, },
set: function (obj, prop, value) { set: function (obj, prop, value) {
if (prop === 'pid') { if (prop === 'pid') {
obj.id = value obj.id = value
return true return true
} }
// @ts-ignore // @ts-ignore
obj[prop] = value obj[prop] = value
return true; return true
} },
}) })
} }
// @ts-ignore // @ts-ignore
const ruleForm = reactive<RuleForm>(pxObj) const ruleForm = reactive<RuleForm>(pxObj)
// @ts-ignore // @ts-ignore
const validateChapterOrSection = (rule, value, callback) => { const validateChapterOrSection = (rule, value, callback) => {
nextTick(() => { nextTick(() => {
const value = ruleForm.pid const value = ruleForm.pid
if (!value && value !== '') { if (!value && value !== '') {
if (type) callback(new Error('请选择新增的章或节')) if (type) callback(new Error('请选择新增的章或节'))
else callback(new Error('请选择编辑的章或节')) else callback(new Error('请选择编辑的章或节'))
} } else callback()
else callback() })
}) }
};
// //
const rules = reactive<FormRules<RuleForm>>({ const rules = reactive<FormRules<RuleForm>>({
pid: [ pid: [
{ required: true, validator: validateChapterOrSection, trigger: 'change' }, { required: true, validator: validateChapterOrSection, trigger: 'change' },
] ],
}) })
const submitForm = async (formEl: FormInstance | undefined) => { const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
await formEl.validate((valid, fields) => { await formEl.validate((valid, fields) => {
if (valid) { if (valid) {
console.log(options.value, '1') console.log(options.value, '1')
console.log(ruleForm); console.log(ruleForm)
// emits('submit', ruleForm) // emits('submit', ruleForm)
} else { } else {
console.log('error submit!', fields) console.log('error submit!', fields)
} }
}) })
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
activePidArr.value = undefined activePidArr.value = undefined
} }
const placeholder = ref('请输入章节名') const placeholder = ref('请输入章节名')
watch(() => ruleForm.pid, newVal => { watch(
() => ruleForm.pid,
(newVal) => {
if (newVal === undefined) placeholder.value = '请输入章节名' if (newVal === undefined) placeholder.value = '请输入章节名'
else if (newVal === '') placeholder.value = '请输入章名' else if (newVal === '') placeholder.value = '请输入章名'
else placeholder.value = '请输入节名' else placeholder.value = '请输入节名'
}) },
)
const activePidArr = ref<string[] | undefined>([]) const activePidArr = ref<string[] | undefined>([])
watch(() => activePidArr.value, newVal => {// pid watch(
() => activePidArr.value,
(newVal) => {
// pid
if (newVal === undefined) { if (newVal === undefined) {
ruleForm.pid = undefined ruleForm.pid = undefined
return return
} }
ruleForm.pid = newVal.slice(-1)[0] ruleForm.pid = newVal.slice(-1)[0]
}) },
)
</script> </script>
<style lang="scss"></style> <style lang="scss"></style>

@ -1,155 +1,196 @@
<template> <template>
<div class="add-or-edit"> <div class="add-or-edit">
<el-drawer v-model="isDrawer" title="新增章节" direction="rtl" size="50%"> <el-drawer v-model="isDrawer" title="新增章节" direction="rtl" size="50%">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto" <el-form
class="demo-ruleForm" :size="formSize" status-icon> ref="ruleFormRef"
<el-form-item label="章节" prop="pid"> style="max-width: 600px"
<el-cascader v-model="activePidArr" :options="options1" :props="CascaderProps" :model="ruleForm"
:show-all-levels="false" clearable /> :rules="rules"
</el-form-item> label-width="auto"
<el-form-item label="章节名" prop="name"> class="demo-ruleForm"
<el-input v-model="ruleForm.name" style="width: 240px" :placeholder="placeholder" /> :size="formSize"
</el-form-item> status-icon
<el-form-item label="总学时" prop="totalclasshours"> >
<el-input v-model="ruleForm.totalclasshours" style="width: 240px" placeholder="请输入总学时" /> <el-form-item label="章节" prop="pid">
</el-form-item> <el-cascader
<el-form-item> v-model="activePidArr"
<el-button type="primary" :loading="loading" @click="submitForm(ruleFormRef)"> :options="options1"
提交 :props="CascaderProps"
</el-button> :show-all-levels="false"
<el-button @click="resetForm(ruleFormRef)">重置</el-button> clearable
</el-form-item> />
</el-form> </el-form-item>
</el-drawer> <el-form-item label="章节名" prop="name">
</div> <el-input
v-model="ruleForm.name"
style="width: 240px"
:placeholder="placeholder"
/>
</el-form-item>
<el-form-item label="总学时" prop="totalclasshours">
<el-input
v-model="ruleForm.totalclasshours"
style="width: 240px"
placeholder="请输入总学时"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
:loading="loading"
@click="submitForm(ruleFormRef)"
>
提交
</el-button>
<el-button @click="resetForm(ruleFormRef)">重置</el-button>
</el-form-item>
</el-form>
</el-drawer>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
function comNum(n: number | undefined) { function comNum(n: number | undefined) {
if (n === undefined) return 1 if (n === undefined) return 1
return n + 1 return n + 1
} }
import { ref, reactive, watch, computed, nextTick } from 'vue' import { ref, reactive, watch, computed, nextTick } from 'vue'
const props = defineProps(['isD', 'data']) const props = defineProps(['isD', 'data'])
const emits = defineEmits(['update:isD','submit']) const emits = defineEmits(['update:isD', 'submit'])
const loading = ref(false) const loading = ref(false)
const updLoading = (boo:boolean) => loading.value = boo const updLoading = (boo: boolean) => (loading.value = boo)
const isDrawer = ref(props.isD) const isDrawer = ref(props.isD)
watch(() => props.isD, newVal => isDrawer.value = newVal) watch(
watch(()=>isDrawer.value,newVal=>emits('update:isD',newVal)) () => props.isD,
(newVal) => (isDrawer.value = newVal),
)
watch(
() => isDrawer.value,
(newVal) => emits('update:isD', newVal),
)
const options1 = computed(() => { const options1 = computed(() => {
const arr = props.data.map((item: any, i: number) => { const arr = props.data.map((item: any, i: number) => {
const obj = { ...item } const obj = { ...item }
if (item.chapterSection) obj.chapterSection = item.chapterSection.map((chap: any) => ({ ...chap, disabled: true })) if (item.chapterSection)
else obj.chapterSection = [] obj.chapterSection = item.chapterSection.map((chap: any) => ({
obj.chapterSection.push({ name: `${i + 1}章第${comNum(item.chapterSection?.length)}`, pid: item.id }) ...chap,
return obj disabled: true,
}))
else obj.chapterSection = []
obj.chapterSection.push({
name: `${i + 1}章第${comNum(item.chapterSection?.length)}`,
pid: item.id,
}) })
arr.push({ name: `${arr.length + 1}`, pid: '' }) return obj
return arr })
arr.push({ name: `${arr.length + 1}`, pid: '' })
return arr
}) })
const CascaderProps = { const CascaderProps = {
label: 'name', label: 'name',
value: 'pid', value: 'pid',
children: 'chapterSection' children: 'chapterSection',
} }
import type { ComponentSize, FormInstance, FormRules } from 'element-plus' import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
interface RuleForm { interface RuleForm {
content: string content: string
courseid: string courseid: string
courseobjectivesid: string courseobjectivesid: string
createBy: string createBy: string
createTime: string createTime: string
id: string id: string
name: string name: string
num: number num: number
numshow: string numshow: string
onlinclasshours: string onlinclasshours: string
pid: string | undefined pid: string | undefined
requirement: string requirement: string
sysOrgCode: string sysOrgCode: string
totalclasshours: string totalclasshours: string
updateBy: string updateBy: string
updateTime: string updateTime: string
zc: string zc: string
ziyuan: string ziyuan: string
zywj: string zywj: string
} }
const formSize = ref<ComponentSize>('default') const formSize = ref<ComponentSize>('default')
const ruleFormRef = ref<FormInstance>() const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({ const ruleForm = reactive<RuleForm>({
"content": "", content: '',
"courseid": "2fa0fd63262230639d2c45a3acd9045c", courseid: '2fa0fd63262230639d2c45a3acd9045c',
"courseobjectivesid": "", courseobjectivesid: '',
"createBy": "", createBy: '',
"createTime": "", createTime: '',
"id": "", id: '',
"name": "", name: '',
"num": 0, num: 0,
"numshow": "", numshow: '',
"onlinclasshours": "", onlinclasshours: '',
"pid": undefined, pid: undefined,
"requirement": "", requirement: '',
"sysOrgCode": "", sysOrgCode: '',
"totalclasshours": "", totalclasshours: '',
"updateBy": "", updateBy: '',
"updateTime": "", updateTime: '',
"zc": "", zc: '',
"ziyuan": "", ziyuan: '',
"zywj": "" zywj: '',
}) })
// @ts-ignore // @ts-ignore
const validateChapterOrSection = (rule, value, callback) => { const validateChapterOrSection = (rule, value, callback) => {
nextTick(()=>{ nextTick(() => {
const value =ruleForm.pid const value = ruleForm.pid
if (!value && value !== '') callback(new Error('请选择新增的章或节')) if (!value && value !== '') callback(new Error('请选择新增的章或节'))
else callback() else callback()
}) })
}; }
// //
const rules = reactive<FormRules<RuleForm>>({ const rules = reactive<FormRules<RuleForm>>({
pid: [ pid: [
{ required: true, validator: validateChapterOrSection, trigger: 'change' }, { required: true, validator: validateChapterOrSection, trigger: 'change' },
] ],
}) })
const submitForm = async (formEl: FormInstance | undefined) => { const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
await formEl.validate((valid, fields) => { await formEl.validate((valid, fields) => {
if (valid) { if (valid) {
emits('submit',ruleForm,updLoading) emits('submit', ruleForm, updLoading)
} else { } else {
console.log('error submit!', fields) console.log('error submit!', fields)
} }
}) })
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
activePidArr.value = undefined activePidArr.value = undefined
} }
const placeholder = ref('请输入章节名') const placeholder = ref('请输入章节名')
watch(() => ruleForm.pid, newVal => { watch(
() => ruleForm.pid,
(newVal) => {
if (newVal === undefined) placeholder.value = '请输入章节名' if (newVal === undefined) placeholder.value = '请输入章节名'
else if (newVal === '') placeholder.value = '请输入章名' else if (newVal === '') placeholder.value = '请输入章名'
else placeholder.value = '请输入节名' else placeholder.value = '请输入节名'
}) },
)
const activePidArr = ref<string[] | undefined>([]) const activePidArr = ref<string[] | undefined>([])
watch(() => activePidArr.value, newVal => {// pid watch(
() => activePidArr.value,
(newVal) => {
// pid
if (newVal === undefined) { if (newVal === undefined) {
ruleForm.pid = undefined ruleForm.pid = undefined
return return
} }
ruleForm.pid = newVal.slice(-1)[0] ruleForm.pid = newVal.slice(-1)[0]
}) },
)
</script> </script>
<style lang="scss"></style> <style lang="scss"></style>

@ -1,72 +1,101 @@
<template> <template>
<div class="add-or-edit"> <div class="add-or-edit">
<el-drawer v-model="isDrawer" title="编辑章节" direction="rtl" size="50%"> <el-drawer v-model="isDrawer" title="编辑章节" direction="rtl" size="50%">
<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto" <el-form
class="demo-ruleForm" :size="formSize" status-icon> ref="ruleFormRef"
<el-form-item label="章节" prop="id"> style="max-width: 600px"
<el-cascader v-model="activeIdArr" :options="options1" :props="CascaderProps" :model="ruleForm"
:show-all-levels="false" clearable /> :rules="rules"
</el-form-item> label-width="auto"
<el-form-item label="章节名" prop="name"> class="demo-ruleForm"
<el-input v-model="ruleForm.name" style="width: 240px" :placeholder="placeholder" /> :size="formSize"
</el-form-item> status-icon
<el-form-item label="总学时" prop="totalclasshours"> >
<el-input v-model="ruleForm.totalclasshours" style="width: 240px" placeholder="请输入总学时" /> <el-form-item label="章节" prop="id">
</el-form-item> <el-cascader
<el-form-item> v-model="activeIdArr"
<el-button type="primary" :loading="loading" @click="submitForm(ruleFormRef)"> :options="options1"
提交 :props="CascaderProps"
</el-button> :show-all-levels="false"
<el-button @click="resetForm(ruleFormRef)">重置</el-button> clearable
</el-form-item> />
</el-form> </el-form-item>
</el-drawer> <el-form-item label="章节名" prop="name">
</div> <el-input
v-model="ruleForm.name"
style="width: 240px"
:placeholder="placeholder"
/>
</el-form-item>
<el-form-item label="总学时" prop="totalclasshours">
<el-input
v-model="ruleForm.totalclasshours"
style="width: 240px"
placeholder="请输入总学时"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
:loading="loading"
@click="submitForm(ruleFormRef)"
>
提交
</el-button>
<el-button @click="resetForm(ruleFormRef)">重置</el-button>
</el-form-item>
</el-form>
</el-drawer>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, watch, computed } from 'vue' import { ref, reactive, watch, computed } from 'vue'
const props = defineProps(['isD', 'data', 'editData']) const props = defineProps(['isD', 'data', 'editData'])
const emits = defineEmits(['update:isD', 'submit']) const emits = defineEmits(['update:isD', 'submit'])
const loading = ref(false) const loading = ref(false)
const updLoading = (boo:boolean) => loading.value = boo const updLoading = (boo: boolean) => (loading.value = boo)
const isDrawer = ref(props.isD) const isDrawer = ref(props.isD)
watch(() => props.isD, newVal => isDrawer.value = newVal) watch(
watch(() => isDrawer.value, newVal => emits('update:isD', newVal)) () => props.isD,
(newVal) => (isDrawer.value = newVal),
)
watch(
() => isDrawer.value,
(newVal) => emits('update:isD', newVal),
)
const options1 = computed(() => props.data) const options1 = computed(() => props.data)
const CascaderProps = { const CascaderProps = {
checkStrictly: true, checkStrictly: true,
label: 'name', label: 'name',
value: 'id', value: 'id',
children: 'chapterSection' children: 'chapterSection',
} }
import type { ComponentSize, FormInstance, FormRules } from 'element-plus' import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
import { isArray } from 'element-plus/es/utils/types.mjs'; import { isArray } from 'element-plus/es/utils/types.mjs'
interface RuleForm { interface RuleForm {
content: string content: string
courseid: string courseid: string
courseobjectivesid: string courseobjectivesid: string
createBy: string createBy: string
createTime: string createTime: string
id: string | undefined id: string | undefined
name: string name: string
num: number num: number
numshow: string numshow: string
onlinclasshours: string onlinclasshours: string
pid: string pid: string
requirement: string requirement: string
sysOrgCode: string sysOrgCode: string
totalclasshours: string totalclasshours: string
updateBy: string updateBy: string
updateTime: string updateTime: string
zc: string zc: string
ziyuan: string ziyuan: string
zywj: string zywj: string
} }
const formSize = ref<ComponentSize>('default') const formSize = ref<ComponentSize>('default')
@ -75,81 +104,91 @@ const ruleForm = reactive<RuleForm>({ ...props.editData })
// //
const rules = reactive<FormRules<RuleForm>>({ const rules = reactive<FormRules<RuleForm>>({
id: [ id: [{ required: true, message: '请选择要更新的章节', trigger: 'change' }],
{ required: true, message: '请选择要更新的章节', trigger: 'change' },
]
}) })
const submitForm = async (formEl: FormInstance | undefined) => { const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
await formEl.validate((valid, fields) => { await formEl.validate((valid, fields) => {
if (valid) { if (valid) {
emits('submit', ruleForm,updLoading) emits('submit', ruleForm, updLoading)
} else { } else {
console.log('error submit!', fields) console.log('error submit!', fields)
} }
}) })
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return if (!formEl) return
formEl.resetFields() formEl.resetFields()
activeIdArr.value = getCheckedChapter(options1.value) activeIdArr.value = getCheckedChapter(options1.value)
} }
watch(() => ruleForm.id, newVal => { watch(
const obj =getCheckedChapterObj(options1.value,newVal) () => ruleForm.id,
(newVal) => {
const obj = getCheckedChapterObj(options1.value, newVal)
// const arr = getCheckedChapter(options1.value) // const arr = getCheckedChapter(options1.value)
// let obj // let obj
// if (arr.length === 1) obj = options1.value.find((item: any) => item.id === arr[0]) // if (arr.length === 1) obj = options1.value.find((item: any) => item.id === arr[0])
// else if (arr.length === 2) obj = options1.value.find((item: any) => item.id === arr[0]).value.find((item: any) => item.id === arr[1]) // else if (arr.length === 2) obj = options1.value.find((item: any) => item.id === arr[0]).value.find((item: any) => item.id === arr[1])
if (obj) Object.assign(ruleForm, obj) if (obj) Object.assign(ruleForm, obj)
}) },
)
const placeholder = ref('请输入章节名') const placeholder = ref('请输入章节名')
watch(() => ruleForm.pid, newVal => { watch(
() => ruleForm.pid,
(newVal) => {
if (newVal === '') placeholder.value = '请输入章名' if (newVal === '') placeholder.value = '请输入章名'
else placeholder.value = '请输入节名' else placeholder.value = '请输入节名'
},{immediate:true}) },
{ immediate: true },
)
// id // id
function getCheckedChapter(array: any) { function getCheckedChapter(array: any) {
let i = 0, arr: any[] = [], f: any let i = 0,
(function fn(array: any) { arr: any[] = [],
if (!isArray(array)) return f: any
const ch = array.find((item: any) => item.id === ruleForm.id) ;(function fn(array: any) {
if (ch === undefined && i < array.length) { if (!isArray(array)) return
f = array[i].id const ch = array.find((item: any) => item.id === ruleForm.id)
fn(array[i++].chapterSection) if (ch === undefined && i < array.length) {
} f = array[i].id
if (ch === undefined) return fn(array[i++].chapterSection)
if (f) arr.push(f) }
arr.push(ch.id) if (ch === undefined) return
}(array)) if (f) arr.push(f)
return arr arr.push(ch.id)
})(array)
return arr
} }
// //
function getCheckedChapterObj(array: any,id:any) { function getCheckedChapterObj(array: any, id: any) {
let i = 0, arr: any[] = []; let i = 0,
(function fn(array: any) { arr: any[] = []
if (!isArray(array)) return ;(function fn(array: any) {
const ch = array.find((item: any) => item.id === id) if (!isArray(array)) return
if (ch === undefined && i < array.length) { const ch = array.find((item: any) => item.id === id)
fn(array[i++].chapterSection) if (ch === undefined && i < array.length) {
} fn(array[i++].chapterSection)
if (ch === undefined) return }
arr.push(ch) if (ch === undefined) return
}(array)) arr.push(ch)
return arr[0] })(array)
return arr[0]
} }
const activeIdArr = ref<string[] | undefined>(getCheckedChapter(options1.value)) const activeIdArr = ref<string[] | undefined>(getCheckedChapter(options1.value))
watch(() => activeIdArr.value, newVal => {// id watch(
() => activeIdArr.value,
(newVal) => {
// id
if (newVal === undefined) { if (newVal === undefined) {
ruleForm.id = undefined ruleForm.id = undefined
return return
} }
ruleForm.id = newVal.slice(-1)[0] ruleForm.id = newVal.slice(-1)[0]
}) },
)
</script> </script>
<style lang="scss"></style> <style lang="scss"></style>

@ -1,50 +1,79 @@
<template> <template>
<div class="course-chapters"> <div class="course-chapters">
<div class="flex-layout"> <div class="flex-layout">
<div class="flex-left"> <div class="flex-left">
<div class="left" ref="atlasCon"> <div class="left" ref="atlasCon">
<!-- 知识图谱 --> <!-- 知识图谱 -->
<atlas-ui @hadRouter="handle" /> <atlas-ui @hadRouter="handle" />
</div>
<div class="right-top radius-10 vertical-line">
<!-- 计算机导论 -->
<theory-ui :learnInfo="learnInfo" />
</div>
<div class="right-bottom radius-10 vertical-line">
<!-- 课程目标 -->
<objective-ui :orogramObjective="orogramObjective" />
</div>
<div class="bottom">
<!-- 可折叠基本概念 -->
<fold-info-ui :foldInfoData="foldInfoData" @add="showHide = true" @edit="hanEdit" @del="flodDel"
:loading="foldDelLoading" />
<FoldAdd v-model:is-d="showHide" v-if="showHide" :data="foldInfoData" @submit="foldAddSubmit" />
<FoldEdit v-model:is-d="showHide1" v-if="showHide1" :editData="activeEditData" :data="foldInfoData"
@submit="foldEditSubmit" />
</div>
</div>
<div class="flex_right">
<div class="top-container">
<img src="" alt="">
</div>
<div class="bottom-container radius-10">
<!-- 查看资源 -->
<look-resource-ui :lookResource="lookResource" />
</div>
</div>
</div> </div>
<div class="right-top radius-10 vertical-line">
<!-- 计算机导论 -->
<theory-ui :learnInfo="learnInfo" />
</div>
<div class="right-bottom radius-10 vertical-line">
<!-- 课程目标 -->
<objective-ui :orogramObjective="orogramObjective" />
</div>
<div class="bottom">
<!-- 可折叠基本概念 -->
<fold-info-ui
:foldInfoData="foldInfoData"
@add="showHide = true"
@edit="hanEdit"
@del="flodDel"
:loading="foldDelLoading"
/>
<FoldAdd
v-model:is-d="showHide"
v-if="showHide"
:data="foldInfoData"
@submit="foldAddSubmit"
/>
<FoldEdit
v-model:is-d="showHide1"
v-if="showHide1"
:editData="activeEditData"
:data="foldInfoData"
@submit="foldEditSubmit"
/>
</div>
</div>
<div class="flex_right">
<div class="top-container">
<img src="" alt="" />
</div>
<div class="bottom-container radius-10">
<!-- 查看资源 -->
<look-resource-ui :lookResource="lookResource" />
</div>
</div>
</div> </div>
</div>
</template> </template>
<script lang='ts' setup> <script lang="ts" setup>
import { getLearnInfoApi, getOrogramObjectiveApi } from '@/api/courseChaptersApi' import {
import { getChapterApi, deleteSectionApi, addChapterApi, updateChapterApi } from '@/api/sectionApi' getLearnInfoApi,
import { theoryUi, objectiveUi, atlasUi, lookResourceUi, foldInfoUi, FoldAdd, FoldEdit } from './components/KnowledgeGraphUi/index' getOrogramObjectiveApi,
} from '@/api/courseChaptersApi'
import {
getChapterApi,
deleteSectionApi,
addChapterApi,
updateChapterApi,
} from '@/api/sectionApi'
import {
theoryUi,
objectiveUi,
atlasUi,
lookResourceUi,
foldInfoUi,
FoldAdd,
FoldEdit,
} from './components/KnowledgeGraphUi/index'
import { ref, reactive } from 'vue' import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus'
const $router = useRouter() const $router = useRouter()
@ -53,12 +82,12 @@ const handle = () => $router.push('/knowledgeAtlas')
// theory-ui // theory-ui
const learnInfo: object[] = reactive([]) const learnInfo: object[] = reactive([])
getLearnInfoApi().then(res => learnInfo.push(...res as object[])) getLearnInfoApi().then((res) => learnInfo.push(...(res as object[])))
// getByIdCourseVoApi('2fa0fd63262230639d2c45a3acd9045c') // getByIdCourseVoApi('2fa0fd63262230639d2c45a3acd9045c')
// objective-ui // objective-ui
const orogramObjective: any = reactive({}) const orogramObjective: any = reactive({})
getOrogramObjectiveApi().then(res => Object.assign(orogramObjective, res)) getOrogramObjectiveApi().then((res) => Object.assign(orogramObjective, res))
// look-resource-ui // look-resource-ui
const lookResource: any = reactive({}) const lookResource: any = reactive({})
@ -66,157 +95,164 @@ const lookResource: any = reactive({})
// fold-info-ui // fold-info-ui
const foldInfoData: any = reactive([]) const foldInfoData: any = reactive([])
function getFold() { function getFold() {
getChapterApi('2fa0fd63262230639d2c45a3acd9045c').then(res => { getChapterApi('2fa0fd63262230639d2c45a3acd9045c').then((res) => {
foldInfoData.length = 0 foldInfoData.length = 0
foldInfoData.push(...res.data) foldInfoData.push(...res.data)
}) })
} }
getFold() getFold()
// //
const showHide = ref(false) const showHide = ref(false)
function foldAddSubmit(data: any, updLoading: Function) { function foldAddSubmit(data: any, updLoading: Function) {
updLoading(true) updLoading(true)
addChapterApi(data).then(() => { addChapterApi(data)
ElMessage({ .then(() => {
message: `添加${data.pid === '' ? '章' : '节'}成功`, ElMessage({
type: 'success' message: `添加${data.pid === '' ? '章' : '节'}成功`,
}) type: 'success',
showHide.value = false })
getFold() showHide.value = false
}).catch(() => { getFold()
ElMessage({ })
message: `添加${data.pid === '' ? '章' : '节'}失败`, .catch(() => {
type: 'error' ElMessage({
}) message: `添加${data.pid === '' ? '章' : '节'}失败`,
}).finally(() => updLoading(false)) type: 'error',
})
})
.finally(() => updLoading(false))
} }
// //
const foldDelLoading = ref(false) const foldDelLoading = ref(false)
function flodDel(id: string) { function flodDel(id: string) {
foldDelLoading.value = true foldDelLoading.value = true
deleteSectionApi(id).then(() => { deleteSectionApi(id)
ElMessage({ .then(() => {
message: `删除成功`, ElMessage({
type: 'success' message: `删除成功`,
}) type: 'success',
getFold() })
}).catch(() => { getFold()
ElMessage({ })
message: `删除失败`, .catch(() => {
type: 'error' ElMessage({
}) message: `删除失败`,
}).finally(() => foldDelLoading.value = false) type: 'error',
})
})
.finally(() => (foldDelLoading.value = false))
} }
// //
const showHide1 = ref(false) const showHide1 = ref(false)
const activeEditData = ref() const activeEditData = ref()
function hanEdit(data: any) { function hanEdit(data: any) {
activeEditData.value = data activeEditData.value = data
showHide1.value = true showHide1.value = true
} }
function foldEditSubmit(data: any, updLoading: Function) { function foldEditSubmit(data: any, updLoading: Function) {
updLoading(true) updLoading(true)
updateChapterApi(data).then(() => { updateChapterApi(data)
ElMessage({ .then(() => {
message: `更新${data.pid === '' ? '章' : '节'}成功`, ElMessage({
type: 'success' message: `更新${data.pid === '' ? '章' : '节'}成功`,
}) type: 'success',
showHide1.value = false })
getFold() showHide1.value = false
}).catch(() => { getFold()
ElMessage({ })
message: `更新${data.pid === '' ? '章' : '节'}失败`, .catch(() => {
type: 'error' ElMessage({
}) message: `更新${data.pid === '' ? '章' : '节'}失败`,
}).finally(() => updLoading(false)) type: 'error',
})
})
.finally(() => updLoading(false))
} }
</script> </script>
<style lang='scss' scoped> <style lang="scss" scoped>
.course-chapters { .course-chapters {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: relative;
background: #f2f7fb;
&,
* {
box-sizing: border-box;
}
.radius-10 {
border-radius: 10px;
overflow: hidden;
}
.vertical-line {
position: relative; position: relative;
background: #F2F7FB;
&, &::before {
* { content: '';
box-sizing: border-box; display: block;
position: absolute;
height: 100%;
width: 12px;
background-color: #2147fb;
} }
}
.flex-layout {
display: flex;
justify-content: space-between;
align-items: flex-start;
.radius-10 { .flex-left {
border-radius: 10px; display: grid;
overflow: hidden; grid-template-columns: 664px 555px;
} justify-content: space-between;
width: 1243px;
.vertical-line { .left {
position: relative; grid-row: 1/3;
height: 424px;
}
&::before { .right-top {
content: ''; width: 100%;
display: block; height: 243px;
position: absolute; }
height: 100%;
width: 12px;
background-color: #2147FB;
}
}
.flex-layout { .right-bottom {
display: flex; align-self: end;
justify-content: space-between; width: 100%;
align-items: flex-start; height: 168px;
}
.flex-left {
display: grid;
grid-template-columns: 664px 555px;
justify-content: space-between;
width: 1243px;
.left {
grid-row: 1/3;
height: 424px;
}
.right-top {
width: 100%;
height: 243px;
}
.right-bottom {
align-self: end;
width: 100%;
height: 168px;
}
.bottom {
margin-top: 15px;
grid-column: 1/3;
width: 100%;
min-width: 100%;
min-height: 521px;
}
}
.flex_right { .bottom {
width: 355px; margin-top: 15px;
grid-column: 1/3;
width: 100%;
min-width: 100%;
min-height: 521px;
}
}
.top-container { .flex_right {
height: 231px; width: 355px;
margin-bottom: 23px;
img { .top-container {
width: 100%; height: 231px;
height: 100%; margin-bottom: 23px;
}
}
.bottom-container { img {
min-height: 945px; width: 100%;
} height: 100%;
} }
} }
.bottom-container {
min-height: 945px;
}
}
}
} }
</style> </style>

@ -25,7 +25,7 @@ function handleClick() {
.info_title { .info_title {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; width: 98%;
.title_name { .title_name {
font-family: Inter, Inter; font-family: Inter, Inter;
font-weight: 400; font-weight: 400;
@ -46,19 +46,4 @@ function handleClick() {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
// .overlay {
// position: absolute;
// top: 181px;
// left: 1278px;
// width: 40px;
// height: 30px;
// // background-color: lightgray;
// border: 1px solid black;
// z-index: 1000;
// display: flex;
// justify-content: center;
// flex-direction: column;
// align-items: center;
// margin-bottom: 10px;
// }
</style> </style>

@ -1,72 +1,72 @@
<script setup> <script setup>
import ellipsis from '@/assets/images/ellipsis.png' // import ellipsis from '@/assets/images/ellipsis.png'
import conheader from '@/views/home/components/ConHeader.vue' // import conheader from '@/views/home/components/ConHeader.vue'
import { ref, computed } from 'vue' // import { ref, computed } from 'vue'
import { userIdenChangeService } from '@/api/user/user.js' // import { userIdenChangeService } from '@/api/user/user.js'
import { ElMessage } from 'element-plus' // import { ElMessage } from 'element-plus'
import InfoContainer from './infoContainer/index.vue' // import InfoContainer from './infoContainer/index.vue'
import myDrawer from './myDrawer/index.vue' // import myDrawer from './myDrawer/index.vue'
const props = defineProps({ // const props = defineProps({
data: { // data: {
type: Object, // type: Object,
}, // },
}) // })
// ============== formModel // // ============== formModel
const formModel = ref() // const formModel = ref()
switch (+props.data.roleId[0]) { // switch (+props.data.roleId[0]) {
case 1: // case 1:
formModel.value = [ // formModel.value = [
{ par: 'name', name: '姓名', content: props.data.name }, // { par: 'name', name: '', content: props.data.name },
{ par: 'sex', name: '性别', content: props.data.sex }, // { par: 'sex', name: '', content: props.data.sex },
{ par: 'nationality', name: '民族', content: props.data.nationality }, // { par: 'nationality', name: '', content: props.data.nationality },
{ par: 'profession', name: '专业', content: props.data.profession }, // { par: 'profession', name: '', content: props.data.profession },
{ par: 'education', name: '学历', content: props.data.education }, // { par: 'education', name: '', content: props.data.education },
{ // {
par: 'academicDegree', // par: 'academicDegree',
name: '学位', // name: '',
content: props.data.academicDegree, // content: props.data.academicDegree,
}, // },
{ // {
par: 'professionalTitle', // par: 'professionalTitle',
name: '职称', // name: '',
content: props.data.professionalTitle, // content: props.data.professionalTitle,
}, // },
{ // {
par: 'emergencyContact', // par: 'emergencyContact',
name: '手机号', // name: '',
content: props.data.emergencyContact, // content: props.data.emergencyContact,
}, // },
{ // {
par: 'joinWorkTime', // par: 'joinWorkTime',
name: '参加工作时间', // name: '',
content: props.data.joinWorkTime, // content: props.data.joinWorkTime,
}, // },
{ // {
par: 'politicalStatus', // par: 'politicalStatus',
name: '政治面貌', // name: '',
content: props.data.politicalStatus, // content: props.data.politicalStatus,
}, // },
] // ]
break // break
case 2: // case 2:
formModel.value = [ // formModel.value = [
{ par: 'name', name: '姓名', content: props.data.name }, // { par: 'name', name: '', content: props.data.name },
{ par: 'sex', name: '性别', content: props.data.sex }, // { par: 'sex', name: '', content: props.data.sex },
{ par: 'nationality', name: '民族', content: props.data.nationality }, // { par: 'nationality', name: '', content: props.data.nationality },
{ par: 'number', name: '学号', content: props.data.number }, // { par: 'number', name: '', content: props.data.number },
{ par: 'birthday', name: '生日', content: props.data.birthday }, // { par: 'birthday', name: '', content: props.data.birthday },
{ par: 'phone', name: '手机号', content: props.data.phone }, // { par: 'phone', name: '', content: props.data.phone },
{ par: 'faculty', name: '院系', content: props.data.faculty }, // { par: 'faculty', name: '', content: props.data.faculty },
{ par: 'major', name: '专业', content: props.data.major }, // { par: 'major', name: '', content: props.data.major },
{ par: 'yearAge', name: '入学年份', content: props.data.yearAge }, // { par: 'yearAge', name: '', content: props.data.yearAge },
{ par: 'className', name: '班级', content: props.data.className }, // { par: 'className', name: '', content: props.data.className },
] // ]
break // break
} // }
// ============== // // ==============
// 1 // // 1
const drawer2 = ref(false) // const drawer2 = ref(false)
</script> </script>
<template> <template>
<div class="info_container" style="width: 95%; height: 306px"> <div class="info_container" style="width: 95%; height: 306px">
@ -76,8 +76,8 @@ const drawer2 = ref(false)
<img :src="ellipsis" @click="drawer2 = true" /> <img :src="ellipsis" @click="drawer2 = true" />
</div> </div>
</div> </div>
<InfoContainer :data="formModel"></InfoContainer> <!-- <InfoContainer :data="formModel"></InfoContainer>
<myDrawer v-model:drawer="drawer2" :data="formModel"></myDrawer> <myDrawer v-model:drawer="drawer2" :data="formModel"></myDrawer> -->
</div> </div>
</template> </template>
<style scoped> <style scoped>

@ -0,0 +1,84 @@
<script setup>
import conheader from '@/views/home/components/ConHeader.vue'
import fe from '@/assets/images/fe.jpg'
</script>
<template>
<div class="lesson_container" style="width: 95%">
<conheader :title="`课程列表`"></conheader>
<div class="lessonlist-content">
<div class="lessonlist-item" v-for="item in 3" :key="item">
<div class="lessonlist-item-img">
<img :src="fe" alt="" style="width: 100%; height: 140px" />
</div>
<div class="lessonlist-item-info">
<h3>课程名称</h3>
<div class="p"><p>编辑</p></div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.lesson_container {
display: flex;
flex-direction: column;
justify-content: space-between;
margin: 0 auto;
padding: 20px 0;
}
.lessonlist-content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 10px 0;
}
.lesson_container {
display: flex;
flex-direction: column;
justify-content: space-between;
margin: 0 auto;
padding: 5px 0;
}
.lessonlist-item {
width: 270px;
height: 200px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.lessonlist-item-img {
width: 100%;
height: 140px;
}
.lessonlist-item-info {
padding: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.lessonlist-item-info h3 {
font-size: 16px;
font-weight: bold;
margin-bottom: 5px;
}
.lessonlist-item-info .p {
width: 100%;
display: flex;
justify-content: end;
}
.lessonlist-item-info p {
font-size: 12px;
color: #a7c4f7;
line-height: 1.5;
box-sizing: border-box;
border: 2px solid #a7c4f7;
border-radius: 10px;
margin-bottom: 5px;
width: 50px;
margin: 5px;
text-align: center;
cursor: pointer;
}
</style>

@ -1,48 +1,21 @@
<script setup> <script setup>
import add from '@/assets/images/add.png' import add from '@/assets/images/add.png'
// import { Plus } from '@element-plus/icons-vue'
import tool from '@/utils/oss.js' import tool from '@/utils/oss.js'
import { userChangeService } from '@/api/user/user.js' import { userChangeService } from '@/api/user/user.js'
import { ref, defineEmits } from 'vue' import { ref, defineEmits, onMounted } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
// import { error } from 'echarts/types/src/util/log.js'
const props = defineProps({ const props = defineProps({
data: { data: {
type: Object, type: Object,
}, },
userData: {
type: Object,
},
}) })
const imageUrl = ref('')
const dialogFormVisible = ref(false) console.log(props.userData, 'props.infoData')
// const imageUrl = ref()
// const rules = {
// username: [
// { required: true, message: '', trigger: 'blur' },
// {
// max: 10,
// min: 5,
// message: '',
// trigger: ['change', 'blur'],
// },
// ],
// nickName: [{ trigger: 'blur' }],
// phone: [
// { trigger: 'blur' },
// {
// pattern: /^1[3456789]\d{9}$/,
// message: '',
// trigger: 'blur',
// // pattern
// },
// ],
// code: [{ message: '', trigger: 'blur' }],
// }
const form = ref()
// {
// username: '',
// nickName: '',
// phone: '',
// }
form.value = { ...props.data }
const formLabelWidth = '70px'
// //
imageUrl.value = props.data.icon imageUrl.value = props.data.icon
// //
@ -50,77 +23,99 @@ const upload = async (option) => {
const res = await tool.oss.upload(option.file) const res = await tool.oss.upload(option.file)
const url = 'https://wenyu132.oss-cn-beijing.aliyuncs.com/' + res.name const url = 'https://wenyu132.oss-cn-beijing.aliyuncs.com/' + res.name
imageUrl.value = url imageUrl.value = url
changeInfo()
} }
const openInfo = () => { //
dialogFormVisible.value = true const emit = defineEmits(['get-avater'])
} let isUploading = ref(false)
//
const emit = defineEmits(['get-message'])
const changeInfo = async () => { const changeInfo = async () => {
const userInfo = { if (!isUploading.value) {
phone: form.value.phone, isUploading.value = true
id: form.value.id, const userInfo = {
nickName: form.value.nickName, id: props.data.id,
icon: imageUrl.value, icon: imageUrl.value,
}
const jsonData = JSON.stringify(userInfo)
await userChangeService(jsonData).then(() => {
ElMessage.success('修改成功')
emit('get-avater', imageUrl.value)
})
isUploading.value = false
} }
const jsonData = JSON.stringify(userInfo)
await userChangeService(jsonData).then(() => {
ElMessage.success('修改成功')
console.log(form.value.nickName, 'nickN')
emit('get-message', form.value.nickName)
})
dialogFormVisible.value = false
} }
const cancleInfo = () => { // onMounted(() => {
dialogFormVisible.value = false // console.log(props.data.icon, 'props.icon')
form.value = { // })
...props.data, //
} const dialog = ref(false)
const radio = ref(3)
const form = ref({})
form.value = { ...props.userData }
const openInfo = () => {
dialog.value = true
}
const onCancel = () => {
dialog.value = false
} }
const onsubmit = async () => {}
const formLabelWidth = '60px'
const loading = ref(false)
</script> </script>
<template> <template>
<div class="ident" style="width: 100%; height: 274px; background: #375fff"> <div class="ident" style="width: 100%; height: 274px; background: #375fff">
<div class="info_container" style="width: 201px; height: 178px"> <div class="info_container" style="width: 201px; height: 178px">
<div class="avater"> <div class="avater">
<img :src="imageUrl" alt="Uploaded" v-if="imageUrl" class="avater" /> <img
:src="imageUrl"
alt="Uploaded"
v-if="imageUrl"
class="avater"
auto-upload
/>
</div> </div>
<el-upload class="click" :http-request="upload" :show-file-list="false"> <el-upload
class="click"
:http-request="upload"
@change="changeInfo"
:show-file-list="false"
auto-upload="false"
>
<img :src="add" /> <img :src="add" />
</el-upload> </el-upload>
<div class="info_content" style="height: 58px" @click="openInfo"> <div class="info_content" style="height: 58px" @click="openInfo">
<div class="name">{{ props.data.username }}</div> <div class="name">{{ props.data.username }}</div>
<!-- <div class="na">{{ props.data.professionalTitle }}</div> -->
</div> </div>
</div> </div>
</div> </div>
<el-dialog <el-drawer v-model="dialog" title="个人信息" class="demo-drawer">
v-model="dialogFormVisible" <div class="content">
title="登录信息" <el-form :model="form">
style="width: 800px; text-align: center" <el-form-item label="姓名" :label-width="formLabelWidth">
> <el-input v-model="form.name" autocomplete="off"></el-input>
<el-form :model="form" :data="form" :rules="rules"> </el-form-item>
<el-form-item label="用户名" :label-width="formLabelWidth"> <el-form-item label="性别" :label-width="formLabelWidth">
<el-input :disabled="true" v-model="form.username" autocomplete="off" /> <el-radio-group v-model="radio">
</el-form-item> <el-radio :value="3"></el-radio>
<el-form-item label="昵称" :label-width="formLabelWidth"> <el-radio :value="6"></el-radio>
<el-input v-model="form.nickName" autocomplete="off" /> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="手机" :label-width="formLabelWidth"> <el-form-item label="民族" :label-width="formLabelWidth">
<el-input v-model="form.phone" autocomplete="off" /> <el-input v-model="form.email" autocomplete="off"></el-input>
</el-form-item> </el-form-item>
</el-form> <el-form-item label="手机号" :label-width="formLabelWidth">
<template #footer> <el-input v-model="form.phone" autocomplete="off"></el-input>
<div class="dialog-footer"> </el-form-item>
<el-button @click="cancleInfo">取消</el-button> </el-form>
<el-button type="primary" @click="changeInfo">确认</el-button> <div class="footer">
<el-button @click="onCancel">取消</el-button>
<el-button type="primary" :loading="loading" @click="onsubmit">
确认
</el-button>
</div> </div>
</template> </div>
</el-dialog> </el-drawer>
</template> </template>
<style scoped> <style scoped>
.el-form-item {
display: flex;
}
.ident { .ident {
background: #ffffff; background: #ffffff;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1); box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);

@ -16,9 +16,9 @@ function confirmClick() {
} }
</script> </script>
<template> <template>
<div class="info_container" style="width: 90%; height: 174px"> <div class="info_container" style="width: 90%">
<conheader title="学生分组" v-model="drawer2"> <conheader :title="`学生分组`"></conheader>
<div>编辑</div> <!-- <div>编辑</div>
<template #drawer> <template #drawer>
<el-drawer v-model="drawer2" :direction="direction"> <el-drawer v-model="drawer2" :direction="direction">
<template #header> <template #header>
@ -36,9 +36,14 @@ function confirmClick() {
</div> </div>
</template> </template>
</el-drawer> </el-drawer>
</template> </template> -->
</conheader>
<div class="info_content" style="width: 194px; height: 112px"> <div class="stu_content">
<ul>
<li v-for="item in 10" :key="item"></li>
</ul>
</div>
<!-- <div class="info_content" style="width: 194px; height: 112px">
<div <div
v-for="(item, index) in name" v-for="(item, index) in name"
:key="index" :key="index"
@ -47,23 +52,25 @@ function confirmClick() {
> >
{{ item }} {{ item }}
</div> </div>
</div> </div> -->
</div> </div>
</template> </template>
<style scoped> <style scoped>
.stu { /* .stu {
background: #ffffff; background: #ffffff;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1); box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
border-radius: 6px 6px 6px 6px; border-radius: 6px 6px 6px 6px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} } */
.info_container { .info_container {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.stu_content {
height: 200px;
}
.info_content { .info_content {
width: 194px; width: 194px;
height: 112px; height: 112px;

@ -1,5 +1,14 @@
<script setup> <script setup>
import { onMounted, ref, computed } from 'vue' import { onMounted, ref, computed } from 'vue'
import {
userChangeService,
userChangePasswordService,
} from '@/api/user/user.js'
// import { defineEmits } from 'vue'
import useUserStore from '@/store/modules/user'
import { useRouter } from 'vue-router'
import { ElMessage, dayjs } from 'element-plus'
const props = defineProps({ const props = defineProps({
name: { name: {
type: String, type: String,
@ -11,6 +20,109 @@ const props = defineProps({
type: Object, type: Object,
}, },
}) })
const router = useRouter()
const formRef = ref()
const pwdForm = ref({
old_pwd: '',
new_pwd: '',
re_pwd: '',
})
// console.log(props.userData.username, 'props.data')
//dialog
//
const dialogFormVisible = ref(false)
//
const passFormVisible = ref(false)
//dialog
const form = ref()
// {
// username: '',
// nickName: '',
// phone: '',
// }
form.value = { ...props.userData }
const formLabelWidth = '70px'
//dialog
const openInfo = () => {
dialogFormVisible.value = true
}
const openPass = () => {
passFormVisible.value = true
}
//
const rules = {
//
old_pwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
pattern: /^\S{6,15}$/,
message: '密码长度必须是6-15位的非空字符串',
trigger: 'blur',
},
],
//
new_pwd: [
{ required: true, message: '请输入新密码', trigger: 'blur' },
{
pattern: /^\S{6,15}$/,
message: '密码长度必须是6-15位的非空字符串',
trigger: 'blur',
},
// { validator: checkOldSame, trigger: 'blur' },
],
//
re_pwd: [
{ required: true, message: '请再次确认新密码', trigger: 'blur' },
{
pattern: /^\S{6,15}$/,
message: '密码长度必须是6-15位的非空字符串',
trigger: 'blur',
},
// { validator: checkNewSame, trigger: 'blur' },
],
}
//
const emit = defineEmits(['get-message'])
const changeInfo = async () => {
const userInfo = {
phone: form.value.phone,
id: form.value.id,
nickName: form.value.nickName,
}
const jsonData = JSON.stringify(userInfo)
await userChangeService(jsonData).then(() => {
ElMessage.success('修改成功')
// console.log(form.value.nickName, 'nickN')
// emit('get-message', form.value.nickName)
})
dialogFormVisible.value = false
}
//
const userStore = useUserStore()
const onSubmit = async () => {
await formRef.value.validate()
const passData = ref({
oldPassword: pwdForm.value.old_pwd,
newPassword: pwdForm.value.new_pwd,
username: props.userData.username,
})
await userChangePasswordService(passData.value)
ElMessage.success('密码修改成功')
pwdForm.value = {}
passFormVisible.value = false
}
//
const onReset = () => {
pwdForm.value = {}
}
const cancleInfo = () => {
dialogFormVisible.value = false
form.value = {
...props.data,
}
}
const username = computed(() => { const username = computed(() => {
if (props.userData.nickName) { if (props.userData.nickName) {
@ -19,19 +131,24 @@ const username = computed(() => {
return props.userData.username return props.userData.username
} }
}) })
//
const daysOnJob = ref() const daysOnJob = ref()
const flagVisible = ref(true) const flagVisible = ref(true)
//
const currentDate = new Date()
const formattedDate = dayjs(currentDate).format('YYYY-MM-DD')
onMounted(() => { onMounted(() => {
console.log(props.name, 'name')
console.log(props.data.nickName === props.name, 'sdf')
username.value = props.data.name username.value = props.data.name
const hireDate = new Date(props.data.joinWorkTime) const hireDate = new Date(props.data.joinWorkTime)
console.log(props.userData.nickName, 'welcome')
// //
const currentDate = new Date() // const currentDate = new Date()
const millisecondsPerDay = 1000 * 60 * 60 * 24 const millisecondsPerDay = 1000 * 60 * 60 * 24
daysOnJob.value = Math.floor((currentDate - hireDate) / millisecondsPerDay) daysOnJob.value = Math.floor((currentDate - hireDate) / millisecondsPerDay)
}) })
//
</script> </script>
<template> <template>
<div class="nav_info"> <div class="nav_info">
@ -44,14 +161,71 @@ onMounted(() => {
<div class="intro" v-else> <div class="intro" v-else>
<p>Hell0,欢迎回来</p> <p>Hell0,欢迎回来</p>
</div> </div>
<div>
<el-button plain round type="primary" @click="openInfo">
管理账号
</el-button>
</div>
<div>
<el-button plain round type="primary" @click="openPass">
修改密码
</el-button>
</div>
<div class="time">{{ formattedDate }}</div>
</div> </div>
<el-dialog
v-model="dialogFormVisible"
title="登录信息"
style="width: 800px; text-align: center"
>
<el-form :model="form" :data="form" :rules="rules">
<el-form-item label="用户名" :label-width="formLabelWidth">
<el-input :disabled="true" v-model="form.username" autocomplete="off" />
</el-form-item>
<el-form-item label="昵称" :label-width="formLabelWidth">
<el-input v-model="form.nickName" autocomplete="off" />
</el-form-item>
<el-form-item label="手机" :label-width="formLabelWidth">
<el-input v-model="form.phone" autocomplete="off" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancleInfo">取消</el-button>
<el-button type="primary" @click="changeInfo">确认</el-button>
</div>
</template>
</el-dialog>
<el-dialog
v-model="passFormVisible"
title="修改密码"
style="width: 700px; text-align: center"
>
<el-form :rules="rules" ref="formRef" :data="pwdForm">
<el-form-item label="原密码">
<el-input type="password" v-model="pwdForm.old_pwd"></el-input>
</el-form-item>
<el-form-item label="新密码" prop="new_pwd">
<el-input type="password" v-model="pwdForm.new_pwd"></el-input>
</el-form-item>
<el-form-item label="确认新密码" prop="re_pwd">
<el-input type="password" v-model="pwdForm.re_pwd"></el-input>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="onReset">重置</el-button>
<el-button @click="onSubmit" type="primary">修改密码</el-button>
</div>
</template>
</el-dialog>
</template> </template>
<style scoped> <style scoped>
.nav_info { .nav_info {
width: 95%; width: 95%;
height: 32px; height: 32px;
display: flex; display: flex;
justify-content: start; justify-content: space-between;
align-items: center; align-items: center;
} }
.name { .name {
@ -67,7 +241,7 @@ onMounted(() => {
margin-right: 68px; margin-right: 68px;
} }
.intro { .intro {
width: 50%; width: 60%;
height: 22px; height: 22px;
font-family: Inter, Inter; font-family: Inter, Inter;
font-weight: bold; font-weight: bold;
@ -78,4 +252,7 @@ onMounted(() => {
font-style: normal; font-style: normal;
text-transform: none; text-transform: none;
} }
.time {
justify-content: end;
}
</style> </style>

@ -1,13 +1,17 @@
<script lang="ts" setup> <script lang="ts" setup>
import status from '@/views/home/components/Status.vue' import status from '@/views/home/components/Status.vue'
import welcome from './components/Welcome.vue' import welcome from './components/Welcome.vue'
import Info from './components/Info.vue' import conheader from '@/views/home/components/ConHeader.vue'
// import Info from './components/Info.vue'
import echarts from './components/Echarts.vue' import echarts from './components/Echarts.vue'
import Class1 from './components/Class1.vue' import lessonlist from './components/Lessonlist.vue'
// import Class1 from './components/Class1.vue'
import Student1 from './components/Student1.vue' import Student1 from './components/Student1.vue'
import Class2 from './components/Class2.vue' // import Class2 from './components/Class2.vue'
import Student2 from './components/Student2.vue' // import Student2 from './components/Student2.vue'
import { userNewLikeService } from '@/api/user/user'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import fe from '@/assets/images/fe.jpg'
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
const userStore = useUserStore() const userStore = useUserStore()
const username = ref() const username = ref()
@ -19,23 +23,30 @@ const rightVisible = ref(false)
userStore.getUserInfo().catch((error) => { userStore.getUserInfo().catch((error) => {
console.log(error) console.log(error)
}) })
let sum: any = localStorage.getItem('sum') || '0' let sum: any = localStorage.getItem('sum') || '0'
const name = ref() const name = ref()
const getMessage = (msg) => { const getMessage = (msg) => {
name.value = msg name.value = msg
console.log(msg, 'msg') // console.log(msg, 'msg')
}
const getAvater = (avater) => {
// console.log(msg, 'msg')
userStore.data.icon = avater
// console.log(data.value.icon, 'icon')
} }
const img = ref()
const courseName = ref()
onMounted(() => { onMounted(() => {
// getData() // getData()
sum = parseInt(sum) + 1 sum = parseInt(sum) + 1
localStorage.setItem('sum', sum.toString()) localStorage.setItem('sum', sum.toString())
console.log(sum, 'sum') // console.log(sum, 'sum')
username.value = userStore.userName username.value = userStore.userName
data.value = userStore.data data.value = userStore.data
infoData.value = userStore.userInfo infoData.value = userStore.userInfo
// console.log(data.value, '11111') // console.log(data.value, '11111')
// console.log(userStore.userInfo, '22222') // console.log(userStore.userInfo, '22222') //
console.log(userStore.data, 'icon') //
username.value = data.value.username username.value = data.value.username
flag.value = true flag.value = true
role.value = data.value.roles[0] role.value = data.value.roles[0]
@ -44,11 +55,136 @@ onMounted(() => {
} else { } else {
rightVisible.value = false rightVisible.value = false
} }
//
// userToplessonService().then((res) => {
// // console.log(res, '')
// })
//
// const courselist = ref({ img: '', name: '' })
// const img = ref()
// const courseName = ref()
userNewLikeService(userStore.data.id).then((res) => {
console.log(res.data, '最新收藏的课程')
// courselist.value = res.data
// courselist.value.img = res.data.img
// courselist.value.name = res.data.name
img.value = res.data.img
courseName.value = res.data.name
console.log(img.value, 'img')
console.log(courseName.value, 'courseName')
})
}) })
</script> </script>
<template> <template>
<div class="container"> <el-row>
<div class="left"> <el-col :span="24">
<div class="nav">
<welcome
:data="infoData"
:userData="data"
:name="name"
@get-message="getMessage"
v-if="flag"
></welcome>
</div>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col :span="18">
<div class="classList">
<lessonlist></lessonlist>
</div>
</el-col>
<el-col :span="6">
<div class="info">
<status
:data="data"
:userData="infoData"
@get-avater="getAvater"
v-if="flag"
></status>
</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="6">
<div class="lesson">
<a
href="#"
style="width: 90%; font-size: 14px; display: flex; margin: 0 auto"
>
<conheader :title="`最多收藏知识点`"></conheader>
</a>
<p class="button" round v-for="item in 10" :key="item">Ro</p>
</div>
</el-col>
<el-col :span="6">
<div class="lesson">
<a
href="#"
style="width: 90%; font-size: 14px; display: flex; margin: 0 auto"
>
<conheader :title="`推荐知识点`"></conheader>
</a>
<p class="button" round v-for="item in 20" :key="item">Round</p>
</div>
</el-col>
<el-col :span="6">
<div class="lesson">
<a
href="#"
style="width: 90%; font-size: 14px; display: flex; margin: 0 auto"
>
<conheader :title="`推荐课程`"></conheader>
</a>
<div class="lessonlist-content">
<div class="lessonlist-item">
<div class="lessonlist-item-img">
<img :src="fe" alt="" style="width: 100%; height: 140px" />
</div>
<div class="lessonlist-item-info">
<h3>课程名称</h3>
</div>
</div>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="lesson">
<a
href="#"
style="width: 90%; font-size: 14px; display: flex; margin: 0 auto"
>
<conheader :title="`最新收藏课程`"></conheader>
</a>
<div class="lessonlist-content">
<div class="lessonlist-item">
<div class="lessonlist-item-img">
<img :src="img" alt="" style="width: 100%; height: 140px" />
</div>
<div class="lessonlist-item-info">
<h3>{{ courseName }}</h3>
</div>
</div>
</div>
</div>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col :span="18">
<div class="some">
<echarts :sum="sum"></echarts>
</div>
</el-col>
<el-col :span="6">
<div class="stu">
<Student1></Student1>
</div>
</el-col>
</el-row>
<!-- <div class="left">
<div class="nav"> <div class="nav">
<welcome <welcome
:data="infoData" :data="infoData"
@ -81,87 +217,201 @@ onMounted(() => {
<div class="stu" style="width: 100%; height: 236px"> <div class="stu" style="width: 100%; height: 236px">
<Student2></Student2> <Student2></Student2>
</div> </div>
</div> </div> -->
</div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.container { .nav {
height: 92px;
background: #ffffff;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
border-radius: 6px 6px 6px 6px;
margin-bottom: 16px;
display: flex; display: flex;
width: 100%; flex-direction: column; //
.left { justify-content: center;
width: 80%; align-items: center;
height: 936px; }
margin-right: 16px; .classList,
display: grid; .info {
grid-template-rows: 1fr 1fr 1fr; /* 使用fr单位来平均分布 */ height: 270px;
height: 300px; /* 设置容器高度 */ background: #ffffff;
.nav { box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
width: 100%; border-radius: 6px 6px 6px 6px;
height: 92px; justify-content: space-between;
background: #ffffff; margin-bottom: 16px;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1); }
border-radius: 6px 6px 6px 6px; .classList {
margin-bottom: 16px; display: flex;
display: flex; justify-content: space-between;
flex-direction: column; // }
justify-content: center; .lesson {
align-items: center; margin-bottom: 16px;
} height: 280px;
.info, background: #ffffff;
.echarts { box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
background: #ffffff; border-radius: 6px 6px 6px 6px;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1); display: flex;
border-radius: 6px 6px 6px 6px; // justify-content: center;
margin-bottom: 16px; align-items: center;
display: flex; // margin: 0 auto;
// flex-direction: column; // flex-wrap: wrap;
justify-content: center; // flex-direction: column;
align-items: center; .button {
.info_container { margin-top: 10px;
display: flex; height: 30px;
flex-direction: column; // border-radius: 10px;
justify-content: space-between; color: #0080ff;
} text-align: center;
} line-height: 30px;
.class { margin: 0 10px;
width: 80%; border: 2px solid #ccc;
height: 444px;
background: #c57676;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
border-radius: 6px 6px 6px 6px;
display: flex;
// flex-direction: column; //
justify-content: center;
align-items: center;
}
} }
.right { a {
width: 20%; text-decoration: none;
height: 930px;
display: flex;
flex-direction: column; //
justify-content: space-between;
.ident,
.class,
.stu {
background: #ffffff;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
border-radius: 6px 6px 6px 6px;
display: flex;
// flex-direction: column; //
justify-content: center;
align-items: center;
.info_container {
display: flex;
flex-direction: column; //
justify-content: space-between;
.info_content {
display: flex;
flex-direction: column; //
justify-content: space-between;
}
}
}
} }
} }
.some,
.stu {
height: 384px;
background: #ffffff;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
border-radius: 6px 6px 6px 6px;
justify-content: space-between;
display: flex;
justify-content: center;
}
.lessonlist-content {
display: flex;
justify-content: center;
align-items: center;
margin: 0 auto;
flex-direction: column;
}
.lessonlist-item {
width: 270px;
height: 180px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.lessonlist-item-img {
width: 100%;
height: 140px;
// justify-content: center;
align-items: center;
margin: 0 auto;
}
.lessonlist-item-info {
padding: 10px;
display: flex;
justify-content: space-between;
}
.lesson_container {
display: flex;
flex-direction: column;
justify-content: space-between;
margin: 0 auto;
padding: 5px 0;
}
.lessonlist-item-info {
padding: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.lessonlist-item-info h3 {
font-size: 16px;
font-weight: bold;
margin-bottom: 5px;
}
.lessonlist-item-info .p {
width: 100%;
display: flex;
justify-content: end;
}
.lessonlist-item-info p {
font-size: 12px;
color: #a7c4f7;
line-height: 1.5;
box-sizing: border-box;
border: 2px solid #a7c4f7;
border-radius: 10px;
margin-bottom: 5px;
width: 50px;
margin: 5px;
text-align: center;
cursor: pointer;
}
// .container {
// display: flex;
// width: 100%;
// .left {
// width: 80%;
// height: 936px;
// margin-right: 16px;
// display: grid;
// grid-template-rows: 1fr 1fr 1fr; /* 使fr */
// height: 300px; /* */
// .info,
// .echarts {
// background: #ffffff;
// box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
// border-radius: 6px 6px 6px 6px;
// margin-bottom: 16px;
// display: flex;
// // flex-direction: column; //
// justify-content: center;
// align-items: center;
// .info_container {
// display: flex;
// flex-direction: column; //
// justify-content: space-between;
// }
// }
// .class {
// width: 80%;
// height: 444px;
// background: #c57676;
// box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
// border-radius: 6px 6px 6px 6px;
// display: flex;
// // flex-direction: column; //
// justify-content: center;
// align-items: center;
// }
// }
// .right {
// width: 20%;
// height: 930px;
// display: flex;
// flex-direction: column; //
// justify-content: space-between;
// .ident,
// .class,
// .stu {
// background: #ffffff;
// box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
// border-radius: 6px 6px 6px 6px;
// display: flex;
// // flex-direction: column; //
// justify-content: center;
// align-items: center;
// .info_container {
// display: flex;
// flex-direction: column; //
// justify-content: space-between;
// .info_content {
// display: flex;
// flex-direction: column; //
// justify-content: space-between;
// }
// }
// }
// }
// }
</style> </style>

@ -281,20 +281,11 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { import { ref, onMounted, onUnmounted, onBeforeUnmount, watch } from 'vue'
// reactive,
ref,
onMounted,
onUnmounted,
onBeforeUnmount,
watch,
} from 'vue'
import { User, Lock, Phone, Check } from '@element-plus/icons-vue' import { User, Lock, Phone, Check } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import useUserStore from '@/store/modules/user' import useUserStore from '@/store/modules/user'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
//token
// import jwtDecode from 'jwt-decode'
// //
import { import {
userRegisterService, userRegisterService,
@ -414,12 +405,11 @@ const checkPasswordMatch = () => {
passwordMatchError.value = '' passwordMatchError.value = ''
} }
} }
//json //json
const handleSubmit = async () => { const handleSubmit = async () => {
// //
await form.value.validate() await form.value.validate()
console.log('开始注册') // console.log('')
if (formModel.value.password === formModel.value.repassword) { if (formModel.value.password === formModel.value.repassword) {
// //
const dataToSend = { const dataToSend = {
@ -430,13 +420,13 @@ const handleSubmit = async () => {
icon: formModel.value.icon, icon: formModel.value.icon,
} }
const jsonData = JSON.stringify(dataToSend) const jsonData = JSON.stringify(dataToSend)
console.log(jsonData) // console.log(jsonData)
// //
userRegisterService(jsonData) userRegisterService(jsonData)
.then(() => { .then(() => {
// //
ElMessage.success('注册成功') ElMessage.success('注册成功')
// // //
isRegister.value = true isRegister.value = true
}) })
.catch((error) => { .catch((error) => {
@ -447,7 +437,6 @@ const handleSubmit = async () => {
passwordMatchError.value = '两次输入的密码不一致' passwordMatchError.value = '两次输入的密码不一致'
} }
} }
// const userGetInfoService
// //
const codecode = ref() const codecode = ref()
const codeSubmit = async () => { const codeSubmit = async () => {
@ -465,7 +454,7 @@ const codeSubmit = async () => {
} }
// //
const phoneChange = () => { const phoneChange = () => {
console.log('开始手机号注册') // console.log('')
isinfo.value = false isinfo.value = false
} }
// //

@ -1,30 +1,5 @@
<template> <template>
<div> <div>学生</div>
<!-- Dialog组件 -->
<Dialog
v-model="dialogVisible"
@confirm="collectData"
:name="readonlyName"
:age="readonlyAge"
/>
</div>
</template> </template>
<script setup> <style lang="scss"></style>
import { ref, readonly } from 'vue'
const dialogVisible = ref(false) // Dialog
const name = ref('John') //
const age = ref(25) //
const readonlyName = readonly(name) // name
const readonlyAge = readonly(age) // age
const collectData = () => {
// Dialog
// ...
console.log(readonlyName.value) // 访
console.log(readonlyAge.value) // 访
}
</script>

@ -1,68 +0,0 @@
<template>
<div>
<el-button type="primary" @click="openDrawer">Open Drawer</el-button>
<el-drawer
title="Drawer Title"
v-model:visible="drawerVisible"
:direction="drawerDirection"
>
<el-table :data="formModel" style="width: 100%">
<el-table-column prop="name" label="Name"></el-table-column>
<el-table-column prop="content" label="Content">
<template v-slot="scope">
<el-input
v-model="scope.row.content"
@input="handleInput(scope.row)"
></el-input>
</template>
</el-table-column>
</el-table>
<template v-slot:footer>
<div>
<el-button @click="cancelEdit">Cancel</el-button>
<el-button type="primary" @click="saveEdit">Save</el-button>
</div>
</template>
</el-drawer>
</div>
</template>
<script>
export default {
data() {
return {
formModel: [
{ name: 'Macbook', content: 9.9 },
{ name: 'iPhone', content: 9.9 },
{ name: '小米电脑', content: 9.9 },
{ name: '小米电脑', content: 9.9 },
{ name: '小米电脑', content: 9.9 },
{ name: '小米电脑', content: 9.9 },
{ name: '小米电脑', content: 9.9 },
{ name: '小米电脑', content: 9.9 },
{ name: '小米电脑', content: 9.9 },
],
drawerVisible: false,
drawerDirection: 'ltr',
}
},
methods: {
openDrawer() {
this.drawerVisible = true
},
cancelEdit() {
this.drawerVisible = false
},
saveEdit() {
//
console.log('Save Edit:', this.formModel)
this.drawerVisible = false
},
handleInput(row) {
//
console.log('Handle Input:', row)
},
},
}
</script>
Loading…
Cancel
Save