Compare commits

...

8 Commits

Author SHA1 Message Date
qxa 96666dd58d 修改发布脚本
部署生产环境 / 发布版本 (push) Successful in 16s Details
部署生产环境 / 编译发布 (push) Successful in 2m57s Details
部署开发环境 / 编译发布 (push) Successful in 2m27s Details
2024-06-14 11:00:40 +08:00
yj 7f49c5d68e 优化
部署生产环境 / 发布版本 (push) Successful in 19s Details
部署生产环境 / 编译发布 (push) Successful in 2m38s Details
2024-06-13 16:23:10 +08:00
yj 36f66440ac 优化
部署生产环境 / 发布版本 (push) Successful in 12s Details
部署生产环境 / 编译发布 (push) Successful in 3m45s Details
2024-06-13 14:08:12 +08:00
yj 644a5e4238 优化
部署生产环境 / 发布版本 (push) Successful in 19s Details
部署生产环境 / 编译发布 (push) Successful in 1m27s Details
2024-06-13 09:37:10 +08:00
yj c4f2ce2c21 优化
部署生产环境 / 发布版本 (push) Successful in 18s Details
部署生产环境 / 编译发布 (push) Failing after 3m1s Details
2024-06-12 17:56:06 +08:00
yj cce7d4f389 保存时数据不对
部署生产环境 / 发布版本 (push) Successful in 13s Details
部署生产环境 / 编译发布 (push) Successful in 3m52s Details
2024-06-12 17:01:27 +08:00
yj 337f1b917c 优化
部署生产环境 / 发布版本 (push) Successful in 20s Details
部署生产环境 / 编译发布 (push) Successful in 1m30s Details
2024-06-12 16:27:26 +08:00
yj 14a8bde1fe 优化
部署生产环境 / 发布版本 (push) Successful in 18s Details
部署生产环境 / 编译发布 (push) Failing after 3m29s Details
2024-06-11 16:31:04 +08:00
9 changed files with 417 additions and 155 deletions

View File

@ -6,8 +6,8 @@ on:
- develop - develop
env: env:
IMAGE_NAME: ${{ gitea.repository_owner }}/usercenter.web IMAGE_NAME: ${{ gitea.repository_owner }}/maketemplate.web
PUBLISH_PATH: usercenter.web PUBLISH_PATH: maketemplate.web
PUBLISH_HOST: 10.255.255.44 PUBLISH_HOST: 10.255.255.44
PUBLISH_PORT: 22 PUBLISH_PORT: 22
PUBLISH_REPLICAS: 1 #启动副本数量 PUBLISH_REPLICAS: 1 #启动副本数量
@ -16,21 +16,17 @@ jobs:
job1: job1:
name: 编译发布 name: 编译发布
runs-on: linux runs-on: linux
container:
image: node:16-bullseye
volumes:
#挂载缓存
- /opt/.runner/node_modules:/cache
steps: steps:
- name: 下载源码 - name: 下载源码
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: 使用缓存 - name: 使用缓存
uses: actions/cache@master uses: actions/cache@master
with: with:
mount: | mount: |
node_modules node_modules
hash_files: |
package.json
- name: 编译项目 - name: 编译项目
run: | run: |

View File

@ -6,8 +6,8 @@ on:
- master - master
env: env:
IMAGE_NAME: ${{ gitea.repository_owner }}/usercenter.web IMAGE_NAME: ${{ gitea.repository_owner }}/maketemplate.web
PUBLISH_PATH: usercenter.web PUBLISH_PATH: maketemplate.web
PUBLISH_HOST: 10.255.255.74 PUBLISH_HOST: 10.255.255.74
PUBLISH_PORT: 10022 PUBLISH_PORT: 10022
PUBLISH_REPLICAS: 1 #启动副本数量 PUBLISH_REPLICAS: 1 #启动副本数量
@ -21,7 +21,7 @@ jobs:
steps: steps:
- name: 下载源码 - name: 下载源码
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: 发布版本 - name: 发布版本
id: publish_version id: publish_version
@ -33,16 +33,15 @@ jobs:
needs: release needs: release
steps: steps:
- name: 下载源码 - name: 下载源码
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: 下载源码
uses: actions/checkout@v3
- name: 使用缓存 - name: 使用缓存
uses: actions/cache@master uses: actions/cache@master
with: with:
mount: | mount: |
node_modules node_modules
hash_files: |
package.json
- name: 编译项目 - name: 编译项目
shell: bash shell: bash

View File

@ -6,8 +6,8 @@ on:
- staging - staging
env: env:
IMAGE_NAME: ${{ gitea.repository_owner }}/usercenter.web IMAGE_NAME: ${{ gitea.repository_owner }}/maketemplate.web
PUBLISH_PATH: usercenter.web PUBLISH_PATH: maketemplate.web
PUBLISH_HOST: 10.255.255.3 PUBLISH_HOST: 10.255.255.3
PUBLISH_PORT: 22 PUBLISH_PORT: 22
PUBLISH_REPLICAS: 1 #启动副本数量 PUBLISH_REPLICAS: 1 #启动副本数量
@ -24,13 +24,15 @@ jobs:
steps: steps:
- name: 下载源码 - name: 下载源码
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: 使用缓存 - name: 使用缓存
uses: actions/cache@master uses: actions/cache@master
with: with:
mount: | mount: |
node_modules node_modules
hash_files: |
package.json
- name: 编译项目 - name: 编译项目
shell: bash shell: bash

View File

