yujialong 1 year ago
parent 46a84cd266
commit be0fcb2407
  1. 4
      .env
  2. 1
      components.d.ts
  3. 3
      src/api/judgment.ts
  4. 132
      src/components/Panel/index.vue
  5. 6
      src/layout/index.vue
  6. 3
      src/store/useCurrentUser.ts
  7. 38
      src/utils/auth.ts
  8. 10
      src/utils/request.ts
  9. 44
      src/views/Home.vue
  10. 23
      src/views/product/strategy/150.vue
  11. 162
      src/views/product/strategy/151.vue
  12. 10
      src/views/product/strategy/CardList.vue
  13. 515
      src/views/report/Index.vue

@ -2,7 +2,7 @@ VITE_APP_TITLE=金融产品设计及数字化营销沙盘
VITE_PORT=9520
VITE_PROXY=http://192.168.31.125:8080
VITE_PUBLIC_PATH=./
VITE_BASE_API=http://192.168.31.51:9000
# VITE_BASE_API=http://121.37.12.51
# VITE_BASE_API=http://192.168.31.217:9000
VITE_BASE_API=http://121.37.12.51
VITE_I18N_LOCALE=zh-cn
VITE_I18N_FALLBACK_LOCALE=zh-cn

1
components.d.ts vendored

