合并冲突

develoop
significative 5 months ago
commit e8b780811b
  1. 4
      .env_1.development
  2. 2
      .env_1.production
  3. 4
      .env_1.test
  4. 65
      .eslintrc_1.cjs
  5. 9
      .prettierrc_1.json
  6. 53
      .stylelintrc_1.cjs
  7. 2
      _1.eslintignore
  8. 24
      _1.gitignore
  9. 4
      _1.stylelintignore
  10. 18
      generated/core/OpenAPI.ts
  11. 2
      generated/services/CourseResourceControllerService.ts
  12. 1
      package.json
  13. 32
      pnpm-lock.yaml
  14. 2
      src/api/courseChaptersApi.ts
  15. 0
      src/assets/icons/audio.png
  16. 0
      src/assets/icons/image.png
  17. 0
      src/assets/icons/test.png
  18. 0
      src/assets/icons/video.png
  19. BIN
      src/assets/images/PDF .png
  20. BIN
      src/assets/images/audio.png
  21. BIN
      src/assets/images/test.png
  22. BIN
      src/assets/images/video.png
  23. 4
      src/store/modules/user.ts
  24. 5
      src/views/MyCourseStudy/ContainerCla.vue
  25. 133
      src/views/MyCourseStudy/courseCollections.vue
  26. 16
      src/views/MyCourseStudy/learningProcess.vue
  27. 20
      src/views/course/CourseObjectives.vue
  28. 300
      src/views/courseResources/componse/resourceAdd.vue
  29. 54
      src/views/courseResources/index.vue
  30. 129
      src/views/home/components/Echart/Echarts.vue
  31. 3
      src/views/home/components/Echarts.vue
  32. 12
      src/views/home/components/Info.vue
  33. 32
      src/views/home/components/Status.vue
  34. 26
      src/views/home/components/Welcome.vue
  35. 12
      src/views/home/index.vue
  36. 2
      src/views/login/index.vue

@ -1,4 +0,0 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '无糖运营平台'
VITE_APP_BASE_API = '/api'

@ -1,2 +0,0 @@
NODE_ENV = 'production'
VITE_APP_TITLE = '无糖运营平台'

@ -1,4 +0,0 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'test'
VITE_APP_TITLE = '无糖运营平台'
VITE_APP_BASE_API = '/test-api'

@ -1,65 +0,0 @@
// @see https://eslint.bootcss.com/docs/rules/
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
jest: true,
},
globals: {
VANTA: 'readonly', //VANTA 已经cdn引入 这里拒绝eslint报错 全局声明一下
ElMessage: 'readonly',
ElMessageBox: 'readonly',
ElLoading: 'readonly',
},
/* 指定如何解析语法 */
parser: 'vue-eslint-parser',
/** 优先级低于 parse 的语法解析配置 */
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parser: '@typescript-eslint/parser',
jsxPragma: 'React',
ecmaFeatures: {
jsx: true,
},
},
/* 继承已有的规则 */
extends: [
'eslint:recommended',
'plugin:vue/vue3-essential',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
plugins: ['vue', '@typescript-eslint'],
/*
* "off" 或 0 ==> 关闭规则
* "warn" 或 1 ==> 打开的规则作为警告(不影响代码执行)
* "error" 或 2 ==> 规则作为一个错误(代码不能执行,界面报错)
*/
rules: {
// eslint(https://eslint.bootcss.com/docs/rules/)
'no-var': 'off', // 要求使用 let 或 const 而不是 var
'no-multiple-empty-lines': ['off', { max: 1 }], // 不允许多个空行
'no-console': process.env.NODE_ENV === 'production' ? 'off' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'off' : 'off',
'no-unexpected-multiline': 'off', // 禁止空余的多行
'no-useless-escape': 'off', // 禁止不必要的转义字符
// typeScript (https://typescript-eslint.io/rules)
'@typescript-eslint/no-unused-vars': 'off', // 禁止定义未使用的变量
'@typescript-eslint/prefer-ts-expect-off': 'off', // 禁止使用 @ts-ignore
'@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间。
'@typescript-eslint/semi': 'off',
// eslint-plugin-vue (https://eslint.vuejs.org/rules/)
'vue/multi-word-component-names': 'off', // 要求组件名称始终为 “-” 链接的单词
'vue/script-setup-uses-vars': 'off', // 防止<script setup>使用的变量<template>被标记为未使用
'vue/no-mutating-props': 'off', // 不允许组件 prop的改变
'vue/attribute-hyphenation': 'off', // 对模板中的自定义组件强制执行属性命名样式
},
}

@ -1,9 +0,0 @@
{
"singleQuote": true,
"semi": false,
"bracketSpacing": true,
"htmlWhitespaceSensitivity": "ignore",
"endOfLine": "auto",
"trailingComma": "all",
"tabWidth": 2
}

