diff --git a/.github/workflows/server-lint.yml b/.github/workflows/server-lint.yml
index 8e1634a2..17cabfe3 100644
--- a/.github/workflows/server-lint.yml
+++ b/.github/workflows/server-lint.yml
@@ -37,6 +37,3 @@ jobs:
- name: Lint
run: cd server && npm run lint
-
- - name: Format
- run: cd server && npm run format
diff --git a/.github/workflows/web-lint.yml b/.github/workflows/web-lint.yml
index ab1b576e..4af9aa2e 100644
--- a/.github/workflows/web-lint.yml
+++ b/.github/workflows/web-lint.yml
@@ -40,6 +40,3 @@ jobs:
- name: Lint
run: cd web && npm run lint
-
- - name: Format
- run: cd web && npm run format
diff --git a/README.md b/README.md
index c1b4665f..02093549 100644
--- a/README.md
+++ b/README.md
@@ -29,12 +29,10 @@
- **XIAOJUSURVEY**是一套轻量、安全的**问卷系统基座**,提供面向个人和企业的一站式产品级解决方案,快速满足各类线上调研场景。
+ **XIAOJUSURVEY**是一套轻量、安全的问卷系统,提供面向个人和企业的一站式产品级解决方案,用于构建各类问卷、考试、测评和复杂表单,快速满足各类线上调研场景。
内部系统已沉淀 40+种题型,累积精选模板 100+,适用于市场调研、客户满意度调研、在线考试、投票、报道、测评等众多场景。数据能力上,经过上亿量级打磨,沉淀了分题统计、交叉分析、多渠道分析等在线报表能力,快速满足专业化分析。
- 开源项目以打造**调研基座**为核心,围绕**平台能力**、**工程架构**、**研发体系**进行建设,大家可以「快速」打造「专属」问卷系统:[快速了解生态发展理念](https://xiaojusurvey.didi.cn/docs/next/community/%E7%94%9F%E6%80%81%E5%BB%BA%E8%AE%BE)
-
# 功能简介
- 问卷管理:创、编、投、收、数据分析
@@ -45,7 +43,7 @@
- 数据安全:传输加密、脱敏等
-> 更全的建设请查阅 [官方 Feature](https://github.com/didi/xiaoju-survey/issues/45)
+> 更全的建设请查阅 [功能介绍](https://xiaojusurvey.didi.cn/docs/next/document/%E4%BA%A7%E5%93%81%E6%89%8B%E5%86%8C/%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D/%E5%9F%BA%E7%A1%80%E6%B5%81%E7%A8%8B)
@@ -220,16 +218,8 @@ npm run serve
## Future Tasks
-1、[官方 Feature](https://github.com/didi/xiaoju-survey/issues/45)
-
-2、[WIP](https://github.com/didi/xiaoju-survey/labels/WIP)
+[欢迎共建](https://github.com/didi/xiaoju-survey/issues/85)
## CHANGELOG
关注重大变更:[MAJOR CHANGELOG](https://github.com/didi/xiaoju-survey/issues/48)
-
-## 文章分享
-
-1、[掘金](https://juejin.cn/user/3705833332160473/posts)、2、[CSDN](https://blog.csdn.net/XIAOJUSURVEY)、3、[InfoQ](https://www.infoq.cn/profile/7E08AC616A07B2/publish)、4、[知乎](https://www.zhihu.com/people/xiaojusurvey)
-
-[欢迎共建](https://github.com/didi/xiaoju-survey/issues/85)
diff --git a/README_EN.md b/README_EN.md
index 166dcf1a..84902ad4 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -29,12 +29,10 @@
- XIAOJUSURVEY is a lightweight, secure questionnaire system foundation that provides one-stop product-level solutions for individuals and enterprises, quickly meeting various online survey scenarios.
+ XIAOJUSURVEY is an open-source form builder and analytics platform to create questionnaires, exams, polls, quizzes, and analyze data online.
The internal system has accumulated over 40 question types and more than 100 selected templates, suitable for market research, customer satisfaction surveys, online exams, voting, reporting, evaluations, and many other scenarios. In terms of data capabilities, it has been honed through hundreds of millions of iterations, resulting in the ability to provide online reports with per-question statistics, cross-analysis, and multi-channel analysis, quickly meeting professional analysis needs.
- The open-source project focuses on building a survey foundation, constructing around platform capabilities, engineering structure, and development systems, allowing everyone to 「quickly」 create their own 「exclusive」 questionnaire system: [quickly understanding the ecological development philosophy](https://xiaojusurvey.didi.cn/docs/next/community/%E7%94%9F%E6%80%81%E5%BB%BA%E8%AE%BE).
-
# Function Overview
- Questionnaire Management: Create, edit, distribute, collect, data analysis.
@@ -45,7 +43,7 @@
- Data Security: Encrypted transmission, data masking, etc.
-> For more comprehensive features, please refer to the official Feature documentation.
+> For more comprehensive features, please refer to the [documentation](https://xiaojusurvey.didi.cn/docs/next/document/%E4%BA%A7%E5%93%81%E6%89%8B%E5%86%8C/%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D/%E5%9F%BA%E7%A1%80%E6%B5%81%E7%A8%8B).
@@ -225,9 +223,3 @@ If you want to become a contributor or expand your technical stack, please check
## CHANGELOG
Follow major changes: [MAJOR CHANGELOG](https://github.com/didi/xiaoju-survey/issues/48)
-
-## Article Sharing
-
-1、[x.com](https://x.com/t_sudoooooo)
-
-[Welcome to contribute.](https://github.com/didi/xiaoju-survey/issues/85)
diff --git a/web/src/management/pages/edit/components/QuestionWrapper.vue b/web/src/management/pages/edit/components/QuestionWrapper.vue
index 1deed875..8ac1b213 100644
--- a/web/src/management/pages/edit/components/QuestionWrapper.vue
+++ b/web/src/management/pages/edit/components/QuestionWrapper.vue
@@ -141,15 +141,8 @@ const onMoveDown = () => {
}
}
const onDelete = async () => {
- if (unref(hasShowLogic)) {
- ElMessageBox.alert('该题目被显示逻辑关联,请先清除逻辑依赖', '提示', {
- confirmButtonText: '确定',
- type: 'warning'
- })
- return
- }
- if (unref(hasJumpLogic)) {
- ElMessageBox.alert('该题目被跳转逻辑关联,请先清除逻辑依赖', '提示', {
+ if (unref(hasShowLogic) || getShowLogicText.value) {
+ ElMessageBox.alert('该问题被逻辑依赖,请先删除逻辑依赖', '提示', {
confirmButtonText: '确定',
type: 'warning'
})
diff --git a/web/src/management/pages/edit/modules/questionModule/SetterPanel.vue b/web/src/management/pages/edit/modules/questionModule/SetterPanel.vue
index 1d478bd5..0b3540b9 100644
--- a/web/src/management/pages/edit/modules/questionModule/SetterPanel.vue
+++ b/web/src/management/pages/edit/modules/questionModule/SetterPanel.vue
@@ -1,37 +1,69 @@
-
-
-
选中题型可以编辑
-
来!试试看~
-
-
- {{ currentEditMeta?.title || '' }}
-
-
+
+
+
+ {{ currentEditMeta?.title || '' }}
+
+
+
+
+
选中题型可以编辑
+
来!试试看~
+
+
+
+
+
+
+
+
-
+
diff --git a/web/src/management/pages/edit/modules/questionModule/components/TypeList.vue b/web/src/management/pages/edit/modules/questionModule/components/TypeList.vue
index 8f8f6b4e..e4d812be 100644
--- a/web/src/management/pages/edit/modules/questionModule/components/TypeList.vue
+++ b/web/src/management/pages/edit/modules/questionModule/components/TypeList.vue
@@ -19,11 +19,14 @@
class="qtopic-item"
:id="'qtopic' + element.type"
@click="onQuestionType({ type: element.type })"
- @mouseenter="showPreview(element, 'qtopic' + element.type)"
- @mouseleave="isShowPreviewImage = false"
- @mousedown="isShowPreviewImage = false"
>
-
+
{{ element.title }}
diff --git a/web/src/management/stores/composables/useEditGlobalBaseConf.ts b/web/src/management/stores/composables/useEditGlobalBaseConf.ts
new file mode 100644
index 00000000..5cdcf959
--- /dev/null
+++ b/web/src/management/stores/composables/useEditGlobalBaseConf.ts
@@ -0,0 +1,99 @@
+import { reactive, type Ref } from 'vue'
+
+export type TypeMethod = 'INIT' | 'MODIFY' | 'REMOVE' | 'ADD'
+
+export default function useEditGlobalBaseConf(
+ questionDetailList: Ref,
+ updateTime: () => void
+) {
+ // 整卷配置数据
+ const globalBaseConfig = reactive({
+ isRequired: true,
+ showIndex: true,
+ showType: true,
+ showSpliter: true
+ })
+
+ // 整卷配置各项选项选中个数统计
+ const optionCheckedCounts = {
+ isRequiredCount: 0,
+ showIndexCount: 0,
+ showTypeCount: 0,
+ showSpliterCount: 0
+ }
+
+ const resetCount = () => {
+ optionCheckedCounts.isRequiredCount = 0
+ optionCheckedCounts.showIndexCount = 0
+ optionCheckedCounts.showTypeCount = 0
+ optionCheckedCounts.showSpliterCount = 0
+ }
+
+ // 初始化统计
+ function initCounts() {
+ resetCount()
+ questionDetailList.value.forEach((question: any) => {
+ calculateCountsForQuestion('INIT', { question })
+ })
+ updateGlobalBaseConf()
+ }
+
+ // 更新统计
+ function updateCounts(type: TypeMethod, data: any) {
+ if (type === 'MODIFY') {
+ calculateOptionCounts(type, data)
+ } else {
+ calculateCountsForQuestion(type, data)
+ }
+ updateGlobalBaseConf()
+ }
+
+ // 计算整卷配置各项选项选中个数
+ function calculateCountsForQuestion(type: TypeMethod, { question }: any) {
+ Object.keys(globalBaseConfig).forEach((key) => {
+ calculateOptionCounts(type, { key, value: question[key] })
+ })
+ }
+
+ // 计算单个选项选中个数
+ function calculateOptionCounts(type: TypeMethod, { key, value }: any) {
+ const _key = `${key}Count` as keyof typeof optionCheckedCounts
+ if (value) {
+ if (type === 'REMOVE') optionCheckedCounts[_key]--
+ else optionCheckedCounts[_key]++
+ } else {
+ if (type === 'MODIFY') optionCheckedCounts[_key]--
+ }
+ }
+
+ // 更新整卷配置状态
+ function updateGlobalBaseConf() {
+ const len = questionDetailList.value.length
+ const { isRequiredCount, showIndexCount, showSpliterCount, showTypeCount } = optionCheckedCounts
+ Object.assign(globalBaseConfig, {
+ isRequired: isRequiredCount === len,
+ showIndex: showIndexCount === len,
+ showSpliter: showSpliterCount === len,
+ showType: showTypeCount === len
+ })
+ }
+
+ // 整卷配置修改
+ function updateGlobalConfOption({ key, value }: { key: string; value: boolean }) {
+ const len = questionDetailList.value.length
+ const _key = `${key}Count` as keyof typeof optionCheckedCounts
+ if (value) optionCheckedCounts[_key] = len
+ else optionCheckedCounts[_key] = 0
+ questionDetailList.value.forEach((question: any) => {
+ question[key] = value
+ })
+ updateTime()
+ }
+
+ return {
+ globalBaseConfig,
+ initCounts,
+ updateCounts,
+ updateGlobalConfOption
+ }
+}
diff --git a/web/src/management/stores/edit.ts b/web/src/management/stores/edit.ts
index 65552a72..dbeee769 100644
--- a/web/src/management/stores/edit.ts
+++ b/web/src/management/stores/edit.ts
@@ -19,6 +19,7 @@ import questionLoader from '@/materials/questions/questionLoader'
import { SurveyPermissions } from '@/management/utils/types/workSpace'
import { getBannerData } from '@/management/api/skin.js'
import { getCollaboratorPermissions } from '@/management/api/space'
+import useEditGlobalBaseConf, { type TypeMethod } from './composables/useEditGlobalBaseConf'
import { CODE_MAP } from '../api/base'
import { RuleBuild } from '@/common/logicEngine/RuleBuild'
@@ -29,7 +30,7 @@ const innerMetaConfig = {
}
}
-function useInitializeSchema(surveyId: Ref) {
+function useInitializeSchema(surveyId: Ref, initializeSchemaCallBack: () => void) {
const schema = reactive({
metaData: null,
bannerConf: {
@@ -133,6 +134,7 @@ function useInitializeSchema(surveyId: Ref) {
logicConf
}
})
+ initializeSchemaCallBack()
initShowLogicEngine()
initJumpLogicEngine()
@@ -150,11 +152,17 @@ function useInitializeSchema(surveyId: Ref) {
}
}
-function useQuestionDataListOperations(
- questionDataList: Ref,
- updateTime: () => void,
+function useQuestionDataListOperations({
+ questionDataList,
+ updateTime,
+ pageOperations,
+ updateCounts
+}: {
+ questionDataList: Ref
+ updateTime: () => void
pageOperations: (type: string) => void
-) {
+ updateCounts: (type: TypeMethod, data: any) => void
+}) {
function copyQuestion({ index }: { index: number }) {
const newQuestion = _cloneDeep(questionDataList.value[index])
newQuestion.field = getNewField(questionDataList.value.map((item) => item.field))
@@ -165,12 +173,14 @@ function useQuestionDataListOperations(
questionDataList.value.splice(index, 0, question)
pageOperations('add')
updateTime()
+ updateCounts('ADD', { question })
}
function deleteQuestion({ index }: { index: number }) {
pageOperations('remove')
- questionDataList.value.splice(index, 1)
+ const [question] = questionDataList.value.splice(index, 1)
updateTime()
+ updateCounts('REMOVE', { question })
}
function moveQuestion({ index, range }: { index: number; range: number }) {
@@ -459,8 +469,13 @@ export const useEditStore = defineStore('edit', () => {
const cooperPermissions = ref(Object.values(SurveyPermissions))
const schemaUpdateTime = ref(Date.now())
const { schema, initSchema, getSchemaFromRemote, showLogicEngine, jumpLogicEngine } =
- useInitializeSchema(surveyId)
+ useInitializeSchema(surveyId, () => {
+ editGlobalBaseConf.initCounts()
+ })
const questionDataList = toRef(schema, 'questionDataList')
+
+ const editGlobalBaseConf = useEditGlobalBaseConf(questionDataList, updateTime)
+
function setQuestionDataList(data: any) {
schema.questionDataList = data
}
@@ -524,9 +539,12 @@ export const useEditStore = defineStore('edit', () => {
} = usePageEdit({ schema, questionDataList }, updateTime)
const { copyQuestion, addQuestion, deleteQuestion, moveQuestion } = useQuestionDataListOperations(
- questionDataList,
- updateTime,
- pageOperations
+ {
+ questionDataList,
+ updateTime,
+ pageOperations,
+ updateCounts: editGlobalBaseConf.updateCounts
+ }
)
function moveQuestionDataList(data: any) {
@@ -602,6 +620,7 @@ export const useEditStore = defineStore('edit', () => {
}
return {
+ editGlobalBaseConf,
surveyId,
setSurveyId,
bannerList,
diff --git a/web/src/render/pages/IndexPage.vue b/web/src/render/pages/IndexPage.vue
index 83569d61..b54dfa68 100644
--- a/web/src/render/pages/IndexPage.vue
+++ b/web/src/render/pages/IndexPage.vue
@@ -2,7 +2,7 @@