@ -9,6 +9,7 @@ declare module 'vue' {
AppHeader: typeof import('./src/layout/components/AppHeader.vue')['default'];
AppMain: typeof import('./src/layout/components/AppMain.vue')['default'];
AppSidebar: typeof import('./src/layout/components/AppSidebar/index.vue')['default'];
Panel: typeof import('./src/components/Panel/index.vue')['default'];
BaseUpload: typeof import('./src/components/Upload/BaseUpload.vue')['default'];
Breadcrumb: typeof import('./src/components/Breadcrumb/index.vue')['default'];
ColumnList: typeof import('./src/components/TableList/ColumnList.vue')['default'];

@ -5,6 +5,7 @@ export const getProcess = async (): Promise<any> => (await axios.post('/judgment
export const getProcessInformationBasedOnRoles = async (id: number): Promise<any> =>
(await axios.post(`/judgment/judgment/stRecord/getProcessInformationBasedOnRoles?systemId=19&parentId=${id}`)).data;
export const addOperation = async (data: Record<string, any>): Promise<any> => (await axios.post('/product/product/bank/operation/addOperation', data)).data;
export const checkPointList = async (projectId: number): Promise<any> => (await axios.post(`/judgment/judgment/stRecord/checkPointList?projectId=${projectId}`)).data;
export const checkPointList = async (projectId: number, displayCollection?: number | string = ''): Promise<any> =>
(await axios.post(`/judgment/judgment/stRecord/checkPointList?projectId=${projectId}&displayCollection=${displayCollection}`)).data;
export const deleteCache = async (projectId: number, checkpoint: number): Promise<any> =>
(await axios.get(`/product/product/bank/operation/deleteCache?projectId=${projectId}&checkpoint=${checkpoint}`)).data;

@ -40,13 +40,14 @@
</div>
</div>
<div>
<el-button @click="toReport"
<el-button class="h-[40px]"
@click="toReport"
v-if="isSubmit">查看实验报告</el-button>
<el-button class="reload"
<el-button class="reload h-[40px]"
@click="reload"
v-show="per == 0">重新开始</el-button>
<el-button type="primary"
class="submit btn"
class="submit btn h-[40px]"
@click="submit"
:disabled="isSubmit || !projectList.length">提交</el-button>
</div>
@ -101,10 +102,9 @@
width="60"
align="center">
<template v-slot="scope">
<template v-if="isSubmit">
<div v-if="!param.competitionId"
class="flex items-center">
class="flex justify-center items-center">
<el-icon v-if="scope.row.finishedResult"
color="#15d500"
:size="16">
@ -206,9 +206,11 @@
:class="{ active: visible }"
@click="visible = !visible"></div>
</div>
<div v-if="isSubmit"
class="z-[199] fixed top-[64px] right-0 bottom-0 left-0 bg-[rgba(0,0,0,.3)]"></div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, toRefs } from 'vue';
import { ref, reactive, onMounted, toRefs, computed, watch } from 'vue';
import { submitOpe } from '@/api/bank';
import { deleteCache } from '@/api/judgment';
import { pageStuAssessment, getProjectBySystemId, getProjectDetail, getDetailById, getCompetition } from '@/api/system';
@ -226,7 +228,7 @@ const route = useRoute();
const param = reactive<Record<string, any>>(route.query);
const curSystemId = ref<number>(1);
const per = ref<number>(0); // (0 1 2)
const isSubmit = ref<boolean>(Cookies.get('st-isSubmit') === 'true'); //
const isSubmit = ref<boolean>(false); //
const entryTime = ref<any>(new Date());
const visible = ref<boolean>(true);
const grade = ref<string | number>('00');
@ -244,7 +246,6 @@ const judgmentId = ref<string | number>('');
const curReq = ref<Record<string, any>[]>([]);
const taskList = ref<Record<string, any>[]>([]);
const pannelTab = ref<string>('first');
const isSelected = ref<boolean>(false); // true
const statusTimer = ref<any>(null);
const reportId = ref<string | number>('');
const countVal = ref<any>('');
@ -252,21 +253,23 @@ const countVal = ref<any>('');
if (param.token) {
// urlcookiecookie
param.token && Cookies.set('sand-token', param.token);
param.projectId && Cookies.set('sand-projectId', param.projectId);
param.systemId && Cookies.set('sand-systemId', param.systemId);
param.classId && Cookies.set('sand-classId', param.classId);
param.cid && Cookies.set('sand-cid', param.cid);
param.assessmentId && Cookies.set('sand-assessmentId', param.assessmentId);
param.competitionId && Cookies.set('sand-competitionId', param.competitionId);
param.stageId && Cookies.set('sand-stageId', param.stageId);
param.teamId && Cookies.set('sand-teamId', param.teamId);
param.mallId && Cookies.set('sand-mallId', param.mallId);
param.endTime && Cookies.set('sand-referrer', param.endTime);
param.referrer && Cookies.set('sand-referrer', param.referrer);
param.className && Cookies.set('sand-referrer', param.className);
param.startTime && Cookies.set('sand-referrer', param.startTime);
param.resultsDetails && Cookies.set('sand-referrer', param.resultsDetails);
param.resultAnnouncementTime && Cookies.set('sand-referrer', param.resultAnnouncementTime);
Cookies.set('sand-projectId', param.projectId ?? '');
Cookies.set('sand-systemId', param.systemId ?? '');
Cookies.set('sand-classId', param.classId ?? '');
Cookies.set('sand-cid', param.cid ?? '');
Cookies.set('sand-assessmentId', param.assessmentId ?? '');
Cookies.set('sand-competitionId', param.competitionId ?? '');
Cookies.set('sand-stageId', param.stageId ?? '');
Cookies.set('sand-teamId', param.teamId ?? '');
Cookies.set('sand-mallId', param.mallId ?? '');
Cookies.set('sand-endTime', param.endTime ?? '');
Cookies.set('sand-referrer', param.referrer ?? '');
Cookies.set('sand-className', param.className ?? '');
Cookies.set('sand-startTime', param.startTime ?? '');
Cookies.set('sand-resultsDetails', param.resultsDetails ?? '');
Cookies.set('sand-resultAnnouncementTime', param.resultAnnouncementTime ?? '');
Cookies.remove('sand-submit');
router.replace('/');
} else {
param.systemId = Cookies.get('sand-systemId');
param.projectId = Cookies.get('sand-projectId');
@ -282,22 +285,19 @@ if (param.token) {
param.startTime = Cookies.get('sand-startTime');
param.resultsDetails = Cookies.get('sand-resultsDetails');
param.resultAnnouncementTime = Cookies.get('sand-resultAnnouncementTime');
isSubmit.value = Cookies.get('sand-submit') === 'true';
}
if (param.projectId) param.projectId = +param.projectId;
onMounted(() => {
per.value = param.assessmentId ? 1 : param.competitionId ? 2 : 0;
if (param.assessmentId) {
getAssList();
} else {
getList();
if (param.competitionId) {
clearInterval(statusTimer);
statusTimer.value = setInterval((_) => {
getCompetitionStatus();
}, 1000);
}
}
});
watch(
route,
() => {
visible.value = route.path === '/';
},
{
immediate: true,
},
);
//
const timeFormat = (num: number): string | number => {
@ -330,6 +330,11 @@ const startCount = () => {
counter(per.value ? countVal.value-- : countVal.value++);
}, 1000);
};
//
const setSubmit = (val: boolean) => {
isSubmit.value = val;
Cookies.set('sand-submit', val);
};
//
const getAssList = async () => {
const { list } = await pageStuAssessment({
@ -393,9 +398,8 @@ const getCompetitionStatus = async () => {
};
//
const selectProject = () => {
isSelected.value = true;
getProDetail();
// setSubmit(false);
setSubmit(false);
countVal.value = 0;
grade.value = '00';
pannelTab.value = 'first';
@ -405,7 +409,7 @@ const reload = async () => {
await deleteCache(param.projectId, Cookies.get('sand-level') ?? '');
reloadCount();
grade.value = '00';
// this.setSubmit(false);
setSubmit(false);
startCount();
};
//
@ -440,7 +444,7 @@ const submit = async () => {
teamId: param.teamId,
mallId: param.mallId,
});
isSubmit.value = true;
setSubmit(true);
clearInterval(statusTimer.value);
let score = 0;
@ -457,24 +461,22 @@ const submit = async () => {
});
grade.value = score < 10 ? '0' + score : score;
reportId.value = retMap.reportId;
Cookies.set('sand-reoprtId', retMap.reportId);
// this.$store.commit('setReportId', reportId);
// this.$store.commit('setTaskList', taskList);
//
// param.competitionId &&
// param.resultsDetails == 0 &&
// ElMessageBox.alert(`${param.resultAnnouncementTime != 0 ? `${param.resultAnnouncementTime}`, '', {
// // if you want to disable its autofocus
// // autofocus: false,
// confirmButtonText: '',
// callback: (action: Action) => {
// ElMessage({
// type: 'info',
// message: `action: ${action}`,
// })
// },
// })
param.competitionId &&
param.resultsDetails == 0 &&
ElMessageBox.alert(`提交成功${param.resultAnnouncementTime != 0 ? ',成绩将在' + param.resultAnnouncementTime + '小时后发布,请去参赛信息模块查看' : ''}`, '提示', {
confirmButtonText: '确定',
callback: (action: Action) => {
ElMessage({
type: 'info',
message: `action: ${action}`,
});
},
});
})
.catch(() => {});
};
@ -487,6 +489,7 @@ const getProDetail = async () => {
});
const pointsList = res.projectJudgmentVos;
const project = res.projectManage;
Cookies.set('sand-projectId', param.projectId);
// /
if (per.value) {
projectList.value = [
@ -514,17 +517,30 @@ const getProDetail = async () => {
//
const getList = async () => {
const data = {
const { projects } = await getProjectBySystemId({
systemId: param.systemId,
cId: param.cid ?? '',
mallId: param.mallId,
permissions: per.value,
};
const { projects } = await getProjectBySystemId(data);
});
projectList.value = projects;
if (!per.value && !param.projectId) param.projectId = projects[0]?.projectId ?? 0; //
getProDetail();
};
onMounted(() => {
per.value = param.assessmentId ? 1 : param.competitionId ? 2 : 0;
if (param.assessmentId) {
getAssList();
} else {
param.cid && getList();
if (param.competitionId) {
clearInterval(statusTimer);
statusTimer.value = setInterval((_) => {
getCompetitionStatus();
}, 1000);
}
}
});
</script>
<style lang="scss" scoped>

@ -7,7 +7,7 @@
:class="{ 'md:ml-sidebar': !hideNav }">
<app-main />
</div>
<!-- <Panel /> -->
<Panel />
</div>
</template>
@ -17,11 +17,11 @@ import { useRoute } from 'vue-router';
import Setting from '@/settings';
import { AppSidebar, AppHeader, AppMain } from './components';
import useResizeHandler from './composables/useResizeHandler';
// import Panel from '@/components/Panel/index.vue';
import Panel from '@/components/Panel/index.vue';
export default defineComponent({
name: 'Layout',
components: { AppSidebar, AppHeader, AppMain },
components: { AppSidebar, AppHeader, AppMain, Panel },
setup() {
const route = useRoute();
//

@ -1,6 +1,6 @@
import { reactive, readonly } from 'vue';
import { RouteRecordRaw } from 'vue-router';
import { removeAccessToken } from '@/utils/auth';
import { removeAccessToken, removeParam } from '@/utils/auth';
import Cookies from 'js-cookie';
export interface CurrentUser {
@ -15,6 +15,7 @@ const state = reactive<CurrentUser>({});
export const logout = (): void => {
removeAccessToken();
removeParam();
window.location.href = decodeURIComponent(Cookies.get('sand-referrer'));
};

@ -1,33 +1,29 @@
import Cookies from 'js-cookie';
const SAND_ACCESS_TOKEN = 'sand-token';
const SAND_ACCESS_AT = 'jwt-access-at';
const SAND_SESSION_TIMEOUT = 'jwt-session-timeout';
export const getAccessToken = (): string | undefined => Cookies.get(SAND_ACCESS_TOKEN);
export const setAccessToken = (token: string): void => {
Cookies.set(SAND_ACCESS_TOKEN, token);
};
export const removeAccessToken = (): void => Cookies.remove(SAND_ACCESS_TOKEN);
export const getAccessAt = (): number => {
const accessAt = Cookies.get(SAND_ACCESS_AT);
return accessAt ? Number(accessAt) : 0;
};
export const setAccessAt = (accessAt: number): void => {
Cookies.set(SAND_ACCESS_AT, String(accessAt));
};
export const getSessionTimeout = (): number => {
const sessionTimeout = Cookies.get(SAND_SESSION_TIMEOUT);
// 默认 30 分钟
return sessionTimeout ? Number(sessionTimeout) : 30;
};
export const setSessionTimeout = (sessionTimeout: number): void => {
Cookies.set(SAND_SESSION_TIMEOUT, String(sessionTimeout));
};
export const removeSessionTimeout = (): void => {
Cookies.remove(SAND_SESSION_TIMEOUT);
export const removeParam = (): void => {
Cookies.remove('sand-classId');
Cookies.remove('sand-cid');
Cookies.remove('sand-assessmentId');
Cookies.remove('sand-competitionId');
Cookies.remove('sand-stageId');
Cookies.remove('sand-teamId');
Cookies.remove('sand-mallId');
Cookies.remove('sand-endTime');
Cookies.remove('sand-className');
Cookies.remove('sand-startTime');
Cookies.remove('sand-resultsDetails');
Cookies.remove('sand-resultAnnouncementTime');
Cookies.remove('sand-projectId');
Cookies.remove('sand-systemId');
Cookies.remove('sand-level');
Cookies.remove('sand-submit');
};
export const getAuthHeaders = (): any => {

@ -1,9 +1,9 @@
import { h } from 'vue';
import axios from 'axios';
import dayjs from 'dayjs';
import { ElMessageBox, ElMessage } from 'element-plus';
import { getAuthHeaders, setAccessAt } from '@/utils/auth';
import { getAuthHeaders } from '@/utils/auth';
import i18n from '@/i18n';
import { logout } from '@/store/useCurrentUser';
const service = axios.create({
baseURL: import.meta.env.VITE_BASE_API,
@ -12,8 +12,6 @@ const service = axios.create({
service.interceptors.request.use(
(config) => {
setAccessAt(new Date().getTime());
// eslint-disable-next-line
config.headers = { ...config.headers, ...getAuthHeaders() };
return config;
},
@ -34,8 +32,8 @@ service.interceptors.response.use(
} = i18n;
if (status === 401) {
ElMessageBox.confirm(t('confirmLogin'), { confirmButtonText: t('loginAgain'), type: 'warning' }).then(() => {
// 未登录。刷新页面以触发登录。无法直接使用router,会导致其它函数不可用的奇怪问题。
window.location.reload();
// 未登录
logout();
});
} else if (status === 403) {
ElMessageBox({

@ -14,10 +14,9 @@
</div>
<div class="relative min-h-[calc(100vh-64px)] pt-5 pl-5 bg-[url('@/assets/images/level/4.png')] bg-[length:100%_100%] bg-no-repeat">
<div class="relative">
<img src="@/assets/images/level/5.png"
alt="" />
<div class="w-[354px] h-[68px] bg-[url('@/assets/images/level/5.png')] bg-[length:100%_100%] bg-no-repeat"></div>
<div class="absolute top-5 left-40 flex items-center cursor-pointer"
@click="collected = !collected">
@click="getLevel(1)">
<img v-if="collected"
src="@/assets/images/level/7.png"
alt="" />
@ -34,7 +33,7 @@
@click="selecLevel(item)">
<span class="num">LV.{{ i + 1 }}</span>
<div class="texts">
<h6>{{ numToChinese(i + 1) }}</h6>
<h6>{{ numToChinese(item.name.split(' ')[0].replace('关卡', '')) }}</h6>
<p class="des mul-ellipsis2">{{ item.name.split(' ')[1] }}</p>
<img v-if="item.collect"
class="icon"
@ -50,18 +49,10 @@
</div>
</div>
<img class="arrow top-0 left-[50%] translate-x-[-50%] animate-pulse"
src="@/assets/images/level/arrow-up.png"
alt="" />
<img class="arrow right-0 top-[50%] translate-y-[-50%] animate-pulse"
src="@/assets/images/level/arrow-right.png"
alt="" />
<img class="arrow bottom-0 left-[50%] translate-x-[-50%] animate-pulse"
src="@/assets/images/level/arrow-down.png"
alt="" />
<img class="arrow left-0 top-[50%] translate-y-[-50%] animate-pulse"
src="@/assets/images/level/arrow-left.png"
alt="" />
<div class="arrow top-0 left-[50%] translate-x-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-up.png')]"></div>
<div class="arrow right-0 top-[50%] translate-y-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-right.png')]"></div>
<div class="arrow bottom-0 left-[50%] translate-x-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-down.png')]"></div>
<div class="arrow left-0 top-[50%] translate-y-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-left.png')]"></div>
<div class="absolute bottom-2 right-1 w-[262px] h-[74px] bg-[url('@/assets/images/level/submit.png')] bg-[length:100%_100%] bg-no-repeat cursor-pointer hover:bg-[url('@/assets/images/level/submit-hover.png')]"
@click="toRole"></div>
</div>
@ -84,10 +75,11 @@ const route = useRoute();
const collected = ref<boolean>(false);
const curLevel = ref<number | string>('');
const levels = ref<Record<string, any>[]>([]);
const projectId = +Cookies.get('sand-projectId');
const projectId = Cookies.get('sand-projectId') ?? route.query.projectId;
//
const getLevel = async () => {
const { data } = await checkPointList(projectId);
const getLevel = async (only: any = '') => {
if (only) collected.value = !collected.value;
const { data } = await checkPointList(+projectId, collected.value ? 1 : '');
levels.value = data;
};
//
@ -265,6 +257,18 @@ onMounted(() => {
}
}
.arrow {
@apply absolute cursor-pointer;
@apply absolute bg-[length:100%_100%] bg-no-repeat animate-pulse cursor-pointer;
}
@keyframes bounce {
0%,
100% {
transform: translateY(-25%);
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
}
50% {
transform: translateY(0);
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
}
</style>

@ -179,9 +179,9 @@ const getConfig = async () => {
temp = JSON.parse(JSON.stringify(temp));
temp.span = 1;
num = cur?.ruleTwo.match(/\d+/g);
num = cur?.ruleTwo?.match(/\d+/g);
if (num?.length) temp.num = num[0];
symbol = cur?.ruleTwo.match(/[<>=]+/g);
symbol = cur?.ruleTwo?.match(/[<>=]+/g);
if (symbol?.length) temp.symbol = symbol[0];
if (e.id === 167) temp.had = cur?.ruleTwo;
result.push(temp);
@ -281,19 +281,24 @@ const addRecord = async (data: Record<string, any>) => {
const rule = <Record<string, any>[]>[];
data.map((e, i) => {
if (isRule(e.stRecordId)) {
e?.recordChildren.map((n, j) => {
rule.push(handleId(n.id, e.subjectId, j ? e.ruleTwo : e.ruleOne, preIds + ',' + e.stRecordId + ',' + n.id, 5));
});
}
const temp = [];
e.personalHitBlacklist && temp.push(300);
e.mateHitRejected && temp.push(301);
e.parentsHitRejected && temp.push(302);
e.otherFamilyMembersHitRejected && temp.push(303);
e.corporateMajorityHitRejected && temp.push(304);
rule.push(handleId(e.stRecordId, e.subjectId, temp.join(), preIds + ',' + e.stRecordId, 1));
if (isRule(e.stRecordId)) {
const len = e?.recordChildren?.length - 1;
e?.recordChildren.map((n, j) => {
if (j !== len) {
rule.push(handleId(n.id, e.subjectId, j ? e.ruleTwo : e.ruleOne, preIds + ',' + e.stRecordId + ',' + n.id, 5));
} else if (temp.length) {
rule.push(handleId(n.id, e.subjectId, temp.join(), preIds + ',' + e.stRecordId + ',' + n.id, 1));
}
});
} else {
rule.push(handleId(e.stRecordId, e.subjectId, temp.join(), preIds + ',' + e.stRecordId, 1));
}
});
await addOperation({

@ -12,10 +12,18 @@
min-width="250"
align="center">
<template #default="{ row }">
<!-- 大病报销 || 贫困户 -->
<div v-if="row.stRecordId == 161 || row.stRecordId == 164"
<!-- 贷记卡账户状态 -->
<div v-if="row.stRecordId == 204"
class="flex items-center">
<span class="whitespace-nowrap">{{ row?.recordChildren[row.span ? 1 : 0]?.name }}</span>
<span class="whitespace-nowrap">{{ row?.recordChildren[0]?.name }}</span>
<el-input class="w-[80px] mx-2"
v-model="row.ruleOne"></el-input>
<span class="whitespace-nowrap">的信用卡</span>
</div>
<!-- 贷记卡审批通过率 -->
<div v-else-if="isRule(row.stRecordId)"
class="flex items-center">
<span class="whitespace-nowrap">{{ row?.recordChildren[0]?.name }}</span>
<div class="w-[90px] ">
<el-select class="mx-2"
v-model="row.symbol">
@ -27,52 +35,51 @@
</div>
<el-input class="w-[80px]"
v-model="row.num"></el-input>
<span class="ml-2 whitespace-nowrap">万元</span>
<span class="ml-2 whitespace-nowrap">{{ row?.recordChildren[1]?.name }}</span>
<div class="w-[90px] ">
<el-select class="mx-2"
v-model="row.symbol1">
<el-option v-for="item in symbols"
:key="item"
:label="item.name"
:value="item.name" />
</el-select>
</div>
<el-input class="w-[80px]"
v-model="row.num1"></el-input>
<span class="ml-2 whitespace-nowrap"></span>
</div>
<!-- 大龄未婚 -->
<div v-else-if="row.stRecordId == 167"
<div v-else-if="row.stRecordId == 230 || row.stRecordId == 231"
class="flex">
<el-select class="w-[80px] ml-2"
v-model="row.ruleOne">
<el-option value="有" />
<el-option value="无" />
</el-select>
</div>
<div v-else
class="flex items-center">
<template v-if="row.span">
<span class="whitespace-nowrap">且近一年</span>
<div class="w-[90px] ">
<el-select class="mx-2"
v-model="row.had">
<el-option value="有" />
<el-option value="无" />
</el-select>
</div>
<span class="ml-2 whitespace-nowrap">缴纳过社保或公积金</span>
</template>
<template v-else>
<span class="whitespace-nowrap">未婚且年龄</span>
<div class="w-[90px] ">
<el-select class="mx-2"
v-model="row.symbol">
<el-option v-for="item in symbols"
:key="item"
:label="item.name"
:value="item.name" />
</el-select>
</div>
<el-input class="w-[80px]"
v-model="row.num"></el-input>
<span class="ml-2 whitespace-nowrap">,</span>
<el-select class="w-[80px] ml-2"
v-model="row.had">
<el-option value="有" />
<el-option value="无" />
<span class="whitespace-nowrap">{{ row?.recordChildren[0]?.name }}</span>
<div class="w-[90px] ">
<el-select class="mx-2"
v-model="row.symbol">
<el-option v-for="item in symbols"
:key="item"
:label="item.name"
:value="item.name" />
</el-select>
<span class="ml-2 whitespace-nowrap">固定资产</span>
</template>
</div>
<el-input class="w-[80px]"
v-model="row.num"></el-input>
<span class="ml-2 whitespace-nowrap">{{ row.stRecordId === 203 || row.stRecordId === 205 ? '元' : row.stRecordId === 207 || row.stRecordId === 229 ? '万元' : ' ' }}</span>
</div>
<span v-else>{{ '命中' + row.name }}</span>
</template>
</el-table-column>
<el-table-column label="配偶拒入标准同本人"
width="160"
align="center">
<template #default="{ row }">
<el-checkbox v-model="row.personalHitBlacklist"></el-checkbox>
<el-checkbox v-model="row.mateRejectedStandardIdentity"></el-checkbox>
</template>
</el-table-column>
</el-table>
@ -86,7 +93,7 @@
<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { accessStrategyGovernmentBlacklistFind, accessStrategyCreditBlacklistSave } from '@/api/model';
import { accessStrategyCreditBlacklistFind, accessStrategyCreditBlacklistSave } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import type { TableColumnCtx } from 'element-plus';
import { useRouter, useRoute } from 'vue-router';
@ -123,43 +130,33 @@ const getConfig = async () => {
const result = [];
process.map((e) => {
const cur = info.value.find((n) => n.stRecordId === e.id);
let num = cur?.ruleOne.match(/\d+/g);
let symbol = cur?.ruleOne.match(/[<>=]+/g);
let had = cur?.ruleOne.match(/[有无]+/g);
let num = cur?.ruleOne?.match(/\d+/g);
let num1 = cur?.ruleTwo?.match(/\d+/g);
let symbol = cur?.ruleOne?.match(/[<>=]+/g);
let symbol1 = cur?.ruleTwo?.match(/[<>=]+/g);
let temp = {
checkpointId: levelId,
projectId,
name: e.name,
recordChildren: e.recordChildren,
isRule: isRule(e.id) ? 1 : 0,
mateRejectedStandardIdentity: !!cur?.mateRejectedStandardIdentity,
symbol: isRule(e.id) ? symbol[0] : '>=',
had: e.id === 167 && had.length ? had[0] : '',
num: isRule(e.id) && num?.length ? num[0] : '',
ruleOne: '',
symbol: symbol?.length ? symbol[0] : '>=',
symbol1: symbol1?.length ? symbol1[0] : '>=',
num: num?.length ? num[0] : '',
num1: num1?.length ? num1[0] : '',
ruleOne: e.id === 204 || e.id === 230 || e.id === 231 ? cur?.ruleOne : '',
ruleTwo: '',
subjectId: e.subjectId,
stRecordId: e.id,
};
result.push(temp);
if (isRule(e.id)) {
temp = JSON.parse(JSON.stringify(temp));
temp.span = 1;
num = cur?.ruleTwo.match(/\d+/g);
if (num?.length) temp.num = num[0];
symbol = cur?.ruleTwo.match(/[<>=]+/g);
if (symbol?.length) temp.symbol = symbol[0];
if (e.id === 167) temp.had = cur?.ruleTwo;
result.push(temp);
}
});
form.value = result;
};
//
const getDetail = async () => {
try {
const { data } = await accessStrategyGovernmentBlacklistFind(levelId, projectId);
const { data } = await accessStrategyCreditBlacklistFind(levelId, projectId);
info.value = data;
getConfig();
} finally {
@ -176,46 +173,25 @@ watch(
},
);
// 3
const isRule = (rule: number): boolean => {
return rule === 161 || rule === 164 || rule === 167;
return rule === 208 || (rule > 215 && rule < 222) || rule === 226;
};
interface SpanMethodProps {
row: Record<string, any>;
column: TableColumnCtx<Record<string, any>>;
rowIndex: number;
columnIndex: number;
}
//
const submit = async () => {
let param = JSON.parse(JSON.stringify(form.value));
param.map((e, i) => {
if (info.value.length) e.id = info.value.find((n) => n.stRecordId === e.stRecordId)?.id;
e.mateRejectedStandardIdentity = +e.mateRejectedStandardIdentity;
if (e.stRecordId == 161 || e.stRecordId == 164) {
if (e.span) {
//
param[i - 1].ruleTwo = e.symbol + e.num;
} else {
e.ruleOne = e.symbol + e.num;
}
} else if (e.stRecordId == 167) {
if (e.span) {
//
param[i - 1].ruleTwo = e.had;
} else {
e.ruleOne = e.symbol + e.num + ',' + e.had;
if (e.stRecordId != 204 && e.stRecordId != 230 && e.stRecordId != 231) {
e.ruleOne = e.symbol + e.num;
if (isRule(e.stRecordId)) {
e.ruleTwo = e.symbol1 + e.num1;
}
}
});
param = param.filter((e) => !e.span);
const recordParam = JSON.parse(JSON.stringify(param));
param.map((e) => {
delete e.recordChildren;
delete e.had;
delete e.name;
delete e.symbol;
delete e.num;
});
await accessStrategyCreditBlacklistSave({ creditBlacklistList: param });
addRecord(recordParam);
@ -227,16 +203,18 @@ const addRecord = async (data: Record<string, any>) => {
const preIds = `1,${Cookies.get('sand-level')},42,67,147,151`; // 1id
const rule = <Record<string, any>[]>[];
data[1].ruleOne && rule.push(handleId(234, 81, data[1].ruleOne, preIds + ',204,234', 3));
data[27].ruleOne && rule.push(handleId(267, 114, data[27].ruleOne === '有' ? 306 : 305, preIds + ',230,267', 1));
data[28].ruleOne && rule.push(handleId(268, 115, data[28].ruleOne === '有' ? 308 : 307, preIds + ',231,267', 1));
data.map((e, i) => {
if (isRule(e.stRecordId)) {
if (e.stRecordId != 204 && e.stRecordId != 230 && e.stRecordId != 231) {
const len = e?.recordChildren?.length - 1;
e?.recordChildren.map((n, j) => {
rule.push(handleId(n.id, e.subjectId, j ? e.ruleTwo : e.ruleOne, preIds + ',' + e.stRecordId + ',' + n.id, 5));
j !== len && rule.push(handleId(n.id, e.subjectId, j ? e.ruleTwo : e.ruleOne, preIds + ',' + e.stRecordId + ',' + n.id, 5));
});
}
const temp = [];
e.personalHitBlacklist && temp.push(300);
rule.push(handleId(e.stRecordId, e.subjectId, temp.join(), preIds + ',' + e.stRecordId, 1));
//
e.mateRejectedStandardIdentity && rule.push(handleId(274, e.subjectId, 309, preIds + ',' + e.stRecordId + ',274', 1));
});
await addOperation({

@ -13,7 +13,7 @@
:class="{ active: item.id === id }"
@click="switchProduct(item.id)">
<h6>{{ item.name }}</h6>
<!-- <p class="type">{{ item.productNumber + ' ' + item.guarantyStyle }}</p> -->
<p class="type">{{ item.remark }}</p>
</li>
</ul>
</div>
@ -96,12 +96,8 @@ const tabChange = (tab: TabsPaneContext, event: Event) => {
h6 {
@apply text-[#14436b];
}
.type,
.status {
@apply my-[15px] text-sm text-[#333];
}
.date {
@apply text-sm text-[#8798a9];
.type {
@apply mt-3 text-sm text-[#8798a9];
}
}
</style>

@ -0,0 +1,515 @@
<template>
<div class="wrap">
<div class="content"
:class="{loading}"
id="pdfDom">
<div class="text-right"
v-if="!loading">
<el-button @click="editReport">
{{ editing ? "保存" : "编辑" }}
</el-button>
<el-button type="primary"
@click="exportPage">导出报告</el-button>
</div>
<h6 class="r-title">标准实验报告</h6>
<div class="info">
<h6 class="l-title">
<img src="@/assets/img/report1.png"
alt="">
基本信息
</h6>
<ul :class="['info-list', {edit: editing}]">
<li>
<label>学生姓名</label>
<el-input v-if="editing"
v-model="infoData.userName"
disabled></el-input>
<span v-else>{{ infoData.userName }}</span>
</li>
<li>
<label>学生学号</label>
<el-input v-if="editing"
v-model="infoData.workNumber"
disabled></el-input>
<span v-else>{{ infoData.workNumber }}</span>
</li>
<li>
<label>实验时间</label>
<el-input v-if="editing"
v-model="infoData.submitTime"
disabled></el-input>
<span v-else>{{ infoData.submitTime }}</span>
</li>
<li>
<label>实验成绩</label>
<el-input v-if="editing"
v-model="infoData.score"
disabled></el-input>
<div v-else
class="score-wrap">
<em>{{ infoData.score }}</em>
<img src="@/assets/img/point.png"
alt="">
</div>
</li>
<li>
<label>学生班级</label>
<el-input v-if="editing"
v-model="infoData.className"></el-input>
<span v-else>{{ infoData.className }}</span>
</li>
<li>
<label>指导老师</label>
<el-input v-if="editing"
v-model="infoData.instructor"></el-input>
<span v-else>{{ infoData.instructor }}</span>
</li>
<li>
<label>实验学时</label>
<el-input v-if="editing"
v-model="infoData.period"></el-input>
<span v-else>{{ infoData.period }}</span>
</li>
</ul>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report2.png"
alt="">
实验项目名称
</h6>
<el-input v-if="editing"
v-model="infoData.projectName"
type="textarea"></el-input>
<div v-else
class="pre-wrap"
v-html="infoData.projectName"></div>
</div>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report3.png"
alt="">
实验目的
</h6>
<quill v-if="editing"
:border="true"
v-model="infoData.purpose"
:height="150" />
<div v-else
:class="['pre-wrap', {edit: editing}]"
v-html="infoData.purpose"></div>
</div>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report4.png"
alt="">
实验数据
</h6>
<el-table :data="expData"
class="table"
border
stripe
header-align="center">
<el-table-column type="index"
label="序号"
align="center"
width="60">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="judgmentName"
label="判分点"
width="200"
align="center"></el-table-column>
<el-table-column v-if="project"
prop="judgmentName"
label="考核点"
align="center"
width="150">
<template slot-scope="scope">
<div v-for="(item, index) in scope.row.lcRuleRecords"
:key="index">
<span>
<span>{{index+1}}. </span>{{item.name}}
</span>
</div>
</template>
</el-table-column>
<el-table-column prop="ruleAnswer"
label="参考答案"
style='word-wrap: break-word'>
<template slot-scope="scope">
<div v-if='scope.row.lcRuleRecords'>
<div v-for="(item, index) in scope.row.lcRuleRecords"
:key="index">
<span>
<span>{{index+1}}. </span>{{item.ruleAnswer}}
</span>
</div>
</div>
<div v-else
v-html="scope.row.referenceAnswer"></div>
</template>
</el-table-column>
<el-table-column prop="userAnswer"
label="学生答案">
<template slot-scope="scope">
<div v-if='scope.row.lcRuleRecords'>
<div v-for="(item, index) in scope.row.lcRuleRecords"
:key="index">
<span v-if='item.userAnswer'>
<span>{{index+1}}. </span>{{item.userAnswer}}
</span>
<span v-else>
<span>{{index+1}}. </span>未填写
</span>
</div>
</div>
<div v-else
v-html='scope.row.answer'
style='white-space: pre-wrap'></div>
</template>
</el-table-column>
<el-table-column v-if="!project"
prop="runResult"
label="学生运行结果"
align="center">
<template slot-scope="scope">
<div class="m-b-20"
v-html='scope.row.runResult'
style='white-space: pre-wrap'></div>
<template v-if="scope.row.runThePictureList">
<img v-for="(img, i) in scope.row.runThePictureList"
:key="i"
width="200"
class="result-pic"
:src="img"
alt="">
</template>
</template>
</el-table-column>
<el-table-column prop="quesScore"
label="分值"
width="80"
align="center"></el-table-column>
<el-table-column prop="score"
label="得分"
width="80"
align="center"></el-table-column>
</el-table>
</div>
<div class="m-b-20">
<h6 class="l-title">
<img src="@/assets/img/report5.png"
alt="">
实验总结与体会
</h6>
<quill v-if="editing"
:border="true"
v-model="infoData.summarize"
:height="150"
:index="1" />
<div v-else
class="pre-wrap"
v-html="infoData.summarize"></div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Loading } from "element-ui";
import html2Canvas from "html2canvas";
import JsPDF from "jspdf";
import util from "@/libs/util";
import breadcrumb from '@/components/breadcrumb'
import quill from "@/components/quill";
export default {
data () {
return {
fromPython: this.$route.query.python, // python
reportId: this.$route.query.reportId,
curriculumId: this.$route.query.curriculumId,
projectId: this.$route.query.projectId,
matchId: this.$route.query.matchId, //
matchName: this.$route.query.matchName, //
breadPath: ['实验记录', '实验情况', '实验报告'],
title: "实验报告",
form: {},
infoData: {},
expData: [],
editing: false,
loadIns: null,
loading: false,
project: false,
userScores: [],
quills: [],
quillIndex1: 0,
quillIndex2: 1,
};
},
components: {
breadcrumb,
quill,
},
mounted () {
this.getData()
},
methods: {
getData () { //
const { reportId } = this
this.$get(`${this.api.reportDetail}?reportId=${reportId}`).then(({ report, userScores }) => {
this.form = report
const form = this.form
this.infoData = {
reportId,
className: form.className,
workNumber: form.workNumber,
experimentalClassName: form.experimentalClassName,
instructor: form.instructor,
period: form.period,
laboratory: form.laboratory,
submitTime: form.submitTime,
score: form.score,
userName: form.userName,
projectName: form.projectName,
purpose: form.purpose,
summarize: form.summarize
}
//
form.assessmentId ?
(this.breadPath = ['实验记录', '实验报告']) :
this.matchName && (this.breadPath = ['全部赛事', this.matchName, '实验报告'])
const { data } = report
this.userScores = userScores
// data使
if (!data) {
this.handleList(userScores)
this.$post(this.api.editExperimentalData, {
reportId,
data: JSON.stringify(userScores)
}).then(res => { }).catch(err => { })
} else {
this.handleList(userScores.find(e => e.lcRuleRecords) ? userScores : JSON.parse(data))
}
}).catch(res => { })
},
//
handleList (list) {
this.project = list.find(e => e.lcRuleRecords) // lcRuleRecords
if (this.project) {
list.map(e => {
e.assessmentPoint = ''
e.referenceAnswer = ''
e.answer = ''
e.lcRuleRecords.map((n, i) => {
e.assessmentPoint += `${i + 1}.${n.name}`
e.referenceAnswer += `${i + 1}.${n.ruleAnswer}`
e.answer += `${i + 1}.${n.userAnswer}`
})
})
} else { // pythonuserScores
list.forEach(e => {
const item = this.userScores.find(n => n.judgmentId == e.judgmentId)
if (item) {
if (item.runThePictureList) e.runThePictureList = item.runThePictureList
if (item.runResult) e.runResult = item.runResult
}
})
}
this.expData = list
},
//
back () {
history.back()
},
exportPage () {
// const form = Object.assign(this.form, this.infoData)
// const list = JSON.parse(JSON.stringify(this.expData))
// list.map((e, i) => {
// const item = this.userScores.find(n => n.judgmentId == e.judgmentId)
// if (item && item.runThePicture) e.runThePicture = item.runThePicture
// if (item && item.runThePictureList) e.runThePictureList = item.runThePictureList
// e.id = i + 1
// if (e.referenceAnswer && typeof e.referenceAnswer === 'string') e.referenceAnswer = e.referenceAnswer.replace(/<[^>]+>/g, '').replace(/(&nbsp;|&amp;|%s)/g, '').replace(/>/g, '&gt;').replace(/</g, '&lt;')
// if (e.answer && typeof e.answer === 'string') e.answer = e.answer.replace(/<[^>]+>/g, '').replace(/(&nbsp;|&amp;|%s)/g, '').replace(/>/g, '&gt;').replace(/</g, '&lt;')
// })
// for (const i in form) {
// if (form[i] && typeof form[i] === 'string') form[i] = form[i].replace(/<[^>]+>/g, '')
// }
// form.purpose = form.purpose.replace(/<[^>]+>/g, '')
// this.$post(this.project ? this.api.exportBankExperimentReport : this.api.exportLabReport, {
// ...form,
// experimentalData: list
// }).then(res => {
// console.log(res)
// util.downloadFileDirect(`.docx`, new Blob([res]))
// }).catch(res => { })
},
editReport () { //
if (this.editing) {
this.$post(`${this.api.updateReport}`, this.infoData).then(res => {
this.editing = false;
util.successMsg("修改成功");
}).catch(err => { });
} else {
this.editing = true;
}
}
}
};
</script>
<style lang="scss" scoped>
.top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
.back {
font-size: 14px;
color: #007eff;
cursor: pointer;
}
}
.breadcrumb {
/deep/.el-breadcrumb__item {
.is-link,
.el-breadcrumb__separator {
font-weight: 400;
color: $main-color;
}
&:last-child {
.is-link {
color: #0b1d30;
}
}
}
}
.wrap {
padding: 12px 300px 20px;
}
code,
kbd,
samp {
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
word-wrap: break-word;
white-space: pre-wrap;
}
/deep/ pre {
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
word-break: break-all;
overflow: hidden;
font-size: 12px;
font-weight: 400;
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
}
.content {
padding: 16px 40px;
background: #fff;
&.loading {
padding-top: 30px;
}
.r-title {
margin-bottom: 40px;
font-size: 24px;
text-align: center;
color: #333;
}
.info {
padding: 20px 16px;
border: 1px solid #e1e6f2;
}
.l-title {
padding: 5px 8px;
background-color: #f7f9fc;
}
.info-list {
display: flex;
flex-wrap: wrap;
padding: 10px 0 0 20px;
li {
display: inline-flex;
width: 25%;
padding: 0 10px;
margin-bottom: 34px;
}
&.edit {
li {
align-items: center;
}
}
label {
font-size: 14px;
color: #333;
white-space: nowrap;
}
span {
min-width: 150px;
padding: 0 10px 3px;
border-bottom: 1px solid #e1e6f2;
}
/deep/.el-input {
width: 174px;
}
}
.score-wrap {
position: relative;
min-width: 150px;
border-bottom: 1px solid #e1e6f2;
em {
position: absolute;
top: -12px;
left: 30px;
font-family: din;
font-size: 30px;
font-weight: 600;
color: #0b1d30;
}
img {
position: absolute;
bottom: -15px;
left: 0;
}
}
/deep/.el-textarea .el-textarea__inner,
.pre-wrap {
min-height: 72px;
padding: 10px 16px;
font-size: 14px;
color: #333;
&.edit {
color: #abb3c6;
border: 1px solid #cacfdb;
border-radius: 4px;
background-color: #f6f7f9;
}
}
/deep/ .table th {
background-color: #e1eaff !important;
.cell {
line-height: 35px;
color: #555555;
}
}
}
.result-pic {
margin: 10px 0;
}
@media (max-width: 1650px) {
.wrap {
padding: 12px 200px 20px;
}
}
@media (max-width: 1430px) {
.wrap {
padding: 12px 100px 20px;
}
}
</style>
Loading…
Cancel
Save