@ -1,53 +0,0 @@
// @see https://stylelint.bootcss.com/
module.exports = {
extends: [
'stylelint-config-standard', // 配置stylelint拓展插件
'stylelint-config-standard-vue', // 配置 vue 中 template 样式格式化
'stylelint-config-standard-scss', // 配置stylelint scss插件
'stylelint-config-recommended-vue/scss', // 配置 vue 中 scss 样式格式化
'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件,
'stylelint-config-prettier', // 配置stylelint和prettier兼容
],
overrides: [
{
files: ['**/*.(scss|css|vue|html)'],
customSyntax: 'postcss-scss',
},
{
files: ['**/*.(html|vue)'],
customSyntax: 'postcss-html',
},
],
ignoreFiles: [
'**/*.js',
'**/*.jsx',
'**/*.tsx',
'**/*.ts',
'**/*.json',
'**/*.md',
'**/*.yaml',
],
/**
* null => 关闭该规则
* always => 必须
*/
rules: {
'value-keyword-case': null, // 在 css 中使用 v-bind,不报错
'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器
'function-url-quotes': 'always', // 要求或禁止 URL 的引号 "always(必须加上引号)"|"never(没有引号)"
'no-empty-source': null, // 关闭禁止空源码
'selector-class-pattern': null, // 关闭强制选择器类名的格式
'property-no-unknown': null, // 禁止未知的属性(true 为不允许)
'block-opening-brace-space-before': 'always', //大括号之前必须有一个空格或不能有空白符
'value-no-vendor-prefix': null, // 关闭 属性值前缀 --webkit-box
'property-no-vendor-prefix': null, // 关闭 属性前缀 -webkit-mask
'selector-pseudo-class-no-unknown': [
// 不允许未知的选择器
true,
{
ignorePseudoClasses: ['global', 'v-deep', 'deep'], // 忽略属性,修改element默认样式的时候能使用到
},
],
},
}

@ -1,2 +0,0 @@
dist
node_modules

24
_1.gitignore vendored

@ -1,24 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