@ -6,8 +6,8 @@ on:
- published - published
env: env:
IMAGE_NAME: ${{ gitea.repository_owner }}/usercenter.web IMAGE_NAME: ${{ gitea.repository_owner }}/maketemplate.web
PUBLISH_PATH: usercenter.web PUBLISH_PATH: maketemplate.web
PUBLISH_HOST: 10.255.255.74 PUBLISH_HOST: 10.255.255.74
PUBLISH_PORT: 10022 PUBLISH_PORT: 10022
PUBLISH_REPLICAS: 1 #启动副本数量 PUBLISH_REPLICAS: 1 #启动副本数量
@ -16,21 +16,18 @@ jobs:
job1: job1:
name: 编译发布 name: 编译发布
runs-on: linux runs-on: linux
container:
image: node:16-bullseye
volumes:
#挂载缓存
- /opt/.runner/node_modules:/cache
steps: steps:
- name: 下载源码 - name: 下载源码
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: 使用缓存 - name: 使用缓存
uses: actions/cache@master uses: actions/cache@master
with: with:
mount: | mount: |
node_modules node_modules
hash_files: |
package.json
- name: 编译项目 - name: 编译项目
shell: bash shell: bash

View File

@ -2,12 +2,12 @@ version: "3"
services: services:
usercenter-web: usercenter-web:
image: ${REGISTRY:-harbor.w.23544.com:8843}/marking/usercenter.web:${TAG:-latest} image: ${REGISTRY:-harbor.w.23544.com:8843}/marking/maketemplate.web:${TAG:-latest}
hostname: marking hostname: marking
environment: environment:
TZ: Asia/Shanghai TZ: Asia/Shanghai
ports: ports:
- 4400:80 - 8898:80
deploy: deploy:
mode: replicated mode: replicated
replicas: ${REPLICAS:-1} replicas: ${REPLICAS:-1}

View File

