Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

同步develop分支 #143

Closed
wants to merge 10 commits into from
39 changes: 39 additions & 0 deletions .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Unit Test Coverage Report
name: Test Coverage

on:
pull_request:
branches:
- feature/workflow
- develop
- main
- releases/**
- feature/**
paths:
- server/**
workflow_dispatch:

jobs:
build:
name: Coverage
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20

- name: Install dependencies
run: cd server && npm install

- name: Run tests and collect coverage
run: cd server && npm run test:cov

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
34 changes: 34 additions & 0 deletions .github/workflows/server-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Lint
name: Server Lint

on:
pull_request:
branches:
- feature/workflow
- develop
- main
- releases/**
- feature/**
paths:
- server/**
workflow_dispatch:

jobs:
build:
name: Lint
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20

- name: Install dependencies
run: cd server && npm install

- name: Lint
run: cd server && npm run lint
34 changes: 34 additions & 0 deletions .github/workflows/web-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Lint
name: Web Lint

on:
pull_request:
branches:
- feature/workflow
- develop
- main
- releases/**
- feature/**
paths:
- web/**
workflow_dispatch:

jobs:
build:
name: Lint
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20

- name: Install dependencies
run: cd web && npm install

- name: Lint
run: cd web && npm run lint
20 changes: 16 additions & 4 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"private": true,
"type": "module",
"scripts": {
"serve": "vite",
"dev": "vite",
"serve": "npm run dev",
"dev": "vite --open",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
Expand Down Expand Up @@ -45,6 +45,7 @@
"@vue/tsconfig": "^0.5.1",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"husky": "^9.0.11",
"npm-run-all2": "^6.1.1",
"prettier": "^3.0.3",
"sass": "^1.72.0",
Expand All @@ -56,8 +57,19 @@
"vite-plugin-virtual-mpa": "^1.11.0",
"vue-tsc": "^1.8.27"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{.vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts}": [
"prettier --write",
"eslint --fix"
]
},
"engines": {
"node": ">=14.21.0",
"npm": ">=6.14.17"
"node": ">=18.0.0",
"npm": ">=8.6.0"
}
}
1 change: 1 addition & 0 deletions web/src/management/config/dnd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DND_GROUP = 'question'
17 changes: 14 additions & 3 deletions web/src/management/pages/edit/components/MaterialGroup.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<template>
<draggable
:list="renderData"
v-model="renderData"
handle=".question-wrapper.isSelected"
filter=".question-wrapper.isSelected .question.isSelected"
:group="DND_GROUP"
:onEnd="checkEnd"
:move="checkMove"
itemKey="field"
Expand Down Expand Up @@ -34,10 +35,12 @@

<script>
import { computed, defineComponent, ref, getCurrentInstance } from 'vue'
import { useStore } from 'vuex'
import QuestionContainerB from '@/materials/questions/QuestionContainerB'
import QuestionWrapper from '@/management/pages/edit/components/QuestionWrapper.vue'
import draggable from 'vuedraggable'
import { filterQuestionPreviewData } from '@/management/utils/index'
import { DND_GROUP } from '@/management/config/dnd'

export default defineComponent({
components: {
Expand All @@ -58,8 +61,15 @@ export default defineComponent({
}
},
setup(props, { emit }) {
const renderData = computed(() => {
return filterQuestionPreviewData(props.questionDataList)
const store = useStore()

const renderData = computed({
get () {
return filterQuestionPreviewData(props.questionDataList)
},
set (questionDataList) {
store.commit('edit/setQuestionDataList', questionDataList)
}
})
const handleSelect = (index) => {
emit('select', index)
Expand Down Expand Up @@ -89,6 +99,7 @@ export default defineComponent({
}

return {
DND_GROUP,
renderData,
handleSelect,
handleChangeSeq,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,58 +6,91 @@
:name="index"
:key="index"
>
<div class="questiontype-list">
<el-popover
v-for="(item, index) in item.questionList"
:key="item.type"
placement="right"
trigger="hover"
:popper-class="'qtype-popper-' + (index % 3)"
:popper-style="{ width: '369px' }"
<draggable
class="questiontype-list"
:list="item.questionList"
:group="{ name: DND_GROUP, pull: 'clone', put: false }"
:clone="getNewQuestion"
item-key="path"
>
<img :src="item.snapshot" width="345px" />
<template #reference>
<div :key="item.type" class="qtopic-item" @click="onQuestionType({ type: item.type })">
<i class="iconfont" :class="['icon-' + item.icon]"></i>
<p class="text">{{ item.title }}</p>
</div>
<template #item="{ element }">
<div
:key="element.type"
class="qtopic-item"
:id="'qtopic' + element.type"
@click="onQuestionType({ type: element.type })"
@mouseenter="showPreview(element, 'qtopic' + element.type)"
@mouseleave="isShowPreviewImage = false"
@mousedown="isShowPreviewImage = false"
>
<i class="iconfont" :class="['icon-' + element.icon]"></i>
<p class="text">{{ element.title }}</p>
</div>
</template>
</el-popover>
</div>
</draggable>
</el-collapse-item>
<Teleport to="body">
<div class="preview-popover" v-show="isShowPreviewImage" :style="{ top: previewTop + 'px'}">
<img :src="previewImg" class="preview-image"/>
<span class="preview-arrow"></span>
</div>
</Teleport>
</el-collapse>
</template>

<script setup>
import questionLoader from '@/materials/questions/questionLoader'
import draggable from 'vuedraggable'
import { DND_GROUP } from '@/management/config/dnd'

import questionMenuConfig, { questionTypeList } from '@/management/config/questionMenuConfig'
import { getQuestionByType } from '@/management/utils/index'
import { useStore } from 'vuex'
import { get as _get } from 'lodash-es'
import { get as _get, isNumber as _isNumber } from 'lodash-es'
import { computed, ref } from 'vue'

const activeNames = ref([0, 1])

const store = useStore()

const activeNames = ref([0, 1])
const previewImg = ref('')
const isShowPreviewImage = ref(false)
const previewTop = ref(0)
const questionDataList = computed(() => _get(store, 'state.edit.schema.questionDataList'))
const newQuestionIndex = computed(() => {
const currentEditOne = _get(store, 'state.edit.currentEditOne')
const index = _isNumber(currentEditOne) ? currentEditOne + 1 : questionDataList.value.length
return index
})

questionLoader.init({
typeList: questionTypeList.map((item) => item.type)
})

const onQuestionType = ({ type }) => {
const getNewQuestion = ({ type }) => {
const fields = questionDataList.value.map((item) => item.field)
const currentEditOne = _get(store, 'state.edit.currentEditOne')
const index =
typeof currentEditOne === 'number' ? currentEditOne + 1 : questionDataList.value.length
const newQuestion = getQuestionByType(type, fields)
newQuestion.title = newQuestion.title = `标题${index + 1}`
newQuestion.title = newQuestion.title = `标题${newQuestionIndex.value + 1}`
if (type === 'vote') {
newQuestion.innerType = 'radio'
}
store.dispatch('edit/addQuestion', { question: newQuestion, index })
store.commit('edit/setCurrentEditOne', index)
return newQuestion
}

const onQuestionType = ({ type }) => {
const newQuestion = getNewQuestion({ type })
store.dispatch('edit/addQuestion', { question: newQuestion, index: newQuestionIndex.value })
store.commit('edit/setCurrentEditOne', newQuestionIndex.value)
}

const showPreview = ({ snapshot }, id) => {
previewImg.value = snapshot

const dragEl = document.getElementById(id)
const { top, height } = dragEl.getBoundingClientRect()
previewTop.value = top + height / 2

isShowPreviewImage.value = true
}
</script>

Expand Down Expand Up @@ -103,9 +136,10 @@ const onQuestionType = ({ type }) => {
background-color: $primary-color-light;
border: 1px solid $primary-color;
}

.text {
font-size: 12px;
user-select: none;
}
}

Expand All @@ -128,4 +162,64 @@ const onQuestionType = ({ type }) => {
.qtype-popper-2 {
transform: translateX(30px);
}
// 设置拖拽到编辑区的样式
.box .qtopic-item {
height: 2px;
width: 100%;
background-color: var(--primary-color);
* {
display: none;
}
}

@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

.preview-popover {
position: fixed;
left: 390px;
z-index: 9;
width: 371px;
padding: 12px;
background: white;
border: 1px solid var(--el-border-color-light);
box-shadow: var(--el-box-shadow-light);
transform: translateY(-50%);
animation: fadeIn 100ms linear forwards;

.preview-image {
width: 100%;
object-fit: contain;
}

.preview-arrow {
position: absolute;
top: 50%;
left: -6px;
height: 10px;
width: 10px;
transform: translateX(-50%);
background: var(--el-border-color-light);
z-index: -1;
transform: rotate(-45deg);

&::before {
position: absolute;
content: "";
height: 10px;
width: 10px;
border: 1px solid var(--el-border-color-light);
background: #ffffff;
border-bottom-color: transparent;
border-right-color: transparent;
}

}
}
</style>
Loading
Loading