量化考核汇总

This commit is contained in:
zwq 2025-09-06 20:30:02 +08:00
parent 8a6cfd58c9
commit e97d71f230
20 changed files with 1589 additions and 0 deletions

76
src/api/base/assesment.ts Normal file
View File

@ -0,0 +1,76 @@
import {get, post} from "@/utils/request";
import {qs} from "@/utils";
export const inspectItemFindAllsApi = async () => {
return await get("/api/inspectItem/findAlls");
};
export const fractionRuleFindAllByItemIdApi = async (params: any) => {
return await get("/api/fractionRule/findAllByItemId", params);
};
export const ruleItemFindByRuleIdApi = async (params: any) => {
return await get("/api/ruleItem/findByRuleId", params);
};
export const evaluationSaveApi = async (params: any) => {
return await post("/api/evaluation/saveBatch", params);
};
export const gradeClassFindAllsApi = async () => {
return await get("/api/gradeClass/findAlls");
};
export const readyToGoSaveApi = async (params: any) => {
return await post("/api/readyToGo/save", params);
};
export const schedulingPlanDelApi = async (params: any) => {
return await post("/api/schedulingPlan/delete" + qs(params));
};
export const updateThirdIdApi = async (params: any) => {
return await post("/api/user/updateThirdId", params);
};
export const schedulingPlanSaveBatcApi = async (params: any) => {
return await post("/api/schedulingPlan/saveBatch", params);
};
export const evaluationFindPageApi = async (params: any) => {
return await get("/api/evaluation/findPagePhoneMain", params);
};
export const evaluationFindPageSummaryApi = async (params: any) => {
return await get("/api/evaluation/findPageSummary", params);
};
export const readyToGoFindPageApi = async (params: any) => {
return await get("/api/readyToGo/findPage", params);
};
export const gradeClassFindByGradeApi = async (params: any) => {
return await get("/api/gradeClass/findByGrade", params);
};
export const cmsArticleFindPageApi = async (params: any) => {
return await get("/api/cmsArticle/findPage", params);
};
//根据id查询部门
export const deptFindAllGradeClassApi = async (param: { pid: number }) => {
return await get("/api/dept/findAllGradeClass", param);
};
export const inspectItemFindAllApi = async () => {
return await get("/api/inspectItem/findAlls");
};
export const evaluationGetWeekReportApi = async () => {
return await get('/api/evaluation/getWeekReport');
};
export const schedulingPlanFindByYYYMMApi = async (param: any) => {
return await get('/api/schedulingPlan/findByYYYYMM', param);
};
export const getSchedulingPlanByUserIdApi = async () => {
return await get("/api/schedulingPlan/getSchedulingPlanByUserId");
};
export const findUserListApi = async () => {
return await get("/api/user/findUserList");
};
export const schedulingPlanApi = async (param: any) => {
return await get("/api/schedulingPlan/findPage", param);
};
export const getSchedulingPlansByUserIdApi = async (param: any) => {
return await get("/api/schedulingPlan/getSchedulingPlansByUserId", param);
};

View File

