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. 48
      src/store/modules/user.ts
  11. 3
      src/views/course/CourseObjectives.vue
  12. 174
      src/views/course/components/KnowledgeGraphUi/AddOrEdit copy.vue
  13. 133
      src/views/course/components/KnowledgeGraphUi/FoldAdd.vue
  14. 107
      src/views/course/components/KnowledgeGraphUi/FoldEdit.vue
  15. 108
      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. 145
      src/views/home/components/Status.vue
  20. 27
      src/views/home/components/Student1.vue
  21. 189
      src/views/home/components/Welcome.vue
  22. 368
      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_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '无糖运营平台'
# VITE_APP_BASE_API = 'http://127.0.0.1:8008'
VITE_APP_BASE_API = 'http://39.106.16.162:8080'
VITE_APP_BASE_API = 'http://127.0.0.1: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) => {
return request({
// <<<<<<< HEAD
// <<<<<<< HEAD
url: '/objective_contents/' + params.id,
method: 'get',
// // params
// =======
// <<<<<<< HEAD
// url: '/api/objective_contents/' + params.id,
// method: 'get',
// params,
// =======
// url: '/objective_contents/' + params.id,
// method: "get",
// // params
// >>>>>>> 1a620e19de970965f426e07348b1dbc4be900eaf
// >>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a
// // params
// =======
// <<<<<<< HEAD
// url: '/api/objective_contents/' + params.id,
// method: 'get',
// params,
// =======
// url: '/objective_contents/' + params.id,
// method: "get",
// // params
// >>>>>>> 1a620e19de970965f426e07348b1dbc4be900eaf
// >>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a
})
}

