ww 3 months ago
commit 4d7de237dc
  1. 2
      src/api/user/chapter.js
  2. 14
      src/api/user/object.js
  3. 11
      src/views/course/basicCourseInformation.vue
  4. 4
      src/views/course/components/course-brief.vue
  5. 60
      src/views/course/components/course-chapters.vue
  6. 570
      src/views/course/components/course-object.vue
  7. 8
      src/views/course/components/courseEdit.vue
  8. 2
      src/views/course/components/knowledge-graph.vue
  9. 68
      src/views/course/components/knowledge-statistic.vue
  10. 9
      src/views/course/courseDetails.vue
  11. 40
      vite.config.ts.timestamp-1723300901027-675730089c647.mjs

@ -6,6 +6,6 @@ export const getChaptersListApi = (params) => {
// 添加课程章节
export const addChaptersApi = (params) => request.post('/chapter2/add', params)
// 删除课程章节
export const delChapterstApi = (id) => {
export const delChaptersApi = (id) => {
return request.delete(`/chapter2/delete/${id}`)
}

@ -0,0 +1,14 @@
import request from '@/utils/request'
// 获取目标类型
export const getObjectType = () => request.get(`/api/objectives_type/list`)
// 修改目标内容
export const updateContents = (params) => {
return request.put(`/api/objective_contents/update`, params)
}
// 获取目标列表
export const getObjectList = (params) => {
return request({
url: '/api/course_objectives/list/' + params.id,
params,
})
}

@ -69,7 +69,7 @@ const onSearch = () => {
const onReset = () => {
params.value.pageNo = 1
params.value.assessmenttype = ''
params.value.teacher = ''
// params.value.teacher = ''
params.value.category = ''
params.value.nature = ''
getCourseList()
@ -198,7 +198,7 @@ const CloseCouresNameChangeEvent = () => {
<el-form-item label="考核类型:" class="short-form-item">
<el-select v-model="params.assessmenttype">
<el-option label="考试" value="1"></el-option>
<el-option label="考" value="2"></el-option>
<el-option label="考" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item>
@ -215,13 +215,6 @@ const CloseCouresNameChangeEvent = () => {
</el-icon>
</div>
<h2 class="course_name">{{ course_name }}</h2>
<!-- <p class="teacher_name">讲师{{ courseList.teacher }}</p>
<p class="credit">
<span>{{ credit_name }}</span>
学时|
<span>{{ classhours_name }}</span>
学分
</p> -->
</li>
<li v-for="item in courseList" :key="item.id">
<img title="点击查看课程详情" :src="item.img" alt="" @click="onGetCourseObject(item.id)" />

@ -149,10 +149,12 @@ onMounted(() => {
font-size: 14px;
.pp {
margin-top: 10px;
line-height: 1.3;
margin-top: 9px;
display: inline;
padding-left: 35px;
color: #2e2e2e;
letter-spacing: 1px;
}
}

@ -6,21 +6,25 @@ import { useRoute } from 'vue-router'
import {
getChaptersListApi,
addChaptersApi,
delchaptersApi,
delChaptersApi,
} from '@/api/user/chapter'
import { onMounted } from 'vue'
const route = useRoute()
// const route = useRoute()
// const router = useRouter()
const courseId = ref()
// const courseId = ref()
const courseId = '719f91586a64413898253c5b7d046fd8'
onMounted(() => {
courseId.value = route.query.id
// courseId.value = route.query.id
// courseId.value = '719f91586a64413898253c5b7d046fd8'
getChaptersList()
})
// console.log(courseId.value, 'courseId.value')
const getChaptersList = async () => {
console.log(courseId.value, 'courseId.value')
const res = await getChaptersListApi({ id: courseId.value })
console.log(courseId, 'courseId.value')
const res = await getChaptersListApi({ id: courseId })
console.log(res, 'get')
const transformedData: Tree[] = res.data.map((item: any) => ({
id: item.id,
name: item.name,
@ -30,15 +34,14 @@ const getChaptersList = async () => {
name: children.name,
pid: children.pid,
children: children.children.map((children: any) => ({
id: children.id,
name: children.name,
pid: children.pid,
knowledgePoints: children.knowledgePoints.map((knowledgePoints: any) => ({
id: knowledgePoints.id,
name: knowledgePoints.name,
pid: knowledgePoints.pid,
})),
})),
}))
dataSource.value = transformedData
console.log(res)
}
interface Tree {
id: number
@ -57,14 +60,14 @@ const append = async (data: Tree) => {
id: id++,
name: `${value}`,
pid: data.id,
courseId: courseId.value,
courseId: courseId,
}
if (!data.children) {
data.children = []
}
data.children.push(newChild)
const res = await addChaptersApi(newChild)
console.log(res)
console.log(res, 'appendres')
if (res.code === 200) {
//
dataSource.value = [...dataSource.value]
@ -83,22 +86,27 @@ const append = async (data: Tree) => {
}
//
const remove = async (node: Node, data: Tree) => {
const res = await getChaptersListApi(data.id)
console.log(res, 'delres')
ElMessageBox.confirm('确定删除本章节吗?', '提示', {
confirmButtonText: '确定',
console.log(node, data)
await ElMessageBox.confirm('您确定删除这条课程信息吗', '温馨提示', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
center: true,
})
const parent = node.parent
const children: Tree[] = parent.data.children || parent.data
const index = children.findIndex((d) => d.id === data.id)
children.splice(index, 1)
dataSource.value = [...dataSource.value]
await delChaptersApi(data.id)
.then(() => {
const parent = node.parent
const children: Tree[] = parent.data.children || parent.data
const index = children.findIndex((d) => d.id === data.id)
children.splice(index, 1)
dataSource.value = [...dataSource.value]
ElMessage.success('删除成功')
})
.catch((err: any) => {
ElMessage.error(err.response.data.message)
})
}
//
const getDetails = (id: any) => { }
const dataSource = ref<Tree[]>([
{
id,
@ -130,7 +138,7 @@ const dataSource = ref<Tree[]>([
:expand-on-click-node="false" empty-text="暂无章节">
<template #default="{ node, data }">
<span class="custom-tree-node">
<span>{{ data.name }}</span>
<span @click="getDetails(data.id)">{{ data.name }}</span>
<span>
<el-button @click="append(data)">添加</el-button>
<el-button @click="remove(node, data)">删除</el-button>

@ -1,361 +1,158 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
// import { id } from 'element-plus/es/locales.mjs'
import * as echarts from 'echarts'
// import { useRoute } from 'vue-router'
const emit = defineEmits(['updateObject'])
import {
getCourseList,
addCourse,
editCourse,
deleteCourse,
getCourseInfo,
} from '@/api/courseChaptersApi'
import { useRoute, useRouter } from 'vue-router'
import { Edit, Delete } from '@element-plus/icons-vue'
import { getObjectType, updateContents, getObjectList } from '@/api/user/object'
import { useRoute } from 'vue-router'
const route = useRoute()
const router = useRouter()
const formData = ref({
description: '',
})
const activeIndex = ref(0)
//
const addPoint = (id: any) => {
console.log(id, 'id')
activeIndex.value = id
dialogVisible.value = true
flog.value = false
// updateDisabledStatus()
}
// const router = useRouter()
const courseId = ref(0)
//
const data = ref({})
//
const params = ref({
content: '',
id: '',
objectiveId: '',
})
//
const getObject = async () => {
const res = await getObjectList({ id: courseId.value })
console.log(res, 'objectres')
data.value = res.data[0].courseObjectivesTrees
params.value = res.data[0].contents[0]
console.log(params.value, 'params.value')
console.log(data.value, 'data.value')
// content.value = res.data[0].contents[0].content
}
//
const type = ref({
id: '',
typeName: '',
})
const getType = async () => {
const res = await getObjectType()
type.value = res.data.slice(1, 5)
console.log(type.value, 'typeres')
}
onMounted(() => {
courseId.value = route.query.id
console.log(courseId.value, 'courseid.vlue')
getObject()
getType()
})
//
const isEditing = ref(false)
const updateContent = () => {
isEditing.value = true
content.value = params.value.content
}
const content = ref('')
const textChange = async (val: any) => {
params.value.content = content.value
//
const saveContent = async () => {
console.log(params.value.content, ' params.value.content')
console.log(params.value, 'params.value')
console.log(params.value.id, 'params.id')
// const jsonstr = JSON.stringify(params)
// const res = await editCourse(jsonstr)
const res = await editCourse({
id: params.value.id,
objectiveId: params.value.objectiveId,
content: params.value.content,
})
console.log(res, 'res')
console.log(content.value, 'text.value')
}
//
const dialogVisible = ref(false)
//
const handleClose = () => {
dialogVisible.value = false
}
const close = () => {
formData.value = {
id: null,
target: '',
description: '',
}
dialogVisible.value = false
}
//
// const filterTarger = (target) => {
// const res = targetList.value.find((item) => {
// if (item.id === target) {
// console.log(item, 'item')
// return item
// }
// })
// return res.label
// }
const editdata = ref({ id: '', objectiveId: '' })
//
const flog = ref(false)
const editBook = async (obj) => {
//
const res = await getCourseInfo({ id: obj.id })
console.log(res, '回显res')
editdata.value.id = res.data.id
editdata.value.objectiveId = res.data.objectiveId
flog.value = true
// console.log(obj, 'obj')
activeIndex.value = res.data.id
formData.value.description = res.data.content
dialogVisible.value = true
}
//
const submit = async () => {
if (flog.value) {
await editCourse({
...editdata.value,
content: formData.value.description,
await ElMessageBox.confirm('您确定要保存吗?', '修改整体目标', {
confirmButtonText: '确定',
cancelButtonText: '取消',
})
.then(async () => {
params.value.content = content.value
const res = await updateContents({
id: params.value.id,
objectiveId: params.value.objectiveId,
content: params.value.content,
})
console.log(res, 'res')
ElMessage.success('保存成功!')
isEditing.value = false
})
} else {
await addCourse({
objectiveId: activeIndex.value,
content: formData.value.description,
.catch(() => {
//
ElMessage.info('您已取消操作')
})
}
getList()
dialogVisible.value = false
formData.value.description = ''
activeIndex.value = ''
}
//
const del = async (obj) => {
await ElMessageBox.confirm('你确认要删除该课程目标吗', '温馨提示', {
type: 'warning',
confirmButtonText: '确认',
cancelButtonText: '取消',
})
await deleteCourse({ id: obj.id })
ElMessage.success('删除成功')
getList()
//
const cancelEdit = () => {
isEditing.value = false
}
const data = ref({})
const courseId = ref(0)
//
const getList = async () => {
const res = await getCourseList({ id: courseId.value })
console.log(res, 'res')
data.value = res.data[0]
params.value = res.data[0].contents[0]
console.log(params.value, 'params.value')
console.log(data.value, 'data.value')
content.value = res.data[0].contents[0].content
}
onMounted(async () => {
if (!Object.keys(route.query).length) {
return router.push('/curriculumCenter/courseDetails')
// return router.push('/curriculumCenter/basicCourseInformation')
}
courseId.value = route.query.id
console.log(courseId.value, 'courseid.vlue')
getList()
let chartDom = document.getElementById('main')
let myChart = echarts.init(chartDom)
let option
option = {
radar: [
{
nameGap: 10,
indicator: [
{
text: '目标一\n',
max: 100,
},
{
text: '目标五\n\n',
max: 100,
},
{
text: '目标四\n\n',
max: 100,
},
{
text: '目标三\n\n',
max: 100,
},
{
text: '目标二\n\n',
max: 100,
},
],
//
center: ['50%', '60%'],
//
radius: 100,
//
startAngle: 90,
//
splitNumber: 5,
shape: 'circle',
name: {
formatter: '{value}',
textStyle: {
color: '#333333',
fontSize: 16,
},
gap: 10,
},
splitArea: {
areaStyle: {
color: [
'transparent',
'transparent',
'rgba(114, 172, 209, 0)',
'transparent',
'rgba(114, 172, 209, 0)',
],
},
},
// 线
axisLine: {
lineStyle: {
color: '#C8D9FF',
},
},
splitLine: {
lineStyle: {
color: '#DADADA',
width: 2,
type: 'dashed', //dashed solid dotted 线线 线
},
},
},
{
nameGap: 10,
indicator: [
{
text: '达成度',
max: 100,
},
{
text: '达成度',
max: 100,
},
{
text: '达成度',
max: 100,
},
{
text: '达成度',
max: 100,
},
{
text: '达成度',
max: 100,
},
],
center: ['50%', '60%'],
radius: 100,
startAngle: 90,
splitNumber: 1,
shape: 'circle',
splitArea: {
show: false,
},
axisLine: {
show: false,
},
name: {
formatter: '{value}',
textStyle: {
color: 'rgba(0,0,0,0.4)',
fontSize: 16,
},
},
splitLine: {
lineStyle: {
color: '#6093FF',
type: 'solid',
width: 8,
},
},
},
],
series: [
{
type: 'radar',
emphasis: {
lineStyle: {
width: 20,
},
},
symbol: 'none',
data: [
{
value: [74, 60, 80, 60, 74],
name: 'Data C',
areaStyle: {
color: '#DBE4F9',
},
},
],
},
{
type: 'radar',
emphasis: {
lineStyle: {
width: 20,
},
},
symbol: 'none',
data: [
{
value: [74, 60, 80, 40, 74],
name: 'Data B',
areaStyle: {
color: '#0052FF',
},
},
],
},
],
}
option && myChart.setOption(option)
})
</script>
<template>
<div class="grid-content course-object" style="height: 450px">
<h1>课程目标</h1>
<div class="all_content">
<div class="graph">
<!-- <div class="graph">
<div class="title">课程目标雷达图</div>
<div id="main" class="radarmap"></div>
</div>
</div> -->
<div class="object">
<span>课程总目标:</span>
<!-- <el-scrollbar height="90px"> -->
<textarea class="textarea" @change="textChange" v-model="content"></textarea>
<!-- </el-scrollbar> -->
<div class="demo-collapse">
<el-collapse v-model="activeName" accordion>
<el-collapse-item title="知识目标" name="1">
<ul>
<li>目标一</li>
<li>目标二</li>
</ul>
</el-collapse-item>
<el-collapse-item title="素质目标" name="2">
<ul>
<li>目标一</li>
<li>目标二</li>
</ul>
</el-collapse-item>
<el-collapse-item title="价值目标" name="3">
<ul>
<li>目标一</li>
<li>目标二</li>
</ul>
</el-collapse-item>
<el-collapse-item title="思政目标" name="4">
<ul>
<li>目标一</li>
<li>目标二</li>
</ul>
</el-collapse-item>
</el-collapse>
<div class="card-header">
<el-card style="max-width: 480px">
<template #header>
<div class="card-header">
<span>课程总目标</span>
<el-button type="primary" :icon="Edit" circle plain @click="updateContent"></el-button>
</div>
</template>
<div class="el-card__body" style="">
<div v-if="isEditing" class="editCon">
<textarea class="textarea" @change="textChange" v-model="content">
{{ params.content }}
</textarea>
<el-button type="primary" @click="saveContent">保存</el-button>
<el-button type="default" @click="cancelEdit">取消</el-button>
</div>
<p class="text" v-else>
{{ params.content }}
</p>
</div>
</el-card>
</div>
</div>
<div class="typeObject">
<ul v-for="item in data" :key="item.id">
<li>
<div class="all">
<div class="left">
<div class="type">{{ item.name }}</div>
<div class="icon">
<el-icon>
<Plus />
</el-icon>
</div>
</div>
<div class="objectdetails">
<el-scrollbar height="89px">
<li v-for="(obj, i) in item.contents" :key="obj.id">
<span>目标{{ i + 1 }}{{ obj.content }}</span>
<div class="icon">
<el-button type="primary" :icon="Edit" circle size="small" plain />
<el-button type="danger" :icon="Delete" circle size="small" plain />
</div>
</li>
</el-scrollbar>
</div>
</div>
<el-divider style="margin: 0; width: 100%" />
</li>
</ul>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.el-tabs__item {
padding: 0 50px;
}
.course-object {
h1 {
padding: 20px;
@ -371,32 +168,53 @@ onMounted(async () => {
display: flex;
justify-content: space-between;
.graph {
// .graph {
// width: 40%;
// height: 100%;
// .title {
// text-align: center;
// font-size: 24px;
// font-weight: 400;
// color: #333333ff;
// }
// .radarmap {
// width: 100%;
// height: 90%;
// margin-top: -60px;
// }
// }
.object {
padding-left: 35px;
width: 40%;
height: 100%;
height: 90%;
.title {
.card-header {
// height: 100%;
text-align: center;
font-size: 24px;
font-weight: 400;
color: #333333ff;
}
.radarmap {
width: 100%;
height: 90%;
margin-top: -60px;
}
}
.el-card__body {
height: 250px;
}
.object {
width: 60%;
button {
margin-left: 20px;
}
.text {
font-size: 14px;
color: #8a8b99;
text-align: left;
line-height: 1.5;
letter-spacing: 1px;
}
}
span {
// text-align: center;
font-size: 20px;
font-weight: 400;
// color: #4984ffff;
}
// span:hover {
@ -408,18 +226,76 @@ onMounted(async () => {
width: 100%;
}
.textarea {
.editCon {
height: 100%;
.textarea {
line-height: 1.5;
width: 90%;
height: 90%;
letter-spacing: 1px;
border: none;
resize: none;
}
}
}
.typeObject {
width: 70%;
// height: 80%;
text-align: center;
// align-items: center;
ul:nth-child(-n + 3) {
border-bottom: none;
}
ul {
width: 90%;
height: 20%;
border: none;
resize: none;
border: 1px solid #dcdfe6;
// box-shadow: 1px -5px 6px rgba(153, 150, 150, 0.5);
}
.demo-collapse {
padding-top: 20px;
.all {
display: flex;
width: 100%;
// box-shadow: 1px 1px 6px rgba(153, 150, 150, 0.5);
// align-content: center;
.left {
width: 20%;
display: flex;
justify-content: center;
border-right: 1px solid #dcdfe6;
flex-wrap: wrap;
align-content: center;
.icon {
margin-left: 10px;
}
.icon:hover {
cursor: pointer;
color: red;
}
}
.objectdetails {
padding-right: 20px;
width: 100%;
// border: 1px solid #8a8b99;
.el-collapse {
--el-collapse-header-font-size: 16px;
li {
width: 100%;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
// align-content: center;
align-items: center;
line-height: 1;
margin-top: 2px;
}
}
}
}

@ -28,13 +28,13 @@ const defaultForm = {
teacher: userStore.data.id,
img: '',
name: '',
category: ref(''),
nature: ref(''),
category: ref(0),
nature: ref(0),
code: '',
credit: '',
classhours: '',
assessmenttype: ref(''),
assessmentway: ref(''),
assessmenttype: ref(0),
assessmentway: ref(0),
teachermethod: '',
teacherway: '',
description: '',

@ -158,7 +158,7 @@
</script>
<template>
<div class="grid-content knowledge-graph" style="height: 500px">
<div class="grid-content knowledge-graph" style="height: 670px">
<!-- <div class="graph">
<div id="3d-graph"></div>
</div> -->

@ -2,11 +2,63 @@
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
import 'echarts-liquidfill'
const liquidechart3 = ref(null) //
const liquidechart1 = ref(null) //
const liquidechart2 = ref(null) //
onMounted(() => {
const myChart3 = echarts.init(liquidechart3.value) // 使 ref
myChart3.setOption({
title: {
text: '目标完成度',
textStyle: {
color: '#888',
fontFamily: 'microsoft yahei',
fontSize: 24,
fontWeight: '400',
align: 'center',
verticalAlign: 'middle',
},
left: 'center',
top: '20%',
},
series: [
{
type: 'liquidFill',
radius: '95%',
waveAnimation: true,
data: [0.3], //
direction: 'left',
itemStyle: {
normal: {
color: '#1890ff',
},
},
outline: {
borderDistance: 3,
itemStyle: {
borderColor: '#4984ff',
borderWidth: 10,
},
},
itemStyle: {
opacity: 0.9,
},
backgroundStyle: {
color: '#fff',
},
label: {
show: true,
color: '#000',
insideColor: '#fff',
fontSize: 24,
fontWeight: 400,
align: 'center',
verticalAlign: 'middle',
},
},
],
})
const myChart1 = echarts.init(liquidechart1.value) // 使 ref
myChart1.setOption({
title: {
@ -116,8 +168,9 @@ onMounted(() => {
<template>
<div class="grid-content knowledge-statistic" style="height: 300px">
<h1>知识点统计</h1>
<!-- <h1>知识点统计</h1> -->
<div class="box">
<div style="width: 300px; height: 250px" ref="liquidechart3"></div>
<div style="width: 300px; height: 250px" ref="liquidechart1"></div>
<div style="width: 300px; height: 250px" ref="liquidechart2"></div>
</div>
@ -126,17 +179,14 @@ onMounted(() => {
<style lang="scss" scoped>
.knowledge-statistic {
h1 {
padding-top: 20px;
text-align: center;
font-size: 24px;
font-weight: 700;
color: #333333ff;
}
display: flex;
align-content: center;
.box {
margin-top: 20px;
display: flex;
justify-content: space-around;
align-content: center;
}
}
</style>

@ -13,12 +13,15 @@ import resourcemanagement from './components/resource-management.vue'
<el-row :gutter="20">
<el-col :span="14">
<course-brief></course-brief>
<courseObject></courseObject>
<knowledgestatistic></knowledgestatistic>
</el-col>
<el-col :span="10">
<KnowledgeGraph></KnowledgeGraph>
<!-- <knowledgegraph></knowledgegraph> -->
<knowledgestatistic></knowledgestatistic>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<courseObject></courseObject>
</el-col>
</el-row>
<el-row :gutter="20">

@ -0,0 +1,40 @@
// vite.config.ts
import vue from "file:///E:/jiaoxue/Teaching_integration_platform_admin_template/node_modules/.pnpm/@vitejs+plugin-vue@5.0.4_vite@5.1.4_vue@3.4.29/node_modules/@vitejs/plugin-vue/dist/index.mjs";
import path from "path";
import { viteMockServe } from "file:///E:/jiaoxue/Teaching_integration_platform_admin_template/node_modules/.pnpm/vite-plugin-mock@3.0.1_esbuild@0.19.12_mockjs@1.1.0_vite@5.1.4/node_modules/vite-plugin-mock/dist/index.mjs";
import { createSvgIconsPlugin } from "file:///E:/jiaoxue/Teaching_integration_platform_admin_template/node_modules/.pnpm/vite-plugin-svg-icons@2.0.1_vite@5.1.4/node_modules/vite-plugin-svg-icons/dist/index.mjs";
var vite_config_default = ({ command }) => {
return {
plugins: [
vue(),
viteMockServe({
enable: command === "serve"
}),
createSvgIconsPlugin({
// Specify the icon folder to be cached
iconDirs: [path.resolve(process.cwd(), "src/assets/icons")],
// Specify symbolId format
symbolId: "icon-[dir]-[name]"
})
],
resolve: {
alias: {
"@": path.resolve("./src")
// 相对路径别名配置,使用 @ 代替 src
}
},
// 配置scss
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: '@import "./src/styles/variable.scss";'
}
}
}
};
};
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJFOlxcXFxqaWFveHVlXFxcXFRlYWNoaW5nX2ludGVncmF0aW9uX3BsYXRmb3JtX2FkbWluX3RlbXBsYXRlXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJFOlxcXFxqaWFveHVlXFxcXFRlYWNoaW5nX2ludGVncmF0aW9uX3BsYXRmb3JtX2FkbWluX3RlbXBsYXRlXFxcXHZpdGUuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9FOi9qaWFveHVlL1RlYWNoaW5nX2ludGVncmF0aW9uX3BsYXRmb3JtX2FkbWluX3RlbXBsYXRlL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHZ1ZSBmcm9tICdAdml0ZWpzL3BsdWdpbi12dWUnXHJcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnXHJcbi8vIFx1NUJGQ1x1NTE2NW1vY2tcdTYzRDJcdTRFRjZcclxuaW1wb3J0IHsgdml0ZU1vY2tTZXJ2ZSB9IGZyb20gJ3ZpdGUtcGx1Z2luLW1vY2snXHJcbi8vIFx1NUJGQ1x1NTE2NXN2Z1x1OTE0RFx1N0Y2RVx1NjNEMlx1NEVGNlxyXG5pbXBvcnQgeyBjcmVhdGVTdmdJY29uc1BsdWdpbiB9IGZyb20gJ3ZpdGUtcGx1Z2luLXN2Zy1pY29ucydcclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgKHsgY29tbWFuZCB9OiBhbnkpID0+IHtcclxuICByZXR1cm4ge1xyXG4gICAgcGx1Z2luczogW1xyXG4gICAgICB2dWUoKSxcclxuICAgICAgdml0ZU1vY2tTZXJ2ZSh7XHJcbiAgICAgICAgZW5hYmxlOiBjb21tYW5kID09PSAnc2VydmUnLFxyXG4gICAgICB9KSxcclxuICAgICAgY3JlYXRlU3ZnSWNvbnNQbHVnaW4oe1xyXG4gICAgICAgIC8vIFNwZWNpZnkgdGhlIGljb24gZm9sZGVyIHRvIGJlIGNhY2hlZFxyXG4gICAgICAgIGljb25EaXJzOiBbcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksICdzcmMvYXNzZXRzL2ljb25zJyldLFxyXG4gICAgICAgIC8vIFNwZWNpZnkgc3ltYm9sSWQgZm9ybWF0XHJcbiAgICAgICAgc3ltYm9sSWQ6ICdpY29uLVtkaXJdLVtuYW1lXScsXHJcbiAgICAgIH0pLFxyXG4gICAgXSxcclxuICAgIHJlc29sdmU6IHtcclxuICAgICAgYWxpYXM6IHtcclxuICAgICAgICAnQCc6IHBhdGgucmVzb2x2ZSgnLi9zcmMnKSwgLy8gXHU3NkY4XHU1QkY5XHU4REVGXHU1Rjg0XHU1MjJCXHU1NDBEXHU5MTREXHU3RjZFXHVGRjBDXHU0RjdGXHU3NTI4IEAgXHU0RUUzXHU2NkZGIHNyY1xyXG4gICAgICB9LFxyXG4gICAgfSxcclxuICAgIC8vIFx1OTE0RFx1N0Y2RXNjc3NcclxuICAgIGNzczoge1xyXG4gICAgICBwcmVwcm9jZXNzb3JPcHRpb25zOiB7XHJcbiAgICAgICAgc2Nzczoge1xyXG4gICAgICAgICAgamF2YXNjcmlwdEVuYWJsZWQ6IHRydWUsXHJcbiAgICAgICAgICBhZGRpdGlvbmFsRGF0YTogJ0BpbXBvcnQgXCIuL3NyYy9zdHlsZXMvdmFyaWFibGUuc2Nzc1wiOycsXHJcbiAgICAgICAgfSxcclxuICAgICAgfSxcclxuICAgIH0sXHJcbiAgfVxyXG59XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFDQSxPQUFPLFNBQVM7QUFDaEIsT0FBTyxVQUFVO0FBRWpCLFNBQVMscUJBQXFCO0FBRTlCLFNBQVMsNEJBQTRCO0FBRXJDLElBQU8sc0JBQVEsQ0FBQyxFQUFFLFFBQVEsTUFBVztBQUNuQyxTQUFPO0FBQUEsSUFDTCxTQUFTO0FBQUEsTUFDUCxJQUFJO0FBQUEsTUFDSixjQUFjO0FBQUEsUUFDWixRQUFRLFlBQVk7QUFBQSxNQUN0QixDQUFDO0FBQUEsTUFDRCxxQkFBcUI7QUFBQTtBQUFBLFFBRW5CLFVBQVUsQ0FBQyxLQUFLLFFBQVEsUUFBUSxJQUFJLEdBQUcsa0JBQWtCLENBQUM7QUFBQTtBQUFBLFFBRTFELFVBQVU7QUFBQSxNQUNaLENBQUM7QUFBQSxJQUNIO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxPQUFPO0FBQUEsUUFDTCxLQUFLLEtBQUssUUFBUSxPQUFPO0FBQUE7QUFBQSxNQUMzQjtBQUFBLElBQ0Y7QUFBQTtBQUFBLElBRUEsS0FBSztBQUFBLE1BQ0gscUJBQXFCO0FBQUEsUUFDbkIsTUFBTTtBQUFBLFVBQ0osbUJBQW1CO0FBQUEsVUFDbkIsZ0JBQWdCO0FBQUEsUUFDbEI7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRjsiLAogICJuYW1lcyI6IFtdCn0K
Loading…
Cancel
Save