@ -1,4 +0,0 @@
/node_modules/*
/dist/*
/html/*
/public/*

@ -19,8 +19,10 @@ export type OpenAPIConfig = {
ENCODE_PATH?: ((path: string) => string) | undefined;
};
export const OpenAPI: OpenAPIConfig = {
BASE: 'http://39.106.16.162:8080',
//BASE: 'http://39.106.16.162:8080',
BASE: 'http://127.0.0.1:8080',
VERSION: '1.0.0',
WITH_CREDENTIALS: false,
CREDENTIALS: 'include',
@ -30,3 +32,17 @@ export const OpenAPI: OpenAPIConfig = {
HEADERS: undefined,
ENCODE_PATH: undefined,
};
// BASE: 'http://39.106.16.162:8080',
// VERSION: '1.0.0',
// WITH_CREDENTIALS: false,
// CREDENTIALS: 'include',
// TOKEN: GET_TKOEN('TOKEN'),
// USERNAME: undefined,
// PASSWORD: undefined,
// HEADERS: {
// Authorization: 'Bearer ' + GET_TKOEN('TOKEN'),
// },
// ENCODE_PATH: undefined,
// }

@ -85,7 +85,7 @@ export class CourseResourceControllerService {
courseResources: CourseResources,
): CancelablePromise<BaseResponse_string_> {
return __request(OpenAPI, {
method: 'GET',
method: 'POST',
url: '/api/courses/save',
body: courseResources,
errors: {

@ -21,6 +21,7 @@
"@element-plus/icons-vue": "^2.3.1",
"@vueup/vue-quill": "^1.2.0",
"@vueuse/core": "^10.9.0",
"ajax": "^0.0.4",
"ali-oss": "^6.20.0",
"axios": "^1.6.8",
"d3": "^5.16.0",

@ -4002,23 +4002,23 @@ snapshots:
'@vue/compiler-core@3.4.29':
dependencies:
'@babel/parser': 7.24.7
'@vue/shared': 3.4.29
'@vue/shared': 3.4.30
entities: 4.5.0
estree-walker: 2.0.2
source-map-js: 1.2.0
'@vue/compiler-dom@3.4.29':
dependencies:
'@vue/compiler-core': 3.4.29
'@vue/shared': 3.4.29
'@vue/compiler-core': 3.4.30
'@vue/shared': 3.4.30
'@vue/compiler-sfc@3.4.29':
dependencies:
'@babel/parser': 7.24.7
'@vue/compiler-core': 3.4.29
'@vue/compiler-dom': 3.4.29
'@vue/compiler-ssr': 3.4.29
'@vue/shared': 3.4.29
'@vue/compiler-core': 3.4.30
'@vue/compiler-dom': 3.4.30
'@vue/compiler-ssr': 3.4.30
'@vue/shared': 3.4.30
estree-walker: 2.0.2
magic-string: 0.30.10
postcss: 8.4.38
@ -4026,8 +4026,8 @@ snapshots:
'@vue/compiler-ssr@3.4.29':
dependencies:
'@vue/compiler-dom': 3.4.29
'@vue/shared': 3.4.29
'@vue/compiler-dom': 3.4.30
'@vue/shared': 3.4.30
'@vue/devtools-api@6.6.3': {}
@ -4046,18 +4046,18 @@ snapshots:
'@vue/reactivity@3.4.29':
dependencies:
'@vue/shared': 3.4.29
'@vue/shared': 3.4.30
'@vue/runtime-core@3.4.29':
dependencies:
'@vue/reactivity': 3.4.29
'@vue/shared': 3.4.29
'@vue/reactivity': 3.4.30
'@vue/shared': 3.4.30
'@vue/runtime-dom@3.4.29':
dependencies:
'@vue/reactivity': 3.4.29
'@vue/runtime-core': 3.4.29
'@vue/shared': 3.4.29
'@vue/reactivity': 3.4.30
'@vue/runtime-core': 3.4.30
'@vue/shared': 3.4.30
csstype: 3.1.3
'@vue/server-renderer@3.4.29(vue@3.4.29)':
@ -4918,7 +4918,7 @@ snapshots:
'@popperjs/core': '@sxzz/popperjs-es@2.11.7'
'@types/lodash': 4.17.5
'@types/lodash-es': 4.17.12
'@vueuse/core': 9.13.0(vue@3.4.29)
'@vueuse/core': 9.13.0(vue@3.4.30)
async-validator: 4.2.5
dayjs: 1.11.11
escape-html: 1.0.3

@ -92,7 +92,7 @@ export const deleteCourse = (params: any) => {
method: 'DELETE',
})
}
// /api/objective_contents/
// /objective_contents/
// 获取详情
export const getCourseInfo = (params: any) => {
return request({

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

@ -54,7 +54,6 @@ const useUserStore = defineStore(
SET_TKOEN('TOKEN', this.token)
// localStorage.setItem('TOKEN', this.token)
ElNotification({
type: 'success',
message: '登录成功!',
@ -62,7 +61,6 @@ const useUserStore = defineStore(
})
return 'ok'
} else {
console.log(res, '33333')
// ElNotification({
// // type: 'error',
// message: res.message,
@ -102,6 +100,8 @@ const useUserStore = defineStore(
const result: any = await userGetInfoService(GET_TKOEN('TOKEN'))
if (result.code === 200) {
const res = await userIdenService(result.data.id)
console.log(res, 'huonghu')
// @ts-expect-error
this.userInfo = res.data

@ -194,18 +194,19 @@ const handleCurrentChange = (page: any) => {
.ClassGd {
position: absolute;
right: 0;
background-color: rgb(217, 217, 217, 0.5);
display: none;
margin-left: 85%;
padding: 3px 5px;
cursor: pointer;
border-radius: 20%;
border-radius: 6px;
& > p {
margin-top: 3px;
margin-bottom: 3px;
font-size: 10px;
font-weight: 350;
color: black;
white-space:nowrap;
&:hover {
color: #2952f6;
font-weight: 35s0;

@ -42,42 +42,42 @@
</ul>
</div>
<!-- 切换栏对应的小页面 -->
<!-- 页面-1 -->
<!-- 简介页面-1 -->
<div class="Res_con" v-show="activeIndex == 1">
<div class="item_2-1" v-for="(item, index) in 5" :key="index">
<div class="item_2-1" v-for="(item, index) in datalist" :key="item.id">
<div class="ResImg-1">
<img src="../../assets/images/kctp.png" />
</div>
<div class="ResClaDic">
<p>课程名称-----{{ item }}</p>
<P>课程描述-----{{ item }}</P>
<div class="ResClaDic-1">
<p>{{index + 1}}.&nbsp;{{ item.name }}</p>
<p style="color: rgb(180,180 ,180 );">&nbsp;{{ item.description }}</p>
</div>
</div>
</div>
<!-- 页面-2 -->
<!-- PPT页面-2 -->
<div class="Res_con" v-show="activeIndex == 2">
<div class="item_2-2" v-for="(item, index) in 7" :key="index">
<div class="item_2-2" v-for="(item, index) in datalist" :key="item.id">
<div class="ResImg-2">
<div class="Img">
<img src="../../assets/icons/ppt.png" />
<img :src="item.img" />
</div>
</div>
<div class="ResClaDic">
<p>PPT名称-----{{ item }}</p>
<p>{{ index + 1 }}.&nbsp;{{ item.name }}</p>
</div>
</div>
</div>
<!-- 页面-3 -->
<!-- 视频页面-3 -->
<div class="Res_con" v-show="activeIndex == 3">
<div class="item_2-3" v-for="(item, index) in 8" :key="index">
<div class="item_2-3" v-for="(item, index) in datalist" :key="index">
<div class="ResImg-2">
<div class="Img">
<img src="../../assets/icons/视频.png" />
</div>
</div>
<div class="ResClaDic">
<p>{{ item }}</p>
<el-button plain @click="centerDialogVisible = true">
<p>{{ index + 1 }}.&nbsp;{{ item.name }}</p>
<el-button plain @click="hand1(item)">
点击播放
</el-button>
</div>
@ -85,20 +85,20 @@
</div>
<el-dialog
v-model="centerDialogVisible"
title="视频播放中"
:title="`${data.name}`"
width="1000"
style="height:600px;"
align-center
class="adad"
>
<span>点击开了一个弹框</span>
<!-- <span>点击开了一个弹框</span> -->
<template #footer>
<div class="dialog-footer">
<video
src="https://www.bilibili.com/video/BV1HV4y1a7n4?p=50&vd_source=9e99d3200788d6043e077de463ef019b"
></video>
<video width="300" height="200" :src="data.img"></video>
</div>
</template>
</el-dialog>
<!-- 页面-4 -->
<!-- 文本页面-4 -->
<div class="Res_con" v-show="activeIndex == 4">
<div class="item_2-4" v-for="(item, index) in 8" :key="index">
<div class="ResImg-2">
@ -112,7 +112,7 @@
</div>
</div>
<!-- 页面-5 -->
<!-- 音频页面-5 -->
<div class="Res_con" v-show="activeIndex == 5">
<div class="item_2-5" v-for="(item, index) in 10" :key="index">
<div class="ResImg-2">
@ -122,9 +122,6 @@
</div>
<div class="ResClaDic">
<p>音频名称-----{{ item }}</p>
<el-button plain @click="centerDialogVisible = true">
点击播放
</el-button>
</div>
</div>
</div>
@ -149,26 +146,23 @@
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import { ref, watch,reactive } from 'vue'
import type { TabsPaneContext } from 'element-plus'
import ContainerCla from './ContainerCla.vue'
import ContainerKno from './ContainerKno.vue'
// import { getAssApi } from '@/api/courseChaptersApi'
import { SeResourceFavourControllerService } from '../../../generated/services/SeResourceFavourControllerService'
const centerDialogVisible = ref(false)
const data = ref<any>({})
function hand1(item:any){
centerDialogVisible.value = true
data.value= item
console.log(data.value);
}
const activeIndex = ref(1)
function hsndelShow(index: number) {
activeIndex.value = index
}
// //=========================
// function handleApi(params) {
// getAssApi(params).then(res => {
// arr.value = res.data.records
// total.value = res.data.total
// console.log(arr.value, '-', total.value)
// })
// }
const arr = ref([])
const total = ref(0)
//
@ -193,19 +187,8 @@ watch(activeIndex, () => {
initFenYie()
getDatalist()
})
// function hand() {
// console.log(res)
// // handleApi(params)
// }
const params = {
current: currentPage1.value,
type: activeIndex.value,
pageSize: pageSize1.value,
sortField: '',
sortOrder: '',
userId: '3',
}
const datalist = ref([
{
@ -221,6 +204,14 @@ const datalist = ref([
])
const getDatalist = async () => {
const params = {
current: currentPage1.value,
type: activeIndex.value,
pageSize: pageSize1.value,
sortField: '',
sortOrder: '',
userId: '3',
}
const res =
await SeResourceFavourControllerService.listPostByPageUsingPost3(params)
datalist.value = res.data.records
@ -228,17 +219,6 @@ const getDatalist = async () => {
console.log(datalist.value[0])
}
getDatalist()
// hand()
// const obj = {
// type: activeIndex.value,
// page: currentPage1.value,
// pageSize: pageSize1.value,
// sortField:'',
// sortOrder:'',
// resourceIdList: ''
// }
// handleApi(obj)
//=========================
const activeName = ref('first')
const handleClick = (tab: TabsPaneContext, event: Event) => {
@ -354,20 +334,20 @@ const handleClick = (tab: TabsPaneContext, event: Event) => {
//
.ResImg-1 {
width: 100%;
height: 60%;
height: 215px;
border-bottom: 1px solid rgb(229, 227, 227);
overflow: hidden;
img {
&>img {
width: 100%;
height: 100%;
}
}
//
.ResClaDic {
.ResClaDic-1 {
width: 100%;
height: 40%;
height: 85px;
padding: 2%;
display: flex;
flex-direction: column;
@ -376,19 +356,25 @@ const handleClick = (tab: TabsPaneContext, event: Event) => {
.ResImg-2 {
width: 100%;
height: 60%;
height: 225px;
border-bottom: 1px solid rgb(214, 214, 214);
}
.Img {
width: 100%;
height: 100%;
display: flex;
display: flex;
justify-content: center;
align-items: center;
padding: 5%;
&>img{
height: 95%;
width: 65%;
}
}
.ResClaDic > p {
.ResClaDic-1 > p {
font-family: Inter, Inter;
font-weight: 500;
font-size: 20px;
@ -401,7 +387,7 @@ const handleClick = (tab: TabsPaneContext, event: Event) => {
.item_2-2,
.item_2-5 {
width: 100%;
height: 300px;
height: 310px;
margin-top: 20px;
border-left: 1px solid #e4e4e4;
border-top: 1px solid #e4e4e4;
@ -410,10 +396,27 @@ const handleClick = (tab: TabsPaneContext, event: Event) => {
border-radius: 6px;
margin-bottom: 32px;
}
.ResClaDic {
width: 100%;
height: 85px;
padding: 2%;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.ResClaDic > p {
font-family: Inter, Inter;
font-weight: 500;
font-size: 20px;
color: #333333;
line-height: 23px;
text-align: left;
margin-left: 5px;
}
.item_2-3,
.item_2-4 {
width: 100%;
height: 300px;
height: 310px;
margin-top: 20px;
border-left: 1px solid #e4e4e4;
border-top: 1px solid #e4e4e4;

@ -12,8 +12,8 @@ const selectedIds = ref([])
const loading = ref(false)
const showCheckbox = ref(false)
const params = ref({
pagesize: '15',
pagenum: '1',
// pagesize: '10',
// pagenum: '1',
userId: '1',
})
@ -28,6 +28,7 @@ const getrecordList = async () => {
params.value.pagenum,
params.value.pagesize,
)
console.log(res)
recordList.value = res.data.records
console.log(res)
//
@ -206,7 +207,7 @@ const goToAnotherPage = (address) => {
<el-pagination
v-model:current-page="params.pagenum"
v-model:page-size="params.pagesize"
:page-sizes="[2, 5, 7, 15]"
:page-sizes="[5, 10, 15, 20]"
:background="true"
layout="jumper,total, sizes, prev, pager, next "
:total="total"
@ -238,17 +239,26 @@ const goToAnotherPage = (address) => {
margin: 10px 0;
}
ul {
width: 100%;
list-style-type: none;
padding: 10;
display: flex;
flex-wrap: wrap;
justify-content: start;
text-align: center;
display: grid;
grid-template-columns: repeat(auto-fill, 272px);
justify-content: space-around;
}
li {
/* margin-bottom: 30px; */
transition: filter 0.3s; /* 添加过渡动画 */
/* flex: 1 0 20%; */
width: calc(20% - 20px);
width: 250px;
width: 100%;
flex-direction: column;
align-items: center;
text-align: center;