@ -25,6 +25,7 @@ export const userPhoneRegisterService = (jsonData) => {
export const userCodeRegisterService = (phoness) => {
return request.post('/api/user/code?phone=' + phoness)
}
//用户信息接口
export const userGetInfoService = (token) =>
request.get('/api/user/info', {
@ -46,3 +47,14 @@ export const userIdenChangeService = (dataToSend) => {
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="FullScreen" circle @click="fullScreen" />
<el-button size="small" icon="Setting" circle />
<el-button
size="small"
icon="Link"
circle
@click="openWeb('http://www.baidu.com/', 'baidu')"
/>
<img
src=""
:src="userStore.data.icon || defImg"
alt=""
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">
<span class="el-dropdown-link">
@ -37,12 +48,16 @@
// import { useDark, useToggle } from '@vueuse/core'
import useLayoutSettingStoe from '@/store/modules/setting'
import useUserStore from '@/store/modules/user'
import { onMounted } from 'vue'
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'
const useStore = useLayoutSettingStoe()
const userStore = useUserStore()
const $router = useRouter()
const $route = useRoute()
//
const fullScreen = () => {
let full = document.fullscreenElement
@ -56,7 +71,6 @@ const fullScreen = () => {
const refresh = () => {
useStore.refresh = !useStore.refresh
}
//
const handleCommand = (command: string) => {
switch (command) {
@ -65,18 +79,28 @@ const handleCommand = (command: string) => {
break
}
}
//
const openWeb = (url, name) => {
window.open(url, name, '_blank')
}
//
onMounted(() => {
userStore.getUserInfo()
console.log(userStore.data.icon, 'icon')
})
const logout = () => {
console.log($route)
userStore.logout()
$router.push({
path: '/login',
query: { redirect: $route.path },
})
}
// import IconEpSunny from '~icons/ep/sunny';
// import IconEpMoon from '~icons/ep/moon';
// const isDark = useDark()
// const toggleDark = () => useToggle(isDark)
</script>

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

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

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

@ -1,7 +1,5 @@
// 创建用户相关的仓库
import { defineStore } from 'pinia'
// 引入登录接口
// import { reqLogin, getUserInfo } from '@/api/user/index'
// 引入登录参数类型
import { loginType } from '@/api/user/types'
// 引入ElementPlus通知插件
@ -21,11 +19,8 @@ import {
userIdenService,
} from '@/api/user/user.js'
const useUserStore = defineStore(
'User',
{
const useUserStore = defineStore('User', {
// @ts-expect-error
state: (): LoginStoreType => {
return {
token: GET_TKOEN('TOKEN') || '',
@ -44,14 +39,10 @@ const useUserStore = defineStore(
// console.log(data, 'pinia')
const res: any = await userLoginService(data).catch((error) => {
ElMessage.error(error.response.data.message)
console.log(error, 'error')
// console.log(error, 'error')
})
if (res.code === 200) {
// @ts-expect-error
this.token = res.data.token as string
// @ts-expect-error
SET_TKOEN('TOKEN', this.token)
// localStorage.setItem('TOKEN', this.token)
ElNotification({
@ -72,13 +63,10 @@ const useUserStore = defineStore(
//手机号登录
async userPhoneLogin(data: loginType) {
const res: any = await userPhoneLoginService(data)
console.log(res, 11111)
// 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({
@ -95,27 +83,19 @@ const useUserStore = defineStore(
return Promise.reject(new Error(res.data.message))
}
},
// 获取用户信息事件
// 获取用户信息
async getUserInfo() {
const result: any = await userGetInfoService(GET_TKOEN('TOKEN'))
if (result.code === 200) {
console.log(result, 'result')
const res = await userIdenService(result.data.id)
console.log(res, 'huonghu')
// @ts-expect-error
// console.log(res, 'res')
this.userInfo = res.data
// console.log(this.userInfo, 'this.userInfo')
// @ts-expect-error
this.data = result.data
console.log(result, '123')
// @ts-expect-error
// console.log(result, '123')
this.userName = result.data.username
// this.avatar = result.data.checkUser.avatar
// @ts-expect-error
this.routes = result.data.permissions
return {
result,
@ -127,30 +107,20 @@ const useUserStore = defineStore(
// 退出登录事件
logout() {
const usePermissionStore = permissionStore()
console.log(usePermissionStore)
// console.log(usePermissionStore)
// 清除token
REMOVE_TOKEN('TOKEN'),
// ;(this.userName = ''), (this.avatar = '')
// @ts-expect-error
(this.userName = ''),
// @ts-expect-error
(this.avatar = '')
// @ts-expect-error
this.token = ''
// @ts-expect-error
this.routes = ''
usePermissionStore.removeRouter()
location.reload()
},
},
getters: {},
},
{
persist: true, // 持久化
},
)
})
export default useUserStore

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

@ -1,20 +1,45 @@
<template>
<div class="add-or-edit">
<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"
class="demo-ruleForm" :size="formSize" status-icon>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
class="demo-ruleForm"
:size="formSize"
status-icon
>
<el-form-item label="章节" prop="pid">
<el-cascader v-model="activePidArr" :options="options" :props="CascaderProps"
:show-all-levels="false" clearable />
<el-cascader
v-model="activePidArr"
:options="options"
:props="CascaderProps"
:show-all-levels="false"
clearable
/>
</el-form-item>
<el-form-item label="章节名" prop="name">
<el-input v-model="ruleForm.name" style="width: 240px" :placeholder="placeholder" />
<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-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
type="primary"
:loading="loading"
@click="submitForm(ruleFormRef)"
>
Create
</el-button>
<el-button @click="resetForm(ruleFormRef)">Reset</el-button>
@ -32,19 +57,31 @@ import { ref, reactive, watch, computed, nextTick } from 'vue'
const props = defineProps(['isD', 'data', 'loading'])
const emits = defineEmits(['update:isD', 'submit'])
const isDrawer = ref(props.isD)
watch(() => props.isD, newVal => isDrawer.value = newVal)
watch(() => isDrawer.value, newVal => emits('update:isD', newVal))
watch(
() => props.isD,
(newVal) => (isDrawer.value = newVal),
)
watch(
() => isDrawer.value,
(newVal) => emits('update:isD', newVal),
)
const type = false
const options = computed(() => {
if (type) {
const arr = props.data.map((item: any, i: number) => {
const obj = { ...item }
if (item.chapterSection) obj.chapterSection = item.chapterSection.map((chap: any) => ({ ...chap, disabled: true }))
if (item.chapterSection)
obj.chapterSection = item.chapterSection.map((chap: any) => ({
...chap,
disabled: true,
}))
else obj.chapterSection = []
obj.chapterSection.push({ name: `${i + 1}章第${comNum(item.chapterSection?.length)}`, pid: item.id })
obj.chapterSection.push({
name: `${i + 1}章第${comNum(item.chapterSection?.length)}`,
pid: item.id,
})
return obj
})
arr.push({ name: `${arr.length + 1}`, pid: '' })
@ -56,10 +93,9 @@ const CascaderProps = {
checkStrictly: !type,
label: 'name',
value: type ? 'pid' : 'id',
children: 'chapterSection'
children: 'chapterSection',
}
import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
interface RuleForm {
@ -89,47 +125,47 @@ const ruleFormRef = ref<FormInstance>()
let o
if (type) {
o = {
"content": "",
"courseid": "",
"courseobjectivesid": "",
"createBy": "",
"createTime": "",
"id": "",
"name": "",
"num": 0,
"numshow": "",
"onlinclasshours": "",
"pid": undefined,
"requirement": "",
"sysOrgCode": "",
"totalclasshours": "",
"updateBy": "",
"updateTime": "",
"zc": "",
"ziyuan": "",
"zywj": ""
content: '',
courseid: '',
courseobjectivesid: '',
createBy: '',
createTime: '',
id: '',
name: '',
num: 0,
numshow: '',
onlinclasshours: '',
pid: undefined,
requirement: '',
sysOrgCode: '',
totalclasshours: '',
updateBy: '',
updateTime: '',
zc: '',
ziyuan: '',
zywj: '',
}
}else{
} else {
o = {
"content": "",
"courseid": "",
"courseobjectivesid": "",
"createBy": "",
"createTime": "",
"id": undefined,
"name": "111",
"num": 0,
"numshow": "",
"onlinclasshours": "",
"pid": "",
"requirement": "",
"sysOrgCode": "",
"totalclasshours": "",
"updateBy": "",
"updateTime": "",
"zc": "",
"ziyuan": "",
"zywj": ""
content: '',
courseid: '',
courseobjectivesid: '',
createBy: '',
createTime: '',
id: undefined,
name: '111',
num: 0,
numshow: '',
onlinclasshours: '',
pid: '',
requirement: '',
sysOrgCode: '',
totalclasshours: '',
updateBy: '',
updateTime: '',
zc: '',
ziyuan: '',
zywj: '',
}
}
let pxObj
@ -139,7 +175,7 @@ else {
get(target, key) {
if (key === 'pid') return target.id
// @ts-ignore
return target[key];
return target[key]
},
set: function (obj, prop, value) {
if (prop === 'pid') {
@ -149,8 +185,8 @@ else {
// @ts-ignore
obj[prop] = value
return true;
}
return true
},
})
}
// @ts-ignore
@ -163,15 +199,14 @@ const validateChapterOrSection = (rule, value, callback) => {
if (!value && value !== '') {
if (type) callback(new Error('请选择新增的章或节'))
else callback(new Error('请选择编辑的章或节'))
}
else callback()
} else callback()
})
};
}
//
const rules = reactive<FormRules<RuleForm>>({
pid: [
{ required: true, validator: validateChapterOrSection, trigger: 'change' },
]
],
})
const submitForm = async (formEl: FormInstance | undefined) => {
@ -179,7 +214,7 @@ const submitForm = async (formEl: FormInstance | undefined) => {
await formEl.validate((valid, fields) => {
if (valid) {
console.log(options.value, '1')
console.log(ruleForm);
console.log(ruleForm)
// emits('submit', ruleForm)
} else {
@ -194,20 +229,25 @@ const resetForm = (formEl: FormInstance | undefined) => {
activePidArr.value = undefined
}
const placeholder = ref('请输入章节名')
watch(() => ruleForm.pid, newVal => {
watch(
() => ruleForm.pid,
(newVal) => {
if (newVal === undefined) placeholder.value = '请输入章节名'
else if (newVal === '') placeholder.value = '请输入章名'
else placeholder.value = '请输入节名'
})
},
)
const activePidArr = ref<string[] | undefined>([])
watch(() => activePidArr.value, newVal => {// pid
watch(
() => activePidArr.value,
(newVal) => {
// pid
if (newVal === undefined) {
ruleForm.pid = undefined
return
}
ruleForm.pid = newVal.slice(-1)[0]
})
},
)
</script>
<style lang="scss"></style>

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

@ -1,20 +1,45 @@
<template>
<div class="add-or-edit">
<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"
class="demo-ruleForm" :size="formSize" status-icon>
<el-form
ref="ruleFormRef"
style="max-width: 600px"
:model="ruleForm"
:rules="rules"
label-width="auto"
class="demo-ruleForm"
:size="formSize"
status-icon
>
<el-form-item label="章节" prop="id">
<el-cascader v-model="activeIdArr" :options="options1" :props="CascaderProps"
:show-all-levels="false" clearable />
<el-cascader
v-model="activeIdArr"
:options="options1"
:props="CascaderProps"
:show-all-levels="false"
clearable
/>
</el-form-item>
<el-form-item label="章节名" prop="name">
<el-input v-model="ruleForm.name" style="width: 240px" :placeholder="placeholder" />
<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-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
type="primary"
:loading="loading"
@click="submitForm(ruleFormRef)"
>
提交
</el-button>
<el-button @click="resetForm(ruleFormRef)">重置</el-button>
@ -28,24 +53,28 @@ import { ref, reactive, watch, computed } from 'vue'
const props = defineProps(['isD', 'data', 'editData'])
const emits = defineEmits(['update:isD', 'submit'])
const loading = ref(false)
const updLoading = (boo:boolean) => loading.value = boo
const updLoading = (boo: boolean) => (loading.value = boo)
const isDrawer = ref(props.isD)
watch(() => props.isD, newVal => isDrawer.value = newVal)
watch(() => isDrawer.value, newVal => emits('update:isD', newVal))
watch(
() => props.isD,
(newVal) => (isDrawer.value = newVal),
)
watch(
() => isDrawer.value,
(newVal) => emits('update:isD', newVal),
)
const options1 = computed(() => props.data)
const CascaderProps = {
checkStrictly: true,
label: 'name',
value: 'id',
children: 'chapterSection'
children: 'chapterSection',
}
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 {
content: string
@ -75,16 +104,14 @@ const ruleForm = reactive<RuleForm>({ ...props.editData })
//
const rules = reactive<FormRules<RuleForm>>({
id: [
{ required: true, message: '请选择要更新的章节', trigger: 'change' },
]
id: [{ required: true, message: '请选择要更新的章节', trigger: 'change' }],
})
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
emits('submit', ruleForm,updLoading)
emits('submit', ruleForm, updLoading)
} else {
console.log('error submit!', fields)
}
@ -97,23 +124,32 @@ const resetForm = (formEl: FormInstance | undefined) => {
activeIdArr.value = getCheckedChapter(options1.value)
}
watch(() => ruleForm.id, newVal => {
const obj =getCheckedChapterObj(options1.value,newVal)
watch(
() => ruleForm.id,
(newVal) => {
const obj = getCheckedChapterObj(options1.value, newVal)
// const arr = getCheckedChapter(options1.value)
// let obj
// 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])
if (obj) Object.assign(ruleForm, obj)
})
},
)
const placeholder = ref('请输入章节名')
watch(() => ruleForm.pid, newVal => {
watch(
() => ruleForm.pid,
(newVal) => {
if (newVal === '') placeholder.value = '请输入章名'
else placeholder.value = '请输入节名'
},{immediate:true})
},
{ immediate: true },
)
// id
function getCheckedChapter(array: any) {
let i = 0, arr: any[] = [], f: any
(function fn(array: any) {
let i = 0,
arr: any[] = [],
f: any
;(function fn(array: any) {
if (!isArray(array)) return
const ch = array.find((item: any) => item.id === ruleForm.id)
if (ch === undefined && i < array.length) {
@ -123,13 +159,14 @@ function getCheckedChapter(array: any) {
if (ch === undefined) return
if (f) arr.push(f)
arr.push(ch.id)
}(array))
})(array)
return arr
}
//
function getCheckedChapterObj(array: any,id:any) {
let i = 0, arr: any[] = [];
(function fn(array: any) {
function getCheckedChapterObj(array: any, id: any) {
let i = 0,
arr: any[] = []
;(function fn(array: any) {
if (!isArray(array)) return
const ch = array.find((item: any) => item.id === id)
if (ch === undefined && i < array.length) {
@ -137,19 +174,21 @@ function getCheckedChapterObj(array: any,id:any) {
}
if (ch === undefined) return
arr.push(ch)
}(array))
})(array)
return arr[0]
}
const activeIdArr = ref<string[] | undefined>(getCheckedChapter(options1.value))
watch(() => activeIdArr.value, newVal => {// id
watch(
() => activeIdArr.value,
(newVal) => {
// id
if (newVal === undefined) {
ruleForm.id = undefined
return
}
ruleForm.id = newVal.slice(-1)[0]
})
},
)
</script>
<style lang="scss"></style>

@ -16,17 +16,31 @@
</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" />
<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="">
<img src="" alt="" />
</div>
<div class="bottom-container radius-10">
<!-- 查看资源 -->
@ -35,16 +49,31 @@
</div>
</div>
</div>
</template>
<script lang='ts' setup>
import { getLearnInfoApi, getOrogramObjectiveApi } from '@/api/courseChaptersApi'
import { getChapterApi, deleteSectionApi, addChapterApi, updateChapterApi } from '@/api/sectionApi'
import { theoryUi, objectiveUi, atlasUi, lookResourceUi, foldInfoUi, FoldAdd, FoldEdit } from './components/KnowledgeGraphUi/index'
<script lang="ts" setup>
import {
getLearnInfoApi,
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 { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus';
import { ElMessage } from 'element-plus'
const $router = useRouter()
@ -53,12 +82,12 @@ const handle = () => $router.push('/knowledgeAtlas')
// theory-ui
const learnInfo: object[] = reactive([])
getLearnInfoApi().then(res => learnInfo.push(...res as object[]))
getLearnInfoApi().then((res) => learnInfo.push(...(res as object[])))
// getByIdCourseVoApi('2fa0fd63262230639d2c45a3acd9045c')
// objective-ui
const orogramObjective: any = reactive({})
getOrogramObjectiveApi().then(res => Object.assign(orogramObjective, res))
getOrogramObjectiveApi().then((res) => Object.assign(orogramObjective, res))
// look-resource-ui
const lookResource: any = reactive({})
@ -66,7 +95,7 @@ const lookResource: any = reactive({})
// fold-info-ui
const foldInfoData: any = reactive([])
function getFold() {
getChapterApi('2fa0fd63262230639d2c45a3acd9045c').then(res => {
getChapterApi('2fa0fd63262230639d2c45a3acd9045c').then((res) => {
foldInfoData.length = 0
foldInfoData.push(...res.data)
})
@ -76,36 +105,42 @@ getFold()
const showHide = ref(false)
function foldAddSubmit(data: any, updLoading: Function) {
updLoading(true)
addChapterApi(data).then(() => {
addChapterApi(data)
.then(() => {
ElMessage({
message: `添加${data.pid === '' ? '章' : '节'}成功`,
type: 'success'
type: 'success',
})
showHide.value = false
getFold()
}).catch(() => {
})
.catch(() => {
ElMessage({
message: `添加${data.pid === '' ? '章' : '节'}失败`,
type: 'error'
type: 'error',
})
}).finally(() => updLoading(false))
})
.finally(() => updLoading(false))
}
//
const foldDelLoading = ref(false)
function flodDel(id: string) {
foldDelLoading.value = true
deleteSectionApi(id).then(() => {
deleteSectionApi(id)
.then(() => {
ElMessage({
message: `删除成功`,
type: 'success'
type: 'success',
})
getFold()
}).catch(() => {
})
.catch(() => {
ElMessage({
message: `删除失败`,
type: 'error'
type: 'error',
})
}).finally(() => foldDelLoading.value = false)
})
.finally(() => (foldDelLoading.value = false))
}
//
const showHide1 = ref(false)
@ -116,35 +151,37 @@ function hanEdit(data: any) {
}
function foldEditSubmit(data: any, updLoading: Function) {
updLoading(true)
updateChapterApi(data).then(() => {
updateChapterApi(data)
.then(() => {
ElMessage({
message: `更新${data.pid === '' ? '章' : '节'}成功`,
type: 'success'
type: 'success',
})
showHide1.value = false
getFold()
}).catch(() => {
})
.catch(() => {
ElMessage({
message: `更新${data.pid === '' ? '章' : '节'}失败`,
type: 'error'
type: 'error',
})
})
}).finally(() => updLoading(false))
.finally(() => updLoading(false))
}
</script>
<style lang='scss' scoped>
<style lang="scss" scoped>
.course-chapters {
width: 100%;
height: 100%;
position: relative;
background: #F2F7FB;
background: #f2f7fb;
&,
* {
box-sizing: border-box;
}
.radius-10 {
border-radius: 10px;
overflow: hidden;
@ -159,7 +196,7 @@ function foldEditSubmit(data: any, updLoading: Function) {
position: absolute;
height: 100%;
width: 12px;
background-color: #2147FB;
background-color: #2147fb;
}
}
@ -217,6 +254,5 @@ function foldEditSubmit(data: any, updLoading: Function) {
}
}
}
}
</style>

@ -25,7 +25,7 @@ function handleClick() {
.info_title {
display: flex;
justify-content: space-between;
align-items: center;
width: 98%;
.title_name {
font-family: Inter, Inter;
font-weight: 400;
@ -46,19 +46,4 @@ function handleClick() {
justify-content: 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>

@ -1,72 +1,72 @@
<script setup>
import ellipsis from '@/assets/images/ellipsis.png'
import conheader from '@/views/home/components/ConHeader.vue'
import { ref, computed } from 'vue'
import { userIdenChangeService } from '@/api/user/user.js'
import { ElMessage } from 'element-plus'
import InfoContainer from './infoContainer/index.vue'
import myDrawer from './myDrawer/index.vue'
const props = defineProps({
data: {
type: Object,
},
})
// ============== formModel
const formModel = ref()
switch (+props.data.roleId[0]) {
case 1:
formModel.value = [
{ par: 'name', name: '姓名', content: props.data.name },
{ par: 'sex', name: '性别', content: props.data.sex },
{ par: 'nationality', name: '民族', content: props.data.nationality },
{ par: 'profession', name: '专业', content: props.data.profession },
{ par: 'education', name: '学历', content: props.data.education },
{
par: 'academicDegree',
name: '学位',
content: props.data.academicDegree,
},
{
par: 'professionalTitle',
name: '职称',
content: props.data.professionalTitle,
},
{
par: 'emergencyContact',
name: '手机号',
content: props.data.emergencyContact,
},
{
par: 'joinWorkTime',
name: '参加工作时间',
content: props.data.joinWorkTime,
},
{
par: 'politicalStatus',
name: '政治面貌',
content: props.data.politicalStatus,
},
]
break
case 2:
formModel.value = [
{ par: 'name', name: '姓名', content: props.data.name },
{ par: 'sex', name: '性别', content: props.data.sex },
{ par: 'nationality', name: '民族', content: props.data.nationality },
{ par: 'number', name: '学号', content: props.data.number },
{ par: 'birthday', name: '生日', content: props.data.birthday },
{ par: 'phone', name: '手机号', content: props.data.phone },
{ par: 'faculty', name: '院系', content: props.data.faculty },
{ par: 'major', name: '专业', content: props.data.major },
{ par: 'yearAge', name: '入学年份', content: props.data.yearAge },
{ par: 'className', name: '班级', content: props.data.className },
]
break
}
// ==============
// import ellipsis from '@/assets/images/ellipsis.png'
// import conheader from '@/views/home/components/ConHeader.vue'
// import { ref, computed } from 'vue'
// import { userIdenChangeService } from '@/api/user/user.js'
// import { ElMessage } from 'element-plus'
// import InfoContainer from './infoContainer/index.vue'
// import myDrawer from './myDrawer/index.vue'
// const props = defineProps({
// data: {
// type: Object,
// },
// })
// // ============== formModel
// const formModel = ref()
// switch (+props.data.roleId[0]) {
// case 1:
// formModel.value = [
// { par: 'name', name: '', content: props.data.name },
// { par: 'sex', name: '', content: props.data.sex },
// { par: 'nationality', name: '', content: props.data.nationality },
// { par: 'profession', name: '', content: props.data.profession },
// { par: 'education', name: '', content: props.data.education },
// {
// par: 'academicDegree',
// name: '',
// content: props.data.academicDegree,
// },
// {
// par: 'professionalTitle',
// name: '',
// content: props.data.professionalTitle,
// },
// {
// par: 'emergencyContact',
// name: '',
// content: props.data.emergencyContact,
// },
// {
// par: 'joinWorkTime',
// name: '',
// content: props.data.joinWorkTime,
// },
// {
// par: 'politicalStatus',
// name: '',
// content: props.data.politicalStatus,
// },
// ]
// break
// case 2:
// formModel.value = [
// { par: 'name', name: '', content: props.data.name },
// { par: 'sex', name: '', content: props.data.sex },
// { par: 'nationality', name: '', content: props.data.nationality },
// { par: 'number', name: '', content: props.data.number },
// { par: 'birthday', name: '', content: props.data.birthday },
// { par: 'phone', name: '', content: props.data.phone },
// { par: 'faculty', name: '', content: props.data.faculty },
// { par: 'major', name: '', content: props.data.major },
// { par: 'yearAge', name: '', content: props.data.yearAge },
// { par: 'className', name: '', content: props.data.className },
// ]
// break
// }
// // ==============
// 1
const drawer2 = ref(false)
// // 1
// const drawer2 = ref(false)
</script>
<template>
<div class="info_container" style="width: 95%; height: 306px">
@ -76,8 +76,8 @@ const drawer2 = ref(false)
<img :src="ellipsis" @click="drawer2 = true" />
</div>
</div>
<InfoContainer :data="formModel"></InfoContainer>
<myDrawer v-model:drawer="drawer2" :data="formModel"></myDrawer>
<!-- <InfoContainer :data="formModel"></InfoContainer>
<myDrawer v-model:drawer="drawer2" :data="formModel"></myDrawer> -->
</div>
</template>
<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>
import add from '@/assets/images/add.png'
// import { Plus } from '@element-plus/icons-vue'
import tool from '@/utils/oss.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 { error } from 'echarts/types/src/util/log.js'
const props = defineProps({
data: {
type: Object,
},
userData: {
type: Object,
},
})
const imageUrl = ref('')
const dialogFormVisible = ref(false)
//
// 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'
console.log(props.userData, 'props.infoData')
const imageUrl = ref()
//
imageUrl.value = props.data.icon
//
@ -50,77 +23,99 @@ const upload = async (option) => {
const res = await tool.oss.upload(option.file)
const url = 'https://wenyu132.oss-cn-beijing.aliyuncs.com/' + res.name
imageUrl.value = url
changeInfo()
}
const openInfo = () => {
dialogFormVisible.value = true
}
//
const emit = defineEmits(['get-message'])
//
const emit = defineEmits(['get-avater'])
let isUploading = ref(false)
const changeInfo = async () => {
if (!isUploading.value) {
isUploading.value = true
const userInfo = {
phone: form.value.phone,
id: form.value.id,
nickName: form.value.nickName,
id: props.data.id,
icon: imageUrl.value,
}
const jsonData = JSON.stringify(userInfo)
await userChangeService(jsonData).then(() => {
ElMessage.success('修改成功')
console.log(form.value.nickName, 'nickN')
emit('get-message', form.value.nickName)
emit('get-avater', imageUrl.value)
})
dialogFormVisible.value = false
}
const cancleInfo = () => {
dialogFormVisible.value = false
form.value = {
...props.data,
isUploading.value = false
}
}
// onMounted(() => {
// console.log(props.data.icon, 'props.icon')
// })
//
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>
<template>
<div class="ident" style="width: 100%; height: 274px; background: #375fff">
<div class="info_container" style="width: 201px; height: 178px">
<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>
<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" />
</el-upload>
<div class="info_content" style="height: 58px" @click="openInfo">
<div class="name">{{ props.data.username }}</div>
<!-- <div class="na">{{ props.data.professionalTitle }}</div> -->
</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-drawer v-model="dialog" title="个人信息" class="demo-drawer">
<div class="content">
<el-form :model="form">
<el-form-item label="姓名" :label-width="formLabelWidth">
<el-input v-model="form.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="性别" :label-width="formLabelWidth">
<el-radio-group v-model="radio">
<el-radio :value="3"></el-radio>
<el-radio :value="6"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="昵称" :label-width="formLabelWidth">
<el-input v-model="form.nickName" autocomplete="off" />
<el-form-item label="民族" :label-width="formLabelWidth">
<el-input v-model="form.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="手机" :label-width="formLabelWidth">
<el-input v-model="form.phone" autocomplete="off" />
<el-form-item label="手机" :label-width="formLabelWidth">
<el-input v-model="form.phone" autocomplete="off"></el-input>
</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 class="footer">
<el-button @click="onCancel">取消</el-button>
<el-button type="primary" :loading="loading" @click="onsubmit">
确认
</el-button>
</div>
</template>
</el-dialog>
</div>
</el-drawer>
</template>
<style scoped>
.el-form-item {
display: flex;
}
.ident {
background: #ffffff;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);

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

@ -1,5 +1,14 @@
<script setup>
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({
name: {
type: String,
@ -11,6 +20,109 @@ const props = defineProps({
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(() => {
if (props.userData.nickName) {
@ -19,19 +131,24 @@ const username = computed(() => {
return props.userData.username
}
})
//
const daysOnJob = ref()
const flagVisible = ref(true)
//
const currentDate = new Date()
const formattedDate = dayjs(currentDate).format('YYYY-MM-DD')
onMounted(() => {
console.log(props.name, 'name')
console.log(props.data.nickName === props.name, 'sdf')
username.value = props.data.name
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
daysOnJob.value = Math.floor((currentDate - hireDate) / millisecondsPerDay)
})
//
</script>
<template>
<div class="nav_info">
@ -44,14 +161,71 @@ onMounted(() => {
<div class="intro" v-else>
<p>Hell0,欢迎回来</p>
</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>
<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>
<style scoped>
.nav_info {
width: 95%;
height: 32px;
display: flex;
justify-content: start;
justify-content: space-between;
align-items: center;
}
.name {
@ -67,7 +241,7 @@ onMounted(() => {
margin-right: 68px;
}
.intro {
width: 50%;
width: 60%;
height: 22px;
font-family: Inter, Inter;
font-weight: bold;
@ -78,4 +252,7 @@ onMounted(() => {
font-style: normal;
text-transform: none;
}
.time {
justify-content: end;
}
</style>

@ -1,13 +1,17 @@
<script lang="ts" setup>
import status from '@/views/home/components/Status.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 Class1 from './components/Class1.vue'
import lessonlist from './components/Lessonlist.vue'
// import Class1 from './components/Class1.vue'
import Student1 from './components/Student1.vue'
import Class2 from './components/Class2.vue'
import Student2 from './components/Student2.vue'
// import Class2 from './components/Class2.vue'
// import Student2 from './components/Student2.vue'
import { userNewLikeService } from '@/api/user/user'
import useUserStore from '@/store/modules/user'
import fe from '@/assets/images/fe.jpg'
import { ref, onMounted } from 'vue'
const userStore = useUserStore()
const username = ref()
@ -19,23 +23,30 @@ const rightVisible = ref(false)
userStore.getUserInfo().catch((error) => {
console.log(error)
})
let sum: any = localStorage.getItem('sum') || '0'
const name = ref()
const getMessage = (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(() => {
// getData()
sum = parseInt(sum) + 1
localStorage.setItem('sum', sum.toString())
console.log(sum, 'sum')
// console.log(sum, 'sum')
username.value = userStore.userName
data.value = userStore.data
infoData.value = userStore.userInfo
// 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
flag.value = true
role.value = data.value.roles[0]
@ -44,11 +55,136 @@ onMounted(() => {
} else {
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>
<template>
<div class="container">
<div class="left">
<el-row>
<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">
<welcome
:data="infoData"
@ -81,22 +217,10 @@ onMounted(() => {
<div class="stu" style="width: 100%; height: 236px">
<Student2></Student2>
</div>
</div>
</div>
</div> -->
</template>
<style lang="scss" scoped>
.container {
display: flex;
width: 100%;
.left {
width: 80%;
height: 936px;
margin-right: 16px;
display: grid;
grid-template-rows: 1fr 1fr 1fr; /* 使用fr单位来平均分布 */
height: 300px; /* 设置容器高度 */
.nav {
width: 100%;
.nav {
height: 92px;
background: #ffffff;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
@ -106,62 +230,188 @@ onMounted(() => {
flex-direction: column; //
justify-content: center;
align-items: center;
}
.info,
.echarts {
}
.classList,
.info {
height: 270px;
background: #ffffff;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
border-radius: 6px 6px 6px 6px;
justify-content: space-between;
margin-bottom: 16px;
}
.classList {
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;
}
.lesson {
margin-bottom: 16px;
height: 280px;
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;
// justify-content: center;
align-items: center;
// margin: 0 auto;
flex-wrap: wrap;
// flex-direction: column;
.button {
margin-top: 10px;
height: 30px;
border-radius: 10px;
color: #0080ff;
text-align: center;
line-height: 30px;
margin: 0 10px;
border: 2px solid #ccc;
}
a {
text-decoration: none;
}
.right {
width: 20%;
height: 930px;
display: flex;
flex-direction: column; //
justify-content: space-between;
.ident,
.class,
.stu {
}
.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;
// flex-direction: column; //
justify-content: center;
align-items: center;
.info_container {
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;
flex-direction: column; //
justify-content: space-between;
.info_content {
}
.lesson_container {
display: flex;
flex-direction: column; //
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>

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

@ -1,30 +1,5 @@
<template>
<div>
<!-- Dialog组件 -->
<Dialog
v-model="dialogVisible"
@confirm="collectData"
:name="readonlyName"
:age="readonlyAge"
/>
</div>
<div>学生</div>
</template>
<script setup>
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>
<style lang="scss"></style>

@ -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