@ -13,6 +13,10 @@ export const findDicTreeByPidApi = async (param: { pid: number }) => {
export const deptFindAllDeptsByPidApi = async (param: { pid: number }) => {
return await get("/api/dept/findAllDeptsByPid", param);
};
//根据id查询部门
export const deptFindByPidApi = async (param: { pid: number }) => {
return await get("/api/dept/findByPid", param);
};
//刷新token
export const refreshTokenApi = async (param: { refresh_token: string }) => {

View File

@ -69,3 +69,6 @@ export const findJsByPhoneApi = async (param: any) => {
export const findJsAllByPhoneApi = async (param: any) => {
return await get("/api/js/findJsAllByPhone", param);
};
export const getUserViewApi = async () => {
return await get("/api/user/getUserView");
};

View File

@ -625,6 +625,62 @@
"style": {
"navigationBarTitleText": "就餐点名详情"
}
},
{
"path": "pages/view/quantitativeAssessment/assessment/assessment",
"style": {
"navigationBarTitleText": "考核评价",
"enablePullDownRefresh": false
}
},
{
"path": "pages/view/quantitativeAssessment/casualShot/casualShot",
"style": {
"navigationBarTitleText": "随手拍",
"enablePullDownRefresh": false
}
},
{
"path": "pages/view/quantitativeAssessment/distribute/distribute",
"style": {
"navigationBarTitleText": "分配",
"enablePullDownRefresh": false
}
},
{
"path": "pages/view/quantitativeAssessment/index/index",
"style": {
"navigationBarTitleText": "量化考核首页",
"enablePullDownRefresh": false
}
},
{
"path": "pages/view/quantitativeAssessment/index/details",
"style": {
"navigationBarTitleText": "量化考核详情",
"enablePullDownRefresh": false
}
},
{
"path": "pages/view/quantitativeAssessment/quantitativeSummary/quantitativeSummary",
"style": {
"navigationBarTitleText": "量化汇总",
"enablePullDownRefresh": false
}
},
{
"path": "pages/view/quantitativeAssessment/index/noticeAnnouncement",
"style": {
"navigationBarTitleText": "通知公告",
"enablePullDownRefresh": false
}
},
{
"path": "pages/view/quantitativeAssessment/index/playPage",
"style": {
"navigationBarTitleText": "播放页面",
"enablePullDownRefresh": false
}
}
],
"globalStyle": {

View File

@ -0,0 +1,191 @@
<!-- src/pages/base/message/detail.vue -->
<template>
<view class="message-detail-page">
<view v-if="isLoading" class="loading-indicator">加载中...</view>
<view v-else-if="messageDetail" class="detail-content">
<view class="detail-header">
<view class="title-tag-row">
<text class="detail-title">{{ messageDetail.title }}</text>
<view class="tag" :class="messageDetail.tagType">{{ messageDetail.tagText }}</view>
</view>
<view class="detail-meta">
<text>{{ messageDetail.date }}</text>
<text>{{ messageDetail.timeAgo }}</text>
</view>
</view>
<view class="detail-body">
<text class="detail-desc">{{ messageDetail.desc }}</text>
<!-- Add more detailed content here as needed -->
</view>
<view class="detail-footer">
<button type="primary" class="action-button">处理</button>
</view>
</view>
<view v-else class="empty-state">消息详情未找到</view>
</view>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
interface MessageDetail {
id: string; // Assuming an ID is passed or can be derived
title: string;
desc: string;
date: string;
timeAgo: string;
tagText: string;
tagType: string;
// Add other fields as necessary
}
const messageId = ref<string>('');
const messageDetail = ref<MessageDetail | null>(null);
const isLoading = ref(false);
onLoad((options) => {
// Assume the identifier is passed as 'id' query parameter
// If you pass the whole object, you can parse it here
if (options && options.id) {
messageId.value = decodeURIComponent(options.id); // Decode if necessary
fetchMessageDetail();
} else {
console.error('Message ID/Data is missing!');
uni.showToast({ title: '加载失败,缺少信息', icon: 'none' });
}
});
//
const fetchMessageDetail = async () => {
console.log(`Fetching details for message ID: ${messageId.value}`);
isLoading.value = true;
await new Promise(resolve => setTimeout(resolve, 300));
// --- Replace with actual API call using messageId.value ---
// Find the mock data based on the passed identifier (using title as ID for now)
const mockTodoList = [
{ id: 'todo1', title: '教务通知 (待办)', desc: '学校召开期初教学准备会议暨首次教学工作例会. 会议强调了新学期的教学重点和要求,请各位老师认真准备。', date: '2025-02-17', timeAgo: '8 mins 前', tagText: '通知', tagType: 'notice', likes: 6, comments: 12 },
{ id: 'todo2', title: '教学日志 (待办)', desc: '请于2025年3月15日前上传教学日志确保内容详实、准确。日志系统入口已在办公平台开放。', date: '2025-02-17', timeAgo: '8 mins 前', tagText: '任务', tagType: 'task', likes: 6, comments: 12 },
// Add mock data for '' if needed, or handle different types
{ id: 'done1', title: '审批完成 (已办)', desc: '您的请假申请已审批通过。', date: '2025-02-16', timeAgo: '1 天前', tagText: '审批', tagType: 'approval', likes: 0, comments: 0 },
];
// Find based on ID (or title if ID is not directly available)
messageDetail.value = mockTodoList.find(item => item.id === messageId.value || item.title === messageId.value) || null;
isLoading.value = false;
if (!messageDetail.value) {
console.error(`Details not found for message ID: ${messageId.value}`);
uni.showToast({ title: '未找到消息详情', icon: 'none' });
} else {
// Set navigation bar title dynamically
uni.setNavigationBarTitle({
title: messageDetail.value.tagText || '消息详情'
});
}
};
</script>
<style scoped lang="scss">
.message-detail-page {
background-color: #f4f5f7;
min-height: 100vh;
padding: 15px;
box-sizing: border-box;
}
.loading-indicator,
.empty-state {
text-align: center;
color: #999;
padding: 40px 15px;
font-size: 14px;
}
.detail-content {
background-color: #fff;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.detail-header {
border-bottom: 1px solid #f0f0f0;
padding-bottom: 15px;
margin-bottom: 20px;
.title-tag-row {
display: flex;
justify-content: space-between;
align-items: flex-start; // Align items to the top
margin-bottom: 10px;
}
.detail-title {
font-size: 18px;
font-weight: bold;
color: #333;
flex: 1; // Allow title to take available space
margin-right: 10px; // Space between title and tag
line-height: 1.4;
}
.tag { // Reuse tag styles from index page if possible, or define here
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: bold;
color: #ffffff;
white-space: nowrap;
flex-shrink: 0; // Prevent tag from shrinking
&.notice { background-color: #447ade; }
&.task { background-color: #19be6b; }
&.approval { background-color: #ff9f0a; }
&.submit { background-color: #8e8e93; }
}
.detail-meta {
font-size: 12px;
color: #999;
text {
margin-right: 15px;
}
}
}
.detail-body {
margin-bottom: 40px;
.detail-desc {
font-size: 15px;
color: #555;
line-height: 1.7;
word-break: break-word;
}
}
.detail-footer {
// text-align: center; // Removed center alignment
// Add margin if needed, e.g., margin-top: 20px;
}
// Style for the action button
.action-button {
width: 100%; // Make button full width
height: 44px; // Standard button height
line-height: 44px; // Match height for vertical centering
font-size: 16px; // Slightly larger font
font-weight: 500; // Medium weight
border-radius: 8px; // Consistent border radius
margin-top: 20px; // Add space above the button
// Ensure primary color is applied correctly (uni-app default should work)
// background-color: #447ade;
// color: #ffffff;
}
</style>

View File

@ -0,0 +1,294 @@
<template>
<BasicLayout>
<view class="mb-15">
<BasicForm @register="register"></BasicForm>
</view>
<view class="wh-full flex-row">
<view class="wi-180 po-re back-F6F7F9">
<scroll-view class="po-ab inset-0" :scroll-y="true">
<template v-for="(item,index) in inspectItemData">
<view class="flex-col-center py-15" @click="onavtion(item,index)" :class="{'white-bg-color':index==avtion}">
<uni-badge size="small" :text="item._rulenum?item._rulenum:0" :offset="[-5,0]" absolute="rightTop"
type="error">
<view class="font-w-500">{{ item.name }}</view>
</uni-badge>
<view class="font-12 text-center">{{ item.fullTimeName }}</view>
</view>
</template>
</scroll-view>
</view>
<view class="flex-1 white-bg-color po-re">
<scroll-view class="po-ab inset-0 py-15" :scroll-y="true">
<template v-for="(item,index) in fractionRuleData[avtion]">
<view @click="onavtionList(item,index)"
class="flex-row items-center mx-10 mb-10 p-15 r-md back-fafafa bor-D8D8D8"
:class="{avtionClass:item.isSelect}">
<view class="flex-1 mr-15">
<view class="">{{ item.inspectStandard }}</view>
<view class="font-12 mt-6">{{ item.scoreType == '1' ? '加' : '扣' }}{{ item.score }}</view>
</view>
<view class="wi-35 he-35 flex-col-center" style="border: 1px solid #999">
<view v-if="item.isSelect">
<BasicIcon type="checkmarkempty" color="#0647ff"></BasicIcon>
</view>
</view>
</view>
</template>
</scroll-view>
</view>
<view>
<up-popup mode="center" :show="showpopup" @close="showpopup=false" bgColor="transparent">
<view :style="'width:'+(getWindowWidth()-30)+'px'" class="white-bg-color r-md p-30">
<view class="font-w-500 font-18 text-center">请确认</view>
<view class="flex-row-center b-r" style="margin-top: 70rpx;padding-bottom: 70rpx">
<template v-if="popupType==3">
<view class="mr-15" v-if="selectItem.title">{{ selectItem.title }}:</view>
<up-number-box button-size="36" v-model="value" @change="valChange"></up-number-box>
<view v-if="selectItem.unit">{{ selectItem.unit }}</view>
</template>
<template v-else-if="popupType==4">
<view class="mr-15" v-if="selectItem.title">{{ selectItem.title }}:</view>
<up-input placeholder="请输入内容" button-size="72" v-model="value" @change="valChange"></up-input>
<view v-if="selectItem.unit">{{ selectItem.unit }}</view>
</template>
<template v-else-if="popupType==1">
<view class="mr-15" v-if="selectItem.title">{{ selectItem.title }}:</view>
<up-radio-group v-model="value" @change="radioChange">
<template v-for="(item1,index1) in ruleItemData">
<up-radio shape="circle" :label="item1.name" :name="item1.id" class="mr-8"></up-radio>
</template>
</up-radio-group>
</template>
<template v-else-if="popupType==2">
<view class="mr-15" v-if="selectItem.title">{{ selectItem.title }}:</view>
<checkbox-group style="width: 100%" @change="changeRuleItem">
<template v-for="(item,index) in ruleItemData">
<checkbox
class="mr-8"
:value="item.id">{{ item.name }}
</checkbox>
</template>
</checkbox-group>
<uni-easyinput placeholder="请输入内容"></uni-easyinput>
</template>
</view>
<view class="flex-row-center gapX-30" style="padding-top: 30px">
<view class="back-F7F8FA wi-240 py-8 r-md flex-row-center" @click="showpopup=false">取消</view>
<view class="back-1B88FF wi-240 py-8 r-md white-color flex-row-center" @click="setItemValue">确认</view>
</view>
</view>
</up-popup>
</view>
</view>
<template #bottom>
<view class="white-bg-color py-5">
<view class="flex-row items-center pb-10 pt-5">
<u-button text="提交" class="mx-15" type="primary" @click="submit"/>
</view>
</view>
</template>
</BasicLayout>
</template>
<script setup lang="ts">
import {getWindowWidth, navigateBack, navigateTo, showToast} from "@/utils/uniapp";
import {
evaluationSaveApi,
fractionRuleFindAllByItemIdApi, getSchedulingPlanByUserIdApi,
gradeClassFindAllsApi,
inspectItemFindAllsApi,
ruleItemFindByRuleIdApi
} from "@/api/base/assesment";
import {onShow} from "@dcloudio/uni-app";
import {deptFindByPidApi, dicApi} from "@/api/system/dic";
import {useForm} from "@/components/BasicForm/hooks/useForm";
import {getUserViewApi} from "@/api/system/login";
function setItemValue() {
console.log(444,value.value)
for (let k in fractionRuleData.value) {
let items = fractionRuleData.value[k];
for (let i = 0; i < items.length; i++) {
if (items[i].id == selectItem.value.id) {
items[i].value = value.value;
}
}
}
showpopup.value = false;
}
const [register, {getValue, setSchema, setValue}] = useForm({
schema: [
{
field: "grade",
label: "年级",
component: "BasicPickerCheckbox",
required: true,
componentProps: {
api: deptFindByPidApi,
param: {pid: 1},
rangeKey: 'deptName',
savaKey: 'id',
ok: async (ysave: any, svalue: any, range: any) => {
let res = await deptFindByPidApi({pid: svalue});
setSchema([{
field: "gradeClassId",
componentProps: {
range: res.result,
rangeKey: 'deptName',
savaKey: 'id'
}
}])
}
}
}, {
field: "gradeClassId",
label: "班级",
component: "BasicPickerCheckbox",
required: true,
componentProps: {
// api: gradeClassFindAllsApi,
rangeKey: 'deptName',
savaKey: 'id'
}
}
]
})
const avtion = ref(0)
const popupType = ref(1)
const inspectItemData: any = ref([]);
const showpopup = ref(false)
const value: any = ref(null);
const authItemIds: any = ref([]);
onShow(async () => {
authItemIds.value = [];
let res = await getSchedulingPlanByUserIdApi();
if (res.result && res.result.length > 0) {
let userres = await getUserViewApi();
if (userres && userres.result) {
authItemIds.value = userres.result.thirdId ? userres.result.thirdId.split(",") : [];
}
} else {
showToast({title: "今日未分配!无法填报!"})
}
getInspectItemData();
})
function valChange() {
console.log(333, value.value)
}
function radioChange() {
console.log(222, value.value)
}
function changeRuleItem(e) {
value.value = e.detail.value;
}
async function getInspectItemData() {
let res = await inspectItemFindAllsApi();
if (res && res.result && res.result.length > 0) {
inspectItemData.value = res.result.filter(item => authItemIds.value.includes(item.id));
avtion.value = 0;
getFractionRuleData();
} else {
inspectItemData.value = [];
}
}
function onavtion(item, index) {
avtion.value = index;
console.log(111, fractionRuleData.value)
getFractionRuleData();
}
const fractionRuleData: any = ref({});
async function getFractionRuleData() {
if (!fractionRuleData.value[avtion.value]) {
let res = await fractionRuleFindAllByItemIdApi({itemId: inspectItemData.value[avtion.value].id});
if (res && res.result) {
fractionRuleData.value[avtion.value] = res.result;
} else {
fractionRuleData.value = [];
}
}
}
const selectItem: any = ref({});
const ruleItemData: any = ref([]);
async function onavtionList(item: any, index: any) {
fractionRuleData.value[avtion.value][index].isSelect = !fractionRuleData.value[avtion.value][index].isSelect
selectItem.value = fractionRuleData.value[avtion.value][index];
popupType.value = selectItem.value.ruleType;
if (fractionRuleData.value[avtion.value][index].isSelect && (popupType.value == 1 || popupType.value == 2 || popupType.value == 3|| popupType.value == 4)) {
if (popupType.value == 1 || popupType.value == 2) {
await getRuleItemData();
if (popupType.value == 1) {
value.value = null;
} else {
value.value = [];
}
} else {
value.value = selectItem.value.defaultValue;
}
showpopup.value = true;
}
inspectItemData.value[avtion.value]._rulenum = fractionRuleData.value[avtion.value].filter(item => item.isSelect).length;
}
async function getRuleItemData() {
let res = await ruleItemFindByRuleIdApi({ruleId: selectItem.value.id});
if (res && res.result) {
ruleItemData.value = res.result;
} else {
ruleItemData.value = [];
}
}
async function submit() {
let itemList: any = [];
for (let key in fractionRuleData.value) {
let items = fractionRuleData.value[key];
for (let j = 0; j < items.length; j++) {
if (items[j].isSelect) {
itemList.push({
ruleId: items[j].id,
value: items[j].value ? items[j].value.toString() : ""
});
}
}
}
if (itemList.length == 0) {
return;
}
let values = await getValue();
if (values.gradeClassId) {
await evaluationSaveApi({
itemList: itemList,
gradeClassId: values.gradeClassId
});
showToast({title: "操作成功"});
navigateBack({delta: 1})
} else {
showToast({title: "请选择班级"});
}
}
</script>
<style scoped lang="scss">
.avtionClass {
border: 1px solid #0647ff !important;
background: #e6ecff !important;
}
</style>

View File

@ -0,0 +1,215 @@
<template>
<BasicLayout>
<view class="p-15">
<BasicForm @register="register"></BasicForm>
</view>
<template #bottom>
<view class="white-bg-color py-5" v-if="!isDisabled">
<view class="flex-row items-center pb-10 pt-5">
<u-button text="提交" class="mx-15" type="primary" @click="submit"/>
</view>
</view>
</template>
</BasicLayout>
</template>
<script lang="ts" setup>
import {useForm} from "@/components/BasicForm/hooks/useForm";
import {deptFindByPidApi} from "@/api/system/dic";
import {deptFindAllGradeClassApi, gradeClassFindAllsApi, readyToGoSaveApi} from "@/api/base/assesment";
import {navigateBack, showToast} from "@/utils/uniapp";
import {useDataStore} from "@/store/modules/data";
const {getData} = useDataStore()
const classData: any = ref([]);
getClassData();
async function getClassData() {
let res = await gradeClassFindAllsApi();
classData.value = res.result;
}
function reloadGrade(params) {
let arr = [];
for (let i = 0; i < classData.value.length; i++) {
if (classData.value[i].grade == params.grade) {
arr.push(classData.value[i]);
}
}
return arr;
}
const isDisabled = ref(false)
const [register, {getValue, setSchema, setValue, setDisabled}] = useForm({
schema: [
{
field: "purpose",
label: "用途",
component: "BasicCheckbox",
required: true,
componentProps: {
data: [
{"value": "表扬栏", "text": "表扬栏"},
{"value": "曝光栏", "text": "曝光栏"},
]
}
}, {
field: "grade",
label: "年级",
component: "BasicPickerCheckbox",
required: false,
ifShow(item) {
return getData._show;
},
componentProps: {
api: deptFindByPidApi,
param: {pid: 1},
rangeKey: 'deptName',
savaKey: 'id',
ok: async (ysave: any, svalue: any, range: any) => {
let res = await deptFindByPidApi({pid: svalue});
console.log(222, res)
setSchema([{
field: "gradeClassId",
componentProps: {
range: res.result,
rangeKey: 'deptName',
savaKey: 'id'
}
}])
}
}
}, {
field: "gradeClassId",
label: "班级",
component: "BasicPickerCheckbox",
required: false,
componentProps: {
api: deptFindAllGradeClassApi,
rangeKey: 'deptName',
savaKey: 'id'
}
}, {
field: "studentName",
label: "学生",
component: "BasicInput",
required: false,
componentProps: {}
},
{
field: "content",
label: "表扬内容",
component: "BasicInput",
required: true,
itemProps: {labelPosition: 'top'},
componentProps: {
type: "textarea"
}
},
{
field: "scfj",
label: "附件类型",
component: "BasicCheckbox",
defaultValue: '照片',
componentProps: {
rangeKey: 'name',
savaKey: 'name',
onChange: async (e: string) => {
if (e == '照片') {
setSchema([{
field: 'pic',
label: e,
componentProps: {
accept: 'image'
}
}])
}
if (e == '视频') {
setSchema([{
field: 'pic',
label: e,
componentProps: {
accept: 'video'
}
}])
}
},
data: [{
text: '照片',
value: '照片',
},
{
text: '视频',
value: '视频',
}]
}
},
{
field: "pic",
label: "照片",
component: "BasicUpload",
required: true,
itemProps: {labelPosition: 'top'},
componentProps: {
accept: 'image',
onChange: (e: any) => {
if (e) {
setSchema([{
field: 'scfj',
componentProps: {
disabled: true
}
}])
} else {
setSchema([{
field: 'scfj',
componentProps: {
disabled: false
}
}])
}
}
}
},
]
})
if (/\.(jpg|jpeg|png|gif|bmp|webp|tiff|svg)$/i.test(getData.pic)) {
getData['scfj'] = '照片'
setSchema([{
field: 'pic',
label: '照片',
componentProps: {
accept: 'image'
}
}])
}
if (/\.(mp4|avi|mov|wmv|flv|mkv|webm)$/i.test(getData.pic)) {
getData['scfj'] = '视频'
setSchema([{
field: 'pic',
label: '视频',
componentProps: {
accept: 'video'
}
}])
}
if (getData._show) {
setValue({})
setValue(getData)
setDisabled(true)
isDisabled.value = true
} else {
setValue({})
setDisabled(false)
isDisabled.value = false;
}
async function submit() {
let values = await getValue();
await readyToGoSaveApi({...values});
showToast({title: "操作成功"});
navigateBack({delta: 1});
}
</script>

View File

@ -0,0 +1,230 @@
<template>
<view class="wh-full">
<BasicListLayout @register="register">
<template v-slot="{data,index}">
<view class="white-bg-color r-md p-15 mb-15">
<view class="font-w-500 mb-10">{{ data['userName'] }}</view>
<view class="mb-10 font-13">检查项目:</view>
<view class="mb-10">
<up-checkbox-group
v-model="data.itemMap"
placement="row"
@change="((e:any)=>checkboxChange(e,data))"
>
<up-checkbox
:customStyle="{marginRight: '15px'}"
v-for="(item, index) in inspectItem"
:key="index"
:label="item['name']"
:name="item['id']"
>
</up-checkbox>
</up-checkbox-group>
</view>
<view v-if="data.remark">
<view class="mb-10 font-13">检查时间:</view>
<view v-for="(item,index) in data.remark.split(',')" :key="index">
<view class="mb-10 font-13">{{ item }}</view>
</view>
</view>
<view class="flex-row-center py-7 r-md" style="border: 1px dashed #999" @click="scheduling(data)">
排班
</view>
</view>
</template>
</BasicListLayout>
<view>
<up-popup :show="showPopup" @close="showPopup=false" bgColor="transparent">
<view :style="'width:'+width+'px;height:'+(height/1.05)+'px'" style="background: #e7e7e7"
class="flex-col ">
<view class="flex-row items-center py-15">
<view class="flex-1"></view>
<view class="flex-1 flex-row-center">排班设置</view>
<view class="flex-1 flex-row justify-end mr-10" @click="showPopup=false">
<BasicIcon type="closeempty" size="20"></BasicIcon>
</view>
</view>
<view class="flex-1 po-re">
<view class="po-ab inset-0 pt-15 px-15">
<template v-for="(item,index) in listData.list" :key="index">
<view class="po-re mb-15">
<BasicForm v-model="item.value" :schema="schema" :formsProps="{labelWidth: 100}"/>
<view @click="deleteMemberFamily(index as number,item)" class="delete-icon">
<BasicIcon type="clear" size="30"/>
</view>
</view>
</template>
<view class="flex-row-center py-8 r-md" style="border: 1px dashed #999" @click="add">
新增一行
</view>
</view>
</view>
<view class="white-bg-color py-5">
<view class="flex-row items-center pb-10 pt-5">
<u-button text="提交" class="mx-15" type="primary" @click="handleSubmit"/>
</view>
</view>
</view>
</up-popup>
</view>
</view>
</template>
<script setup lang="ts">
import {getWindowHeight, getWindowWidth, hideLoading, showLoading} from "@/utils/uniapp";
import 'dayjs/locale/zh-cn';
import {
getSchedulingPlansByUserIdApi,
inspectItemFindAllApi,
schedulingPlanApi,
schedulingPlanDelApi,
schedulingPlanSaveBatcApi,
updateThirdIdApi
} from "@/api/base/assesment";
import {cloneDeep, forEach, map} from 'lodash'
import {useLayout} from "@/components/BasicListLayout/hooks/useLayout";
async function checkboxChange(e: any, data: any) {
await updateThirdIdApi({
id: data.userId,
thirdId: e.join(',')
})
}
const width = ref(0)
const height = ref(0)
const showPopup = ref(false)
const schema = [
{
field: "schedulingStartDate",
label: "开始时间",
required: true,
component: "BasicDateTimes",
componentProps: {}
}, {
field: "schedulingEndDate",
label: "结束时间",
component: "BasicDateTimes",
required: true,
componentProps: {}
},
]
const listData = reactive<any>(
{
list: []
}
)
function add() {
listData.list.push({
value: {schedulingEndDate: '', schedulingStartDate: ''}
})
}
let schedulingData: any
async function scheduling(data: any) {
schedulingData = data
showLoading({title: '加载中'})
const {result, resultCode} = await getSchedulingPlansByUserIdApi({userId: data['userId']})
if (resultCode == 1 && result && result.length > 0) {
listData.list = map(result, (item) => {
item['value'] = {
schedulingEndDate: item['schedulingEndDate'],
schedulingStartDate: item['schedulingStartDate'],
}
return item
})
} else {
listData.list = []
}
hideLoading()
showPopup.value = true
}
async function handleSubmit() {
showLoading({title: '加载中'})
await schedulingPlanSaveBatcApi({
planDtos: map(listData.list, (item) => {
return {
...item,
schedulingEndDate: item.value['schedulingEndDate'],
schedulingStartDate: item.value['schedulingStartDate'],
}
}),
userId: schedulingData['userId']
})
hideLoading()
showPopup.value = false
await reload()
}
async function deleteMemberFamily(index: number, item: any) {
const list = cloneDeep(listData.list)
list.splice(index, 1)
if (item.id) {
await schedulingPlanDelApi({ids: item.id})
}
listData.list = list
}
onMounted(async () => {
width.value = getWindowWidth()
height.value = getWindowHeight()
})
const [register, {reload}] = useLayout({
api: schedulingPlanApi,
request: (data) => {
forEach(data, (item) => {
let itemMap = []
for (const itemKey in item.itemMap) {
if (item.itemMap[itemKey]) {
itemMap.push(itemKey)
}
}
item.itemMap = itemMap
})
return data
},
showSearch: true,
searchKey: 'userName',
componentProps: {},
})
const inspectItem = ref([])
async function getInspectItemFindAll() {
let {result, resultCode} = await inspectItemFindAllApi();
if (resultCode == 1 && result) {
inspectItem.value = result
}
}
getInspectItemFindAll()
</script>
<style scoped lang="scss">
.table_box {
border-right: 1px solid #D8D8D8;
}
.b-r {
border-bottom: 1px solid #D8D8D8;
}
.t-r {
border-top: 1px solid #D8D8D8;
}
.delete-icon {
position: absolute;
right: -14px;
top: -13px;
z-index: 1;
}
</style>

View File

@ -0,0 +1,59 @@
<template>
<view class="p-15">
<BasicListLayout @register="register">
<template v-slot="{data,index}">
<view class="white-bg-color r-md p-15 mb-15 flex-row items-center">
<view class="flex-1">
<view class="font-w-500 flex-row">
<view class="mr-5">{{ data.fullName }}</view>
<view class="mr-5">{{ data.remark }}</view>
<view v-if="data.roleName=='系统管理员'">{{ data.roleName }}{{ data.userName }}</view>
</view>
<template v-for="(arr,key) in data.items">
<view class="font-14 font-w-500 mt-15">{{ key }}</view>
<view class="font-14 mt-6" v-for="(item,index) in arr">
{{ item.inspectStandard }},{{
item.scoreType == 2 ? '扣' : '加'
}}{{ Math.abs(item.score) }};
</view>
</template>
<view style="text-align: right">
<view>{{ data.createdTime.split(" ")[0] }}</view>
</view>
</view>
</view>
</template>
</BasicListLayout>
</view>
</template>
<script setup lang="ts">
import {useDataStore} from "@/store/modules/data";
import {useLayout} from "@/components/BasicListLayout/hooks/useLayout";
import {evaluationFindPageApi} from "@/api/base/assesment";
import Template from "@/components/BasicQrcode/_template/template.vue";
const useData = useDataStore()
const {getData} = storeToRefs(useData)
const [register, lhkh] = useLayout({
api: evaluationFindPageApi,
param: {
showWeek: 1
},
componentProps: {
loadingMoreEnabled: false,
auto: false
},
})
console.log(111, getData.value)
if (getData.value.gradeClassId) {
lhkh.setParam({gradeClassId: getData.value.gradeClassId})
lhkh.reload()
}
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,298 @@
<template>
<view class="w-full h-full main_bg flex-col">
<view class="p-15">
<view class="flex-row items-center justify-between">
<view class="flex-row items-center">
<view class="wi-120 he-120 r-50">
<image class="wh-full"
src="/static/base/logo.jpg"></image>
</view>
<view class="white-color ml-15">
<view class="font-18">你好{{ getUser.name }}</view>
</view>
</view>
<view @click="tuichu">
<svg t="1726666280409" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="4480" width="25" height="25">
<path
d="M512.2 953.1c-99.6 0-199.7-33.3-282.2-101.7C42 695.6 15.9 416 171.7 228s435.5-214.1 623.4-58.3c53.8 44.6 95.2 99.5 123 163.1 7.5 17.2-0.3 37.3-17.6 44.9-17.2 7.5-37.3-0.3-44.9-17.6-23.5-53.8-58.5-100.2-104.1-137.9C592.6 90.3 356 112.5 224.1 271.5 92.3 430.5 114.4 667.1 273.5 799c159 131.8 395.6 109.7 527.5-49.3 19.7-23.8 36.4-49.8 49.6-77.4 8.1-17 28.5-24.1 45.4-16 17 8.1 24.1 28.5 16 45.4-15.6 32.6-35.3 63.4-58.6 91.4-87.4 105.5-213.9 160-341.2 160z"
fill="#ffffff" p-id="4481"></path>
<path
d="M910.9 544.6H440.8c-18.8 0-34.1-15.3-34.1-34.1s15.3-34.1 34.1-34.1h470.1c18.8 0 34.1 15.3 34.1 34.1 0 18.9-15.3 34.1-34.1 34.1z"
fill="#ffffff" p-id="4482"></path>
</svg>
</view>
</view>
</view>
<view class="flex-1 back-F6F6F6 flex-col">
<view class="px-15 pt-15">
<BasicTitle title="我的应用" :isBorder="false" line/>
<view class="white-bg-color py-15 grid gridCols-4 mt-15 r-md">
<view class="flex-col-center" @click="tokhpj">
<image class="wi-88 he-88" src="/static/base/1.png"/>
<view class="font-12 mt-8">考核评价</view>
</view>
<view class="flex-col-center" @click="tossp">
<image class="wi-88 he-88" src="/static/base/2.png"/>
<view class="font-12 mt-8">随手拍</view>
</view>
<view class="flex-col-center" @click="navigateTo('/pages/view/quantitativeAssessment/distribute/distribute')">
<image class="wi-88 he-88" src="/static/base/3.png"/>
<view class="font-12 mt-8">分配</view>
</view>
<view class="flex-col-center" @click="navigateTo('/pages/view/quantitativeAssessment/quantitativeSummary/quantitativeSummary')">
<image class="wi-88 he-88" src="/static/base/4.png"/>
<view class="font-12 mt-8">量化汇总</view>
</view>
</view>
</view>
<view class="px-15 mt-15">
<BasicTabs ref="tabsRef" :list="tabs" bar-width="100rpx" :current="current" @change="tabsChange"/>
</view>
<view class="flex-1 ov-hidden">
<view v-if="current==0" class="wh-full">
<BasicListLayout @register="register">
<template v-slot="{data,index}">
<view @click="onlhkh(data)" class="white-bg-color r-md p-15 mb-15 flex-row ">
<view class="flex-1">
<view class="font-w-500 flex-row">
<view class="mr-5">{{ data.fullName }}</view>
<view class="mr-5">{{ data.score }}</view>
本周得分{{ data.score ? (100 + parseFloat(data.score)) : 100 }}
</view>
<view class="grid gridCols-4 mt-15 gapY-15">
<template v-for="(item,key) in inspectItems">
<view class="flex-col-center">
<view class="font-w-500">{{ item.name }}</view>
<view class="mt-5" v-if="data['item'+item.id]">{{ data['item' + item.id] }}</view>
<view class="wi-45 he-45 mt-5" v-else>
<image src="/static/base/tb.jpg" class="wh-full"></image>
</view>
</view>
</template>
</view>
<!-- <template v-for="(arr,key) in data.items">-->
<!-- <view class="font-14 font-w-500 mt-15">{{ key }}</view>-->
<!-- <view class="font-14 mt-6" v-for="(item,index) in arr">-->
<!-- {{ item.inspectStandard }},{{-->
<!-- item.scoreType == 2 ? '扣' : '加'-->
<!-- }}{{ Math.abs(item.score) }};-->
<!-- </view>-->
<!-- </template>-->
</view>
</view>
</template>
</BasicListLayout>
</view>
<view v-if="current==1" class="wh-full">
<BasicListLayout @register="sspregister">
<template v-slot="{data,index}">
<view @click="onssp(data)" class="white-bg-color r-md p-15 mb-15 flex-col">
<view class="mb-15">
<view class="font-w-500 flex-row">
<view class="mr-5">{{ data.fullName }}</view>
<view class="mr-5" v-if="data.studentName">{{ data.studentName }}</view>
{{ data.purpose }}
</view>
<view class="font-12 mt-15" v-html="data.content">
</view>
</view>
<view class="flex-row flex-wrap list_box">
<view class=" r-md mr-15 flex-row" v-for="(item,key) in data.pic.split(',')">
<image v-if="/\.(jpg|jpeg|png|gif|bmp|webp|tiff|svg)$/i.test(item)" :src="imagUrl(item)"
class="wi-160 he-160"></image>
<view @click.stop="videoplay(imagUrl(item))" class="wi-260 he-360 po-re"
v-if="/\.(mp4|avi|mov|wmv|flv|mkv|webm)$/i.test(item)">
<video class="wi-260 he-360"
:src="imagUrl(item)"></video>
<view class="uni-video-cover1">
<svg t="1729239497913" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="4290" width="40" height="40">
<path
d="M512 853.333333c-187.733333 0-341.333333-153.6-341.333333-341.333333s153.6-341.333333 341.333333-341.333333 341.333333 153.6 341.333333 341.333333-153.6 341.333333-341.333333 341.333333z m0-85.333333c140.8 0 256-115.2 256-256s-115.2-256-256-256-256 115.2-256 256 115.2 256 256 256z m128-256l-213.333333 128V384l213.333333 128z"
fill="#e6e6e6" p-id="4291"></path>
</svg>
</view>
</view>
</view>
</view>
<view style="text-align: right">{{ data.createdTime.split(" ")[0] }}</view>
</view>
</template>
</BasicListLayout>
</view>
<view v-if="current==2" class="wh-full po-re">
<!-- <view class="po-ab inset-0 ov-auto p-15">-->
<!-- <template v-for="(data,index) in totzggList">-->
<!-- </template>-->
<!-- </view>-->
<BasicListLayout @register="tzggregister">
<template v-slot="{data,index}">
<view class="white-bg-color r-md p-15 mb-15 flex-row items-center" @click="totzgg(data)">
<view class="wi-100 he-100 r-50 mr-10" v-if="data.thumbnails">
<image :src="imagUrl(data.thumbnails)"
class="wh-full"></image>
</view>
<view class="flex-1">
<view class="font-w-500">{{ data.title }}</view>
<view class="font-12 text-ellipsis-1 mt-5" v-html="data.description"></view>
</view>
</view>
</template>
</BasicListLayout>
</view>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import {navigateTo, reLaunch, showToast} from "@/utils/uniapp";
import {useLayout} from "@/components/BasicListLayout/hooks/useLayout";
import {
cmsArticleFindPageApi,
evaluationFindPageSummaryApi,
getSchedulingPlanByUserIdApi,
inspectItemFindAllsApi,
readyToGoFindPageApi
} from "@/api/base/assesment";
import {imagUrl} from "@/utils";
import {onShow} from "@dcloudio/uni-app";
import {useUserStore} from "@/store/modules/user";
import Template from "@/components/BasicQrcode/_template/template.vue";
import {useDataStore} from "@/store/modules/data";
import {getUserViewApi} from "@/api/system/login";
const tabs = ['量化考核', '随手拍', '通知公告']
const current = ref(0)
const tabsRef = ref(null)
const {setData} = useDataStore()
function onssp(data: any) {
setData({
_show: true,
...data
})
navigateTo('/pages/view/quantitativeAssessment/casualShot/casualShot')
}
function videoplay(url: string) {
navigateTo('/pages//view/quantitativeAssessment/index/playPage?url=' + encodeURIComponent(url))
}
function onlhkh(data: any) {
setData(data)
navigateTo('/pages/view/quantitativeAssessment/index/details?gradeClassId=' + data.gradeClassId)
}
function totzgg(data: any) {
setData(data)
navigateTo('/pages/view/quantitativeAssessment/index/noticeAnnouncement')
}
const {getUser, logout} = useUserStore();
const inspectItems: any = ref([]);
function tuichu() {
logout()
reLaunch('/pages/system/login/login')
}
const thirdId: any = ref('');
onShow(async () => {
let res = await inspectItemFindAllsApi();
inspectItems.value = res.result;
await lhkh.reload()
let userres = await getUserViewApi();
if (userres && userres.result) {
thirdId.value = userres.result.thirdId ? userres.result.thirdId : "";
} else {
thirdId.value = "";
}
})
const [register, lhkh] = useLayout({
api: evaluationFindPageSummaryApi,
param: {
showWeek: 1
},
componentProps: {
fixed: false,
loadingMoreEnabled: false,
auto: false
},
})
const [sspregister, ssp] = useLayout({
api: readyToGoFindPageApi,
param: {
showWeek: 1
},
componentProps: {
fixed: false,
loadingMoreEnabled: false,
auto: false
},
})
async function tokhpj() {
if (thirdId.value) {
let res = await getSchedulingPlanByUserIdApi();
if (res.result && res.result.length > 0) {
navigateTo('/pages/view/quantitativeAssessment/assessment/assessment')
} else {
showToast({title: "今日未分配!无法填报!"})
}
} else {
showToast({title: "未配置权限!"})
}
}
function tossp() {
setData({});
navigateTo('/pages/view/quantitativeAssessment/casualShot/casualShot')
}
const totzggList = ref<any>([])
cmsArticleFindPageApi({showWeek: 1}).then(res => {
totzggList.value = res.rows
})
const [tzggregister, tzgg] = useLayout({
api: cmsArticleFindPageApi,
param: {
showWeek: 1
},
componentProps: {
fixed: false,
loadingMoreEnabled: false,
auto: false
},
})
function tabsChange(index: any) {
current.value = index
if (index == 0) {
lhkh.reload()
}
if (index == 1) {
ssp.reload()
}
if (index == 2) {
tzgg.reload()
}
}
</script>
<style scoped lang="scss">
.main_bg {
//background: #4651fa;
background: url("@/static/base/top.png") no-repeat;
background-size: 100% 100%;
}
</style>

View File

@ -0,0 +1,22 @@
<template>
<view class="flex-col items-center p-15 white-bg-color wh-full">
<view class="w-7_5 mx-auto text-center font-w-800 font-16">
{{ getData.title }}
</view>
<view class="mt-15 font-10 color-9">
<text class="mr-20">发布人:{{ getData.createdUserName }}</text>
<text>{{ getData.createdTime }}</text>
</view>
<view v-if="getData.thumbnails" class="my-15">
<BasicImage :src="imagUrl(getData.thumbnails)"/>
</view>
<view v-html="getData.content"></view>
</view>
</template>
<script lang="ts" setup>
import {useDataStore} from "@/store/modules/data";
import {imagUrl} from "@/utils";
const {getData} = useDataStore()
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,15 @@
<template>
<view class="wh-full">
<video :src="src" class="wh-full"></video>
</view>
</template>
<script setup>
import {ref} from "vue";
import {onLoad} from "@dcloudio/uni-app";
const src = ref('')
onLoad(({url}) => {
src.value = decodeURIComponent(url)
})
</script>

View File

@ -0,0 +1,126 @@
<template>
<!-- <view :style="'width:'+height+'px;height:'+width+'px;transform-origin:'+(height/2)+'px '+(height/2)+'px'"-->
<!-- style="transform: rotate(270deg);" class="p-15 flex-col"> -->
<view class="flex-col wh-full">
<swiper class="h-full" :circular="true" :autoplay="false" :vertical="true">
<template v-for="(citem,cindex) in dataLiat" :key="cindex">
<swiper-item>
<view class="h-full po-re">
<scroll-view :scroll-x="true" :scroll-y='false' class="po-ab inset-0">
<view :style="'width:'+(head.length*100)+'px;height:'+height+'px'" class="h-full flex-col">
<view class="grid back-aacbfb py-5 justify-items-center"
:style="`grid-template-columns: repeat(${head.length},minmax(0, 1fr))`">
<template v-for="(item,index) in head" :key="index">
<view class="font-w-500 px-5 flex-row justify-between items-center" style="width: 115px" v-if="index==0"
:style="{ position: 'sticky', left: '0', backgroundColor: '#aacbfb', zIndex: 10 }">
<view v-for="(zitem,xindex) in item['name'].split(',')" :key="'z_'+xindex">
{{ zitem }}
</view>
</view>
<view class="font-w-500" v-else>{{ item['name'] }}</view>
</template>
</view>
<template v-for="(bitem,bindex) in citem" :key="bindex">
<view class="flex-1 grid py-5 justify-items-center"
:style="`grid-template-columns: repeat(${head.length},minmax(0, 1fr))`">
<template v-for="(ditem,dindex) in head" :key="dindex">
<view class="font-13 flex-row justify-between items-center px-5" style="width: 115px" v-if="dindex==0"
:style="{ position: 'sticky', left: '0', backgroundColor: '#f8f8f8', zIndex: 10 }">
<view> {{ bitem['gradeFullName'] }}</view>
<view>{{ 100 + parseFloat(bitem['totalScore']) }}</view>
</view>
<!-- <view class="font-13 flex-col-center" v-else-if="dindex==1"-->
<!-- :style="{ position: 'sticky', left: '0', backgroundColor: '#f8f8f8', zIndex: 10 }">-->
<!-- -->
<!-- </view>-->
<view class="font-13 flex-col-center" v-else>
<view v-if="bitem['itemScoreMap'][ ditem['id']]">
{{ bitem['itemScoreMap'][ditem['id']] }}
</view>
<view v-else>
<image src="/static/base/tb.jpg" class="wi-50 he-50"></image>
</view>
</view>
</template>
</view>
</template>
</view>
</scroll-view>
</view>
</swiper-item>
</template>
</swiper>
</view>
</template>
<script setup lang="ts">
import {getWindowHeight, getWindowWidth} from "@/utils/uniapp";
import {evaluationGetWeekReportApi, inspectItemFindAllApi} from "@/api/base/assesment";
import {groupBy, values} from 'lodash'
const width = ref(0)
const height = ref(0)
onMounted(() => {
width.value = getWindowWidth()
height.value = getWindowHeight()
})
const head = ref([])
const dataLiat = ref<any>([])
async function getWeekData() {
let res = await inspectItemFindAllApi();
let arr: any = [{name: "班级,得分"}];
if (res.result && res.result.length) {
for (let i = 0; i < res.result.length; i++) {
arr.push(res.result[i]);
}
}
// arr.push();
head.value = arr
let res1 = await evaluationGetWeekReportApi();
const grouped = groupBy(res1.result, 'gradeNum');
dataLiat.value = values(grouped);
// forEach(result, (data) => {
// let rowDatas: any = [];
// if (data && data.length > 0) {
// weekData.value = data;
// for (let i = 0; i < weekData.value.length; i++) {
// let item: any = [];
// item.push("<span style='color:black'>" + weekData.value[i].gradeFullName + "</span>");
// let itemScoreMap: any = weekData.value[i].itemScoreMap;
// for (let j = 0; j < res.length; j++) {
// let score: any = itemScoreMap[res[j].id]
// if (score == undefined || score >= 0) {
// let pic = basicImageUrl + "/upload/assets/dp/4.png";
// item.push("<div class=\"image-container\" style='display: flex;align-items: center'><img style='width: 23px' src='" + pic + "'/></div>")
// } else {
// item.push("<span style='color:black'>" + score + "</span>");
// }
// }
// item.push("<span style='color:black'>" + (100 + weekData.value[i].totalScore) + "</span>");
// rowDatas.push(item);
// }
// } else {
// weekData.value = [];
// }
// evaluationConfig.push({
// evenRowBGC: 'rgba(17,17,17,0)',
// oddRowBGC: 'rgba(17,17,17,0)',
// headerBGC: 'rgba(27,126,242,0.34)',
// rowNum: rowDatas.length,
// index: false,
// header: arr,
// data: rowDatas
// })
// })
}
getWeekData()
</script>
<style scoped lang="scss">
</style>

BIN
src/static/base/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
src/static/base/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
src/static/base/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
src/static/base/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
src/static/base/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
src/static/base/tb.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

BIN
src/static/base/top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 KiB