Compare commits

...

5 Commits

  1. 18
      src/api/courseChaptersApi.ts
  2. 28
      src/api/user/user.js
  3. BIN
      src/assets/images/default.png
  4. BIN
      src/assets/images/fe.jpg
  5. 32
      src/layout/tabbar/setting/index.vue
  6. 3
      src/setting.ts
  7. 6
      src/store/index.ts
  8. 97
      src/store/modules/user.ts
  9. 1
      src/views/course/CourseObjectives.vue
  10. 172
      src/views/course/components/KnowledgeGraphUi/AddOrEdit copy.vue
  11. 150
      src/views/course/components/KnowledgeGraphUi/FoldAdd.vue
  12. 101
      src/views/course/components/KnowledgeGraphUi/FoldEdit.vue
  13. 80
      src/views/course/components/KnowledgeGraphUi/foldInfoUi.vue
  14. 234
      src/views/course/courseChapters.vue
  15. 42
      src/views/home/components/ConHeader.vue
  16. 41
      src/views/home/components/Echart/Echarts.vue
  17. 48
      src/views/home/components/Echarts.vue
  18. 287
      src/views/home/components/Info keep.vue
  19. 156
      src/views/home/components/Info.vue
  20. 102
      src/views/home/components/Lessonlist.vue
  21. 205
      src/views/home/components/Status.vue
  22. 137
      src/views/home/components/Student1.vue
  23. 97
      src/views/home/components/Student2.vue
  24. 239
      src/views/home/components/Welcome.vue
  25. 47
      src/views/home/components/infoContainer/index.vue
  26. 120
      src/views/home/components/myDrawer/index.vue
  27. 304
      src/views/home/index.vue
  28. 22
      src/views/login/index.vue
  29. 257
      src/views/student/index.vue
  30. 68
      src/views/student/login.vue

@ -96,7 +96,25 @@ 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,
method: 'get',
// // params
// =======
// <<<<<<< HEAD
// url: '/api/objective_contents/' + params.id,
// method: 'get',
// params,
// =======
// url: '/objective_contents/' + params.id,
// method: "get",
// // params
// >>>>>>> 1a620e19de970965f426e07348b1dbc4be900eaf
// >>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a
=======
url: '/api/objective_contents/' + params.id, url: '/api/objective_contents/' + params.id,
// method: 'get', // method: 'get',
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
}) })
} }

@ -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,30 @@ 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)
}
//获取学生列表
export const userStudentListService = (id) => {
return request.post('/api/coursesteacher/studentList?userId=' + id)
}
//获取课程列表
// export const userLessonListService = (id) => {
// return request.post('/api/coursesteacher/studentList?userId=' + id)
// }
//获取浏览量
export const userLookService = () => {
return request.get('/api/report/receptionBrowse')
}
//获取图表
export const userPicService = () => {
return request.get('/api/report/browseStatistics')
}

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>