@ -3,12 +3,9 @@ import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { id } from 'element-plus/es/locales.mjs'
import * as echarts from 'echarts'
<<<<<<< HEAD
// import { useRoute } from 'vue-router'
=======
<<<<<<< HEAD
import { useRoute } from 'vue-router'
>>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a
import {
getCourseList,
addCourse,
@ -16,14 +13,7 @@ import {
deleteCourse,
getCourseInfo,
} from '@/api/courseChaptersApi'
<<<<<<< HEAD
import { useRoute, useRouter } from 'vue-router'
=======
=======
import { useRoute ,useRouter} from 'vue-router'
import { getCourseList, addCourse, editCourse, deleteCourse, getCourseInfo } from '@/api/courseChaptersApi'
>>>>>>> 1a620e19de970965f426e07348b1dbc4be900eaf
>>>>>>> 991fa5ab08c56c84c5a276226f8fbc2ec78f859a
const route = useRoute()
const router = useRouter()
// id id
@ -70,7 +60,7 @@ const handleClose = () => {
const submit = async () => {
if (flog.value) {
await editCourse({
id: activeIndex.value,
...editdata.value,
content: formData.value.description,
})
} else {
@ -124,11 +114,13 @@ const filterTarger = (target) => {
return res.label
}
const editdata = ref({ id: '', objectiveId:'' })
//
const flog = ref(false)
const editBook = async (obj) => {
const res = await getCourseInfo({ id: obj.id })
editdata.value.id = res.data.id
editdata.value.objectiveId = res.data.objectiveId
flog.value = true
console.log(obj)
activeIndex.value = res.data.id

@ -1,62 +1,53 @@
<script lang="ts" setup>
<script setup>
import { ref } from 'vue'
// import axios from 'axios'
import { CourseResourceControllerService } from '../../../../generated/services/CourseResourceControllerService'
const props = defineProps(['dafulIndex'])
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
const visibilerDrawer = ref(false)
import { ElMessage } from 'element-plus'
//
const visibleDramwer = ref(false)
import { CourseResourceControllerService } from '../../../../generated/services/CourseResourceControllerService'
//
const defaultForm = {
description: '',
id: '',
img: '',
img: '', //
name: '',
type: '',
type: '', //
path: '',
}
const imageUrl = ref('')
const onSelectFile = (uploadFile) => {
// console.log(uploadFile)
//
imageUrl.value = URL.createObjectURL(uploadFile.raw)
//
formModel.value.img = uploadFile.raw
}
//
const formModel = ref({
...defaultForm,
})
//
const rules = {
name: [
{ required: true, message: '请输入资源名称', trigger: 'blur' },
{ min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' },
],
}
//open
const open = async (row) => {
visibleDramwer.value = true
//console.log(row.id)
const open = (row) => {
visibilerDrawer.value = true
// console.log(row)
if (row.id) {
//row.id
const res = await CourseResourceControllerService.getAllUsingGet1(row.id)
//
formModel.value = res.data.records
console.log(res)
//
//
//row.id
console.log('编辑回显')
} else {
//
formModel.value = {
...defaultForm,
}
} //form
//
imageUrl.value = ''
console.log('添加')
}
}
defineExpose({
open,
})
const selectVal = ref(props.dafulIndex)
//
const rules = {
name: [
{ required: true, message: '请输入资源名称', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' },
],
type: [{ required: true, trigger: 'blur' }],
}
const selectOp = ref([
{ label: 'ppt', value: '1' },
{ label: '图片', value: '2' },
@ -65,127 +56,115 @@ const selectOp = ref([
{ label: '文件', value: '5' },
{ label: '音频', value: '6' },
])
const fileList = ref([])
function clearFileList() {
fileList.value.length = 0
}
const handleSel = () => {
fileList.value.length = 0
}
//
import type { UploadProps } from 'element-plus'
const clearFileList = () => {
console.log(fileList)
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
fileList.value = []
}
const handlePreview: UploadProps['onPreview'] = (file) => {
console.log(file)
}
const formRef = ref()
function isSubmit() {
formRef.value.validate((valid, fields) => {
if (valid) {
const params = {
name: formModel.value.name,
type: selectVal.value,
img: fileList.value[0]?.raw,
description: formModel.value.description,
}
console.log('根据参数:', params, '去调用接口???')
} else {
console.log('error submit!', fields)
}
})
}
// upd
const beforeAvatarUpload = (rawFile) => {
console.log('执行了')
switch (+selectVal.value) {
switch (+formModel.value.type.value) {
case 1:
if (rawFile.type !== 'application/vnd.ms-powerpoint') {
if (rawFile.type !== 'applicationnd.ms-powerpoint') {
clearFileList()
ElMessage.error('必须是ppt文件!')
} else {
clearFileList()
fileList.value.push(rawFile)
}
break
case 2:
if (!rawFile.type.startsWith('image/')) {
clearFileList()
ElMessage.error('必须是??文件!')
ElMessage.error('必须是图片文件!')
} else {
fileList.value.push(rawFile)
}
break
case 3:
if (!rawFile.type.startsWith('video/')) {
clearFileList()
ElMessage.error('必须是视频文件!')
} else {
clearFileList()
fileList.value.push(rawFile)
}
break
case 4:
if (!rawFile.type.startsWith('applicationf')) {
clearFileList()
ElMessage.error('必须是pdf文件!')
} else {
clearFileList()
fileList.value.push(rawFile)
}
break
case 5:
if (
!rawFile.type.startsWith(
'applicationnd.openxmlformats-officedocument.wordprocessingml.document',
) &&
!rawFile.type.startsWith('application/msword')
) {
clearFileList()
ElMessage.error('必须是word文件!')
} else {
clearFileList()
fileList.value.push(rawFile)
}
break
case 6:
if (!rawFile.type.startsWith('audio/')) {
clearFileList()
ElMessage.error('必须是音频文件!')
} else {
clearFileList()
fileList.value.push(rawFile)
}
break
// case 3:
// if (false) {
// clearFileList()
// ElMessage.error('??')
// } else {
// clearFileList()
// fileList.value.push(rawFile)
// }
// break
// case 4:
// if (false) {
// clearFileList()
// ElMessage.error('??')
// } else {
// clearFileList()
// fileList.value.push(rawFile)
// }
// break
// case 5:
// if (false) {
// clearFileList()
// ElMessage.error('??')
// } else {
// clearFileList()
// fileList.value.push(rawFile)
// }
// break
// case 6:
// if (false) {
// clearFileList()
// ElMessage.error('??')
// } else {
// clearFileList()
// fileList.value.push(rawFile)
// }
// break
}
}
//
const emit = defineEmits('success')
const isSubmit = async () => {
//
if (formModel.value.id) {
console.log('编辑')
} else {
console.log(formModel.value)
await CourseResourceControllerService.saveCourseResourceUsingGet1(
formModel.value,
)
ElMessage.success('添加成功')
visibilerDrawer.value = false
//
emit('success', 'add')
}
}
const isabolish = () => {
visibilerDrawer.value = false
formModel.value = []
imageUrl.value = ''
// console.log(formModel.value)
}
defineExpose({
open,
})
</script>
<template>
<el-drawer
v-model="visibleDramwer"
:title="formModel.id ? '编辑资源' : '添加资源'"
direction="rtl"
size="50%"
>
<!-- 添加资源表单 -->
<el-form
class="resourceformModel"
:model="formModel"
ref="formRef"
:rules="rules"
label-width="100px"
>
<el-drawer v-model="visibilerDrawer" title="标题" direction="rtl" size="50%">
<el-form :model="formModel" ref="fromRef" :rules="rules">
<el-form-item label="资源名称" prop="name">
<el-input
v-model="formModel.name"
placeholder="请输入资源名称"
></el-input>
</el-form-item>
<el-form-item label="资源类型">
<el-form-item label="资源类型" prop="type">
<el-select
@change="handleSel"
v-model="selectVal"
v-model="formModel.type"
placeholder="请选择资源类型"
size="large"
style="width: 100%"
@ -198,47 +177,58 @@ const beforeAvatarUpload = (rawFile) => {
/>
</el-select>
</el-form-item>
<el-form-item label="上传资源" prop="fileList">
<el-form-item label="资源封面" prop="img">
<!-- 此处需要关闭自动上传 -->
<el-upload
v-model:file-list="fileList"
:limit="1"
class="upload-demo"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
:on-preview="handlePreview"
:on-remove="handleRemove"
list-type="picture"
class="avatar-uploader"
:show-file-list="false"
:auto-upload="false"
:before-upload="beforeAvatarUpload"
:on-change="onSelectFile"
>
<el-button type="primary">点击上传资源</el-button>
<template #tip>
<div class="el-upload__tip">
jpg/png files with a size less than 500kb
</div>
</template>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
</el-form-item>
<el-form-item label="资源简介" prop="description">
<div class="editor">
<quill-editor
v-model:content="formModel.description"
content-type="html"
theme="snow"
></quill-editor>
</div>
<el-input
v-model="formModel.description"
placeholder="请输入资源简介"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary">取消</el-button>
<el-button type="primary" @click="isabolish">取消</el-button>
<el-button type="info" @click="isSubmit">确定</el-button>
</el-form-item>
</el-form>
</el-drawer>
</template>
<style lang="scss" scoped>
.editor {
width: 100%;
:deep(.ql-editor) {
min-height: 200px;
.avatar-uploader {
:deep() {
.avatar {
width: 178px;
height: 178px;
display: block;
}
.el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
}
}
</style>

@ -1,11 +1,11 @@
<script setup>
//
import ppt from '@/assets/icons/ppt (1).png'
import image from '@/assets/icons/图片 (2).png'
import video from '@/assets/icons/视频 .png'
import image from '@/assets/icons/image.png'
import video from '@/assets/icons/video.png'
import pdf from '@/assets/icons/pdf (1).png'
import test from '@/assets/icons/文件.png'
import audio from '@/assets/icons/音频1.png'
import test from '@/assets/icons/test.png'
import audio from '@/assets/icons/audio.png'
import { ElMessageBox, ElMessage } from 'element-plus'
import { ref } from 'vue'
@ -19,7 +19,7 @@ const total = ref(0)
const pptresourceList = ref([])
const loading = ref(false)
const params = ref({
pagesize: '15',
pagesize: '10',
pagenum: '1',
type: '1', //ppt
})
@ -27,6 +27,7 @@ const params = ref({
//
const getpptresourceList = async () => {
loading.value = true
console.log(params.value.pagenum)
const res = await CourseResourceControllerService.getAllUsingGet1(
params.value.pagenum,
params.value.pagesize,
@ -58,6 +59,8 @@ const onSizeChange = (size) => {
}
const onCurrentChange = (page) => {
pptresourceList.value.pagenum = page
params.value.pagenum = page
console.log(page)
getpptresourceList()
}
@ -82,7 +85,7 @@ const param = ref({
download: '0',
content: '',
address: '/portal',
type: '4',
type: '1',
})
//
const generateRecords = async (rescource) => {
@ -92,20 +95,32 @@ const generateRecords = async (rescource) => {
// console.log(param)
}
const resourceAddRef = ref()
//
const rescourceRef = ref()
//
const onAddResource = () => {
resourceAddRef.value.open({})
rescourceRef.value.open({})
}
//
const onEditResource = (row) => {
resourceAddRef.value.open(row)
rescourceRef.value.open(row)
}
//
const onsuccess = (state) => {
if (state == 'add') {
//
const lastPage = Math.ceil((total.value + 1) / params.value.pagesize)
//
params.value.pagenum = lastPage
getpptresourceList()
} else {
//
getpptresourceList()
}
}
</script>
<template>
<div>
<div class="top">
<el-button @click="onAddResource">添加资源</el-button>
<el-button @click="onAddResource()">添加资源</el-button>
</div>
<div class="body">
<div class="nav">
@ -181,7 +196,7 @@ const onEditResource = (row) => {
<el-icon @click="onDeleteResource(resource.id)">
<Delete />
</el-icon>
<el-icon @click="onEditResource(row)">
<el-icon @click="onEditResource(resource)">
<Edit />
</el-icon>
</div>
@ -204,7 +219,7 @@ const onEditResource = (row) => {
<el-pagination
v-model:current-page="currentPage4"
v-model:page-size="pageSize4"
:page-sizes="[1, 2, 3, 4]"
:page-sizes="[5, 10, 15, 20]"
:small="small"
:disabled="disabled"
:background="background"
@ -216,10 +231,7 @@ const onEditResource = (row) => {
/>
</div>
<!-- 添加编辑的抽屉 -->
<resource-add
:dafulIndex="params.type"
ref="resourceAddRef"
></resource-add>
<resource-add ref="rescourceRef" @success="onsuccess"></resource-add>
<!-- -->
</div>
</div>
@ -263,10 +275,16 @@ ul {
flex-wrap: wrap;
/* justify-content: space-evenly; */
justify-content: start;
display: grid;
grid-template-columns: repeat(auto-fill, 272px);
justify-content: space-around;
}
li {
transition: filter 0.3s; /* 添加过渡动画 */
width: calc(25% - 25px);
width: 250px;
width: 100%;
flex-direction: column;
align-items: center;
margin-bottom: 10px;

@ -7,79 +7,96 @@ onMounted(() => {
//
myChart.setOption({
//
grid: {
left: '4%', //
right: '10%', //
bottom: '20%', //
top: '10%', //
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999',
},
},
},
legend: {
left: 'center', //
bottom: 0, //
orient: 'horizontal', //
itemWidth: 16, // 0
itemHeight: 0, // 0
data: ['本月', '上月'],
},
// grid: {
// left: '3%',
// right: '4%',
// bottom: '3%',
// containLabel: true
// },
toolbox: {
feature: {
saveAsImage: {},
dataView: { show: true, readOnly: false },
magicType: { show: true, type: ['line', 'bar'] },
restore: { show: true },
saveAsImage: { show: true },
},
},
xAxis: {
type: 'category',
boundaryGap: true,
data: [
'09-01',
'09-03',
'09-05',
'09-07',
'09-09',
'09-11',
'09-13',
'09-15',
],
},
yAxis: {
type: 'value',
legend: {
data: ['本月', '上月'],
},
xAxis: [
{
type: 'category',
data: [
'09-01',
'09-03',
'09-05',
'09-07',
'09-09',
'09-11',
'09-13',
'09-15',
],
axisPointer: {
type: 'shadow',
},
},
],
yAxis: [
{
type: 'value',
name: '浏览次数',
min: 0,
max: 200,
interval: 40,
axisLabel: {
formatter: '{value}',
},
},
{
type: 'value',
name: '',
min: 0,
max: 100,
interval: 20,
axisLabel: {
formatter: '{value}',
},
},
],
series: [
{
name: '本月',
// itemStyle: {
// color: '#0052D9'
// },
symbol: 'circle',
itemStyle: {
color: '#0052D9', //
borderWidth: 1.5, //
borderColor: 'white', //
type: 'bar',
tooltip: {
valueFormatter: function (value) {
return (value as number) + ' 次'
},
},
symbolSize: 8, //
type: 'line',
data: [20, 38, 60, 65, 90, 55, 36, 30],
data: [2, 4, 7, 23, 25, 76, 35, 62, 32, 20, 6, 3],
},
{
name: '上月',
symbol: 'circle',
itemStyle: {
color: '#B5C7FF', //
borderWidth: 1.5, //
borderColor: 'white', //
type: 'bar',
tooltip: {
valueFormatter: function (value) {
return (value as number) + ' 次'
},
},
symbolSize: 8, //
data: [2, 5, 9, 26, 28, 70, 75, 82, 48, 18, 6, 2],
},
{
type: 'line',
data: [22, 25, 48, 70, 80, 45, 24, 38],
yAxisIndex: 1,
data: [2, 4, 7, 23, 25, 76, 35, 62, 32, 20, 6, 3],
},
{
type: 'line',
yAxisIndex: 1,
data: [2, 5, 9, 26, 28, 70, 75, 82, 48, 18, 6, 2],
},
],
})

@ -1,10 +1,11 @@
<script setup>
import echarts from '@/views/home/components/Echart/Echarts.vue'
import conheader from '@/views/home/components/ConHeader.vue'
defineProps(['sum'])
</script>
<template>
<div class="info_container" style="width: 95%; height: 384px">
<conheader title="主页访问数据(次)"></conheader>
<conheader :title="`主页访问数据(${sum}次)`"></conheader>
<div class="info_content" style="width: 75%; height: 100%">
<echarts></echarts>
</div>

@ -10,7 +10,6 @@ const props = defineProps({
type: Object,
},
})
console.log(props.data, 'djegd ')
const formModel = ref()
const loading = ref()
//true
@ -19,6 +18,7 @@ const editForm = ref({
name: '',
content: '',
})
const readonlyField = computed(() => editForm.value.name)
const editRowIndex = ref()
const openEditDialog = (row) => {
@ -46,14 +46,18 @@ const cancelEdit = () => {
}
onMounted(() => {
if (props.data.roleId === 1) {
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: 'degree', name: '学位', content: props.data.degree },
{
par: 'academicDegree',
name: '学位',
content: props.data.academicDegree,
},
{
par: 'professionalTitle',
name: '职称',
@ -75,7 +79,7 @@ onMounted(() => {
content: props.data.politicalStatus,
},
]
} else if (props.data.roleId === 2) {
} else if (props.data.roleId[0] === '2') {
formModel.value = [
{ par: 'name', name: '姓名', content: props.data.name },
{ par: 'sex', name: '性别', content: props.data.sex },

@ -1,6 +1,7 @@
<script setup>
import add from '@/assets/images/add.png'
// import { Plus } from '@element-plus/icons-vue'
import tool from '@/utils/oss.js'
import { userChangeService } from '@/api/user/user.js'
const dialogFormVisible = ref(false)
import { ref } from 'vue'
@ -10,7 +11,6 @@ const props = defineProps({
},
})
// const data = ref(props.data, 'dsfd')
console.log(props.data, 44444)
const imageUrl = ref('')
//
const form = ref()
@ -42,37 +42,21 @@ const formLabelWidth = '70px'
//
imageUrl.value = props.data.icon
//
const openFileInput = () => {
const input = document.createElement('input')
input.type = 'file'
input.accept = 'image/*'
input.style.display = 'none'
input.onchange = (event) => {
const file = event.target.files[0]
if (file) {
const reader = new FileReader()
reader.onload = () => {
imageUrl.value = reader.result
}
reader.readAsDataURL(file)
changeInfo()
}
}
document.body.appendChild(input)
input.click()
document.body.removeChild(input)
const upload = async (option) => {
const res = await tool.oss.upload(option.file)
const url = 'https://wenyu132.oss-cn-beijing.aliyuncs.com/' + res.name
imageUrl.value = url
changeInfo()
}
//
const changeInfo = async () => {
const userInfo = {
// username: form.value.username,
phone: form.value.phone,
id: form.value.id,
nickName: form.value.nickName,
icon: imageUrl.value,
}
const jsonData = JSON.stringify(userInfo)
console.log(jsonData)
await userChangeService(jsonData)
dialogFormVisible.value = false
}
@ -83,9 +67,9 @@ const changeInfo = async () => {
<div class="avater">
<img :src="imageUrl" alt="Uploaded" v-if="imageUrl" class="avater" />
</div>
<div class="click" @click="openFileInput" :http-request="upload">
<el-upload class="click" :http-request="upload" :show-file-list="false">
<img :src="add" />
</div>
</el-upload>
<div
class="info_content"
style="height: 58px"

@ -1,14 +1,34 @@
<script setup>
import { onMounted, ref, computed } from 'vue'
const props = defineProps({
username: String,
data: {
type: Object,
},
})
const username = ref()
const daysOnJob = ref()
const flagVisible = ref(true)
onMounted(() => {
username.value = props.data.name
const hireDate = new Date(props.data.joinWorkTime)
console.log(props.data.name, 'welcome')
//
const currentDate = new Date()
const millisecondsPerDay = 1000 * 60 * 60 * 24
daysOnJob.value = Math.floor((currentDate - hireDate) / millisecondsPerDay)
})
</script>
<template>
<div class="nav_info">
<div class="name">
{{ props.username }}
{{ username }}
</div>
<div class="intro" v-if="props.data.roleId[0] === '1'">
<p>今天是你工作的第{{ daysOnJob }}~~</p>
</div>
<div class="intro" v-else>
<p>Hell0,欢迎回来</p>
</div>
<div class="intro">今天是你的第一天~~</div>
</div>
</template>
<style scoped>

@ -19,19 +19,21 @@ const rightVisible = ref(false)
userStore.getUserInfo().catch((error) => {
console.log(error)
})
let sum: any = localStorage.getItem('sum') || '0'
onMounted(() => {
// getData()
sum = parseInt(sum) + 1
localStorage.setItem('sum', sum.toString())
console.log(sum, 'sum')
username.value = userStore.userName
data.value = userStore.data
infoData.value = userStore.userInfo
// console.log(data.value, '11111')
// console.log(userStore.userInfo, '22222')
// console.log(userStore, 'userStore')
username.value = data.value.username
flag.value = true
role.value = data.value.roles[0]
if (role.value === '老师') {
if (role.value === '1') {
rightVisible.value = true
} else {
rightVisible.value = false
@ -42,13 +44,13 @@ onMounted(() => {
<div class="container">
<div class="left">
<div class="nav">
<welcome :username="username"></welcome>
<welcome :data="infoData" v-if="flag"></welcome>
</div>
<div class="info" style="width: 100%; height: 368px">
<Info :data="infoData" v-if="flag"></Info>
</div>
<div class="echarts" style="width: 100%; height: 444px">
<echarts></echarts>
<echarts :sum="sum"></echarts>
</div>
</div>
<div v-if="rightVisible" class="right">

@ -580,7 +580,7 @@ onUnmounted(() => {
// background: url('../../assets/images/background.jpg') no-repeat;
.loin_form {
position: relative;
top: 30vh;
top: 20vh;
width: 80%;
// background: url('../../assets/images/login_form.png') no-repeat;
// background-size: cover;

Loading…
Cancel
Save