|
|
@@ -8,34 +8,35 @@
|
|
|
label-width="140px"
|
|
|
label-position="top">
|
|
|
<el-form-item label="タイトル" style="margin-left: 30px;margin-top: -35px;">
|
|
|
- <el-input v-model="queryParams.title" class="table-input" :maxlength="100" ></el-input>
|
|
|
+ <el-input v-model="queryParams.title" class="table-input" :maxlength="100" disabled></el-input>
|
|
|
</el-form-item>
|
|
|
- <el-form-item label="説明文" style="margin-left: 30px;margin-top: -15px;">
|
|
|
+ <el-form-item label="説明文" style="margin-left: 30px;margin-top: -15px;" >
|
|
|
<el-input
|
|
|
v-model="queryParams.description"
|
|
|
class="table-input"
|
|
|
:maxlength="255"
|
|
|
type="textarea"
|
|
|
:rows="2"
|
|
|
+ disabled
|
|
|
></el-input>
|
|
|
</el-form-item>
|
|
|
<div style=" padding-left: 29px;margin-top: -15px;">公開範囲</div>
|
|
|
<el-form-item label="FC" prop="brandCode" style="margin-left: 60px; display: flex; align-items: center; margin-top: 10px;">
|
|
|
<div class="el-form-item__label" style="flex-shrink: 0; margin-right: 20px;"></div>
|
|
|
<el-checkbox-group v-model="queryParams.brandCode">
|
|
|
- <el-checkbox v-for="dict in yamada_fc_brand" :key="dict.value" :label="dict.value" style="margin-right: 60px;">{{ dict.label }}</el-checkbox>
|
|
|
+ <el-checkbox disabled v-for="dict in yamada_fc_brand" :key="dict.value" :label="dict.value" style="margin-right: 60px;">{{ dict.label }}</el-checkbox>
|
|
|
</el-checkbox-group>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="業種" prop="businessTypeCode" class="el-form-item__businessTypeCode">
|
|
|
<div class="el-form-item__label" style="flex-shrink: 0; margin-right: 14px;"></div>
|
|
|
<el-checkbox-group v-model="queryParams.businessTypeCode">
|
|
|
- <el-checkbox v-for="dict in yamada_business_type" :key="dict.value" :label="dict.value" style="margin-right: 32px;">{{ dict.label }}</el-checkbox>
|
|
|
+ <el-checkbox disabled v-for="dict in yamada_business_type" :key="dict.value" :label="dict.value" style="margin-right: 32px;">{{ dict.label }}</el-checkbox>
|
|
|
</el-checkbox-group>
|
|
|
</el-form-item>
|
|
|
<div class="container">
|
|
|
<div class="area-header-row">
|
|
|
<h1 class="area-title">エリア</h1>
|
|
|
- <RegionTree class="region-tree-container" :treeData="regionTree" @check-change="handleCheckChange" />
|
|
|
+ <RegionTree class="region-tree-container" :treeData="regionTree" @check-change="handleCheckChange" disabled />
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 公開期間 -->
|
|
|
@@ -47,17 +48,19 @@
|
|
|
label="immediate"
|
|
|
v-model="queryParams.releaseType"
|
|
|
class="vertical-radio"
|
|
|
+ disabled
|
|
|
>即時公開</el-radio>
|
|
|
<el-radio
|
|
|
label="scheduled"
|
|
|
v-model="queryParams.releaseType"
|
|
|
class="scheduled-radio"
|
|
|
+ disabled
|
|
|
>期間指定</el-radio>
|
|
|
<div class="scheduled-row">
|
|
|
<!-- 期間指定时显示的日期选择(同行) -->
|
|
|
<div class="date-group" >
|
|
|
<!-- 日期选择器代码保持不变 -->
|
|
|
- <el-select v-model="queryParams.startYear" placeholder="" class="date-select" :disabled="queryParams.releaseType === 'immediate'" @change="formatDate">
|
|
|
+ <el-select v-model="queryParams.startYear" placeholder="" class="date-select" disabled @change="formatDate">
|
|
|
<el-option v-for="year in years" :key="year" :label="year" :value="year"></el-option>
|
|
|
</el-select>
|
|
|
<span class="date-label">年</span>
|
|
|
@@ -66,7 +69,7 @@
|
|
|
placeholder=""
|
|
|
class="date-select-small"
|
|
|
@change="formatDate"
|
|
|
- :disabled="queryParams.releaseType === 'immediate'"
|
|
|
+ disabled
|
|
|
>
|
|
|
<el-option
|
|
|
v-for="month in months"
|
|
|
@@ -81,7 +84,7 @@
|
|
|
placeholder=""
|
|
|
class="date-select-small"
|
|
|
@change="formatDate"
|
|
|
- :disabled="queryParams.releaseType === 'immediate'"
|
|
|
+ disabled
|
|
|
>
|
|
|
<el-option
|
|
|
v-for="day in days"
|
|
|
@@ -97,7 +100,7 @@
|
|
|
placeholder=""
|
|
|
class="date-select"
|
|
|
@change="formatDate"
|
|
|
- :disabled="queryParams.releaseType === 'immediate'"
|
|
|
+ disabled
|
|
|
>
|
|
|
<el-option
|
|
|
v-for="year in years"
|
|
|
@@ -112,7 +115,7 @@
|
|
|
placeholder=""
|
|
|
class="date-select-small"
|
|
|
@change="formatDate"
|
|
|
- :disabled="queryParams.releaseType === 'immediate'"
|
|
|
+ disabled
|
|
|
>
|
|
|
<el-option
|
|
|
v-for="month in months"
|
|
|
@@ -127,7 +130,7 @@
|
|
|
placeholder=""
|
|
|
class="date-select-small"
|
|
|
@change="formatDate"
|
|
|
- :disabled="queryParams.releaseType === 'immediate'"
|
|
|
+ disabled
|
|
|
>
|
|
|
<el-option
|
|
|
v-for="day in days"
|
|
|
@@ -145,7 +148,7 @@
|
|
|
|
|
|
<div v-for="(question, index) in questions" :key="question.sortOrder" class="question-block">
|
|
|
<el-form-item style="margin-left: 50px; margin-top: 3px;">
|
|
|
- <el-button class="append-button" @click="addQuestionAbove(index)">この上に設問を追加</el-button>
|
|
|
+ <el-button disabled class="append-button" @click="addQuestionAbove(index)">この上に設問を追加</el-button>
|
|
|
</el-form-item>
|
|
|
<el-form-item style="margin-left: 55px;">
|
|
|
<template #label>
|
|
|
@@ -154,10 +157,10 @@
|
|
|
<span style="color: #666; margin-left: 8px;">: {{ question.sortOrder }}</span>
|
|
|
</div>
|
|
|
</template>
|
|
|
- <el-input v-model="question.questionText" class="small-input" type="textarea" :rows="2" :maxlength="255"></el-input>
|
|
|
+ <el-input disabled v-model="question.questionText" class="small-input" type="textarea" :rows="2" :maxlength="255"></el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="回答型" style="margin-left: 55px;margin-top: -15px">
|
|
|
- <el-radio-group v-model="question.questionType" class="custom-radio-group" @change="handleQuestionTypeChange(question, $event)">
|
|
|
+ <el-radio-group disabled v-model="question.questionTypeStr" class="custom-radio-group" @change="handleQuestionTypeChange(question, $event)">
|
|
|
<el-radio label="INPUT_BOX_50">入力ボックス(50文字)</el-radio>
|
|
|
<el-radio label="INPUT_BOX_100">入力ボックス(100文字)</el-radio>
|
|
|
<el-radio label="CHECK_BOX">チェックボックス</el-radio>
|
|
|
@@ -167,25 +170,27 @@
|
|
|
</el-form-item>
|
|
|
<el-form-item>
|
|
|
<el-input
|
|
|
- v-if="question.questionType === 'INPUT_BOX_50'"
|
|
|
+ v-if="question.questionTypeStr === 'INPUT_BOX_50'"
|
|
|
v-model="question.input50"
|
|
|
:maxlength="50"
|
|
|
class="textarea-input"
|
|
|
type="textarea"
|
|
|
:rows="2"
|
|
|
+ disabled
|
|
|
></el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item>
|
|
|
<el-input
|
|
|
- v-if="question.questionType === 'INPUT_BOX_100'"
|
|
|
+ v-if="question.questionTypeStr === 'INPUT_BOX_100'"
|
|
|
v-model="question.input100"
|
|
|
:maxlength="100"
|
|
|
class="textarea-input100"
|
|
|
type="textarea"
|
|
|
:rows="2"
|
|
|
+ disabled
|
|
|
></el-input>
|
|
|
</el-form-item>
|
|
|
- <el-form-item v-if="question.questionType === 'CHECK_BOX'" style="margin-left: 125px;margin-top: -60px;">
|
|
|
+ <el-form-item v-if="question.questionTypeStr === 'CHECK_BOX'" style="margin-left: 125px;margin-top: -60px;">
|
|
|
<!-- 循环渲染每一行:复选框 + 输入框 + 削除按钮 -->
|
|
|
<div
|
|
|
v-for="(item, itemIndex) in question.checkboxItems"
|
|
|
@@ -197,24 +202,28 @@
|
|
|
<el-checkbox
|
|
|
v-model="item.checked"
|
|
|
class="checkbox-item"
|
|
|
+ disabled
|
|
|
></el-checkbox>
|
|
|
<el-input
|
|
|
v-model="item.optionText"
|
|
|
class="input-item"
|
|
|
+ disabled
|
|
|
></el-input>
|
|
|
<el-button
|
|
|
type="text"
|
|
|
class="delete-btn"
|
|
|
@click="deleteCheckboxItem(index, itemIndex)"
|
|
|
+ disabled
|
|
|
>削除</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
<el-button
|
|
|
class="append-btn"
|
|
|
@click="addCheckboxItem(index)"
|
|
|
+ disabled
|
|
|
>追加</el-button>
|
|
|
</el-form-item>
|
|
|
- <el-form-item v-if="question.questionType === 'RADIO_BUTTON'" style="margin-left: 125px;margin-top: -60px;">
|
|
|
+ <el-form-item v-if="question.questionTypeStr === 'RADIO_BUTTON'" style="margin-left: 125px;margin-top: -60px;">
|
|
|
<!-- 循环渲染每一行:单选按钮 + 输入框 + 削除按钮 -->
|
|
|
<div
|
|
|
v-for="(item, itemIndex) in question.radioItems"
|
|
|
@@ -227,38 +236,42 @@
|
|
|
:label="item.value"
|
|
|
v-model="question.radioGroupValue"
|
|
|
class="hidden-label-radio"
|
|
|
+ disabled
|
|
|
></el-radio>
|
|
|
<el-input
|
|
|
v-model="item.optionText"
|
|
|
class="radio-item"
|
|
|
+ disabled
|
|
|
></el-input>
|
|
|
<el-button
|
|
|
type="text"
|
|
|
class="radio-btn"
|
|
|
@click="deleteRadioItem(index, itemIndex)"
|
|
|
+ disabled
|
|
|
>削除</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
<el-button
|
|
|
class="append-btn"
|
|
|
@click="addRadioItem(index)"
|
|
|
+ disabled
|
|
|
>追加</el-button>
|
|
|
</el-form-item>
|
|
|
- <el-form-item v-if="question.questionType === 'NUMBER_SELECT'" style="margin-left: 120px;margin-top: -50px">
|
|
|
+ <el-form-item v-if="question.questionTypeStr === 'NUMBER_SELECT'" style="margin-left: 120px;margin-top: -50px">
|
|
|
<div style="display: flex; flex-direction: column; gap: 10px; width: 100%;">
|
|
|
<!-- 選択肢部分 -->
|
|
|
<div style="display: flex; align-items: center; width: 100%;">
|
|
|
<span>選択肢</span>
|
|
|
<div style="width: 35px;"></div>
|
|
|
- <el-input type="number" min="0" max="999" v-model="question.numberSelectStart" class="mx-2"
|
|
|
+ <el-input type="number" disabled min="0" max="999" v-model="question.numberSelectStart" class="mx-2"
|
|
|
style="width: 60px;margin-right: 10px;"></el-input>
|
|
|
<span>~</span>
|
|
|
- <el-input type="number" min="0" max="999" v-model="question.numberSelectEnd" class="mx-2" style="width: 60px;margin-left: 10px;"></el-input>
|
|
|
+ <el-input disabled type="number" min="0" max="999" v-model="question.numberSelectEnd" class="mx-2" style="width: 60px;margin-left: 10px;"></el-input>
|
|
|
</div>
|
|
|
<!-- 単位部分 -->
|
|
|
<div style="display: flex; align-items: center; width: 100%; flex-wrap: nowrap; white-space: nowrap;">
|
|
|
<span>単位</span>
|
|
|
- <el-radio-group v-model="question.unitHas" class="mx-radio-group">
|
|
|
+ <el-radio-group disabled v-model="question.unitHas" class="mx-radio-group">
|
|
|
<el-radio :label="false" class="radio-group">なし</el-radio>
|
|
|
<el-radio :label="true">あり</el-radio>
|
|
|
</el-radio-group>
|
|
|
@@ -272,13 +285,9 @@
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
<el-form-item style="margin-left: 50px; margin-top: -10px;">
|
|
|
- <el-button class="append-button" @click="addQuestionBelow(index)">この下に設問を追加</el-button>
|
|
|
+ <el-button class="append-button" disabled @click="addQuestionBelow(index)">この下に設問を追加</el-button>
|
|
|
</el-form-item>
|
|
|
</div>
|
|
|
-
|
|
|
- <el-form-item style="text-align: center;">
|
|
|
- <el-button @click="Confirm" class="confirm-button">確認</el-button>
|
|
|
- </el-form-item>
|
|
|
</el-form>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -287,7 +296,7 @@
|
|
|
|
|
|
<script name="SurveyDetail" setup>
|
|
|
|
|
|
-import { getRegionTree, addSurvey} from "@/api/fcbi/survey.js"
|
|
|
+import { getRegionTree,listSurveyDetail} from "@/api/fcbi/survey.js"
|
|
|
import { reactive, toRefs, ref, watch, onMounted } from 'vue';
|
|
|
import RegionTree from '../../../components/RegionTree.vue';
|
|
|
import { ElMessage } from "element-plus";
|
|
|
@@ -336,8 +345,8 @@ const data = reactive({
|
|
|
questions: [
|
|
|
{
|
|
|
questionText: '',
|
|
|
- questionType: 'INPUT_BOX_50',
|
|
|
- oldQuestionType: 'INPUT_BOX_50',
|
|
|
+ questionTypeStr: 'INPUT_BOX_50',
|
|
|
+ oldQuestionTypeStr: 'INPUT_BOX_50',
|
|
|
input50: '',
|
|
|
input100: '',
|
|
|
checkboxItems: [
|
|
|
@@ -429,7 +438,7 @@ const adjustSortOrders = (startIndex) => {
|
|
|
// 回答类型切换时重置前一类型的状态
|
|
|
const handleQuestionTypeChange = (question, newType) => {
|
|
|
// 保存旧类型用于判断需要重置哪些数据
|
|
|
- const oldType = question.questionType;
|
|
|
+ const oldType = question.questionTypeStr;
|
|
|
|
|
|
// 如果类型未变化,不执行重置
|
|
|
if (oldType === newType) return;
|
|
|
@@ -469,7 +478,7 @@ const handleQuestionTypeChange = (question, newType) => {
|
|
|
}
|
|
|
|
|
|
// 更新为新类型(确保数据同步)
|
|
|
- question.questionType = newType;
|
|
|
+ question.questionTypeStr = newType;
|
|
|
};
|
|
|
|
|
|
//ボタンの追加方法
|
|
|
@@ -571,20 +580,14 @@ watch(
|
|
|
);
|
|
|
|
|
|
watch(
|
|
|
- () => data.questions.map(q => q.questionType),
|
|
|
+ () => data.questions.map(q => q.questionTypeStr),
|
|
|
(newTypes, oldTypes) => {
|
|
|
data.questions.forEach((question, index) => {
|
|
|
const newType = newTypes[index];
|
|
|
const oldType = oldTypes[index];
|
|
|
-
|
|
|
- // 类型未变化则跳过
|
|
|
if (newType === oldType) return;
|
|
|
-
|
|
|
- // 执行重置逻辑
|
|
|
resetOldTypeData(question, oldType);
|
|
|
-
|
|
|
- // 更新旧类型记录
|
|
|
- question.oldQuestionType = oldType;
|
|
|
+ question.oldQuestionTypeStr = oldType; // 记录旧类型
|
|
|
});
|
|
|
},
|
|
|
{ deep: true }
|
|
|
@@ -593,13 +596,12 @@ watch(
|
|
|
const resetOldTypeData = (question, oldType) => {
|
|
|
switch (oldType) {
|
|
|
case 'INPUT_BOX_50':
|
|
|
- question.input50 = ''; // 清空输入
|
|
|
+ question.input50 = '';
|
|
|
break;
|
|
|
case 'INPUT_BOX_100':
|
|
|
- question.input100 = ''; // 清空输入
|
|
|
+ question.input100 = '';
|
|
|
break;
|
|
|
case 'CHECK_BOX':
|
|
|
- // 强制重置为3个空选项
|
|
|
question.checkboxItems = [
|
|
|
{ checked: false, optionText: '', sortOrder: 1 },
|
|
|
{ checked: false, optionText: '', sortOrder: 2 },
|
|
|
@@ -607,7 +609,6 @@ const resetOldTypeData = (question, oldType) => {
|
|
|
];
|
|
|
break;
|
|
|
case 'RADIO_BUTTON':
|
|
|
- // 强制重置为3个空选项,清空选中值
|
|
|
question.radioItems = [
|
|
|
{ value: 'option1', optionText: '', sortOrder: 1 },
|
|
|
{ value: 'option2', optionText: '', sortOrder: 2 },
|
|
|
@@ -616,7 +617,6 @@ const resetOldTypeData = (question, oldType) => {
|
|
|
question.radioGroupValue = null;
|
|
|
break;
|
|
|
case 'NUMBER_SELECT':
|
|
|
- // 清空所有数字选择器相关数据
|
|
|
question.numberSelectStart = '';
|
|
|
question.numberSelectEnd = '';
|
|
|
question.unitHas = false;
|
|
|
@@ -626,32 +626,250 @@ const resetOldTypeData = (question, oldType) => {
|
|
|
};
|
|
|
|
|
|
onMounted(async () => {
|
|
|
- const response = await getRegionTree();
|
|
|
- if (response?.success) {
|
|
|
- const regions = response.data.regions || []
|
|
|
+ // 先加载地区数据
|
|
|
+ const regionResponse = await getRegionTree();
|
|
|
+ if (regionResponse?.success) {
|
|
|
+ const regions = regionResponse.data.regions || []
|
|
|
regionTree.value = regions
|
|
|
surveyStore.setRegionTree(regions)
|
|
|
if (regionTree.value.length > 0) {
|
|
|
updateSelectedRegions(regionTree.value);
|
|
|
}
|
|
|
} else {
|
|
|
- error.value = response?.message || '地域データの取得に失敗しました';
|
|
|
- console.error('地域データの取得に失敗しました:', response);
|
|
|
+ error.value = regionResponse?.message || '地域データの取得に失敗しました';
|
|
|
+ console.error('地域データの取得に失敗しました:', regionResponse);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 加载问卷详情数据
|
|
|
+ if (surveyId) {
|
|
|
+ try {
|
|
|
+ const requestData = { surveyId };
|
|
|
+ const surveyResponse = await listSurveyDetail(requestData);
|
|
|
+
|
|
|
+ if (surveyResponse.code === 200) {
|
|
|
+ // 从返回结果中获取问卷数据(假设rows是数组,取第一个元素)
|
|
|
+ const surveyData = surveyResponse.rows?.[0] || {};
|
|
|
+
|
|
|
+ // 绑定基本信息(标题、描述、公开范围等)
|
|
|
+ bindSurveyBasicInfo(surveyData);
|
|
|
+
|
|
|
+ // 处理问题数据(后端返回的是JSON字符串)
|
|
|
+ let questionArray = [];
|
|
|
+ if (surveyData.question) {
|
|
|
+ try {
|
|
|
+ // 解析JSON字符串为数组
|
|
|
+ questionArray = JSON.parse(surveyData.question);
|
|
|
+
|
|
|
+ // 验证解析结果是否为数组
|
|
|
+ if (!Array.isArray(questionArray)) {
|
|
|
+ console.warn('question字段解析后不是数组,已初始化为空数组');
|
|
|
+ questionArray = [];
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ // 处理JSON解析错误
|
|
|
+ console.error('question字段JSON解析失败:', e);
|
|
|
+ console.error('原始字符串内容:', surveyData.question);
|
|
|
+ ElMessage.error('アンケートの問題データ形式が無効です');
|
|
|
+ questionArray = [];
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 处理question字段为空的情况
|
|
|
+ console.log('question字段为空,初始化为空数组');
|
|
|
+ questionArray = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 绑定问题列表
|
|
|
+ bindSurveyQuestions(questionArray);
|
|
|
+
|
|
|
+ // 绑定地区选择
|
|
|
+ bindSelectedRegions(surveyData.region || []);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // 处理接口返回错误状态
|
|
|
+ ElMessage.error(surveyResponse?.message || 'アンケートデータの取得に失敗しました');
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ // 处理接口调用异常
|
|
|
+ console.error('アンケートデータの取得中にエラーが発生しました:', err);
|
|
|
+ ElMessage.error('アンケートデータの取得中にエラーが発生しました');
|
|
|
+ }
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+const bindSurveyBasicInfo = (surveyData) => {
|
|
|
+ // 标题和描述
|
|
|
+ queryParams.value.title = surveyData.title || '';
|
|
|
+ queryParams.value.description = surveyData.description || '';
|
|
|
+
|
|
|
+ // 公开范围 - FC
|
|
|
+ if (surveyData.brandCode) {
|
|
|
+ queryParams.value.brandCode = typeof surveyData.brandCode === 'string'
|
|
|
+ ? JSON.parse(surveyData.brandCode)
|
|
|
+ : (surveyData.brandCode || []);
|
|
|
+ } else {
|
|
|
+ queryParams.value.brandCode = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 公开范围 - 業種
|
|
|
+ if (surveyData.businessTypeCode) {
|
|
|
+ queryParams.value.businessTypeCode = typeof surveyData.businessTypeCode === 'string'
|
|
|
+ ? JSON.parse(surveyData.businessTypeCode)
|
|
|
+ : (surveyData.businessTypeCode || []);
|
|
|
+ } else {
|
|
|
+ queryParams.value.businessTypeCode = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 公开期间
|
|
|
+ if (surveyData.publicMode === 'INSTANT') {
|
|
|
+ queryParams.value.releaseType = 'immediate';
|
|
|
+ } else if (surveyData.publicMode === 'PERIOD') {
|
|
|
+ queryParams.value.releaseType = 'scheduled';
|
|
|
+ // 解析开始日期
|
|
|
+ if (surveyData.publicStartTime) {
|
|
|
+ const startDate = new Date(surveyData.publicStartTime);
|
|
|
+ queryParams.value.startYear = startDate.getFullYear();
|
|
|
+ queryParams.value.startMonth = startDate.getMonth() + 1;
|
|
|
+ queryParams.value.startDay = startDate.getDate();
|
|
|
+ }
|
|
|
+ // 解析结束日期
|
|
|
+ if (surveyData.publicEndTime) {
|
|
|
+ const endDate = new Date(surveyData.publicEndTime);
|
|
|
+ queryParams.value.endYear = endDate.getFullYear();
|
|
|
+ queryParams.value.endMonth = endDate.getMonth() + 1;
|
|
|
+ queryParams.value.endDay = endDate.getDate();
|
|
|
+ }
|
|
|
+ formatDate();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const bindSurveyQuestions = (questionsData) => {
|
|
|
+ if (!questionsData.length) return;
|
|
|
+
|
|
|
+ // 清空现有问题
|
|
|
+ data.questions = [];
|
|
|
+
|
|
|
+ // 绑定每个问题
|
|
|
+ questionsData.forEach((q, index) => {
|
|
|
+ const question = {
|
|
|
+ questionText: q.questionText || '',
|
|
|
+ questionTypeStr: q.questionTypeStr || 'INPUT_BOX_50',
|
|
|
+ oldQuestionTypeStr: q.questionTypeStr || 'INPUT_BOX_50',
|
|
|
+ input50: '',
|
|
|
+ input100: '',
|
|
|
+ checkboxItems: [],
|
|
|
+ radioItems: [],
|
|
|
+ radioGroupValue: null,
|
|
|
+ numberSelectStart: '',
|
|
|
+ numberSelectEnd: '',
|
|
|
+ unitHas: false,
|
|
|
+ sortOrder: index + 1,
|
|
|
+ questionUnit: ''
|
|
|
+ };
|
|
|
+
|
|
|
+ // 根据问题类型绑定不同的内容
|
|
|
+ switch (question.questionTypeStr) {
|
|
|
+ case 'INPUT_BOX_50':
|
|
|
+ question.input50 = q.input50 || '';
|
|
|
+ break;
|
|
|
+ case 'INPUT_BOX_100':
|
|
|
+ question.input100 = q.input100 || '';
|
|
|
+ break;
|
|
|
+ case 'CHECK_BOX':
|
|
|
+ question.checkboxItems = q.checkboxItems || [
|
|
|
+ { checked: false, optionText: '', sortOrder: 1 },
|
|
|
+ { checked: false, optionText: '', sortOrder: 2 },
|
|
|
+ { checked: false, optionText: '', sortOrder: 3 },
|
|
|
+ ];
|
|
|
+ break;
|
|
|
+ case 'RADIO_BUTTON':
|
|
|
+ question.radioItems = q.radioItems || [
|
|
|
+ { value: 'option1', optionText: '', sortOrder: 1 },
|
|
|
+ { value: 'option2', optionText: '', sortOrder: 2 },
|
|
|
+ { value: 'option3', optionText: '', sortOrder: 3 },
|
|
|
+ ];
|
|
|
+ question.radioGroupValue = q.radioGroupValue || null;
|
|
|
+ break;
|
|
|
+ case 'NUMBER_SELECT':
|
|
|
+ question.numberSelectStart = q.numberSelectStart || '';
|
|
|
+ question.numberSelectEnd = q.numberSelectEnd || '';
|
|
|
+ question.unitHas = q.unitHas || false;
|
|
|
+ question.questionUnit = q.questionUnit || '';
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ data.questions.push(question);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const bindSelectedRegions = (region) => {
|
|
|
+
|
|
|
+ const regionData = typeof region === 'string' ? JSON.parse(region) : region;
|
|
|
+
|
|
|
+ selectedRegions.value = [...regionData];
|
|
|
+ queryParams.value.regions = [...regionData];
|
|
|
+
|
|
|
+ regionData.forEach(region => {
|
|
|
+ checkRegionNode(regionTree.value, region.regionCode);
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const checkRegionNode = (nodes, regionCode, parentNode = null) => {
|
|
|
+ for (const node of nodes) {
|
|
|
+ if (node.regionCode === regionCode) {
|
|
|
+ node.checked = true;
|
|
|
+ // 子节点选中后,更新其父节点状态
|
|
|
+ updateParentNodeStatus(parentNode);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (node.children && node.children.length > 0) {
|
|
|
+ // 递归查找子节点时,将当前节点作为父节点传入
|
|
|
+ const found = checkRegionNode(node.children, regionCode, node);
|
|
|
+ if (found) return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+};
|
|
|
+
|
|
|
+const updateParentNodeStatus = (parentNode) => {
|
|
|
+ if (!parentNode) return; // 没有父节点则终止
|
|
|
+
|
|
|
+ const children = parentNode.children || [];
|
|
|
+ // 统计子节点中选中的数量
|
|
|
+ const checkedCount = children.filter(child => child.checked).length;
|
|
|
+
|
|
|
+ if (checkedCount === 0) {
|
|
|
+ // 没有子节点选中:父节点不选中,也不是半选
|
|
|
+ parentNode.checked = false;
|
|
|
+ parentNode.indeterminate = false;
|
|
|
+ } else if (checkedCount === children.length) {
|
|
|
+ // 所有子节点都选中:父节点选中,不是半选
|
|
|
+ parentNode.checked = true;
|
|
|
+ parentNode.indeterminate = false;
|
|
|
+ } else {
|
|
|
+ // 部分子节点选中:父节点不选中,但为半选
|
|
|
+ parentNode.checked = false;
|
|
|
+ parentNode.indeterminate = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 继续向上更新父节点的父节点(递归)
|
|
|
+ updateParentNodeStatus(parentNode.parent);
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
// 選択した状態変更の処理
|
|
|
const handleCheckChange = (regionId, isChecked) => {
|
|
|
const region = findRegionById(regionTree.value, regionId);
|
|
|
if (region) {
|
|
|
if (isChecked) {
|
|
|
- if (!selectedRegions.value.some(r => r.region_code === region.region_code)) {
|
|
|
+ if (!selectedRegions.value.some(r => r.regionCode === region.regionCode)) {
|
|
|
selectedRegions.value.push({
|
|
|
- region_code: region.region_code
|
|
|
+ regionCode: region.regionCode // 字段名修改
|
|
|
});
|
|
|
}
|
|
|
} else {
|
|
|
- selectedRegions.value = selectedRegions.value.filter(r => r.region_code !== region.region_code);
|
|
|
+ selectedRegions.value = selectedRegions.value.filter(r => r.regionCode !== region.regionCode);
|
|
|
}
|
|
|
queryParams.value.regions = selectedRegions.value;
|
|
|
}
|
|
|
@@ -683,7 +901,6 @@ const updateSelectedRegions = (nodes) => {
|
|
|
// 選択したすべてのサブエリアオブジェクトを再帰的に収集する(親ノードをスキップ)
|
|
|
const collectSelectedRegions = (nodes, isParent = false) => {
|
|
|
nodes.forEach(node => {
|
|
|
- // 親ノード(上位ノード)の場合は、収集をスキップして再帰的な子ノードを続行します
|
|
|
if (isParent) {
|
|
|
if (node.children && node.children.length > 0) {
|
|
|
collectSelectedRegions(node.children, false);
|
|
|
@@ -692,7 +909,7 @@ const collectSelectedRegions = (nodes, isParent = false) => {
|
|
|
}
|
|
|
if (node.checked) {
|
|
|
selectedRegions.value.push({
|
|
|
- region_code: node.region_code
|
|
|
+ regionCode: node.regionCode
|
|
|
});
|
|
|
}
|
|
|
if (node.children && node.children.length > 0) {
|
|
|
@@ -700,157 +917,6 @@ const collectSelectedRegions = (nodes, isParent = false) => {
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
-
|
|
|
-// 確認按钮点击处理函数
|
|
|
-const Confirm = async () => {
|
|
|
- if (!queryParams.value.title) {
|
|
|
- ElMessage.error('タイトルを入力してください');
|
|
|
- return;
|
|
|
- }
|
|
|
- if (queryParams.value.releaseType === 'scheduled') {
|
|
|
- if (!queryParams.value.startYear || !queryParams.value.startMonth || !queryParams.value.startDay ||
|
|
|
- !queryParams.value.endYear || !queryParams.value.endMonth || !queryParams.value.endDay) {
|
|
|
- ElMessage.error('期間指定の場合は全ての日付を入力してください');
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- if (regionTree.value.length > 0) {
|
|
|
- updateSelectedRegions(regionTree.value);
|
|
|
- }
|
|
|
- formatDate();
|
|
|
- if (queryParams.value.releaseType === 'scheduled') {
|
|
|
- // 确保日期格式正确(YYYY-MM-DD)
|
|
|
- const startDate = new Date(queryParams.publicStartTime);
|
|
|
- const endDate = new Date(queryParams.publicEndTime);
|
|
|
-
|
|
|
- // 检查日期是否有效且开始时间大于结束时间
|
|
|
- if (!isNaN(startDate.getTime()) && !isNaN(endDate.getTime()) && startDate > endDate) {
|
|
|
- ElMessage.error('公開開始日時は公開終了日時より後に設定できません');
|
|
|
- return; // 中断提交
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- let hasError = false;
|
|
|
- const questionsData = data.questions.map(question => {
|
|
|
- if (!question.questionText || question.questionText.trim() === '') {
|
|
|
- ElMessage.warning(`設問文${question.sortOrder}の設問文を入力してください`);
|
|
|
- hasError = true;
|
|
|
- return null;
|
|
|
- }
|
|
|
- const questionData = {
|
|
|
- questionText: question.questionText,
|
|
|
- questionType: question.questionType,
|
|
|
- input50: question.input50,
|
|
|
- input100: question.input100,
|
|
|
- numberSelectStart: question.numberSelectStart,
|
|
|
- numberSelectEnd: question.numberSelectEnd,
|
|
|
- questionUnit: question.questionUnit,
|
|
|
- unitHas: question.unitHas,
|
|
|
- sortOrder: question.sortOrder
|
|
|
- };
|
|
|
-
|
|
|
- // CHECKBOXタイプの問題を処理するオプション
|
|
|
- if (question.questionType === 'CHECK_BOX') {
|
|
|
- questionData.checkboxItems = question.checkboxItems.map((item, itemIndex) => {
|
|
|
- // 新增:校验optionText是否为空
|
|
|
- if (!item.optionText || item.optionText.trim() === '') {
|
|
|
- ElMessage.warning(`設問文${question.sortOrder}の選択肢${itemIndex + 1}を入力してください`);
|
|
|
- hasError = true;
|
|
|
- }
|
|
|
- return {
|
|
|
- optionText: item.optionText,
|
|
|
- sortOrder: item.sortOrder
|
|
|
- };
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // RADIOタイプの問題を処理するオプション
|
|
|
- if (question.questionType === 'RADIO_BUTTON') {
|
|
|
- questionData.radioItems = question.radioItems.map((item, itemIndex) => {
|
|
|
- // 新增:校验optionText是否为空
|
|
|
- if (!item.optionText || item.optionText.trim() === '') {
|
|
|
- ElMessage.warning(`設問文${question.sortOrder}の選択肢${itemIndex + 1}を入力してください`);
|
|
|
- hasError = true;
|
|
|
- }
|
|
|
- return {
|
|
|
- optionText: item.optionText,
|
|
|
- sortOrder: item.sortOrder
|
|
|
- };
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // SELECTタイプの問題:動的生成オプション
|
|
|
- if (question.questionType === 'NUMBER_SELECT') {
|
|
|
- // 先判断start或end是否为空(包括空字符串、纯空格)
|
|
|
- const isStartEmpty = !question.numberSelectStart || question.numberSelectStart.trim() === '';
|
|
|
- const isEndEmpty = !question.numberSelectEnd || question.numberSelectEnd.trim() === '';
|
|
|
-
|
|
|
- if (isStartEmpty) {
|
|
|
- ElMessage.warning(`設問文${question.sortOrder}の選択肢1を入力してください`);
|
|
|
- hasError = true;
|
|
|
- }
|
|
|
-
|
|
|
- if (isEndEmpty) {
|
|
|
- ElMessage.warning(`設問文${question.sortOrder}の選択肢2を入力してください`);
|
|
|
- hasError = true;
|
|
|
- }
|
|
|
-
|
|
|
- if (isStartEmpty || isEndEmpty) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- const start = parseInt(question.numberSelectStart);
|
|
|
- const end = parseInt(question.numberSelectEnd);
|
|
|
-
|
|
|
- if (!isNaN(start) && !isNaN(end) && start <= end) {
|
|
|
- // startからendへのオプションの動的生成
|
|
|
- questionData.selectOptions = Array.from({ length: end - start + 1 }, (_, i) => ({
|
|
|
- optionText: (start + i).toString(),
|
|
|
- sortOrder: i + 1
|
|
|
- }));
|
|
|
- } else {
|
|
|
- ElMessage.warning(`SELECTタイプ問題の範囲が無効です:${start}~${end}`);
|
|
|
- hasError = true; // 标记有错误
|
|
|
- return null; // 临时返回null
|
|
|
- }
|
|
|
- // 新增:単位「あり」时的输入框空值校验
|
|
|
- if (question.unitHas && (!question.questionUnit || question.questionUnit.trim() === '')) {
|
|
|
- ElMessage.warning(`設問文${question.sortOrder}の単位を入力してください`);
|
|
|
- hasError = true;
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return questionData;
|
|
|
- });
|
|
|
- if (hasError) {
|
|
|
- return;
|
|
|
- }
|
|
|
- const validQuestionsData = questionsData.filter(q => q !== null);
|
|
|
- const params = {
|
|
|
- title: queryParams.value.title,
|
|
|
- description: queryParams.value.description,
|
|
|
- publicStartTime: queryParams.publicStartTime,
|
|
|
- publicEndTime: queryParams.publicEndTime,
|
|
|
- publicMode: queryParams.publicMode,
|
|
|
- brandCodes: queryParams.value.brandCode,
|
|
|
- businessTypeCodes: queryParams.value.businessTypeCode,
|
|
|
- numberSelectStart: queryParams.value.numberSelectStart,
|
|
|
- numberSelectEnd: queryParams.value.numberSelectEnd,
|
|
|
- questions: validQuestionsData,
|
|
|
- regions: queryParams.value.regions
|
|
|
- };
|
|
|
- addSurvey(params).then((res) => {
|
|
|
- if (res.success) {
|
|
|
- surveyStore.updateFormData({
|
|
|
- queryParams: data.queryParams,
|
|
|
- questions: data.questions
|
|
|
- });
|
|
|
- router.push({ name: 'SurveyDecision' });
|
|
|
- }
|
|
|
- });
|
|
|
-};
|
|
|
</script>
|
|
|
|
|
|
|