@ -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,11 +19,8 @@ import {
userIdenService, userIdenService,
} from '@/api/user/user.js' } from '@/api/user/user.js'
const useUserStore = defineStore( const useUserStore = defineStore('User', {
'User',
{
// @ts-expect-error // @ts-expect-error
state: (): LoginStoreType => { state: (): LoginStoreType => {
return { return {
token: GET_TKOEN('TOKEN') || '', token: GET_TKOEN('TOKEN') || '',
@ -44,8 +39,88 @@ const useUserStore = defineStore(
// console.log(data, 'pinia') // console.log(data, 'pinia')
const res: any = await userLoginService(data).catch((error) => { const res: any = await userLoginService(data).catch((error) => {
ElMessage.error(error.response.data.message) ElMessage.error(error.response.data.message)
console.log(error, 'error') // 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))
}
},
//手机号登录
async userPhoneLogin(data: loginType) {
const res: any = await userPhoneLoginService(data)
// console.log(res, 11111)
if (res.code === 200) {
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()}!`,
})
<<<<<<< HEAD
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) {
console.log(result, 'result')
const res = await userIdenService(result.data.id)
// console.log(res, 'res')
this.userInfo = res.data
// console.log(this.userInfo, 'this.userInfo')
this.data = result.data
// console.log(result, '123')
this.userName = result.data.username
// this.avatar = result.data.checkUser.avatar
this.routes = result.data.permissions
return {
result,
}
} else {
return Promise.reject('登录过期')
}
},
// 退出登录事件
logout() {
const usePermissionStore = permissionStore()
// console.log(usePermissionStore)
// 清除token
REMOVE_TOKEN('TOKEN'),
// ;(this.userName = ''), (this.avatar = '')
// @ts-expect-error
(this.userName = ''),
// @ts-expect-error
(this.avatar = '')
this.token = ''
this.routes = ''
usePermissionStore.removeRouter()
location.reload()
=======
if (res.code === 200) { if (res.code === 200) {
// @ts-expect-error // @ts-expect-error
@ -147,11 +222,9 @@ const useUserStore = defineStore(
usePermissionStore.removeRouter() usePermissionStore.removeRouter()
location.reload() location.reload()
}, },
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
}, },
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: '课程目标一',

@ -1,20 +1,45 @@
<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"
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-form-item label="章节" prop="pid">
<el-cascader v-model="activePidArr" :options="options" :props="CascaderProps" <el-cascader
:show-all-levels="false" clearable /> v-model="activePidArr"
:options="options"
:props="CascaderProps"
:show-all-levels="false"
clearable
/>
</el-form-item> </el-form-item>
<el-form-item label="章节名" prop="name"> <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>
<el-form-item label="总学时" prop="totalclasshours"> <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-form-item> <el-form-item>
<el-button type="primary" :loading="loading" @click="submitForm(ruleFormRef)"> <el-button
type="primary"
:loading="loading"
@click="submitForm(ruleFormRef)"
>
Create Create
</el-button> </el-button>
<el-button @click="resetForm(ruleFormRef)">Reset</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 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)
obj.chapterSection = item.chapterSection.map((chap: any) => ({
...chap,
disabled: true,
}))
else obj.chapterSection = [] 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 return obj
}) })
arr.push({ name: `${arr.length + 1}`, pid: '' }) arr.push({ name: `${arr.length + 1}`, pid: '' })
@ -56,10 +93,9 @@ 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 {
@ -89,47 +125,47 @@ 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
@ -139,7 +175,7 @@ else {
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') {
@ -149,8 +185,8 @@ else {
// @ts-ignore // @ts-ignore
obj[prop] = value obj[prop] = value
return true; return true
} },
}) })
} }
// @ts-ignore // @ts-ignore
@ -163,15 +199,14 @@ const validateChapterOrSection = (rule, value, callback) => {
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) => {
@ -179,7 +214,7 @@ const submitForm = async (formEl: FormInstance | undefined) => {
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 {
@ -194,20 +229,25 @@ const resetForm = (formEl: FormInstance | undefined) => {
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,4 +1,54 @@
<template> <template>
<<<<<<< HEAD
<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-item label="章节" prop="pid">
<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-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>
=======
<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 ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" :rules="rules" label-width="auto"
@ -22,6 +72,7 @@
</el-form> </el-form>
</el-drawer> </el-drawer>
</div> </div>
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
function comNum(n: number | undefined) { function comNum(n: number | undefined) {
@ -36,6 +87,28 @@ const updLoading = (boo: boolean) => (loading.value = boo)
const isDrawer = ref(props.isD) const isDrawer = ref(props.isD)
watch( watch(
<<<<<<< HEAD
() => 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,
}))
else obj.chapterSection = []
obj.chapterSection.push({
name: `${i + 1}章第${comNum(item.chapterSection?.length)}`,
pid: item.id,
=======
() => props.isD, () => props.isD,
(newVal) => (isDrawer.value = newVal), (newVal) => (isDrawer.value = newVal),
) )
@ -58,14 +131,23 @@ const options1 = computed(() => {
pid: item.id, pid: item.id,
}) })
return obj return obj
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
})
return obj
}) })
arr.push({ name: `${arr.length + 1}`, pid: '' }) arr.push({ name: `${arr.length + 1}`, pid: '' })
return arr return arr
}) })
const CascaderProps = { const CascaderProps = {
<<<<<<< HEAD
label: 'name',
value: 'pid',
children: 'chapterSection',
=======
label: 'name', label: 'name',
value: 'pid', value: 'pid',
children: 'chapterSection', children: 'chapterSection',
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
} }
import type { ComponentSize, FormInstance, FormRules } from 'element-plus' import type { ComponentSize, FormInstance, FormRules } from 'element-plus'
@ -95,6 +177,7 @@ interface RuleForm {
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>({
<<<<<<< HEAD
content: '', content: '',
courseid: '2fa0fd63262230639d2c45a3acd9045c', courseid: '2fa0fd63262230639d2c45a3acd9045c',
courseobjectivesid: '', courseobjectivesid: '',
@ -139,6 +222,52 @@ const submitForm = async (formEl: FormInstance | undefined) => {
console.log('error submit!', fields) console.log('error submit!', fields)
} }
}) })
=======
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
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)
} else {
console.log('error submit!', fields)
}
})
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
} }
const resetForm = (formEl: FormInstance | undefined) => { const resetForm = (formEl: FormInstance | undefined) => {
@ -148,6 +277,26 @@ const resetForm = (formEl: FormInstance | undefined) => {
} }
const placeholder = ref('请输入章节名') const placeholder = ref('请输入章节名')
watch( watch(
<<<<<<< HEAD
() => 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
if (newVal === undefined) {
ruleForm.pid = undefined
return
}
ruleForm.pid = newVal.slice(-1)[0]
},
=======
() => ruleForm.pid, () => ruleForm.pid,
(newVal) => { (newVal) => {
if (newVal === undefined) placeholder.value = '请输入章节名' if (newVal === undefined) placeholder.value = '请输入章节名'
@ -166,6 +315,7 @@ watch(
} }
ruleForm.pid = newVal.slice(-1)[0] ruleForm.pid = newVal.slice(-1)[0]
}, },
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
) )
</script> </script>
<style lang="scss"></style> <style lang="scss"></style>

@ -1,20 +1,45 @@
<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"
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-form-item label="章节" prop="id">
<el-cascader v-model="activeIdArr" :options="options1" :props="CascaderProps" <el-cascader
:show-all-levels="false" clearable /> v-model="activeIdArr"
:options="options1"
:props="CascaderProps"
:show-all-levels="false"
clearable
/>
</el-form-item> </el-form-item>
<el-form-item label="章节名" prop="name"> <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>
<el-form-item label="总学时" prop="totalclasshours"> <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-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>
<el-button @click="resetForm(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 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
@ -75,9 +104,7 @@ 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) => {
@ -97,23 +124,32 @@ const resetForm = (formEl: FormInstance | undefined) => {
activeIdArr.value = getCheckedChapter(options1.value) activeIdArr.value = getCheckedChapter(options1.value)
} }
watch(() => ruleForm.id, newVal => { watch(
() => ruleForm.id,
(newVal) => {
const obj = getCheckedChapterObj(options1.value, 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[] = [],
f: any
;(function fn(array: any) {
if (!isArray(array)) return if (!isArray(array)) return
const ch = array.find((item: any) => item.id === ruleForm.id) const ch = array.find((item: any) => item.id === ruleForm.id)
if (ch === undefined && i < array.length) { if (ch === undefined && i < array.length) {
@ -123,13 +159,14 @@ function getCheckedChapter(array: any) {
if (ch === undefined) return if (ch === undefined) return
if (f) arr.push(f) if (f) arr.push(f)
arr.push(ch.id) arr.push(ch.id)
}(array)) })(array)
return arr 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[] = []
;(function fn(array: any) {
if (!isArray(array)) return if (!isArray(array)) return
const ch = array.find((item: any) => item.id === id) const ch = array.find((item: any) => item.id === id)
if (ch === undefined && i < array.length) { if (ch === undefined && i < array.length) {
@ -137,19 +174,21 @@ function getCheckedChapterObj(array: any,id:any) {
} }
if (ch === undefined) return if (ch === undefined) return
arr.push(ch) arr.push(ch)
}(array)) })(array)
return arr[0] 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>

@ -2,7 +2,15 @@
<div class="fold-info-ui"> <div class="fold-info-ui">
<div class="demo-collapse"> <div class="demo-collapse">
<el-collapse class="collapse"> <el-collapse class="collapse">
<<<<<<< HEAD
<button
class="my-button"
style="position: absolute; left: 0; top: 0"
@click.stop="emits('add')"
>
=======
<button class="my-button" style="position: absolute; left: 0; top: 0" @click.stop="emits('add')"> <button class="my-button" style="position: absolute; left: 0; top: 0" @click.stop="emits('add')">
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
新增 新增
</button> </button>
<el-collapse-item v-for="item in foldInfoData" :key="item.id"> <el-collapse-item v-for="item in foldInfoData" :key="item.id">
@ -22,10 +30,26 @@
</div> </div>
<div class="my-tag">本章资源</div> <div class="my-tag">本章资源</div>
</div> </div>
<<<<<<< HEAD
<button
class="my-button"
@click.stop="emits('edit', item)"
style="margin-right: 10px"
>
编辑
</button>
<my-btn
:id="item.id"
type="danger"
class="is-el-button"
style="margin-right: 10px"
>
=======
<button class="my-button" @click.stop="emits('edit', item)" style="margin-right: 10px"> <button class="my-button" @click.stop="emits('edit', item)" style="margin-right: 10px">
编辑 编辑
</button> </button>
<my-btn :id="item.id" type="danger" class="is-el-button" style="margin-right: 10px"> <my-btn :id="item.id" type="danger" class="is-el-button" style="margin-right: 10px">
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
删除 删除
</my-btn> </my-btn>
</div> </div>
@ -39,7 +63,15 @@
<div class="left"></div> <div class="left"></div>
<div class="right"> <div class="right">
<div class="structure-item"> <div class="structure-item">
<<<<<<< HEAD
<div
class="structure-item-titile-box"
v-for="(obj, ind) in item.chapterSection"
:key="item.id"
>
=======
<div class="structure-item-titile-box" v-for="(obj, ind) in item.chapterSection" :key="item.id"> <div class="structure-item-titile-box" v-for="(obj, ind) in item.chapterSection" :key="item.id">
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
<div class="titile-box-titile"> <div class="titile-box-titile">
<div class="sequence">{{ ind + 1 }}</div> <div class="sequence">{{ ind + 1 }}</div>
<div class="tit-box"> <div class="tit-box">
@ -53,10 +85,26 @@
</div> </div>
</div> </div>
<div class="tit-box-edit"> <div class="tit-box-edit">
<<<<<<< HEAD
<button
class="my-button"
@click.stop="emits('edit', obj)"
style="margin-right: 10px"
>
编辑
</button>
<my-btn
:id="obj.id"
type="danger"
class="is-el-button"
style="margin-right: 10px"
>
=======
<button class="my-button" @click.stop="emits('edit', obj)" style="margin-right: 10px"> <button class="my-button" @click.stop="emits('edit', obj)" style="margin-right: 10px">
编辑 编辑
</button> </button>
<my-btn :id="obj.id" type="danger" class="is-el-button" style="margin-right: 10px"> <my-btn :id="obj.id" type="danger" class="is-el-button" style="margin-right: 10px">
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
删除 删除
</my-btn> </my-btn>
</div> </div>
@ -177,7 +225,9 @@ const MyBtn = {
$line: 1px dashed #d9d9d9; $line: 1px dashed #d9d9d9;
.left { .left {
width: calc($title-icon-width + $title--icon-m-r + $title-index-width / 2); width: calc(
$title-icon-width + $title--icon-m-r + $title-index-width / 2
);
border-right: $line; border-right: $line;
} }
@ -258,7 +308,11 @@ const MyBtn = {
gap: 38px; gap: 38px;
flex-wrap: wrap; flex-wrap: wrap;
<<<<<<< HEAD
& > * { & > * {
=======
&>* {
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
border: 1px solid #0052d9; border: 1px solid #0052d9;
font-weight: bold; font-weight: bold;
font-size: 12px; font-size: 12px;
@ -309,6 +363,29 @@ const MyBtn = {
cursor: pointer; cursor: pointer;
&:hover { &:hover {
<<<<<<< HEAD
background: linear-gradient(
128deg,
lighten($color-start, 5%) 0%,
lighten($color-end, 5%) 100%
);
}
&:active {
background: linear-gradient(
128deg,
darken($color-start, 10%) 0%,
darken($color-end, 10%) 100%
);
}
&:disabled {
background: linear-gradient(
128deg,
lighten($color-start, 20%) 0%,
lighten($color-end, 20%) 100%
);
=======
background: linear-gradient(128deg, background: linear-gradient(128deg,
lighten($color-start, 5%) 0%, lighten($color-start, 5%) 0%,
lighten($color-end, 5%) 100%); lighten($color-end, 5%) 100%);
@ -324,6 +401,7 @@ const MyBtn = {
background: linear-gradient(128deg, background: linear-gradient(128deg,
lighten($color-start, 20%) 0%, lighten($color-start, 20%) 0%,
lighten($color-end, 20%) 100%); lighten($color-end, 20%) 100%);
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
} }
} }

@ -1,4 +1,12 @@
<template> <template>
<<<<<<< HEAD
<div class="course-chapters">
<div class="flex-layout">
<div class="flex-left">
<div class="left" ref="atlasCon">
<!-- 知识图谱 -->
<atlas-ui @hadRouter="handle" />
=======
<div class="course-chapters"> <div class="course-chapters">
<div class="flex-layout"> <div class="flex-layout">
<div class="flex-left"> <div class="flex-left">
@ -31,12 +39,77 @@
<look-resource-ui :lookResource="lookResource" /> <look-resource-ui :lookResource="lookResource" />
</div> </div>
</div> </div>
>>>>>>> d7b4e7a9c5db447232028c52d0cc49bb8a28830e
</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>
<<<<<<< HEAD
</div> </div>
=======
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { import {
<<<<<<< HEAD
getLearnInfoApi,
getOrogramObjectiveApi,
} from '@/api/courseChaptersApi'
import {
getChapterApi,
deleteSectionApi,
addChapterApi,
updateChapterApi,
} from '@/api/sectionApi'
import {
theoryUi,
objectiveUi,
atlasUi,
lookResourceUi,
foldInfoUi,
FoldAdd,
FoldEdit,
=======
getLearnInfoApi, getLearnInfoApi,
getOrogramObjectiveApi, getOrogramObjectiveApi,
} from '@/api/courseChaptersApi' } from '@/api/courseChaptersApi'
@ -54,6 +127,7 @@ import {
foldInfoUi, foldInfoUi,
FoldAdd, FoldAdd,
FoldEdit, FoldEdit,
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
} from './components/KnowledgeGraphUi/index' } from './components/KnowledgeGraphUi/index'
import { ref, reactive } from 'vue' import { ref, reactive } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
@ -79,15 +153,69 @@ const lookResource: any = reactive({})
// fold-info-ui // fold-info-ui
const foldInfoData: any = reactive([]) const foldInfoData: any = reactive([])
function getFold() { function getFold() {
<<<<<<< HEAD
getChapterApi('2fa0fd63262230639d2c45a3acd9045c').then((res) => {
foldInfoData.length = 0
foldInfoData.push(...res.data)
})
=======
getChapterApi('2fa0fd63262230639d2c45a3acd9045c').then((res) => { getChapterApi('2fa0fd63262230639d2c45a3acd9045c').then((res) => {
foldInfoData.length = 0 foldInfoData.length = 0
foldInfoData.push(...res.data) foldInfoData.push(...res.data)
}) })
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
} }
getFold() getFold()
// //
const showHide = ref(false) const showHide = ref(false)
function foldAddSubmit(data: any, updLoading: Function) { function foldAddSubmit(data: any, updLoading: Function) {
<<<<<<< HEAD
updLoading(true)
addChapterApi(data)
.then(() => {
ElMessage({
message: `添加${data.pid === '' ? '章' : '节'}成功`,
type: 'success',
})
showHide.value = false
getFold()
})
.catch(() => {
ElMessage({
message: `添加${data.pid === '' ? '章' : '节'}失败`,
type: 'error',
})
})
.finally(() => updLoading(false))
}
//
<<<<<<< HEAD
const foldDelLoading = ref(false)
function flodDel(id: string) {
foldDelLoading.value = true
deleteSectionApi(id)
.then(() => {
ElMessage({
message: `删除成功`,
type: 'success',
})
getFold()
})
.catch(() => {
ElMessage({
message: `删除失败`,
type: 'error',
})
})
.finally(() => (foldDelLoading.value = false))
=======
function flodDel(id: string,setLoading:Function) {
setLoading(true)
deleteSectionApi(id).then(() => {
ElMessage({
message: `删除成功`,
type: 'success'
=======
updLoading(true) updLoading(true)
addChapterApi(data) addChapterApi(data)
.then(() => { .then(() => {
@ -117,6 +245,7 @@ function flodDel(id: string) {
type: 'success', type: 'success',
}) })
getFold() getFold()
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
}) })
.catch(() => { .catch(() => {
ElMessage({ ElMessage({
@ -124,7 +253,12 @@ function flodDel(id: string) {
type: 'error', type: 'error',
}) })
}) })
<<<<<<< HEAD
}).finally(() =>setLoading(false))
>>>>>>> d7b4e7a9c5db447232028c52d0cc49bb8a28830e
=======
.finally(() => (foldDelLoading.value = false)) .finally(() => (foldDelLoading.value = false))
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
} }
// //
const showHide1 = ref(false) const showHide1 = ref(false)
@ -134,6 +268,7 @@ function hanEdit(data: any) {
showHide1.value = true showHide1.value = true
} }
function foldEditSubmit(data: any, updLoading: Function) { function foldEditSubmit(data: any, updLoading: Function) {
<<<<<<< HEAD
updLoading(true) updLoading(true)
updateChapterApi(data) updateChapterApi(data)
.then(() => { .then(() => {
@ -151,6 +286,25 @@ function foldEditSubmit(data: any, updLoading: Function) {
}) })
}) })
.finally(() => updLoading(false)) .finally(() => updLoading(false))
=======
updLoading(true)
updateChapterApi(data)
.then(() => {
ElMessage({
message: `更新${data.pid === '' ? '章' : '节'}成功`,
type: 'success',
})
showHide1.value = false
getFold()
})
.catch(() => {
ElMessage({
message: `更新${data.pid === '' ? '章' : '节'}失败`,
type: 'error',
})
})
.finally(() => updLoading(false))
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
} }
</script> </script>
@ -171,6 +325,76 @@ function foldEditSubmit(data: any, updLoading: Function) {
overflow: hidden; overflow: hidden;
} }
.vertical-line {
position: relative;
<<<<<<< HEAD
=======
background: #f2f7fb;
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
&::before {
content: '';
display: block;
position: absolute;
height: 100%;
width: 12px;
background-color: #2147fb;
}
}
.flex-layout {
display: flex;
justify-content: space-between;
align-items: flex-start;
.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;
}
}
<<<<<<< HEAD
.flex_right {
width: 355px;
.top-container {
height: 231px;
margin-bottom: 23px;
img {
width: 100%;
height: 100%;
=======
.radius-10 {
border-radius: 10px;
overflow: hidden;
}
.vertical-line { .vertical-line {
position: relative; position: relative;
@ -181,8 +405,17 @@ function foldEditSubmit(data: any, updLoading: Function) {
height: 100%; height: 100%;
width: 12px; width: 12px;
background-color: #2147fb; background-color: #2147fb;
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
}
}
.bottom-container {
min-height: 945px;
}
} }
<<<<<<< HEAD
} }
=======
.flex-layout { .flex-layout {
display: flex; display: flex;
@ -238,5 +471,6 @@ function foldEditSubmit(data: any, updLoading: Function) {
} }
} }
} }
>>>>>>> 0b7db324dad8347654933e91ae7e6ca8d2dabd05
} }
</style> </style>

@ -1,31 +1,38 @@
<template> <template>
<div class="info_title"> <div class="info_title">
<div class="title_name">{{ props.title }}</div> <div class="title_name">{{ props.title }}</div>
<!-- <router-link to="`${props.router}`"> -->
<div class="icon"> <div class="icon">
<img :src="ellipsis" @click="handleClick" /> <img :src="ellipsis" @click="router.push(urouter)" />
<!-- <p style="text-decoration: none">查看更多</p> -->
</div> </div>
<!-- </router-link> -->
</div> </div>
<slot name="drawer"></slot> <slot name="drawer"></slot>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { defineProps } from 'vue'
import ellipsis from '@/assets/images/ellipsis.png' import ellipsis from '@/assets/images/ellipsis.png'
import { defineProps } from 'vue'
const props = defineProps({ const props = defineProps({
title: String, title: String,
modelValue: Boolean, modelValue: Boolean,
urouter: String,
}) })
const emit = defineEmits(['update:modelValue']) console.log(props.title, 'router111')
function handleClick() { import { useRouter } from 'vue-router'
emit('update:modelValue', true) const router = useRouter()
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.info_title { .info_title {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; width: 100%;
height: 32px;
text-decoration: none;
// background-color: blue;
.title_name { .title_name {
font-family: Inter, Inter; font-family: Inter, Inter;
font-weight: 400; font-weight: 400;
@ -39,26 +46,15 @@ function handleClick() {
} }
.icon { .icon {
width: 32px;
height: 32px; height: 32px;
border-radius: 3px 3px 3px 3px; border-radius: 3px 3px 3px 3px;
display: flex; display: flex;
text-decoration: none;
// color: rgba(0, 0, 0, 0.9);
// background-color: #f5f5f5;
font-size: small;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
cursor: pointer;
} }
// .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,8 +1,18 @@
<script setup lang="ts"> <script setup lang="ts">
//
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { ref, onMounted, Ref } from 'vue' import { ref, onMounted, Ref, toRefs, computed } from 'vue'
import { defineProps } from 'vue'
const echarsDom: Ref<HTMLElement | any> = ref(null) const echarsDom: Ref<HTMLElement | any> = ref(null)
const props = defineProps({
// lastMonthBrowseList: String,
// dataList: String,
// thisMonthBrowseList: String,
count: Object,
})
onMounted(() => { onMounted(() => {
console.log(props.count.dateList, 'count')
const myChart = echarts.init(echarsDom.value) const myChart = echarts.init(echarsDom.value)
// //
myChart.setOption({ myChart.setOption({
@ -30,16 +40,7 @@ onMounted(() => {
xAxis: [ xAxis: [
{ {
type: 'category', type: 'category',
data: [ data: props.count.dateList.split(','),
'09-01',
'09-03',
'09-05',
'09-07',
'09-09',
'09-11',
'09-13',
'09-15',
],
axisPointer: { axisPointer: {
type: 'shadow', type: 'shadow',
}, },
@ -50,8 +51,8 @@ onMounted(() => {
type: 'value', type: 'value',
name: '浏览次数', name: '浏览次数',
min: 0, min: 0,
max: 200, max: 600,
interval: 40, interval: 100,
axisLabel: { axisLabel: {
formatter: '{value}', formatter: '{value}',
}, },
@ -60,8 +61,8 @@ onMounted(() => {
type: 'value', type: 'value',
name: '', name: '',
min: 0, min: 0,
max: 100, max: 600,
interval: 20, interval: 100,
axisLabel: { axisLabel: {
formatter: '{value}', formatter: '{value}',
}, },
@ -76,7 +77,7 @@ onMounted(() => {
return (value as number) + ' 次' return (value as number) + ' 次'
}, },
}, },
data: [2, 4, 7, 23, 25, 76, 35, 62, 32, 20, 6, 3], data: props.count.thisMonthBrowseList.split(','),
}, },
{ {
name: '上月', name: '上月',
@ -86,17 +87,17 @@ onMounted(() => {
return (value as number) + ' 次' return (value as number) + ' 次'
}, },
}, },
data: [2, 5, 9, 26, 28, 70, 75, 82, 48, 18, 6, 2], data: props.count.lastMonthBrowseList.split(','),
}, },
{ {
type: 'line', type: 'line',
yAxisIndex: 1, yAxisIndex: 1,
data: [2, 4, 7, 23, 25, 76, 35, 62, 32, 20, 6, 3], data: props.count.thisMonthBrowseList.split(','),
}, },
{ {
type: 'line', type: 'line',
yAxisIndex: 1, yAxisIndex: 1,
data: [2, 5, 9, 26, 28, 70, 75, 82, 48, 18, 6, 2], data: props.count.lastMonthBrowseList.split(','),
}, },
], ],
}) })
@ -115,6 +116,6 @@ onMounted(() => {
<style scoped> <style scoped>
.main { .main {
width: 100%; width: 100%;
height: 352px; height: 335px;
} }
</style> </style>

@ -1,13 +1,37 @@
<script setup> <script setup>
import echarts from '@/views/home/components/Echart/Echarts.vue' import echarts from '@/views/home/components/Echart/Echarts.vue'
import conheader from '@/views/home/components/ConHeader.vue' import conheader from '@/views/home/components/ConHeader.vue'
defineProps(['sum']) import { userPicService } from '@/api/user/user'
import { ref, onMounted } from 'vue'
// const dataList = ref()
// const lastMonthBrowseList = ref()
// const thisMonthBrowseList = ref()
const flag = ref(false)
const count = ref()
onMounted(() => {
userPicService().then((res) => {
flag.value = true
// dataList.value = res.data.dateList
// lastMonthBrowseList.value = res.data.lastMonthBrowseList
// thisMonthBrowseList.value = res.data.thisMonthBrowseList
count.value = res.data
console.log(res.data, 'echart11')
console.log(count.value, 'echart')
})
})
</script> </script>
<template> <template>
<div class="info_container" style="width: 95%; height: 384px"> <div
<conheader :title="`主页访问数据(${sum}次)`"></conheader> class="info_container"
<div class="info_content" style="width: 75%; height: 100%"> style="width: 95%; height: 85%; background: #fff; align-items: center"
<echarts></echarts> >
<conheader :title="`主页访问数据`"></conheader>
<div
class="info_content"
style="width: 95%; margin-top: 10px; height: 90%; margin-left: -30px"
>
<echarts :count="count" v-if="flag"></echarts>
</div> </div>
</div> </div>
</template> </template>
@ -16,14 +40,22 @@ defineProps(['sum'])
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-between; justify-content: space-between;
margin-bottom: 20px;
/* justify-content: flex-start; */
} }
.echarts { /* .echarts {
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;
margin-bottom: 16px;
display: flex; display: flex;
justify-content: center; justify-content: start;
align-items: center; align-items: center;
} */
.info_content {
display: flex;
justify-content: start;
align-items: bottom;
background: #fff;
} }
</style> </style>

@ -1,287 +0,0 @@
<script setup>
import conheader from '@/views/home/components/ConHeader.vue'
import { onMounted, ref, computed } from 'vue'
import { userIdenChangeService } from '@/api/user/user.js'
import { Edit } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
const props = defineProps({
data: {
type: Object,
},
})
const formModel = ref()
const newFormModel = ref()
const loading = ref()
//true
const editDialogVisible = ref(false)
const editForm = ref({
name: '',
content: '',
})
const readonlyField = computed(() => editForm.value.name)
const editRowIndex = ref()
const openEditDialog = (row) => {
editForm.value = { ...row }
editRowIndex.value = formModel.value.indexOf(row)
editDialogVisible.value = true
}
//
const saveEdit = () => {
const index = editRowIndex.value
if (index !== -1) {
formModel.value[index] = { ...editForm.value }
}
// console.log(editRowIndex.value, 'edit')
editDialogVisible.value = false
}
//
const cancelEdit = () => {
editDialogVisible.value = false
//
editForm.value = {
name: '',
content: '',
}
}
const formValue = []
onMounted(() => {
if (props.data.roleId[0] === '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,
},
]
newFormModel.value = { ...formModel.value }
formValue.value = formModel.value
} else if (props.data.roleId[0] === '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 },
]
newFormModel.value = { ...formModel.value }
formValue.value = formModel.value
}
// else {
// formModel.value = [
// { name: '', content: res.data.name },
// { name: '', content: res.data.id },
// { 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 },
// ]
// }
})
// 1
const drawer2 = ref(false)
const direction = ref('rtl')
const data1 = ref([])
const confirmClick = () => {
drawer2.value = false
data1.value = formModel.value
const values = {}
data1.value.map((item) => (values[item.par] = item.content))
const dataToSend = {
...values,
roleId: props.data.roleId,
id: props.data.id,
userId: props.data.userId,
}
userIdenChangeService(dataToSend)
.then(() => {
ElMessage.success('修改成功')
})
.catch((error) => {
console.log(error)
})
}
function cancelClick() {
drawer2.value = false
}
</script>
<template>
<div class="info_container" style="width: 95%; height: 306px">
<conheader title="个人信息" v-model="drawer2">
<template #drawer>
<el-drawer v-model="drawer2" :direction="direction" class="table">
<template #header>
<h4>个人信息</h4>
</template>
<template #default>
<div>
<el-table :data="formModel" style="width: 100%">
<el-table-column prop="name" label="标题"></el-table-column>
<el-table-column prop="content" label="内容"></el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button
type="primary"
class="el-icon-edit"
:icon="Edit"
plain
circle
@click="openEditDialog(row)"
></el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<template #footer>
<div style="flex: auto">
<el-button @click="cancelClick" size="medium">取消</el-button>
<el-button type="primary" @click="confirmClick">确认</el-button>
</div>
</template>
</el-drawer>
<el-dialog
v-model="editDialogVisible"
title="详细信息"
style="width: 800px; text-align: center"
:readonly-field="readonlyField"
>
<el-form :model="editForm" label-width="80px">
<el-form-item label="名称" prop="name">
<el-input v-model="editForm.name"></el-input>
</el-form-item>
<el-form-item label="内容" prop="content">
<template v-if="editForm.name !== '性别'">
<el-input v-model="editForm.content"></el-input>
</template>
<template v-else>
<el-select
v-model="editForm.content"
filterable
placeholder="Select"
>
<el-option
v-for="item in [
{
value: '男',
label: '男',
},
{
value: '女',
label: '女',
},
]"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-form-item>
</el-form>
<template #footer>
<div>
<el-button @click="cancelEdit">取消</el-button>
<el-button type="primary" @click="saveEdit">保存</el-button>
</div>
</template>
</el-dialog>
</template>
</conheader>
<div
class="info_content"
style="width: 60%; height: 244px"
v-loading="loading"
>
<div class="item" :key="item.name" v-for="item in newFormModel">
<div class="name">{{ item.name }}</div>
<div class="content">{{ item.content }}</div>
</div>
</div>
</div>
</template>
<style scoped>
.info_container {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.info_content {
display: grid;
display: wrap;
grid-template-columns: repeat(4, 1fr);
gap: 10px; /* 设置元素之间的间隔 */
}
.item {
width: 100%;
height: 60px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.name {
font-family: Inter, Inter;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.4);
line-height: 22px;
text-align: left;
font-style: normal;
text-transform: none;
}
.content {
font-family: Inter, Inter;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.9);
line-height: 22px;
text-align: left;
font-style: normal;
text-transform: none;
}
.table {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.custom-input {
margin-bottom: 20px;
height: 40px; /* 自定义输入框高度 */
padding: 0 10px; /* 自定义输入框内边距 */
font-size: 16px; /* 自定义输入框字体大小 */
/* 其他样式自定义 */
}
</style>

@ -1,156 +0,0 @@
<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
}
// ==============
// 1
const drawer2 = ref(false)
</script>
<template>
<div class="info_container" style="width: 95%; height: 306px">
<div class="info_title">
<div class="title_name">个人信息</div>
<div class="icon">
<img :src="ellipsis" @click="drawer2 = true" />
</div>
</div>
<InfoContainer :data="formModel"></InfoContainer>
<myDrawer v-model:drawer="drawer2" :data="formModel"></myDrawer>
</div>
</template>
<style scoped>
.info_container {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.info_content {
display: grid;
display: wrap;
grid-template-columns: repeat(4, 1fr);
gap: 10px; /* 设置元素之间的间隔 */
}
.item {
width: 100%;
height: 60px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.name {
font-family: Inter, Inter;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.4);
line-height: 22px;
text-align: left;
font-style: normal;
text-transform: none;
}
.content {
font-family: Inter, Inter;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.9);
line-height: 22px;
text-align: left;
font-style: normal;
text-transform: none;
}
.custom-input {
margin-bottom: 20px;
height: 40px; /* 自定义输入框高度 */
padding: 0 10px; /* 自定义输入框内边距 */
font-size: 16px; /* 自定义输入框字体大小 */
/* 其他样式自定义 */
}
/* ======= */
.info_title {
display: flex;
justify-content: space-between;
align-items: center;
.title_name {
font-family: Inter, Inter;
font-weight: 400;
font-size: 20px;
color: rgba(0, 0, 0, 0.9);
line-height: 30px;
text-align: left;
font-style: normal;
text-transform: none;
}
}
.icon {
width: 32px;
height: 32px;
border-radius: 3px 3px 3px 3px;
display: flex;
justify-content: center;
align-items: center;
}
</style>

@ -0,0 +1,102 @@
<script setup>
import conheader from '@/views/home/components/ConHeader.vue'
import fe from '@/assets/images/fe.jpg'
// import { userLessonListService } from '@/api/user/user.js'
// const getLesList = async () => {
// const res = await userLessonListService()
// console.log(res)
// }
// getLesList()
</script>
<template>
<div class="lesson_container" style="width: 95%; height: 90%">
<conheader
:title="`课程列表`"
:urouter="'/curriculumCenter/basicCourseInformation'"
></conheader>
<div class="lessonlist-content">
<div class="lessonlist-item" v-for="item in 4" :key="item">
<div class="lessonlist-item-img">
<img
src=""
alt=""
style="width: 100%; height: 125px; border-radius: 10px 10px 0px 0px"
/>
</div>
<div class="lessonlist-item-info">
<h3>软件构造</h3>
<div class="p"><p>编辑</p></div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.lesson_container {
/* background-color: purple; */
display: flex;
flex-direction: column;
justify-content: space-between;
margin: 0 auto;
padding: 5px 0;
}
.lessonlist-content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin: 10px 0px;
}
.lessonlist-item {
width: 23%;
height: 175px;
border-radius: 10px 10px 0px 0px;
background-color: #fff;
/* background-color: #aeb1b5; */
display: flex;
flex-direction: column;
justify-content: space-between;
border: 1px solid #e8e8f2;
/* border-radius: 6px 6px 6px 6px; */
/* box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); */
}
.lessonlist-item-info {
box-sizing: border-box;
padding: 6px 5px;
/* background-color: pink; */
/* padding: 10px; */
/* display: flex;
flex-direction: column;
justify-content: space-between;
border: 1px solid #e8e8f2; */
/* border: 1px solid #e8e8f2; */
}
.lessonlist-item-info h3 {
font-size: 16px;
font-weight: bold;
margin-bottom: 5px;
}
.lessonlist-item-info .p {
/* font-size: 14px;
color: #858689; */
/* 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,126 +1,132 @@
<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 { Edit } from '@element-plus/icons-vue'
import { tool, client } from '@/utils/alioss.js'
// 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) 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
// console.log(props.data.username, 'img')
// //
const upload = async (option) => { 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 imageUrl.value = res.url
imageUrl.value = url
changeInfo() changeInfo()
// console.log(imageUrl.value, 'img')
} }
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 () => {
// console.log('', imageUrl.value)
if (!isUploading.value) {
isUploading.value = true
const userInfo = { const userInfo = {
phone: form.value.phone, id: props.data.id,
id: form.value.id,
nickName: form.value.nickName,
icon: imageUrl.value, icon: imageUrl.value,
username: props.data.username,
} }
const jsonData = JSON.stringify(userInfo) const jsonData = JSON.stringify(userInfo)
await userChangeService(jsonData).then(() => { await userChangeService(jsonData).then(() => {
ElMessage.success('修改成功') ElMessage.success('修改成功')
console.log(form.value.nickName, 'nickN') // console.log(imageUrl.value, 'fs')
emit('get-message', form.value.nickName) emit('get-avater', imageUrl.value)
}) })
dialogFormVisible.value = false isUploading.value = false
} }
const cancleInfo = () => {
dialogFormVisible.value = false
form.value = {
...props.data,
} }
// 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> </script>
<template> <template>
<div class="ident" style="width: 100%; height: 274px; background: #375fff"> <div class="ident" style="width: 100%; height: 100%; background: #375fff">
<div class="info_container" style="width: 201px; height: 178px"> <div class="info_container" style="width: 60%; height: 65%">
<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"
: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">
<div class="name">{{ props.data.username }}</div> <div class="name">{{ props.data.username }}</div>
<div class="na">
{{ props.userData.professionalTitle }}
<el-icon class="icon" @click="openInfo">
<Edit />
</el-icon>
</div> </div>
</div> </div>
</div> </div>
<el-dialog </div>
v-model="dialogFormVisible" <el-drawer v-model="dialog" title="个人信息" class="demo-drawer">
title="登录信息" <div class="content">
style="width: 800px; text-align: center" <el-form :model="form">
> <el-form-item label="姓名" :label-width="formLabelWidth">
<el-form :model="form" :data="form" :rules="rules"> <el-input v-model="form.name" autocomplete="off"></el-input>
<el-form-item label="用户名" :label-width="formLabelWidth"> </el-form-item>
<el-input :disabled="true" v-model="form.username" autocomplete="off" /> <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>
<el-form-item label="昵称" :label-width="formLabelWidth"> <el-form-item label="民族" :label-width="formLabelWidth">
<el-input v-model="form.nickName" autocomplete="off" /> <el-input v-model="form.email" autocomplete="off"></el-input>
</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.phone" autocomplete="off"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <div class="footer">
<div class="dialog-footer"> <el-button @click="onCancel">取消</el-button>
<el-button @click="cancleInfo">取消</el-button> <el-button type="primary" :loading="loading" @click="onsubmit">
<el-button type="primary" @click="changeInfo">确认</el-button> 确认
</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);
@ -150,6 +156,33 @@ const cancleInfo = () => {
font-style: normal; font-style: normal;
text-transform: none; text-transform: none;
} }
.na {
/* height: 28px; */
font-family: Inter, Inter;
font-weight: normal;
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
line-height: 24px;
text-align: left;
font-style: normal;
text-transform: none;
align-items: center;
display: flex;
/* justify-content: space-between; */
.icon {
font-size: 20px;
margin-left: 5px;
}
.icon:hover {
color: #cddefa;
}
}
.footer {
display: flex;
justify-content: space-around;
align-items: center;
margin-top: 20px;
}
.iden { .iden {
width: 126px; width: 126px;
height: 22px; height: 22px;
@ -163,10 +196,10 @@ const cancleInfo = () => {
text-transform: none; text-transform: none;
} }
.avater { .avater {
width: 80px; width: 90px;
height: 80px; height: 90px;
background: #b5c7ff; background: #b5c7ff;
border-radius: 40px 40px 40px 40px; border-radius: 50px 50px 50px 50px;
display: flex; display: flex;
} }
span { span {
@ -185,8 +218,8 @@ span {
top: 18px; top: 18px;
} }
.click { .click {
width: 24px; width: 13%;
height: 24px; height: 13%;
border-radius: 100px 100px 100px 100px; border-radius: 100px 100px 100px 100px;
border: 2px solid #ffffff; border: 2px solid #ffffff;
background: #0052d9; background: #0052d9;
@ -194,7 +227,7 @@ span {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin-left: 60px; margin-left: 65px;
margin-top: -60px; margin-top: -50px;
} }
</style> </style>

@ -1,79 +1,108 @@
<script setup> <script setup>
import conheader from '@/views/home/components/ConHeader.vue' import conheader from '@/views/home/components/ConHeader.vue'
import { ref } from 'vue' import { ref, computed } from 'vue'
const name = ['Aa', 'Bb', 'Cc', 'Dd'] import { useRouter } from 'vue-router'
const getRandomColor = () => { import { userStudentListService } from '@/api/user/user'
// import useUserStore from '@/store/modules/user'
return '#' + Math.floor(Math.random() * 16777215).toString(16) const userStore = useUserStore()
} const router = useRouter()
const drawer2 = ref(false) const loading = ref(false)
const direction = ref('rtl') const stuList = ref([])
function cancelClick() { const getStuList = async () => {
drawer2.value = false loading.value = true
} const res = await userStudentListService(userStore.data.id)
function confirmClick() { // console.log(res.data, 'userRes')
drawer2.value = false stuList.value = res.data
// console.log(stuList.value[1].icon, 'rrr')
loading.value = false
} }
getStuList()
</script> </script>
<template> <template>
<div class="info_container" style="width: 90%; height: 174px">
<conheader title="学生分组" v-model="drawer2">
<div>编辑</div>
<template #drawer>
<el-drawer v-model="drawer2" :direction="direction">
<template #header>
<h4>78</h4>
</template>
<template #default>
<div></div>
</template>
<template #footer>
<div style="flex: auto">
<el-button @click="cancelClick">cancel</el-button>
<el-button type="primary" @click="confirmClick">
confirm
</el-button>
</div>
</template>
</el-drawer>
</template>
</conheader>
<div class="info_content" style="width: 194px; height: 112px">
<div <div
v-for="(item, index) in name" class="info_container"
:key="index" style="width: 85%; height: 90%; background: #fff; align-items: center"
class="stu_color"
:style="{ backgroundColor: getRandomColor() }"
> >
{{ item }} <conheader
:title="`学生`"
:urouter="'/studentManagement/student'"
></conheader>
<div class="stu_content" v-loading="loading">
<ul>
<li class="stu-item" v-for="(item, index) in stuList" :key="index">
<img :src="item.icon" class="stu-item-img" />
<div class="stu-item-info">
<h4>{{ item.name }}</h4>
<h4 style="color: #666">{{ item.number }}</h4>
</div> </div>
</li>
</ul>
</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;
justify-content: space-between; */
}
.stu_content {
height: 86%;
overflow: hidden;
text-overflow: ellipsis;
font-family: 'Microsoft YaHei';
/* background-color: rgb(100, 100, 64); */
}
.stu-item {
margin-top: 20px;
/* height: 100%; */
/* border-radius: 10px; */
/* background-color: #0080ff; */
border-bottom: 1px solid #ededed;
/* border-radius: 10px; */
/* box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); */
box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.07);
display: flex; display: flex;
padding: 5px;
/* margin: 10px; */
justify-content: space-between; justify-content: space-between;
} }
.info_content { .stu-item-img {
width: 194px; background-color: yellow;
height: 112px; border-radius: 50%;
flex-wrap: wrap; width: 40px;
display: grid; height: 40px;
grid-template-columns: repeat(3, 1fr); justify-content: center;
gap: 24px; /* 设置元素之间的间隔 */ align-items: center;
grid-row-gap: 16px;
} }
.stu_color { .stu-item-info {
/* margin-left: 15px; */
width: 80%;
height: 40px;
background-color: #ffffff;
display: flex;
flex-direction: column;
justify-content: space-between;
}
h4 {
margin-left: 15px;
font-weight: bold;
font-size: 14px;
font-family: Inter, Inter;
/* font-weight: 400; */
/* font-size: 20px; */
/* font-family: 'soft'; */
/* color: #000000 */
}
/* */
/* .stu_color {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@ -89,7 +118,7 @@ function confirmClick() {
font-style: normal; font-style: normal;
text-transform: none; text-transform: none;
transition: background-color 0.3s; transition: background-color 0.3s;
} } */
.stu_color:hover { .stu_color:hover {
background-color: #f2f2f2; /* 鼠标移入时的背景色变化 */ background-color: #f2f2f2; /* 鼠标移入时的背景色变化 */
filter: brightness(1.1); filter: brightness(1.1);

@ -1,97 +0,0 @@
<script setup>
import conheader from '@/views/home/components/ConHeader.vue'
import { ref } from 'vue'
const name = ['Aa', 'Bb', 'Cc', 'Dd']
const getRandomColor = () => {
//
return '#' + Math.floor(Math.random() * 16777215).toString(16)
}
const drawer2 = ref(false)
const direction = ref('rtl')
function cancelClick() {
drawer2.value = false
}
function confirmClick() {
drawer2.value = false
}
</script>
<template>
<div class="info_container" style="width: 90%; height: 174px">
<conheader title="已分组别" v-model="drawer2">
<div>编辑</div>
<template #drawer>
<el-drawer v-model="drawer2" :direction="direction">
<template #header>
<h4>78</h4>
</template>
<template #default>
<div></div>
</template>
<template #footer>
<div style="flex: auto">
<el-button @click="cancelClick">cancel</el-button>
<el-button type="primary" @click="confirmClick">
confirm
</el-button>
</div>
</template>
</el-drawer>
</template>
</conheader>
<div class="info_content" style="width: 194px; height: 112px">
<div
v-for="(item, index) in name"
:key="index"
class="stu_color"
:style="{ backgroundColor: getRandomColor() }"
>
{{ item }}
</div>
</div>
</div>
</template>
<style scoped>
.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;
}
.info_content {
width: 194px;
height: 112px;
flex-wrap: wrap;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px; /* 设置元素之间的间隔 */
grid-row-gap: 16px;
}
.stu_color {
display: flex;
justify-content: center;
align-items: center;
width: 49px;
height: 48px;
border-radius: 40px 40px 40px 40px;
font-family: Inter, Inter;
font-weight: normal;
font-size: 14px;
color: rgba(255, 255, 255, 0.9);
line-height: 22px;
text-align: left;
font-style: normal;
text-transform: none;
transition: background-color 0.3s;
}
.stu_color:hover {
background-color: #f2f2f2; /* 鼠标移入时的背景色变化 */
filter: brightness(1.1);
}
</style>

@ -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,7 +20,145 @@ 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({})
const formLabelWidth = '80px'
//dialog
const openInfo = () => {
dialogFormVisible.value = true
form.value = { ...props.userData }
}
const openPass = () => {
passFormVisible.value = true
}
//
const infoRules = {
phone: [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{
pattern: /^1[3-9]\d{9}$/,
message: '手机号格式不正确',
trigger: 'blur',
},
],
nickName: [
{ required: true, message: '请输入昵称', trigger: 'blur' },
{
pattern: /^[\u4e00-\u9fa5a-zA-Z0-9_]{1,10}$/,
message: '昵称格式不正确',
trigger: 'blur',
},
],
}
// ---
//
const checkOldSame = (rule, value, callback) => {
if (value === props.userData.password) {
callback(new Error('新密码不能与旧密码相同'))
} else {
callback()
}
}
const checkNewSame = (rule, value, cb) => {
if (value !== pwdForm.value.new_pwd) {
cb(new Error('新密码和确认再次输入的新密码不一样!'))
} else {
cb()
}
}
// ---
//
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 infoRef = ref()
//
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)
// const valid = await infoRef.value.validate()
await userChangeService(jsonData).then(() => {
ElMessage.success('修改成功')
emit('get-message', form.value.nickName)
})
dialogFormVisible.value = false
}
const cancleInfo = () => {
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)
.then(() => {
ElMessage.success('密码修改成功')
passFormVisible.value = false
})
.catch((error) => {
console.log(error, 'error')
ElMessage.error(error.response.data.message)
})
pwdForm.value = {}
}
//
const onReset = () => {
pwdForm.value = {}
}
//
const username = computed(() => { const username = computed(() => {
if (props.userData.nickName) { if (props.userData.nickName) {
return props.userData.nickName return props.userData.nickName
@ -19,16 +166,20 @@ 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)
}) })
@ -44,14 +195,87 @@ 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>
<el-dialog
v-model="dialogFormVisible"
title="登录信息"
style="width: 800px; text-align: center"
>
<el-form :rules="infoRules" ref="infoRef" :model="form">
<el-form-item
label="用户名"
:label-width="formLabelWidth"
prop="username"
>
<el-input :disabled="true" v-model="form.username" autocomplete="off" />
</el-form-item>
<el-form-item label="昵称" :label-width="formLabelWidth" prop="nickName">
<el-input v-model="form.nickName" autocomplete="off" />
</el-form-item>
<el-form-item label="手机" :label-width="formLabelWidth" prop="phone">
<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> </div>
</template> </template>
</el-dialog>
<el-dialog
v-model="passFormVisible"
title="修改密码"
style="width: 800px; text-align: center"
>
<el-form :rules="rules" ref="formRef" :data="pwdForm">
<el-form-item label="原密码" prop="old_pwd" :label-width="formLabelWidth">
<el-input
type="password"
v-model="pwdForm.old_pwd"
show-password
></el-input>
</el-form-item>
<el-form-item label="新密码" prop="new_pwd" :label-width="formLabelWidth">
<el-input
type="password"
v-model="pwdForm.new_pwd"
show-password
></el-input>
</el-form-item>
<el-form-item
label="确认密码"
prop="re_pwd"
:label-width="formLabelWidth"
>
<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> <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 +291,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 +302,7 @@ onMounted(() => {
font-style: normal; font-style: normal;
text-transform: none; text-transform: none;
} }
.time {
justify-content: end;
}
</style> </style>

@ -1,47 +0,0 @@
<template>
<div class="info_content" style="width: 60%; height: 244px">
<div class="item" :key="item.name" v-for="item in data">
<div class="name">{{ item.name }}</div>
<div class="content">{{ item.content }}</div>
</div>
</div>
</template>
<script setup lang="ts">
defineProps(['data'])
</script>
<style scoped>
.info_content {
display: grid;
display: wrap;
grid-template-columns: repeat(4, 1fr);
gap: 10px; /* 设置元素之间的间隔 */
}
.item {
width: 100%;
height: 60px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.name {
font-family: Inter, Inter;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.4);
line-height: 22px;
text-align: left;
font-style: normal;
text-transform: none;
}
.content {
font-family: Inter, Inter;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.9);
line-height: 22px;
text-align: left;
font-style: normal;
text-transform: none;
}
</style>

@ -1,120 +0,0 @@
<template>
<el-drawer v-model="drawer2" class="table">
<template #header>
<h4>个人信息</h4>
</template>
<template #default>
<div>
<el-table :data="parData" style="width: 100%">
<el-table-column prop="name" label="标题"></el-table-column>
<el-table-column prop="content" label="内容"></el-table-column>
<el-table-column label="操作">
<template #default="{ row }">
<el-button
type="primary"
class="el-icon-edit"
:icon="Edit"
plain
circle
@click="hanEdit(row)"
></el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<template #footer>
<div style="flex: auto">
<el-button @click="() => {}" size="medium">取消</el-button>
<el-button type="primary" @click="() => {}">确认</el-button>
</div>
</template>
</el-drawer>
<el-dialog
v-model="isDialog"
title="详细信息"
style="width: 800px; text-align: center"
>
<el-form :model="activeItem" label-width="80px">
<el-form-item label="名称" prop="name">
<el-input v-model="activeItem.name"></el-input>
</el-form-item>
<el-form-item label="内容" prop="content">
<template v-if="activeItem.name !== '性别'">
<el-input v-model="activeItem.content"></el-input>
</template>
<template v-else>
<el-select
v-model="activeItem.content"
filterable
placeholder="Select"
>
<el-option
v-for="item in arr"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-form-item>
</el-form>
<template #footer>
<div>
<el-button @click="isDialog = false">取消</el-button>
<el-button type="primary" @click="saveEdit">保存</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { Edit } from '@element-plus/icons-vue'
import { ref, reactive, watch } from 'vue'
const props = defineProps(['drawer', 'data'])
const emits = defineEmits(['update:drawer'])
const arr = ref([
{
value: '男',
label: '男',
},
{
value: '女',
label: '女',
},
])
// ================
const drawer2 = ref(props.drawer)
watch(
() => drawer2.value,
(newVal) => emits('update:drawer', newVal),
)
watch(
() => props.drawer,
(newVal) => (drawer2.value = newVal),
)
const parData = ref(props.data.map((item: any) => ({ ...item })))
// ==========
const isDialog = ref(false)
const activeItem = reactive({})
const activeRow = ref()
//
function hanEdit(row: any) {
Object.assign(activeItem, row)
activeRow.value = row
isDialog.value = true
}
//
function saveEdit() {
Object.assign(activeRow.value, activeItem)
console.log(parData.value, 'value')
}
</script>
<style scoped>
.table {
display: flex;
flex-direction: column;
justify-content: space-between;
}
</style>

@ -1,41 +1,52 @@
<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, userLookService } 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'
import { useRouter } from 'vue-router'
const router = useRouter()
const userStore = useUserStore() const userStore = useUserStore()
const username = ref() const username = ref()
const data = ref({}) const data = ref({})
const infoData = ref() const infoData = ref()
const flag = ref(false) const flag = ref(false)
const role = ref(null) const role = ref(null)
const loading = ref(false)
const rightVisible = ref(false) 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'
const name = ref() const name = ref()
const getMessage = (msg) => { const getMessage = (msg) => {
name.value = msg name.value = msg
console.log(msg, 'msg')
} }
const getAvater = (avater) => {
// console.log(msg, 'msg')
userStore.data.icon = avater
// console.log(data.value.icon, 'icon')
}
const courselist = ref([])
const img = ref()
const courseName = ref()
const courseTea = ref()
onMounted(() => { onMounted(() => {
// getData() // getData()
sum = parseInt(sum) + 1
localStorage.setItem('sum', sum.toString())
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,59 +55,152 @@ onMounted(() => {
} else { } else {
rightVisible.value = false rightVisible.value = false
} }
//
// userToplessonService().then((res) => {
// // console.log(res, '')
// })
//
const res = userNewLikeService(userStore.data.id).then((res) => {
console.log(res.data.id, '最新收藏的课程')
courselist.value = res.data
// console.log(courselist.value.id, 'course')
img.value = res.data.img
courseName.value = res.data.name
courseTea.value = res.data.teacher
})
//echart
userLookService()
}) })
</script> </script>
<template> <template>
<div class="container"> <el-row>
<div class="left"> <el-col :span="24">
<div class="nav"> <div class="nav">
<welcome <welcome
:data="infoData" :data="infoData"
:userData="data" :userData="data"
:name="name" :name="name"
@get-message="getMessage"
v-if="flag" v-if="flag"
></welcome> ></welcome>
</div> </div>
<div class="info" style="width: 100%; height: 368px"> </el-col>
<Info :data="infoData" v-if="flag"></Info> </el-row>
<el-row :gutter="15">
<el-col :span="18">
<div class="classList">
<lessonlist></lessonlist>
</div> </div>
<div class="echarts" style="width: 100%; height: 444px"> </el-col>
<echarts :sum="sum"></echarts> <el-col :span="6">
<div class="info">
<status
:data="data"
:userData="infoData"
@get-avater="getAvater"
v-if="flag"
></status>
</div> </div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="6">
<div class="lesson">
<a
href="#"
style="
font-size: 14px;
display: flex;
margin: 0px auto;
margin: 0px 30px;
"
>
<conheader
:title="`学习最多知识点`"
:urouter="'/curriculumCenter/knowledgePoints'"
></conheader>
</a>
<div class="con">
<p class="button" round v-for="item in 30" :key="item">
Spring clould
</p>
</div> </div>
<div v-if="rightVisible" class="right">
<status :data="data" @get-message="getMessage" v-if="flag"></status>
<div class="class" style="width: 100%; height: 388px">
<Class1></Class1>
</div> </div>
<div class="stu" style="width: 100%; height: 236px"> </el-col>
<Student1></Student1> <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="con">
<p class="button" round v-for="item in 30" :key="item">Roshabei</p>
</div> </div>
</div> </div>
<div v-else class="right"> </el-col>
<status :data="data" v-if="flag"></status> <el-col :span="6">
<div class="class" style="width: 100%; height: 388px"> <div class="lesson">
<Class2></Class2> <a
href="#"
style="width: 90%; font-size: 14px; display: flex; margin: 0 auto"
>
<conheader :title="`推荐课程`"></conheader>
</a>
<div class="con">
<ul>
<li class="lessonlist-item" v-for="item in 4" :key="item">
<img :src="fe" class="lessonlist-item-img" />
<div class="lessonlist-item-info">
<h5>{{ courseName }}</h5>
<p>{{ courseTea }}</p>
</div> </div>
<div class="stu" style="width: 100%; height: 236px"> </li>
<Student2></Student2> </ul>
</div> </div>
</div> </div>
</el-col>
<el-col :span="6">
<div class="lesson" v-loading="loading">
<a
href="#"
style="width: 90%; font-size: 12px; display: flex; margin: 0 auto"
>
<conheader :title="`最新收藏课程`"></conheader>
</a>
<div class="con">
<ul>
<li class="lessonlist-item" v-for="item in courselist" :key="item">
<img :src="img" class="lessonlist-item-img" />
<div class="lessonlist-item-info">
<h5>{{ courseName }}</h5>
<p>{{ courseTea }}</p>
</div> </div>
</li>
</ul>
</div>
</div>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col :span="18">
<div class="some">
<echarts></echarts>
</div>
</el-col>
<el-col :span="6">
<div class="stu">
<Student1></Student1>
</div>
</el-col>
</el-row>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.container { * {
display: flex; box-sizing: border-box;
width: 100%; }
.left {
width: 80%;
height: 936px;
margin-right: 16px;
display: grid;
grid-template-rows: 1fr 1fr 1fr; /* 使用fr单位来平均分布 */
height: 300px; /* 设置容器高度 */
.nav { .nav {
width: 100%;
height: 92px; height: 92px;
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);
@ -107,61 +211,121 @@ onMounted(() => {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.info, .classList,
.echarts { .info {
// background-color: yellow;
height: 270px;
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;
margin-bottom: 16px; justify-content: space-between;
display: flex;
// flex-direction: column; //
justify-content: center;
align-items: center; align-items: center;
.info_container { margin-bottom: 16px;
}
.classList {
display: flex; display: flex;
flex-direction: column; //
justify-content: space-between; justify-content: space-between;
} }
} .lesson {
.class { // background-color: pink;
width: 80%; padding-top: 5px;
height: 444px; margin-bottom: 16px;
background: #c57676; height: 290px;
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; overflow: hidden;
// flex-direction: column; // text-overflow: ellipsis;
justify-content: center; // flex-direction: column;
align-items: center;
} }
} .con {
.right {
width: 20%;
height: 930px;
display: flex; display: flex;
flex-direction: column; // // justify-content: space-between;
// height: 100%;
// align-items: center;
// margin: 0 auto;
// background-color: yellow;
padding: 5px;
margin-top: 5px;
flex-wrap: wrap;
justify-content: space-evenly;
padding-bottom: 30px;
}
.button {
justify-content: space-between; justify-content: space-between;
.ident, margin-bottom: 5px;
.class, height: 30px;
border-radius: 10px;
// color: #0080ff;
text-align: center;
line-height: 30px;
margin: 5px 10px;
border: 2px solid #ccc;
}
a {
text-decoration: none;
}
.some,
.stu { .stu {
padding-top: 5px;
height: 380px;
// background: #9f7b7b;
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;
justify-content: space-between;
display: flex; display: flex;
// flex-direction: column; //
justify-content: center; justify-content: center;
align-items: center; align-items: center;
.info_container { }
// .lessonlist-content {
// display: flex;
// justify-content: center;
// align-items: center;
// margin: 0 auto;
// flex-direction: column;
// }
ul {
width: 100%;
height: 100%;
display: flex; display: flex;
flex-direction: column; // flex-direction: column;
justify-content: space-between; // justify-content: center;
.info_content { // align-items: center;
}
.lessonlist-item {
height: 50px;
// margin: 0 auto;
border-radius: 10px;
// background-color: #0080ff;
box-shadow: 0 0 2px rgba(0, 0, 0, 0.1);
display: flex; display: flex;
flex-direction: column; // padding: 5px;
margin: 5px;
justify-content: space-between; justify-content: space-between;
// align-items: center;
} }
.lessonlist-item-img {
width: 17%;
height: 40px;
justify-content: center;
align-items: center;
} }
.lessonlist-item-info {
margin-left: 5px;
width: 80%;
height: 40px;
background-color: #ffffff;
display: flex;
flex-direction: column;
justify-content: space-evenly;
h3 {
font-weight: bold;
} }
p {
font-size: small;
color: #a0a5ab;
} }
} }
</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,
@ -408,18 +399,16 @@ watch(isToggle, () => {
const passwordMatchError = ref('') const passwordMatchError = ref('')
const checkPasswordMatch = () => { const checkPasswordMatch = () => {
if (formModel.value.password !== formModel.value.repassword) { if (formModel.value.password !== formModel.value.repassword) {
// passwordMatchError.value = ''
ElMessage('两次输入的密码不一致') ElMessage('两次输入的密码不一致')
} else { } else {
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 +419,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 +436,6 @@ const handleSubmit = async () => {
passwordMatchError.value = '两次输入的密码不一致' passwordMatchError.value = '两次输入的密码不一致'
} }
} }
// const userGetInfoService
// //
const codecode = ref() const codecode = ref()
const codeSubmit = async () => { const codeSubmit = async () => {
@ -465,7 +453,7 @@ const codeSubmit = async () => {
} }
// //
const phoneChange = () => { const phoneChange = () => {
console.log('开始手机号注册') // console.log('')
isinfo.value = false isinfo.value = false
} }
// //

@ -1,30 +1,241 @@
<script setup>
import { Search, Edit, Delete } from '@element-plus/icons-vue'
import { ref } from 'vue'
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Home',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Office',
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Home',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Office',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Office',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
tag: 'Office',
},
]
const loading = ref(false)
</script>
<template> <template>
<div> <page-container title="文章分类">
<!-- Dialog组件 --> <el-card class="page-container">
<Dialog <template #header>
v-model="dialogVisible" <div class="card-header">
@confirm="collectData" <span>学生信息</span>
:name="readonlyName" <el-button type="primary">重置密码</el-button>
:age="readonlyAge"
/>
</div> </div>
</template> </template>
<div class="content">
<el-form style="display: flex">
<el-form-item style="width: 250px">
<el-input class="input_search"></el-input>
<el-icon><Search /></el-icon>
</el-form-item>
<el-button class="btn_search">搜索</el-button>
</el-form>
<el-table
class="tableBox"
:data="tableData"
v-loading="loading"
:header-cell-style="{
background: '#FAFAFA',
color: '#666',
fontSize: '14px',
fontWeight: 'bold',
height: '45px',
lineHeight: '45px',
borderTop: '1px solid #ebeef5',
textAlign: 'center',
}"
:cell-style="{
color: '#666',
fontSize: '14px',
height: '40px',
lineHeight: '40px',
textAlign: 'center',
}"
:row-style="{
height: '40px',
}"
style="width: 100%"
>
<el-table-column type="selection" width="55" height="100" />
<el-table-column prop="date" label="日期" />
<el-table-column prop="name" label="姓名" />
<el-table-column prop="state" label="状态" />
<el-table-column prop="city" label="City" width="300" />
<el-table-column prop="address" label="Address" />
<el-table-column prop="zip" label="Zip" />
<el-table-column fixed="right" label="操作" min-width="125">
<template #default>
<el-button
type="primary"
size="small"
:icon="Edit"
circle
plain
@click="handleClick"
></el-button>
<el-button
:icon="Delete"
type="danger"
size="small"
circle
plain
></el-button>
</template>
</el-table-column>
<template #empty>
<el-empty description="没有数据" />
</template>
</el-table>
<script setup> <!-- <el-table :data="tableData" style="width: 100%">
import { ref, readonly } from 'vue' <el-table-column type="selection" width="65" />
<el-table-column prop="cate_name" label="分类名称" />
const dialogVisible = ref(false) // Dialog <el-table-column prop="cate_alias" label="分类别名" />
const name = ref('John') // <el-table-column prop="address" label="操作">
const age = ref(25) // <template #default="{ row, $index }">
<el-button
const readonlyName = readonly(name) // name @click="onEditChannel(row, $index)"
const readonlyAge = readonly(age) // age :icon="Edit"
type="primary"
circle
plain
></el-button>
<el-button
@click="onDelChannel(row)"
:icon="Delete"
type="danger"
circle
plain
></el-button>
</template>
</el-table-column>
<template #empty>
<el-empty description="没有数据" />
</template>
</el-table> -->
<el-pagination
v-model:current-page="currentPage4"
v-model:page-size="pageSize4"
:page-sizes="[10, 20, 30, 40]"
:size="small"
:disabled="disabled"
:background="background"
layout="total, sizes, prev, pager, next, jumper"
:total="40"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</el-card>
</page-container>
</template>
const collectData = () => { <style lang="scss" scoped>
// Dialog .page-container {
// ... min-height: 100%;
box-sizing: border-box;
background: #ffffff;
box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.1);
flex: 1;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.content {
min-height: 440px;
}
console.log(readonlyName.value) // 访 .input_search {
console.log(readonlyAge.value) // 访 position: relative;
// border-radius: 8px;
} }
</script> .el-icon {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
.btn_search {
margin-left: 15px;
border-radius: 8px;
font-size: 13px;
background-color: #377be5;
color: #fff;
}
.el-table {
font-family: Arial, sans-serif;
font-size: 14px;
font-weight: normal;
color: #666;
// height: 10px;
}
.el-table .el-table-column {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 16px;
font-weight: bold;
color: #af4141;
}
::v-deep.el-table td.el-table__cell div {
// margin-left: -6px;
// width: 170px;
height: 40px;
line-height: 40px;
}
::v-deep .el-scrollbar__wrap {
padding: 0px 0px;
}
.el-pagination {
margin-top: 30px;
text-align: center;
justify-content: end;
font-size: 12px;
}
</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