@ -2,21 +2,37 @@
<div> <div>
<span>坐标</span> <span>坐标</span>
<div> <div>
<el-button type="primary" @click="changeFabricPosition(true, 'top')">上移</el-button> <el-button type="primary" @click="changeFabricPosition(true, 'top')"
<el-button type="primary" @click="changeFabricPosition(false, 'top')">下移</el-button> >上移</el-button
<el-button type="primary" @click="changeFabricPosition(true, 'left')">左移</el-button> >
<el-button type="primary" @click="changeFabricPosition(false, 'left')">右移</el-button> <el-button type="primary" @click="changeFabricPosition(false, 'top')"
>下移</el-button
>
<el-button type="primary" @click="changeFabricPosition(true, 'left')"
>左移</el-button
>
<el-button type="primary" @click="changeFabricPosition(false, 'left')"
>右移</el-button
>
</div> </div>
</div> </div>
<div> <div>
<span>宽度</span> <span>宽度</span>
<el-input-number v-model="fabricPosition.width" :min="1" @change="changeFabricPosition($event, 'width')" <el-input-number
:max="fabricPosition.imgDomWidth" /> v-model="fabricPosition.width"
:min="1"
@change="changeFabricPosition($event, 'width')"
:max="fabricPosition.imgDomWidth"
/>
</div> </div>
<div> <div>
<span>高度</span> <span>高度</span>
<el-input-number v-model="fabricPosition.height" :min="1" @change="changeFabricPosition($event, 'height')" <el-input-number
:max="fabricPosition.imgDomHight" /> v-model="fabricPosition.height"
:min="1"
@change="changeFabricPosition($event, 'height')"
:max="fabricPosition.imgDomHight"
/>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -28,8 +44,8 @@ const fabricPosition = reactive<any>({
width: 0, width: 0,
height: 0, height: 0,
imgDomHight: 1, imgDomHight: 1,
imgDomWidth: 1 imgDomWidth: 1,
}) });
const setSize = (data: any, imgDomWidth: number, imgDomHight: number): void => { const setSize = (data: any, imgDomWidth: number, imgDomHight: number): void => {
fabricPosition.top = data.top; fabricPosition.top = data.top;
@ -38,23 +54,22 @@ const setSize = (data: any, imgDomWidth: number, imgDomHight: number): void => {
fabricPosition.height = data.height; fabricPosition.height = data.height;
fabricPosition.imgDomWidth = imgDomWidth; fabricPosition.imgDomWidth = imgDomWidth;
fabricPosition.imgDomHight = imgDomHight; fabricPosition.imgDomHight = imgDomHight;
} };
const changeFabricPosition = (value: number | boolean, str: string): void => { const changeFabricPosition = (value: number | boolean, str: string): void => {
if (typeof value === 'boolean') { if (typeof value === "boolean") {
if (str === 'top') { if (str === "top") {
props.change(value ? fabricPosition.top-- : fabricPosition.top++, str) props.change(value, str);
} else { } else {
props.change(value ? fabricPosition.left-- : fabricPosition.left++, str) props.change(value, str);
} }
} else { } else {
props.change(value, str) props.change(value, str);
}
} }
};
defineExpose({ defineExpose({
setSize, setSize,
}); });
</script> </script>
<style lang="scss" scoped></style> <style lang="scss" scoped></style>

View File

@ -9,7 +9,7 @@
> >
<div> <div>
<div style="font-size: 20px; margin-bottom: 20px; font-weight: bold"> <div style="font-size: 20px; margin-bottom: 20px; font-weight: bold">
锁定模板后无法修改请确认模板信息后操作 锁定模板后仅可调整位置和大小无法增删题目请确认模板信息后操作
</div> </div>
<div style="height: 70vh; overflow-y: auto"> <div style="height: 70vh; overflow-y: auto">
<el-collapse v-model="activeNames"> <el-collapse v-model="activeNames">
@ -17,7 +17,7 @@
<div v-if="item.key !== 'otherPoint'"> <div v-if="item.key !== 'otherPoint'">
<div v-if="item.data.length"> <div v-if="item.data.length">
<div v-for="row in item.data"> <div v-for="row in item.data">
{{ row.questionBefore }}-{{ row.questionAfter }} 总分{{ row.score }} {{ row.questionBefore }}-{{ row.questionAfter }} 每题{{ row.score }}
</div> </div>
</div> </div>
<div v-else> <div v-else>
@ -53,33 +53,7 @@ const activeNames = ref([
"otherPoint", "otherPoint",
]); ]);
const list = ref<any>([]); const list = ref<any>([]);
const getData = (data: any, templateInfo: any): void => { const getData = (data: any): void => {
//
let msg = "";
if (!templateInfo.headList[2].point.length && !templateInfo.tailsList[2].point.length) {
msg = "考号未框选!";
}
if (!templateInfo.headList[1].point.length && !templateInfo.tailsList[1].point.length) {
msg = "学科未框选!";
}
if (templateInfo.hasPosition) {
if (templateInfo.imgSrc.length === 2) {
if (
templateInfo.headList[0].point.length !== 4 ||
templateInfo.tailsList[0].point.length !== 4
) {
msg = "定位点未框选完成!";
}
} else {
if (templateInfo.headList[0].point.length !== 4) {
msg = "定位点未框选完成!";
}
}
}
if (msg) {
ElMessage.error(msg);
return;
}
// //
changeData(data); changeData(data);
// //

View File

@ -24,7 +24,12 @@
<img src="@/assets/image/icon1.png" alt="" v-if="item.index !== 5" /> <img src="@/assets/image/icon1.png" alt="" v-if="item.index !== 5" />
</div> </div>
</div> </div>
<div class="warp-nav-tab-delete" title="清空全部痕迹" @click="clearFabricGroup"> <div
class="warp-nav-tab-delete"
title="清空全部痕迹"
@click="clearFabricGroup"
v-if="!isLockStatus"
>
<img src="@/assets/image/icon2.png" alt="" /> <img src="@/assets/image/icon2.png" alt="" />
<span>清空全部痕迹</span> <span>清空全部痕迹</span>
</div> </div>
@ -92,6 +97,7 @@
alt="" alt=""
id="picture-img" id="picture-img"
style="user-select: none" style="user-select: none"
@load="canvasLoad"
/> />
<canvas id="picture"></canvas> <canvas id="picture"></canvas>
</div> </div>
@ -145,7 +151,7 @@
}} }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="得分" width="50px" align="center"> <el-table-column label="每题分数" align="center">
<template #default="scope"> <template #default="scope">
{{ scope.row.customFrom.score }} {{ scope.row.customFrom.score }}
</template> </template>
@ -163,8 +169,12 @@
<el-button type="primary" size="large" @click="btnClick('save')" <el-button type="primary" size="large" @click="btnClick('save')"
> </el-button > </el-button
> >
<el-button type="primary" size="large" @click="btnClick('lock')" <el-button
> </el-button type="primary"
size="large"
@click="btnClick('lock')"
:disabled="isLockStatus || isLockDisabled"
>{{ isLockStatus ? "已锁定" : "锁 定" }}</el-button
> >
</div> </div>
</div> </div>
@ -232,6 +242,7 @@
<span>考号长度</span> <span>考号长度</span>
<div> <div>
<el-input-number <el-input-number
:disabled="isLockStatus"
:min="4" :min="4"
:max="12" :max="12"
v-model="drawerForm.examId.examIdLength" v-model="drawerForm.examId.examIdLength"
@ -266,9 +277,9 @@
</div> </div>
</div> </div>
<FabricSize <FabricSize
:change="changeFabricPosition" :change="changeFabricPositionNumber"
ref="FabricSizeRef" ref="FabricSizeRef"
v-if="ctx.getActiveObject()" v-if="currentFabric"
/> />
</div> </div>
<div class="drawer-custom-style-body-footer"> <div class="drawer-custom-style-body-footer">
@ -306,7 +317,10 @@
<div> <div>
<span>排列</span> <span>排列</span>
<div> <div>
<el-radio-group v-model="drawerForm.objective.range"> <el-radio-group
v-model="drawerForm.objective.range"
:disabled="isLockStatus"
>
<el-radio :value="0">横向</el-radio> <el-radio :value="0">横向</el-radio>
<el-radio :value="1">竖向</el-radio> <el-radio :value="1">竖向</el-radio>
</el-radio-group> </el-radio-group>
@ -319,7 +333,7 @@
style="width: 164px" style="width: 164px"
v-model="drawerForm.objective.optionNumber" v-model="drawerForm.objective.optionNumber"
:min="2" :min="2"
:disabled="drawerForm.objective.questionTypeValue === 2" :disabled="drawerForm.objective.questionTypeValue === 2 || isLockStatus"
:step-strictly="true" :step-strictly="true"
:max="24" :max="24"
/> />
@ -329,6 +343,7 @@
<span>题量</span> <span>题量</span>
<div> <div>
<el-input-number <el-input-number
:disabled="isLockStatus"
style="width: 164px" style="width: 164px"
v-model="drawerForm.objective.questionNumber" v-model="drawerForm.objective.questionNumber"
:min="1" :min="1"
@ -341,6 +356,7 @@
<span>题号</span> <span>题号</span>
<div> <div>
<el-input-number <el-input-number
:disabled="isLockStatus"
v-model="drawerForm.objective.questionBefore" v-model="drawerForm.objective.questionBefore"
:min="1" :min="1"
:controls="false" :controls="false"
@ -357,9 +373,10 @@
</div> </div>
</div> </div>
<div> <div>
<span>得分</span> <span>每题分数</span>
<div> <div>
<el-input-number <el-input-number
:disabled="isLockStatus"
style="width: 164px" style="width: 164px"
v-model="drawerForm.objective.score" v-model="drawerForm.objective.score"
:min="0" :min="0"
@ -398,9 +415,9 @@
</div> </div>
</div> </div>
<FabricSize <FabricSize
:change="changeFabricPosition" :change="changeFabricPositionNumber"
ref="FabricSizeRef" ref="FabricSizeRef"
v-if="ctx.getActiveObject()" v-if="currentFabric"
/> />
</div> </div>
<div class="drawer-custom-style-body-footer"> <div class="drawer-custom-style-body-footer">
@ -445,6 +462,7 @@
<div> <div>
<el-input-number <el-input-number
v-model="drawerForm.subjective.questionBefore" v-model="drawerForm.subjective.questionBefore"
:disabled="isLockStatus"
:min="1" :min="1"
:controls="false" :controls="false"
:step-strictly="true" :step-strictly="true"
@ -457,6 +475,7 @@
<el-input-number <el-input-number
v-model="drawerForm.subjective.questionAfter" v-model="drawerForm.subjective.questionAfter"
:disabled="isLockStatus"
:min="1" :min="1"
:controls="false" :controls="false"
:step-strictly="true" :step-strictly="true"
@ -465,10 +484,11 @@
</div> </div>
</div> </div>
<div> <div>
<span>得分</span> <span>每题分数</span>
<div> <div>
<el-input-number <el-input-number
v-model="drawerForm.subjective.score" v-model="drawerForm.subjective.score"
:disabled="isLockStatus"
style="width: 152px" style="width: 152px"
:min="0" :min="0"
:precision="1" :precision="1"
@ -477,9 +497,9 @@
</div> </div>
</div> </div>
<FabricSize <FabricSize
:change="changeFabricPosition" :change="changeFabricPositionNumber"
ref="FabricSizeRef" ref="FabricSizeRef"
v-if="ctx.getActiveObject()" v-if="currentFabric"
/> />
</div> </div>
<div class="drawer-custom-style-body-footer"> <div class="drawer-custom-style-body-footer">
@ -503,7 +523,7 @@
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, reactive, ref, nextTick } from "vue"; import { onMounted, reactive, ref, nextTick, watch } from "vue";
import { fabric } from "fabric"; import { fabric } from "fabric";
import { createWorker } from "tesseract.js"; import { createWorker } from "tesseract.js";
import html2canvas from "html2canvas"; import html2canvas from "html2canvas";
@ -712,6 +732,9 @@ const templateInfo = reactive<any>({
questionList: [], questionList: [],
otherData: [], otherData: [],
}); });
const isLockStatus = ref<boolean>(false);
const isLockDisabled = ref<boolean>(false);
const currentNavListIndex = ref<number>(3);
// //
const ctx = ref<any>(null); const ctx = ref<any>(null);
const fabricGroup = ref<any>(null); const fabricGroup = ref<any>(null);
@ -721,11 +744,13 @@ const currentFabric = ref<any>(null);
onMounted(() => { onMounted(() => {
GetOcrDetail(router.currentRoute.value.query.mid as string).then((res: any) => { GetOcrDetail(router.currentRoute.value.query.mid as string).then((res: any) => {
if (res.code === 200) { if (res.code === 200) {
templateInfo.name = res.data.mainName; const { mainName, hasPosition, paperType, detail, isLock } = res.data;
templateInfo.hasPosition = res.data.hasPosition; isLockStatus.value = isLock;
templateInfo.type = res.data.paperType === 1 ? "A3" : "A4"; templateInfo.name = mainName;
templateInfo.otherData = res.data.detail; templateInfo.hasPosition = hasPosition;
res.data.detail.forEach((item: any, index: number) => { templateInfo.type = paperType === 1 ? "A3" : "A4";
templateInfo.otherData = detail.sort((a: any, b: any) => a.pageIndex - b.pageIndex);
templateInfo.otherData.forEach((item: any, index: number) => {
templateInfo.imgSrc.push(item.tempPicture64); templateInfo.imgSrc.push(item.tempPicture64);
if (item.tempData) { if (item.tempData) {
index === 0 index === 0
@ -733,7 +758,46 @@ onMounted(() => {
: (templateInfo.tailsList = JSON.parse(JSON.parse(item.tempData).tempData)); : (templateInfo.tailsList = JSON.parse(JSON.parse(item.tempData).tempData));
} }
}); });
nextTick(() => { }
});
});
watch(
() => templateInfo,
(_new, _old) => {
if (!_new.headList[2].point.length && !_new.tailsList[2].point.length) {
isLockDisabled.value = true;
currentNavListIndex.value = 2;
return;
}
if (!_new.headList[1].point.length && !_new.tailsList[1].point.length) {
isLockDisabled.value = true;
currentNavListIndex.value = 1;
return;
}
if (_new.hasPosition) {
if (_new.imgSrc.length === 2) {
if (_new.headList[0].point.length !== 4 || _new.tailsList[0].point.length !== 4) {
isLockDisabled.value = true;
currentNavListIndex.value = 0;
return;
}
} else {
if (_new.headList[0].point.length !== 4) {
isLockDisabled.value = true;
currentNavListIndex.value = 0;
return;
}
}
}
isLockDisabled.value = false;
},
{ deep: true }
);
//
const canvasLoad = (): void => {
if (!ctx.value) {
initCanvas(); initCanvas();
navListIndex.value = templateInfo.hasPosition ? 0 : 1; //1 navListIndex.value = templateInfo.hasPosition ? 0 : 1; //1
if (!templateInfo.hasPosition) { if (!templateInfo.hasPosition) {
@ -742,11 +806,10 @@ onMounted(() => {
} }
setQuestionList(); // setQuestionList(); //
showFabricData(); // showFabricData(); //
setStepClick(currentNavListIndex.value, false); //
setNavTitle(); // setNavTitle(); //
});
} }
}); };
});
// //
const initCanvas = (): void => { const initCanvas = (): void => {
@ -756,6 +819,10 @@ const initCanvas = (): void => {
height: imgDom.value.clientHeight, height: imgDom.value.clientHeight,
}); });
ctx.value.on("mouse:down", (e: any) => { ctx.value.on("mouse:down", (e: any) => {
if (isLockStatus.value && !e.target) {
ElMessage.error("已锁定,无法新增!");
return;
}
const templateInfoItem = getTemplateInfo(true); const templateInfoItem = getTemplateInfo(true);
if (templateInfoItem[0].point.length === 4) { if (templateInfoItem[0].point.length === 4) {
if (isMoveOutView()) { if (isMoveOutView()) {
@ -772,6 +839,9 @@ const initCanvas = (): void => {
} }
} }
} }
if (e.target) {
setStepClick(e.target.get("fabricType"));
}
canvasMouseDown(e.e, e.target, e.subTargets); canvasMouseDown(e.e, e.target, e.subTargets);
}); });
ctx.value.on("mouse:move", (e: any) => { ctx.value.on("mouse:move", (e: any) => {
@ -860,9 +930,15 @@ const canvasMouseDown = (e: MouseEvent, target: any, subTargets: any): void => {
const itemTarget = target const itemTarget = target
.getObjects() .getObjects()
.find((i: any) => i.fabricId === row.fabricId); .find((i: any) => i.fabricId === row.fabricId);
itemTarget && row.fabricId === itemTarget.fabricId if (itemTarget && row.fabricId === itemTarget.fabricId) {
? itemTarget.set({ visible: true }) if (isLockStatus.value && itemTarget.get("text") === "删除") {
: row.set({ visible: false }); row.set({ visible: false });
} else {
itemTarget.set({ visible: true });
}
} else {
row.set({ visible: false });
}
} else { } else {
row.set({ visible: false }); row.set({ visible: false });
} }
@ -928,7 +1004,7 @@ const canvasMouseUp = async (): Promise<void> => {
hasControls: false, hasControls: false,
subTargetCheck: true, subTargetCheck: true,
borderColor: "transparent", borderColor: "transparent",
selectionBackgroundColor: "transparent", selectionBackgroundColor: "red",
fabricType: navListIndex.value, fabricType: navListIndex.value,
fabricId: cteatedNumber(), fabricId: cteatedNumber(),
}).on("mousemove", (e: any) => { }).on("mousemove", (e: any) => {
@ -971,9 +1047,13 @@ const canvasMouseUp = async (): Promise<void> => {
}).then((res) => { }).then((res) => {
if (res.code === 200) { if (res.code === 200) {
const rectTitle = ["右上角", "右下角"]; const rectTitle = ["右上角", "右下角"];
const rectFooterTitle = ["左下角", "右下角"];
if (rectTitle.includes(getCurrentText())) { if (rectTitle.includes(getCurrentText())) {
res.data.x = res.data.x + res.data.width; res.data.x = res.data.x + res.data.width;
} }
if (rectFooterTitle.includes(getCurrentText())) {
res.data.y = res.data.y - res.data.height;
}
addFabric( addFabric(
"rect", "rect",
{ ...obj, title: getTextTitle(), rectPosition: res.data }, { ...obj, title: getTextTitle(), rectPosition: res.data },
@ -981,7 +1061,9 @@ const canvasMouseUp = async (): Promise<void> => {
left: rectTitle.includes(getCurrentText()) left: rectTitle.includes(getCurrentText())
? res.data.x - res.data.width ? res.data.x - res.data.width
: res.data.x, : res.data.x,
top: res.data.y, top: rectFooterTitle.includes(getCurrentText())
? res.data.y + res.data.height
: res.data.y,
width: res.data.width, width: res.data.width,
height: res.data.height, height: res.data.height,
stroke: "red", stroke: "red",
@ -1062,14 +1144,18 @@ const createText = (
text: string, text: string,
left: number, left: number,
top: number, top: number,
backgroundColor: string = "rgba(0,0,0,0.5)" backgroundColor: string = "rgba(0,0,0,0.5)",
fill: string = "white",
fontSize: number = 16,
fontWeight: string = "normal"
): any => { ): any => {
return new fabric.Text(text, { return new fabric.Text(text, {
left, left,
top, top,
fontSize: 16, fontSize,
fill: "white", fill,
backgroundColor, backgroundColor,
fontWeight,
fabricId: cteatedNumber(), fabricId: cteatedNumber(),
}); });
}; };
@ -1145,13 +1231,14 @@ const createFabric = (): any[] => {
case 1: case 1:
case 5: case 5:
return [titleText, deleteText]; return [titleText, deleteText];
case 3:
return [deleteText, editText];
default: default:
return [titleText, deleteText, editText]; return [titleText, deleteText, editText];
} }
}; };
// //
const setStepClick = (index: number): void => { const setStepClick = (index: number, isElMessage: boolean = true): void => {
if (navListIndex.value === index) { if (navListIndex.value === index) {
return; return;
} }
@ -1190,7 +1277,7 @@ const setStepClick = (index: number): void => {
checkTemplateInfo(index); checkTemplateInfo(index);
if (msg) { if (msg) {
ElMessage.error(msg); if (isElMessage) ElMessage.error(msg);
return; return;
} }
if (index === 1) { if (index === 1) {
@ -1231,6 +1318,9 @@ const saveFabricData = (): void => {
type: "text", type: "text",
text: child.get("text"), text: child.get("text"),
backgroundColor: child.get("backgroundColor"), backgroundColor: child.get("backgroundColor"),
fill: child.get("fill"),
fontSize: child.get("fontSize"),
fontWeight: child.get("fontWeight"),
...childItem, ...childItem,
}); });
} else { } else {
@ -1311,6 +1401,7 @@ const boxSelectAfter = async (): Promise<void> => {
lock: true, lock: true,
text: `识别中...`, text: `识别中...`,
background: "rgba(0, 0, 0, 0.7)", background: "rgba(0, 0, 0, 0.7)",
body: true,
}); });
const canvas = await html2canvas(imgDom.value, { const canvas = await html2canvas(imgDom.value, {
scale: 4, scale: 4,
@ -1395,7 +1486,7 @@ const isDisabledDraw = (): boolean => {
fabricItem.forEach((item: any) => { fabricItem.forEach((item: any) => {
let row = item.getObjects().filter((obj: any) => obj.get("text") === "缺考"); let row = item.getObjects().filter((obj: any) => obj.get("text") === "缺考");
if (row) { if (row) {
hasQueKao.push(row); hasQueKao.push(...row);
} }
}); });
isDisabledDrawStatus = hasQueKao.length === 0; isDisabledDrawStatus = hasQueKao.length === 0;
@ -1533,11 +1624,12 @@ const showFabricData = (): void => {
top: item.top, top: item.top,
width: item.width, width: item.width,
height: item.height, height: item.height,
fontSize: 16,
fill: "white",
backgroundColor: item.backgroundColor, backgroundColor: item.backgroundColor,
fill: item.fill || "white",
fontSize: item.fontSize || 16,
fabricId: cteatedNumber(), fabricId: cteatedNumber(),
visible: !textFabricList.value.includes(item.text), visible: !textFabricList.value.includes(item.text),
fontWeight: item.fontWeight || "normal",
}).on("mousedown", (e: any) => { }).on("mousedown", (e: any) => {
if (textFabricList.value.includes(item.text)) { if (textFabricList.value.includes(item.text)) {
addEventClick(e); addEventClick(e);
@ -1555,7 +1647,7 @@ const showFabricData = (): void => {
hasControls: false, hasControls: false,
subTargetCheck: true, subTargetCheck: true,
borderColor: "transparent", borderColor: "transparent",
selectionBackgroundColor: "transparent", selectionBackgroundColor: "rgba(255,0,0,0.5)",
fabricType: item.fabricType, fabricType: item.fabricType,
left: item.left, left: item.left,
top: item.top, top: item.top,
@ -1622,6 +1714,22 @@ const cteatedNumber = (): string => {
return `${Math.floor(Math.random() * 100000000)}+${+new Date()}`; return `${Math.floor(Math.random() * 100000000)}+${+new Date()}`;
}; };
//
const changeFabricPositionNumber = (value: number | boolean, str: string): void => {
let number = 0;
if (typeof value === "boolean") {
number = JSON.parse(JSON.stringify(currentFabric.value.target.get(str)));
if (value) {
number--;
} else {
number++;
}
} else {
number = value;
}
changeFabricPosition(number, str);
};
// //
const changeFabricPosition = (value: number, str: string): void => { const changeFabricPosition = (value: number, str: string): void => {
if (value) { if (value) {
@ -1682,7 +1790,8 @@ const changeFabricPosition = (value: number, str: string): void => {
maxRect.set("top", value / 2 - value); maxRect.set("top", value / 2 - value);
currentFabric.value.target.set(str, value + textList[0].height * 2); currentFabric.value.target.set(str, value + textList[0].height * 2);
} }
let rectWidth, rectHeight; let rectWidth = 0,
rectHeight = 0;
switch (navListIndex.value) { switch (navListIndex.value) {
// //
case 2: case 2:
@ -1712,17 +1821,25 @@ const changeFabricPosition = (value: number, str: string): void => {
// //
let questionNumber = currentFabric.value.target.customFrom.questionNumber; let questionNumber = currentFabric.value.target.customFrom.questionNumber;
let optionNumber = currentFabric.value.target.customFrom.optionNumber; let optionNumber = currentFabric.value.target.customFrom.optionNumber;
rectWidth = maxRect.get("width") / optionNumber; let range = currentFabric.value.target.customFrom.range;
rectHeight = maxRect.get("height") / questionNumber; rectWidth = maxRect.get("width") / (range ? questionNumber : optionNumber);
rectHeight = maxRect.get("height") / (range ? optionNumber : questionNumber);
changeTextPosition(); changeTextPosition();
deleteSmallRect(); deleteSmallRect();
for (let index = 0; index < optionNumber * questionNumber; index++) { for (let index = 0; index < optionNumber * questionNumber; index++) {
currentFabric.value.target.add( currentFabric.value.target.add(
new fabric.Rect({ new fabric.Rect({
left: maxRect.get("left") + (index % optionNumber) * rectWidth, left:
maxRect.get("left") +
(index % (range ? questionNumber : optionNumber)) * rectWidth,
top: top:
maxRect.get("top") + maxRect.get("top") +
getOffsetTop(optionNumber, questionNumber, index, rectHeight), getOffsetTop(
range ? questionNumber : optionNumber,
range ? optionNumber : questionNumber,
index,
rectHeight
),
stroke: "red", stroke: "red",
strokeWidth: 1, strokeWidth: 1,
fill: "transparent", fill: "transparent",
@ -1732,6 +1849,35 @@ const changeFabricPosition = (value: number, str: string): void => {
}) })
); );
} }
//
const questionNumberList = currentFabric.value.target
.getObjects()
.filter(
(item: any) =>
item.get("type") === "text" &&
!textFabricList.value.includes(item.get("text"))
);
questionNumberList.forEach((item: any, index: number) => {
if (range) {
item.set({
left:
maxRect.get("left") +
rectWidth * index +
rectWidth / 2 -
(questionNumber + 1),
top: maxRect.get("top") + 4,
});
} else {
item.set({
top:
maxRect.get("top") +
rectHeight * index +
rectHeight / 2 -
(questionNumber + 1),
left: maxRect.get("left") + 4,
});
}
});
break; break;
case 4: case 4:
// //
@ -1853,7 +1999,7 @@ const changeFabricInfo = (bool: boolean): void => {
left: fabricItem.get("customFrom").left, left: fabricItem.get("customFrom").left,
top: fabricItem.get("customFrom").top, top: fabricItem.get("customFrom").top,
width: fabricItem.get("customFrom").width, width: fabricItem.get("customFrom").width,
height: fabricItem.get("customFrom").top, height: fabricItem.get("customFrom").height,
}; };
if (bool) { if (bool) {
switch (navListIndex.value) { switch (navListIndex.value) {
@ -1965,12 +2111,11 @@ const changeFabricInfo = (bool: boolean): void => {
case 3: case 3:
// //
// //
function createdObjectiveRect(): void { function createdObjectiveRect(
let rect = fabricItem rect: any,
.getObjects() rectWidth: number,
.find((row: any) => row.get("type") === "rect"); rectHeight: number
let rectWidth = rect.get("width") / drawerForm.objective.optionNumber; ): void {
let rectHeight = rect.get("height") / drawerForm.objective.questionNumber;
for ( for (
let index = 0; let index = 0;
index < index <
@ -1981,12 +2126,20 @@ const changeFabricInfo = (bool: boolean): void => {
new fabric.Rect({ new fabric.Rect({
left: left:
rect.get("left") + rect.get("left") +
(index % drawerForm.objective.optionNumber) * rectWidth, (index %
(drawerForm.objective.range
? drawerForm.objective.questionNumber
: drawerForm.objective.optionNumber)) *
rectWidth,
top: top:
rect.get("top") + rect.get("top") +
getOffsetTop( getOffsetTop(
drawerForm.objective.optionNumber, drawerForm.objective.range
drawerForm.objective.questionNumber, ? drawerForm.objective.questionNumber
: drawerForm.objective.optionNumber,
drawerForm.objective.range
? drawerForm.objective.optionNumber
: drawerForm.objective.questionNumber,
index, index,
rectHeight rectHeight
), ),
@ -2004,11 +2157,21 @@ const changeFabricInfo = (bool: boolean): void => {
ElMessage.error("题目重复!"); ElMessage.error("题目重复!");
return; return;
} else { } else {
deleteSmallRect(); let rect = fabricItem
createdObjectiveRect(); .getObjects()
textTitle.set({ .find((row: any) => row.get("type") === "rect");
text: `${drawerForm.objective.questionBefore}-${drawerForm.objective.questionAfter}`, let rectWidth =
}); rect.get("width") /
(drawerForm.objective.range
? drawerForm.objective.questionNumber
: drawerForm.objective.optionNumber);
let rectHeight =
rect.get("height") /
(drawerForm.objective.range
? drawerForm.objective.optionNumber
: drawerForm.objective.questionNumber);
deleteSmallRect(navListIndex.value);
createdObjectiveRect(rect, rectWidth, rectHeight);
fabricItem.set({ fabricItem.set({
customFrom: { customFrom: {
fabricAttribute: drawerForm.objective.questionTypeValue, fabricAttribute: drawerForm.objective.questionTypeValue,
@ -2021,6 +2184,7 @@ const changeFabricInfo = (bool: boolean): void => {
...obj, ...obj,
}, },
}); });
objectiveNumber(fabricItem, rect, rectWidth, rectHeight);
} }
break; break;
@ -2124,8 +2288,72 @@ const getOffsetTop = (
return offsetTop * top; return offsetTop * top;
}; };
//
const objectiveNumber = (
fabricItem: any,
rect: any,
rectWidth: number,
rectHeight: number
): void => {
//
const obj = {
fontSize: 12,
fill: "black",
fontWeight: "normal",
fabricId: cteatedNumber(),
backgroundColor: "transparent",
};
if (drawerForm.objective.range) {
//
for (let index = 0; index < drawerForm.objective.questionNumber; index++) {
let textNumber = 0 as any;
if (drawerForm.objective.questionBefore % 1 === 0) {
textNumber = drawerForm.objective.questionBefore++;
} else {
let before = drawerForm.objective.questionBefore.toString().split(".")[0] * 1;
let after = drawerForm.objective.questionBefore.toString().split(".")[1] * 1;
textNumber = `${before}.${after + index}`;
}
fabricItem.add(
new fabric.Text(`${textNumber}`, {
left:
rect.get("left") +
rectWidth * index +
rectWidth / 2 -
(drawerForm.objective.questionNumber + 1),
top: rect.get("top") + 4,
...obj,
})
);
}
} else {
//
for (let index = 0; index < drawerForm.objective.questionNumber; index++) {
let textNumber = 0 as any;
if (drawerForm.objective.questionBefore % 1 === 0) {
textNumber = drawerForm.objective.questionBefore++;
} else {
let before = drawerForm.objective.questionBefore.toString().split(".")[0] * 1;
let after = drawerForm.objective.questionBefore.toString().split(".")[1] * 1;
textNumber = `${before}.${after + index}`;
}
fabricItem.add(
new fabric.Text(`${textNumber}`, {
left: rect.get("left") + 4,
top:
rect.get("top") +
rectHeight * index +
rectHeight / 2 -
(drawerForm.objective.questionNumber + 1),
...obj,
})
);
}
}
};
// //
const deleteSmallRect = (): void => { const deleteSmallRect = (index?: number): void => {
if (currentFabric.value) { if (currentFabric.value) {
const maxRect = currentFabric.value.target const maxRect = currentFabric.value.target
.getObjects() .getObjects()
@ -2139,6 +2367,19 @@ const deleteSmallRect = (): void => {
item.get("type") === "rect" && item.get("fabricId") !== maxRect.get("fabricId") item.get("type") === "rect" && item.get("fabricId") !== maxRect.get("fabricId")
); );
currentFabric.value.target.remove(...deleteRectArr); currentFabric.value.target.remove(...deleteRectArr);
switch (index) {
case 3:
//
const allDelText = currentFabric.value.target
.getObjects()
.filter(
(item: any) =>
item.get("type") === "text" &&
!textFabricList.value.includes(item.get("text"))
);
currentFabric.value.target.remove(...allDelText);
break;
}
} }
}; };
@ -2293,6 +2534,10 @@ const isQuestionNumerRepeat = (): boolean => {
// //
const changeExamType = (type: number): void => { const changeExamType = (type: number): void => {
if (isLockStatus.value) {
ElMessage.error("已锁定,无法修改!");
return;
}
drawerForm.examId.examType = type; drawerForm.examId.examType = type;
}; };
@ -2333,6 +2578,10 @@ const changeQuestion = (e?: any): void => {
// //
const changeObjectiveQuestionType = (item: { value: number; text: string }): void => { const changeObjectiveQuestionType = (item: { value: number; text: string }): void => {
if (isLockStatus.value) {
ElMessage.error("已锁定,无法修改!");
return;
}
if (navListIndex.value === 3) { if (navListIndex.value === 3) {
drawerForm.objective.questionTypeValue = item.value; drawerForm.objective.questionTypeValue = item.value;
drawerForm.objective.optionNumber = drawerForm.objective.optionNumber =
@ -2657,16 +2906,40 @@ const changeData = (): any => {
item.from.subjectPoint = item.from.subjectPoint =
item.tempData[1].point.length == 1 ? item.tempData[1].point[0].customFrom : {}; item.tempData[1].point.length == 1 ? item.tempData[1].point[0].customFrom : {};
item.from.examIDPoint = item.tempData[2].point.map((row: any) => { item.from.examIDPoint = item.tempData[2].point.map((row: any) => {
return row.customFrom; return {
...row.customFrom,
width: row.width,
height: row.height - 36.16,
top: row.top + 17,
left: row.left,
};
}); });
item.from.objectiveQuestionsPoint = item.tempData[3].point.map((row: any) => { item.from.objectiveQuestionsPoint = item.tempData[3].point.map((row: any) => {
return row.customFrom; return {
...row.customFrom,
width: row.width,
height: row.height - 36.16,
top: row.top + 17,
left: row.left,
};
}); });
item.from.subjectiveQuestionsPoint = item.tempData[4].point.map((row: any) => { item.from.subjectiveQuestionsPoint = item.tempData[4].point.map((row: any) => {
return row.customFrom; return {
...row.customFrom,
width: row.width,
height: row.height - 36.16,
top: row.top + 17,
left: row.left,
};
}); });
item.from.otherPoint = item.tempData[5].point.map((row: any) => { item.from.otherPoint = item.tempData[5].point.map((row: any) => {
return row.customFrom; return {
...row.customFrom,
width: row.width,
height: row.height - 36.16 / 2,
top: row.top + 17,
left: row.left,
};
}); });
divideByTwoProperties( divideByTwoProperties(
item.from.subjectiveQuestionsPoint, item.from.subjectiveQuestionsPoint,
@ -2714,7 +2987,7 @@ const btnClick = (str: string): void => {
if (str === "save") { if (str === "save") {
save(true); save(true);
} else { } else {
LockListRef.value.getData(data, templateInfo); LockListRef.value.getData(data);
} }
}; };
@ -2931,14 +3204,19 @@ const save = async (isShow: boolean = false): Promise<void> => {
width: 100%; width: 100%;
overflow: auto; overflow: auto;
@mixin isPageType($number, $type) { @mixin isPageType($type) {
width: 100%; width: 100%;
height: 100%; height: 100%;
> #zoom-div { > #zoom-div {
margin: 0 auto; margin: 0 auto;
width: calc(210mm * #{$number}); @if $type == "A3" {
height: 297mm; width: 1570px;
} @else {
width: 1200px;
}
height: auto;
flex-shrink: 0; flex-shrink: 0;
position: relative; position: relative;
transform-origin: left top; transform-origin: left top;
@ -2986,11 +3264,11 @@ const save = async (isShow: boolean = false): Promise<void> => {
} }
.A4 { .A4 {
@include isPageType(1, "A4"); @include isPageType("A4");
} }
.A3 { .A3 {
@include isPageType(2, "A3"); @include isPageType("A3");
} }
} }
} }

View File

@ -101,7 +101,8 @@ class Request {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
loading = ElLoading.service({ loading = ElLoading.service({
lock: true, lock: true,
background: 'rgba(255,255, 255, 0.3)', background: 'rgba(0,0, 0, 0.7)',
text: `加载中...`,
body: true body: true
}) })
if (config.interceptors?.requestInterceptors) { if (config.interceptors?.requestInterceptors) {