|
|
@@ -0,0 +1,351 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+ <el-form ref="queryRef" :inline="true" :model="queryParams">
|
|
|
+ <el-form-item label="アンケートコード" prop="surveyCode">
|
|
|
+ <el-input v-model="queryParams.surveyCode"
|
|
|
+ clearable maxlength="13" @keyup.enter="handleQuery"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="FC会員名" prop="fcMemberName">
|
|
|
+ <el-input v-model="queryParams.fcMemberName"
|
|
|
+ clearable
|
|
|
+ maxlength="255" @keyup.enter="handleQuery"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button class="append-button" @click="handleExport">CSV出力</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ <el-row v-show="initLoadingCompleted" :gutter="10" class="mb8">
|
|
|
+ <el-col :span="11">
|
|
|
+ <el-form-item label="回答日付">
|
|
|
+ <div class="date-range-container">
|
|
|
+ <el-select v-model="queryParams.startYear" placeholder="" class="date-select" @change="formatDate">
|
|
|
+ <el-option v-for="year in years" :key="year" :label="year" :value="year"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <span class="date-label">年</span>
|
|
|
+ <el-select
|
|
|
+ v-model="queryParams.startMonth"
|
|
|
+ placeholder=""
|
|
|
+ class="date-select-small"
|
|
|
+ @change="formatDate"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="month in months"
|
|
|
+ :key="month"
|
|
|
+ :label="month"
|
|
|
+ :value="month"
|
|
|
+ ></el-option>
|
|
|
+ </el-select>
|
|
|
+ <span class="date-label">月</span>
|
|
|
+ <el-select
|
|
|
+ v-model="queryParams.startDay"
|
|
|
+ placeholder=""
|
|
|
+ class="date-select-small"
|
|
|
+ @change="formatDate"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="day in days"
|
|
|
+ :key="day"
|
|
|
+ :label="day"
|
|
|
+ :value="day"
|
|
|
+ ></el-option>
|
|
|
+ </el-select>
|
|
|
+ <span class="date-label">日</span>
|
|
|
+ <span class="date-label">~</span>
|
|
|
+ <el-select
|
|
|
+ v-model="queryParams.endYear"
|
|
|
+ placeholder=""
|
|
|
+ class="date-select"
|
|
|
+ @change="formatDate"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="year in years"
|
|
|
+ :key="year"
|
|
|
+ :label="year"
|
|
|
+ :value="year"
|
|
|
+ ></el-option>
|
|
|
+ </el-select>
|
|
|
+ <span class="date-label">年</span>
|
|
|
+ <el-select
|
|
|
+ v-model="queryParams.endMonth"
|
|
|
+ placeholder=""
|
|
|
+ class="date-select-small"
|
|
|
+ @change="formatDate"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="month in months"
|
|
|
+ :key="month"
|
|
|
+ :label="month"
|
|
|
+ :value="month"
|
|
|
+ ></el-option>
|
|
|
+ </el-select>
|
|
|
+ <span class="date-label">月</span>
|
|
|
+ <el-select
|
|
|
+ v-model="queryParams.endDay"
|
|
|
+ placeholder=""
|
|
|
+ class="date-select-small"
|
|
|
+ @change="formatDate"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="day in days"
|
|
|
+ :key="day"
|
|
|
+ :label="day"
|
|
|
+ :value="day"
|
|
|
+ ></el-option>
|
|
|
+ </el-select>
|
|
|
+ <span class="date-label">日</span>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button icon="Search" type="primary" @click="handleQuery">検索</el-button>
|
|
|
+ <el-button icon="Refresh" @click="resetQuery">クリア</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <el-table v-show="initLoadingCompleted" v-loading="listLoading" :border="true" :data="certificationItemList">
|
|
|
+ <el-table-column
|
|
|
+ :show-overflow-tooltip="true"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ label="アンケートコード"
|
|
|
+ min-width="50"
|
|
|
+ prop="surveyCode"
|
|
|
+ >
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="アンケートタイトル" min-width="60"
|
|
|
+ prop="title"
|
|
|
+ >
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column :show-overflow-tooltip="true" align="left" header-align="center" label="FC会員名" min-width="70"
|
|
|
+ prop="fcMemberName"
|
|
|
+ width=""/>
|
|
|
+ <el-table-column :show-overflow-tooltip="true" align="center" header-align="center" label="回答状態" min-width="80"
|
|
|
+ prop="answerStatus"
|
|
|
+ width=""/>
|
|
|
+ <el-table-column :show-overflow-tooltip="true" align="center" header-align="center" label="回答日付" min-width="100"
|
|
|
+ prop="answerTime"
|
|
|
+ width=""/>
|
|
|
+ <el-table-column :show-overflow-tooltip="true" align="right" header-align="center" label="質問総数" min-width="50"
|
|
|
+ prop="totalQuestions"
|
|
|
+ width=""/>
|
|
|
+ <el-table-column :show-overflow-tooltip="true" align="right" header-align="center" label="回答数" min-width="30"
|
|
|
+ prop="answeredQuestions"
|
|
|
+ width=""/>
|
|
|
+ <el-table-column :show-overflow-tooltip="true" align="right" header-align="center" label="未回答数" min-width="30"
|
|
|
+ prop="unansweredQuestions"
|
|
|
+ width=""/>
|
|
|
+ <el-table-column
|
|
|
+ :show-overflow-tooltip="true"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ label="回答完成率"
|
|
|
+ min-width="50"
|
|
|
+ >
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.completionRate }}%
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column align="center" class-name="small-padding fixed-width" label="操作" min-width="180" width="180">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button icon="Edit" link type="primary" >回答詳細</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <pagination v-show="listTotalCnt>0"
|
|
|
+ v-model:limit="queryParams.pageSize"
|
|
|
+ v-model:page="queryParams.pageNum"
|
|
|
+ :total="listTotalCnt"
|
|
|
+ @pagination="getSearchList"/>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script name="SurveyResultsList" setup>
|
|
|
+
|
|
|
+import { listSurveyDetails} from "@/api/fcbi/survey.js"
|
|
|
+import { useRoute } from 'vue-router'
|
|
|
+import {download} from "@/utils/request.js";
|
|
|
+import {formatMsg} from "@/utils/yamada.js"
|
|
|
+import {ElMessage} from "element-plus";
|
|
|
+// 認証項目のテーブルデータを格納するリアクティブ変数
|
|
|
+const certificationItemList = ref([]);
|
|
|
+// データ読み込み中のローディング状態を管理するリアクティブ変数
|
|
|
+const listLoading = ref(false);
|
|
|
+// 検索結果の総件数を格納するリアクティブ変数
|
|
|
+const listTotalCnt = ref(0);
|
|
|
+// 初期ロードが完了したかどうかを示すリアクティブ変数
|
|
|
+const initLoadingCompleted = ref(false);
|
|
|
+const {proxy} = getCurrentInstance();
|
|
|
+const route= useRoute()
|
|
|
+const surveyCode = route.params.surveyCode
|
|
|
+
|
|
|
+/**
|
|
|
+ * コンポーネントの状態を管理するリアクティブオブジェクト
|
|
|
+ */
|
|
|
+const data = reactive({
|
|
|
+ form: {},
|
|
|
+ // 検索条件を格納するオブジェクト
|
|
|
+ queryParams: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 100,
|
|
|
+ startYear: '',
|
|
|
+ startMonth: '',
|
|
|
+ startDay: '',
|
|
|
+ endYear: '',
|
|
|
+ endMonth: '',
|
|
|
+ endDay: '',
|
|
|
+ publicStartTime: '',
|
|
|
+ publicEndTime: '',
|
|
|
+ surveyCode: null,
|
|
|
+ fcMemberName: null,
|
|
|
+ },
|
|
|
+});
|
|
|
+
|
|
|
+// リアクティブオブジェクトからプロパティを参照可能なオブジェクトに変換
|
|
|
+const {queryParams} = toRefs(data);
|
|
|
+
|
|
|
+const currentYear = new Date().getFullYear();
|
|
|
+const years = Array.from({ length: 11 }, (_, i) => currentYear + i);
|
|
|
+const months = Array.from({ length: 12 }, (_, i) => i + 1);
|
|
|
+const days = Array.from({ length: 31 }, (_, i) => i + 1);
|
|
|
+
|
|
|
+const formatDate = () => {
|
|
|
+ const publicStartTime = `${queryParams.value.startYear}-${String(queryParams.value.startMonth).padStart(2, '0')}-${String(queryParams.value.startDay).padStart(2, '0')}`;
|
|
|
+ const publicEndTime = `${queryParams.value.endYear}-${String(queryParams.value.endMonth).padStart(2, '0')}-${String(queryParams.value.endDay).padStart(2, '0')}`;
|
|
|
+ queryParams.publicStartTime = publicStartTime;
|
|
|
+ queryParams.publicEndTime = publicEndTime;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * 日付範囲の完全性と有効性を検証します
|
|
|
+ * - 6つの値のうちいずれか1つに値が設定されている場合は、すべての値を入力する必要があります
|
|
|
+ * - すべての値が入力された場合、開始日は終了日よりも前でなければなりません
|
|
|
+ */
|
|
|
+const validateDateRange = () => {
|
|
|
+ const { startYear, startMonth, startDay, endYear, endMonth, endDay } = queryParams.value;
|
|
|
+
|
|
|
+ // すべての日付フィールドの値を収集します
|
|
|
+ const dateFields = [startYear, startMonth, startDay, endYear, endMonth, endDay];
|
|
|
+ // いずれかのフィールドに値が設定されているかどうかを判断します
|
|
|
+ const hasAnyValue = dateFields.some(value => value !== '');
|
|
|
+
|
|
|
+ // 値が設定されているフィールドが存在する場合、すべてのフィールドに値が設定されているかどうかを確認します
|
|
|
+ if (hasAnyValue) {
|
|
|
+ const isComplete = dateFields.every(value => value !== '');
|
|
|
+ if (!isComplete) {
|
|
|
+ ElMessage.error(formatMsg('Y0002'));
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // すべてのフィールドに値が設定されている場合、開始日が終了日以前であることを検証します
|
|
|
+ const startDate = new Date(startYear, startMonth - 1, startDay);
|
|
|
+ const endDate = new Date(endYear, endMonth - 1, endDay);
|
|
|
+
|
|
|
+ if (startDate > endDate) {
|
|
|
+ ElMessage.error(formatMsg('Y0003'));
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * 検索ボタンのクリックイベントハンドラー
|
|
|
+ * 検索条件を初期ページに設定して検索を実行する
|
|
|
+ */
|
|
|
+function handleQuery() {
|
|
|
+ if (!validateDateRange()) return;
|
|
|
+ queryParams.value.pageNum = 1;
|
|
|
+ getSearchList();
|
|
|
+}
|
|
|
+
|
|
|
+function getSearchList() {
|
|
|
+ listLoading.value = true;
|
|
|
+ let params = {
|
|
|
+ pageNum: queryParams.value.pageNum,
|
|
|
+ pageSize: queryParams.value.pageSize,
|
|
|
+ surveyCode: queryParams.value.surveyCode,
|
|
|
+ fcMemberName: queryParams.value.fcMemberName,
|
|
|
+ publicStartTime: queryParams.publicStartTime,
|
|
|
+ publicEndTime: queryParams.publicEndTime,
|
|
|
+ };
|
|
|
+ listSurveyDetails(params).then(response => {
|
|
|
+ certificationItemList.value = response.rows;
|
|
|
+ listTotalCnt.value = response.total;
|
|
|
+ listLoading.value = false;
|
|
|
+ initLoadingCompleted.value = true;
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function handleExport() {
|
|
|
+ // 检查アンケートコード是否为空
|
|
|
+ if (!queryParams.value.surveyCode) {
|
|
|
+ ElMessage.error(formatMsg('E0003', "アンケートコード"));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const exportParams = {
|
|
|
+ pageNum: queryParams.value.pageNum,
|
|
|
+ pageSize: queryParams.value.pageSize,
|
|
|
+ surveyCode: queryParams.value.surveyCode,
|
|
|
+ fcMemberName: queryParams.value.fcMemberName,
|
|
|
+ publicStartTime: queryParams.publicStartTime,
|
|
|
+ publicEndTime: queryParams.publicEndTime,
|
|
|
+ };
|
|
|
+
|
|
|
+ download('system/survey/export', exportParams, `ymdf_survey${new Date().getTime()}.csv`);
|
|
|
+}
|
|
|
+/**
|
|
|
+ * リセット ボタンアクション
|
|
|
+ */
|
|
|
+function resetQuery() {
|
|
|
+ proxy.resetForm("queryRef");
|
|
|
+ queryParams.value.startYear = '';
|
|
|
+ queryParams.value.startMonth = '';
|
|
|
+ queryParams.value.startDay = '';
|
|
|
+ queryParams.value.endYear = '';
|
|
|
+ queryParams.value.endMonth = '';
|
|
|
+ queryParams.value.endDay = '';
|
|
|
+ queryParams.publicStartTime = '';
|
|
|
+ queryParams.publicEndTime = '';
|
|
|
+ handleQuery();
|
|
|
+}
|
|
|
+// コンポーネント初期化時に検索を実行
|
|
|
+onMounted(() => {
|
|
|
+ if (surveyCode) {
|
|
|
+ queryParams.value.surveyCode = surveyCode;
|
|
|
+ }
|
|
|
+ getSearchList();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style>
|
|
|
+.append-button{
|
|
|
+ background-color: black;
|
|
|
+ color: white;
|
|
|
+}
|
|
|
+
|
|
|
+.circle-checkbox .el-checkbox__inner {
|
|
|
+ border-radius: 50%;
|
|
|
+}
|
|
|
+
|
|
|
+.date-range-container {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-left: 9%;
|
|
|
+ gap: 8px;
|
|
|
+}
|
|
|
+/* 年份选择器宽度 */
|
|
|
+.date-select {
|
|
|
+ min-width: 80px;
|
|
|
+}
|
|
|
+/* 月/日选择器宽度 */
|
|
|
+.date-select-small {
|
|
|
+ min-width: 60px;
|
|
|
+}
|
|
|
+/* 日期单位文本样式(年/月/日) */
|
|
|
+.date-label {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+</style>
|