diff --git a/src/api/survey/evaluationForm.js b/src/api/survey/evaluationForm.js new file mode 100644 index 0000000..7753833 --- /dev/null +++ b/src/api/survey/evaluationForm.js @@ -0,0 +1,40 @@ +import request from "@/utils/request"; + +function customParamsSerializer(params) { + let result = ''; + for (let key in params) { + if (params.hasOwnProperty(key)) { + if (Array.isArray(params[key])) { + params[key].forEach((item, index) => { + if (item.key) { + result += `${key}[${index}][key]=${item.key}&${key}[${index}][op]=${item.op}&${key}[${index}][value]=${item.value}&`; + } else { + result += `${key}[${index}]=${item}&`; + } + }); + } else { + result += `${key}=${params[key]}&`; + } + } + } + return result.slice(0, -1); +} + +export function index(params, isLoading = false) { + return request({ + method: "get", + url: "/api/admin/course-content-evaluation-form/index", + params, + paramsSerializer: customParamsSerializer, + isLoading + }); +} + +export function show(params, isLoading = true) { + return request({ + method: "get", + url: "/api/admin/course-content-evaluation-form/show", + params, + isLoading + }); +} diff --git a/src/views/dashboard/index.vue b/src/views/dashboard/index.vue index 7a829f7..49a210c 100644 --- a/src/views/dashboard/index.vue +++ b/src/views/dashboard/index.vue @@ -88,8 +88,8 @@ > {{ config.name }} - +
课程体系
@@ -97,15 +97,15 @@
培养人数(去重)
-
-
{{ item.name }}
+ class="table-row" + > +
{{ item.name }}
{{ item.course_periods_total }}期
{{ item.course_signs_total }}人
-
+
+ @@ -467,7 +467,7 @@ export default { if (!currentConfig) return null // 使用当前配置中的累计字段 - return { + return { name: '累计(已去重)', course_periods_total: currentConfig.course_periods_total || 0, course_signs_unique_total: currentConfig.course_signs_unique_total || 0 @@ -518,10 +518,10 @@ export default { handler(newVal) { if (newVal && newVal.length > 0) { this.currentYearIndex = 0 - this.$nextTick(() => { + this.$nextTick(() => { this.startYearConfigRotation() - }) - } + }) + } }, deep: true }, @@ -605,8 +605,8 @@ export default { valueData = JSON.parse(firstItem.value) if (!Array.isArray(valueData)) { valueData = [] - } - } catch (e) { + } + } catch (e) { console.error('解析配置值失败:', e) valueData = [] } diff --git a/src/views/statistics/index.vue b/src/views/statistics/index.vue index 08b6ed0..6028ca6 100644 --- a/src/views/statistics/index.vue +++ b/src/views/statistics/index.vue @@ -81,7 +81,15 @@ 'stats-container-half': category.layout === 'half' }">
- +
+ + +
@@ -108,7 +116,15 @@ 'stats-container-half': category.layout === 'half' }">
- +
+ + +
@@ -274,13 +290,13 @@ export default { label: '跟班学员数', cardClass: 'student-card-3' }, - // { - // key: 'company_ganbu_total', - // icon: 'el-icon-s-check', - // value: '0', - // label: '全市干部参与数', - // cardClass: 'student-card-4' - // }, + { + key: 'company_ganbu_total', + icon: 'el-icon-s-check', + value: '0', + label: '全市干部参与企业', + cardClass: 'student-card-4' + }, { key: 'company_join_total', icon: 'el-icon-s-promotion', @@ -408,7 +424,9 @@ export default { uniquePeople: 0 }, // 三个全覆盖手动修改数据 - threeCoverageManualData: {} + threeCoverageManualData: {}, + // 统计元数据 + statistics_metadata: {} } }, watch: { @@ -985,9 +1003,17 @@ export default { this.regionSummary = { totalPeople: 0, uniquePeople: 0 } } + // 保存统计元数据 + if (data && data.statistics_metadata) { + this.statistics_metadata = data.statistics_metadata + } else { + this.statistics_metadata = {} + } + console.log('统计数据已更新:', this.statsCategories) console.log('课程分类明细数据已更新:', this.courseDetailData) console.log('区域明细数据已更新:', this.regionData) + console.log('统计元数据:', this.statistics_metadata) }, // 获取课程体系列表 @@ -1163,6 +1189,40 @@ export default { // 获取手动修改的值 getManualValue(key) { return this.threeCoverageManualData[key] || '0' + }, + // 检查是否有元数据 + hasMetadata(key) { + return key && this.statistics_metadata && this.statistics_metadata[key] + }, + // 显示统计规则信息 + showMetadataInfo(key, label) { + if (!this.hasMetadata(key)) { + return + } + + const metadata = this.statistics_metadata[key] + const from = metadata.from || '暂无统计规则说明' + const verify = metadata.verify || '暂无验证方式说明' + const title = label || '统计说明' + + this.$alert( + `
+
+ 统计规则:
+ ${from} +
+
+ 验证方式:
+ ${verify} +
+
`, + title, + { + dangerouslyUseHTMLString: true, + confirmButtonText: '确定', + customClass: 'stats-metadata-dialog' + } + ) } } } @@ -1375,19 +1435,28 @@ export default { } } -.stats-download { +.stats-actions { position: absolute; top: 8px; right: 8px; + display: flex; + align-items: center; + gap: 8px; + z-index: 3; +} + +.stats-download, +.stats-info { font-size: 0.9rem; color: rgba(255, 255, 255, 0.8); cursor: pointer; - transition: color 0.2s ease; - z-index: 3; + transition: all 0.2s ease; } -.stats-download:hover { +.stats-download:hover, +.stats-info:hover { color: #fff; + transform: scale(1.1); } .stats-icon { @@ -1634,4 +1703,15 @@ export default { } } } + +/* 统计元数据弹窗样式 */ +::v-deep .stats-metadata-dialog { + .el-message-box__message { + padding: 10px 0; + } + + .el-message-box__content { + padding: 20px; + } +} diff --git a/src/views/stockCompany/components/addStockCompany.vue b/src/views/stockCompany/components/addStockCompany.vue index 8cc3c15..4aaff02 100644 --- a/src/views/stockCompany/components/addStockCompany.vue +++ b/src/views/stockCompany/components/addStockCompany.vue @@ -85,6 +85,7 @@ id: '', selectCompanyVisible: false, form: { + company_id: '', company_name: '', stock_date: '', enrollment_date: '', @@ -128,6 +129,7 @@ this.selectCompanyVisible = true }, handleCompanySelect(data) { + this.form.company_id = data.company_id this.form.company_name = data.company_name this.form.enrollment_date = data.enrollment_date } @@ -141,6 +143,7 @@ } else { this.id = '' this.form = { + company_id: '', company_name: '', stock_date: '', enrollment_date: '', diff --git a/src/views/stockCompany/components/selectCompany.vue b/src/views/stockCompany/components/selectCompany.vue index 9656985..e7d5d8a 100644 --- a/src/views/stockCompany/components/selectCompany.vue +++ b/src/views/stockCompany/components/selectCompany.vue @@ -109,8 +109,8 @@ v-for="(courseSign, cIdx) in user.course_signs" :key="cIdx" class="course-item" - :class="{ 'selected': selectedCourse && selectedCourse.company_name === scope.row.company_name && selectedCourse.userIndex === uIdx && selectedCourse.courseIndex === cIdx }" - @click="handleSelectCourse(scope.row.company_name, user, courseSign, uIdx, cIdx)"> + :class="{ 'selected': selectedCourse && selectedCourse.company_id === scope.row.id && selectedCourse.userIndex === uIdx && selectedCourse.courseIndex === cIdx }" + @click="handleSelectCourse(scope.row, user, courseSign, uIdx, cIdx)"> {{ courseSign.course && courseSign.course.name ? courseSign.course.name : '-' }} - {{ courseSign.course && courseSign.course.start_date ? courseSign.course.start_date : '-' }}
@@ -313,19 +313,21 @@ export default { this.page = val this.getList() }, - handleSelectCourse(companyName, user, courseSign, userIndex, courseIndex) { + handleSelectCourse(company, user, courseSign, userIndex, courseIndex) { const enrollmentDate = courseSign.course && courseSign.course.start_date ? courseSign.course.start_date : '' this.selectedCourse = { - company_name: companyName, + company_id: company.id, + company_name: company.company_name, enrollment_date: enrollmentDate, userIndex, courseIndex } - // 触发选择事件,传递企业名称和入学时间 + // 触发选择事件,传递企业ID、企业名称和入学时间 this.$emit('select', { - company_name: companyName, + company_id: company.id, + company_name: company.company_name, enrollment_date: enrollmentDate }) diff --git a/src/views/student/index.vue b/src/views/student/index.vue index 1ab60e7..6e1c0d5 100644 --- a/src/views/student/index.vue +++ b/src/views/student/index.vue @@ -126,6 +126,12 @@
+
+ + + + +
- +
-
{{ surveyData.title }}
+
{{ surveyData ? surveyData.title : '' }}
- 创建时间:{{ surveyData.createTime }} - 截止时间:{{ surveyData.deadline }} + + 开始时间:{{ surveyData.start_time }} + + + 截止时间:{{ surveyData.end_time }} + + + 关联课程:{{ surveyData.course.name }} +
- 关闭 + 关闭 +
+ +
+ + + +
-
-
+
+ +
-
-
{{ surveyData.responses }}
+
+ +
+
{{ surveyData.responses || surveyData.course_content_evaluation_forms_count || 0 }}
回复数
-
-
{{ surveyData.questions.length }}
+
+ +
+
{{ surveyData.questionsCount || surveyData.course_content_evaluation_asks_count || (questions && questions.length) || 0 }}
题目数
-
-
-
{{ surveyData.avgScore || '-' }}
-
平均分
+
+
+ +
+
{{ avgRateScore.toFixed(1) }}
+
平均评分
-
-
-
-
{{ idx+1 }}. {{ q.title }}
-
- 题型:{{ typeText(q.type) }} + + +
+ +
+
+
+
+
+ {{ idx + 1 }}. + {{ q.name }} + * +
+
+ 题型:{{ getQuestionTypeText(q.edit_input) }} + + {{ q.course_content.theme }} + + + {{ q.course_content.teacher.name }} + +
+
+
+ + +
+
+ + + + + + + + + +
+ +
+ + +
+
+
+
+ * + {{ dim.name || dim.field }} +
+
+ + + + + + + + + +
+ +
+
+
+ + +
+ + + + +
+ + +
+ + + +
+ + +
+ +
-
- - - + + + +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + +
-
- -
评分题,用户可打分
+
+
+ + + +
+
+ + + {{ currentResponse.user && currentResponse.user.name ? currentResponse.user.name : '-' }} + + + {{ currentResponse.user && currentResponse.user.no ? currentResponse.user.no : '-' }} + + + {{ currentResponse.created_at || '-' }} + + + {{ currentResponse.user && currentResponse.user.company_name ? currentResponse.user.company_name : '-' }} + + + {{ currentResponse.user && currentResponse.user.company_position ? currentResponse.user.company_position : '-' }} + +
-
- + +
+
+
+ {{ idx + 1 }}. + {{ q.name }} + * + ({{ getQuestionTypeText(q.edit_input) }}) +
+
+
+ +
+ {{ getAnswerForQuestion(q.id) || '未填写' }} +
+ +
+ + {{ getAnswerForQuestion(q.id).join('、') || '未填写' }} + + {{ getAnswerForQuestion(q.id) || '未填写' }} +
+ +
+
+
+ {{ dim.name || dim.field }}: + {{ getAnswerForQuestion(q.id)[dim.field] || '未填写' }} +
+
+ 未填写 +
+ +
+ {{ getAnswerForQuestion(q.id) || '未填写' }} +
+
+ 未填写 +
+
-
+
+ 关闭 +
+
+ + diff --git a/src/views/survey/index.vue b/src/views/survey/index.vue index 1bc389a..fb141f1 100644 --- a/src/views/survey/index.vue +++ b/src/views/survey/index.vue @@ -197,6 +197,7 @@ import SurveyFillDialog from "./components/SurveyFillDialog.vue"; import { index as courseApi } from "@/api/course/index.js"; import { index, destroy, save, qrCode} from "@/api/survey/evaluations.js"; +import { index as formIndex } from "@/api/survey/index.js"; export default { components: { @@ -297,36 +298,36 @@ export default { this.$refs.SurveyCreateWizard.isShow = true; }, - viewResults(survey) { - this.resultsSurveyData = { - id: 1, - title: "问卷1", - description: "请对本次智能制造专题课程进行评价和反馈", - status: "published", - type: "feedback", - bindType: "course", - bindCourse: "2025产业加速营 | 智能制造专题", - createTime: "2025-06-01 10:00", - deadline: "2025-06-10 23:59", - responses: 1, - questions: 6, - avgScore: 4.6, - questions: [ - { - id: 101, - type: "single", - title: "单选框", - options: ["单选1", "单选2"], - }, - // { - // id: 102, - // type: 'rate', - // title: '请为本次课程打分', - // rateMax: 5 - // } - ], - }; - this.resultsDialogVisible = true; + async viewResults(survey) { + try { + // 获取问卷问题列表 + const questionsRes = await formIndex({ + page: 1, + page_size: 999, + sort_name: 'sort', + sort_type: 'ASC', + show_relation: ['courseContent.teacher'], + filter: [{ + key: 'course_content_evaluation_id', + op: 'eq', + value: survey.id + }], + }); + + // 组合数据 + this.resultsSurveyData = { + ...survey, + questions: questionsRes.data || [], + // 统计信息从survey对象中获取 + responses: survey.course_content_evaluation_forms_count || 0, + questionsCount: survey.course_content_evaluation_asks_count || (questionsRes.data && questionsRes.data.length) || 0, + }; + + this.resultsDialogVisible = true; + } catch (error) { + console.error('获取问卷结果失败:', error); + this.$message.error('获取问卷结果失败,请重试'); + } }, async previewSurvey(survey) { try {