From 737179a0ce34147269cccf288fecd0e7bb4c309b Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期三, 11 二月 2026 10:42:19 +0800
Subject: [PATCH] 成绩查询+个人中心
---
src/router/main/index.js | 10
src/views/main/score/index.vue | 182 ++++++
src/views/main/appraisalPlan/index.vue | 143 ++++
src/router/main/score/index.js | 9
src/views/main/components/UploadIdCard.vue | 239 ++++++++
src/router/main/examTicket/index.js | 9
src/views/main/home/index.vue | 13
src/views/main/notice/list.vue | 4
src/utils/tool.js | 51 +
src/views/main/appraisalPlan/components/signupDialog.vue | 190 +++++++
src/views/main/certificate/index.vue | 202 +++++++
src/views/main/components/MyHeader.vue | 5
src/router/main/certificate/index.js | 9
src/views/main/center/index.vue | 176 ++++++
src/views/main/components/UploadBtn.vue | 16
public/favicon.ico | 0
src/router/main/center/index.js | 9
src/views/main/examTicket/index.vue | 170 ++++++
src/assets/images/uploadBox/face.png | 0
src/views/main/appraisalPlan/components/signupSuccessDialog.vue | 63 ++
src/assets/images/uploadBox/emblem.png | 0
src/views/main/center/mySignup/index.vue | 71 ++
22 files changed, 1,542 insertions(+), 29 deletions(-)
diff --git a/public/favicon.ico b/public/favicon.ico
index df36fcf..b0d8840 100644
--- a/public/favicon.ico
+++ b/public/favicon.ico
Binary files differ
diff --git a/src/assets/images/uploadBox/emblem.png b/src/assets/images/uploadBox/emblem.png
new file mode 100644
index 0000000..6d2b696
--- /dev/null
+++ b/src/assets/images/uploadBox/emblem.png
Binary files differ
diff --git a/src/assets/images/uploadBox/face.png b/src/assets/images/uploadBox/face.png
new file mode 100644
index 0000000..52c2958
--- /dev/null
+++ b/src/assets/images/uploadBox/face.png
Binary files differ
diff --git a/src/router/main/center/index.js b/src/router/main/center/index.js
new file mode 100644
index 0000000..1a3fdc6
--- /dev/null
+++ b/src/router/main/center/index.js
@@ -0,0 +1,9 @@
+const score = [
+ {
+ path: 'center',
+ name: '涓汉涓績',
+ component: () => import('@/views/main/center/index.vue'),
+ },
+]
+
+export default score
\ No newline at end of file
diff --git a/src/router/main/certificate/index.js b/src/router/main/certificate/index.js
new file mode 100644
index 0000000..4983dfe
--- /dev/null
+++ b/src/router/main/certificate/index.js
@@ -0,0 +1,9 @@
+const certificate = [
+ {
+ path: 'certificate',
+ name: '璇佷功鏌ヨ',
+ component: () => import('@/views/main/certificate/index.vue'),
+ },
+]
+
+export default certificate
\ No newline at end of file
diff --git a/src/router/main/examTicket/index.js b/src/router/main/examTicket/index.js
new file mode 100644
index 0000000..24ccd43
--- /dev/null
+++ b/src/router/main/examTicket/index.js
@@ -0,0 +1,9 @@
+const examTicket = [
+ {
+ path: 'examTicket',
+ name: '鍑嗚�冭瘉鏌ヨ',
+ component: () => import('@/views/main/examTicket/index.vue'),
+ },
+]
+
+export default examTicket
\ No newline at end of file
diff --git a/src/router/main/index.js b/src/router/main/index.js
index 448bc1a..be598fb 100644
--- a/src/router/main/index.js
+++ b/src/router/main/index.js
@@ -1,11 +1,19 @@
import home from '@/router/main/home/index.js'
import notice from '@/router/main/notice/index.js'
import appraisalPlan from '@/router/main/appraisalPlan'
+import examTicket from '@/router/main/examTicket/index.js'
+import score from '@/router/main/score/index.js'
+import certificate from '@/router/main/certificate/index.js'
+import center from '@/router/main/center/index.js'
const mainRouter = [
...home,
...notice,
- ...appraisalPlan
+ ...appraisalPlan,
+ ...examTicket,
+ ...score,
+ ...certificate,
+ ...center
]
const router = [
{
diff --git a/src/router/main/score/index.js b/src/router/main/score/index.js
new file mode 100644
index 0000000..f932815
--- /dev/null
+++ b/src/router/main/score/index.js
@@ -0,0 +1,9 @@
+const score = [
+ {
+ path: 'score',
+ name: '鎴愮哗鏌ヨ',
+ component: () => import('@/views/main/score/index.vue'),
+ },
+]
+
+export default score
\ No newline at end of file
diff --git a/src/utils/tool.js b/src/utils/tool.js
index 9826791..411e105 100644
--- a/src/utils/tool.js
+++ b/src/utils/tool.js
@@ -5,12 +5,12 @@
* @returns {string} 鍥剧墖鐨勫畬鏁碪RL
*/
export const getImageUrl = (imageName) => {
- try {
- return new URL('../assets/images/' + imageName, import.meta.url).href;
- } catch (error) {
- console.warn(`Failed to load image: ${imageName}`, error);
- return "";
- }
+ // 浣跨敤 Vite 鐨� glob 鍔熻兘鍔ㄦ�佸鍏ュ浘鐗囪祫婧�
+ const modules = import.meta.glob('../assets/images/**/*.{png,jpg,jpeg,gif,svg,webp}', { eager: true });
+ // 绉婚櫎寮�澶寸殑鏂滄潬
+ const cleanName = imageName.startsWith('/') ? imageName.slice(1) : imageName;
+ const path = `../assets/images/${cleanName}`;
+ return modules[path]?.default || '';
};
export const getUUID = () => {
let s = []
@@ -66,11 +66,39 @@
}
}
-export const getOccupationName = (code) => {
+export const getOccupationName = (id) => {
const { occupationItems } = useOptionItemsStore()
- const obj = occupationItems.find(ele => ele.code == code)
+ const obj = occupationItems.find(ele => ele.id == id)
- return obj?.name || ''
+ return obj?.occupationJob || ''
+}
+
+const levelKey = {
+ '5': '浜旂骇',
+ '4': '鍥涚骇',
+ '3': '涓夌骇',
+ '2': '浜岀骇',
+ '1': '涓�绾�'
+}
+
+export const getLevelItems = (occupationId) => {
+ const { occupationItems } = useOptionItemsStore()
+ const obj = occupationItems.find(ele => ele.id == occupationId)
+ if (!obj) return []
+ let levelItems = []
+ obj.levelStr.split(',').forEach(ele => {
+ levelItems.push({ name: levelKey[ele], value: ele },)
+ })
+ return levelItems || []
+}
+
+export const getLevelName = (levelStr) => {
+ let levelList = levelStr?.split(',') || []
+ let tempList = []
+ levelList.forEach(ele => {
+ tempList.push(levelKey[ele])
+ })
+ return tempList.join(',')
}
export const getJobName = (occupationCode, jobCode) => {
@@ -82,4 +110,9 @@
if (!job) return ''
return job.jobName || ''
+}
+
+export const getFileUrlName = (url = '') => {
+ const fullFilename = url.substring(url.lastIndexOf('/') + 1);
+ return fullFilename || ''
}
\ No newline at end of file
diff --git a/src/views/main/appraisalPlan/components/signupDialog.vue b/src/views/main/appraisalPlan/components/signupDialog.vue
new file mode 100644
index 0000000..ea3f84e
--- /dev/null
+++ b/src/views/main/appraisalPlan/components/signupDialog.vue
@@ -0,0 +1,190 @@
+<template>
+ <el-dialog
+ v-model="dialogFlag"
+ width="700"
+ title="濉啓鎶ュ悕淇℃伅"
+ align-center
+ :show-close="false"
+ :close-on-click-modal="false"
+ :close-on-press-escape="false"
+ >
+ <el-divider class="m-0"></el-divider>
+ <div class="py-7">
+ <el-row align="middle">
+ <el-col :span="3" style="display: flex; flex-direction: column; align-items: center;">
+ <el-row>
+ <el-tag round :color="active==1?'#0069ff':'#999999'" style="width: 36px;height: 36px;">
+ <el-text class="text-white text-lg">1</el-text>
+ </el-tag>
+ </el-row>
+ <el-row class="mt-1"><el-text :style="{color: active==1?'#0069ff':'#666666'}">濉啓璧勬枡</el-text></el-row>
+ </el-col>
+ <el-col :span="18">
+ <div style="width: 100%;border-top: 1px solid #c3c3c3; margin-top: -10px;"></div>
+ </el-col>
+ <el-col :span="3" style="display: flex; flex-direction: column; align-items: center;">
+ <el-row>
+ <el-tag round :color="active==2?'#0069ff':'#fff'" style="width: 36px;height: 36px;border-color: #999999;">
+ <el-text class="text-lg" :style="{color: active==2?'#fff':'#999999' }">2</el-text>
+ </el-tag>
+ </el-row>
+ <el-row class="mt-1"><el-text :style="{color: active==2?'#0069ff':'#666666'}">纭淇℃伅</el-text></el-row>
+ </el-col>
+ </el-row>
+ <el-form ref="form" :model="signupInfo" :rules="rules" class="pb-6">
+ <template v-if="active==1">
+ <contentTitle title="鑰冭瘯淇℃伅" />
+ <div class="px-3">
+ <el-form-item>
+ <el-text>璇勪环鑱屼笟锛�</el-text>
+ <el-text class="text-black">{{ signupInfo.occupationJob }}</el-text>
+ </el-form-item>
+ <el-form-item>
+ <el-text>璇勪环绛夌骇锛�</el-text>
+ <el-text class="text-black">{{ signupInfo.levelText }}</el-text>
+ </el-form-item>
+ </div>
+ <contentTitle title="鑰冭瘯绉戠洰" />
+ <div class="px-3">
+ <el-form-item label="绉戠洰" prop="subject">
+ <el-checkbox-group v-model="signupInfo.subject">
+ <el-checkbox
+ v-for="(subject,index) in subjectItems"
+ :key="`subject${index}`"
+ :label="subject.label"
+ :value="subject.value"
+ />
+ </el-checkbox-group>
+ </el-form-item>
+ </div>
+ <div class="px-3">
+ <el-form-item label="濮撳悕" prop="name" class="flex-1 mr-6">
+ <el-input v-model="signupInfo.name" />
+ </el-form-item>
+ <el-form-item label="鎬у埆" prop="gender" class="flex-1 mr-6">
+ <el-radio-group v-model="signupInfo.gender">
+ <el-radio :value="1">鐢�</el-radio>
+ <el-radio :value="2">濂�</el-radio>
+ </el-radio-group>
+ </el-form-item>
+ <el-form-item label="鎵嬫満鍙�" prop="mobilePhone" class="flex-1 mr-6">
+ <el-input v-model="signupInfo.mobilePhone" />
+ </el-form-item>
+ <el-form-item label="韬唤璇佸彿" prop="idNumber" class="flex-1 mr-6">
+ <el-input v-model="signupInfo.idNumber" />
+ </el-form-item>
+ </div>
+ </template>
+ <template v-else-if="active == 2">
+ <contentTitle title="鑰冭瘯淇℃伅" />
+ <div class="px-3">
+ <el-form-item>
+ <el-text>璇勪环鑱屼笟锛�</el-text>
+ <el-text class="text-black">{{ signupInfo.occupationJob }}</el-text>
+ </el-form-item>
+ <el-form-item>
+ <el-text>璇勪环绛夌骇锛�</el-text>
+ <el-text class="text-black">{{ signupInfo.levelText }}</el-text>
+ </el-form-item>
+ </div>
+ <contentTitle title="鑰冭瘯绉戠洰" />
+ </template>
+ </el-form>
+ </div>
+ <el-divider class="m-0"></el-divider>
+ <template #footer>
+ <el-row justify="end">
+ <el-button @click="close">鍙栨秷</el-button>
+ <el-button type="primary" @click="lastStep" v-if="active==2">涓婁竴姝�</el-button>
+ <el-button type="primary" @click="nextStep" v-if="active==1">涓嬩竴姝�</el-button>
+ <el-button type="primary" @click="confirm" :loading="confirmLoading" v-if="active==2">鎻愪氦鎶ュ悕</el-button>
+ </el-row>
+ </template>
+ </el-dialog>
+</template>
+<script>
+import contentTitle from '@/views/main/components/contentTitle.vue'
+export default {
+ components: {
+ contentTitle
+ },
+ data() {
+ return {
+ dialogFlag: false,
+ active: 1,
+ subjectItems: [
+ { label: '鐞嗚鐭ヨ瘑', value: 'theory' },
+ { label: '瀹炴搷鎶�鑳�', value: 'operation' }
+ ],
+ signupInfo: {
+ occupationJob: '浜掕仈缃戣惀閿�甯�',
+ levelText: '涓夌骇',
+ subject: [],
+ name: '榛勫┓濠�',
+ gender: 2,
+ mobilePhone: '13537710000',
+ idNumber: '445224200000000'
+ },
+ rules: {
+ subject: [ this.$rules.required() ],
+ name: [ this.$rules.required() ],
+ gender: [ this.$rules.required() ],
+ mobilePhone: [ this.$rules.required() ],
+ idNumber: [ this.$rules.required() ],
+ },
+ confirmLoading: false
+ }
+ },
+ props: {
+ modelValue: {
+ type: Boolean,
+ default: false
+ },
+ currentPlan: {
+ type: Object,
+ default: () => {
+ return {}
+ }
+ }
+ },
+ watch: {
+ modelValue(val) {
+ this.dialogFlag = val
+ },
+ dialogFlag(val) {
+ this.$emit('update:modelValue', val)
+ },
+ },
+ mounted() {
+
+ },
+ methods: {
+ lastStep() {
+ if (this.active == 2) {
+ this.active--
+ }
+ },
+ async nextStep() {
+ if (this.active == 1) {
+ // try {
+ // await this.$refs.form.validateField('code')
+ // } catch(error) {
+ // return
+ // }
+ }
+ this.active++
+ },
+ close() {
+ this.dialogFlag = false
+ },
+ confirm() {
+ this.dialogFlag = false
+ this.active = 1
+ this.$emit('signupSuccess')
+ }
+ }
+}
+</script>
+
+<style scoped>
+</style>
\ No newline at end of file
diff --git a/src/views/main/appraisalPlan/components/signupSuccessDialog.vue b/src/views/main/appraisalPlan/components/signupSuccessDialog.vue
new file mode 100644
index 0000000..50f7139
--- /dev/null
+++ b/src/views/main/appraisalPlan/components/signupSuccessDialog.vue
@@ -0,0 +1,63 @@
+<template>
+ <el-dialog
+ v-model="dialogFlag"
+ width="700"
+ title="鎶ュ悕鎴愬姛"
+ align-center
+ :show-close="false"
+ :close-on-click-modal="false"
+ :close-on-press-escape="false"
+ >
+ <el-divider class="m-0"></el-divider>
+ <div class="py-7">
+ <el-row justify="center">
+ <Icon icon="iconoir:check-circle-solid" width="70" height="70" style="color: #1ba53a" />
+ </el-row>
+ <el-row justify="center" class="mt-2">
+ <el-text class="text-black text-lg font-medium">鎻愪氦鎶ュ悕鎴愬姛锛岃鑰愬績绛夊緟瀹℃牳缁撴灉銆�</el-text>
+ </el-row>
+ <el-row justify="center" class="mt-2">
+ <el-text style="color: #666666;">瀹℃牳缁撴灉浼氫互鐭俊褰㈠紡鍙戦�佺粰鎮紝鎮ㄤ篃鍙互鍒般�愮敤鎴蜂腑蹇冦��-銆愭垜鐨勬姤鍚嶃�戞煡鐪嬪鏍哥粨鏋溿��</el-text>
+ </el-row>
+ </div>
+ <el-divider class="m-0"></el-divider>
+ <template #footer>
+ <el-row justify="end">
+ <el-button type="primary" @click="dialogFlag=false">濂界殑</el-button>
+ </el-row>
+ </template>
+ </el-dialog>
+</template>
+<script>
+export default {
+ components: {
+ },
+ data() {
+ return {
+ dialogFlag: false,
+ }
+ },
+ props: {
+ modelValue: {
+ type: Boolean,
+ default: false
+ },
+ },
+ watch: {
+ modelValue(val) {
+ this.dialogFlag = val
+ },
+ dialogFlag(val) {
+ this.$emit('update:modelValue', val)
+ },
+ },
+ mounted() {
+
+ },
+ methods: {
+ }
+}
+</script>
+
+<style scoped>
+</style>
\ No newline at end of file
diff --git a/src/views/main/appraisalPlan/index.vue b/src/views/main/appraisalPlan/index.vue
index 6624bc0..b7f0a51 100644
--- a/src/views/main/appraisalPlan/index.vue
+++ b/src/views/main/appraisalPlan/index.vue
@@ -8,7 +8,7 @@
<el-text class="text-title">璇勪环璁″垝</el-text>
</el-row>
- <el-row class="mt-5">
+ <el-row class="mt-5 custom-input">
<el-input
v-model="filter.keyword"
style="width: 739px;height: 70px;"
@@ -24,7 +24,7 @@
</div>
</div>
<div class="main-content py-4">
- <el-form-item label="绛夌骇锛�" class="mb-6">
+ <el-form-item label="绛夌骇锛�" class="mb-4">
<el-radio-group v-model="filter.level">
<el-radio
v-for="(item,index) in levelItems"
@@ -35,7 +35,7 @@
</el-radio>
</el-radio-group>
</el-form-item>
- <el-form-item label="鑰冪偣锛�" class="mb-6">
+ <el-form-item label="鑰冪偣锛�" class="mb-4">
<el-select v-model="filter.area" placeholder="绛涢�夊湴甯�" style="width: 240px">
<el-option
v-for="item in areaItems"
@@ -46,6 +46,38 @@
</el-select>
</el-form-item>
+ <div v-if="calendarFlag">
+ <el-row>
+ <el-text class="text-lg ">璇勪环璁″垝鏈堝巻</el-text>
+ </el-row>
+ <el-form-item class="my-2">
+ <el-select v-model="year" placeholder="绛涢�夊勾浠�" style="width: 240px">
+ <el-option
+ v-for="item in yearItems"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-table :data="monthList" border style="width: 100%" class="mb-6">
+ <el-table-column
+ v-for="(item,index) in monthHeaders"
+ :prop="item.value"
+ :label="item.label"
+ :key="`month${index}`"
+ align="center"
+ >
+ <template #default="{ row }">
+ <div v-if="row[item.value]">
+ <Icon icon="iconamoon:check-duotone" width="22" height="22" style="color: var(--el-color-primary)" />
+ </div>
+ <span v-else></span>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+
<el-table
:data="filterList"
table-layout="auto"
@@ -61,8 +93,24 @@
:align="item.align || 'start'"
:sortable="item.sortable"
>
- <template #signupTime="{ row }">
- {{ row }}
+ <template #default="{ row }">
+ <div v-if="item.value=='signupTime'">
+ <el-row>鎶ュ悕寮�濮嬫椂闂达細{{ row.startTime }}</el-row>
+ <el-row>鎶ュ悕缁撴潫鏃堕棿锛歿{ row.endTime }}</el-row>
+ </div>
+ <div v-if="item.value=='orgInfo'">
+ <el-row>鏈烘瀯鍚嶇О锛歿{ row.orgInfo.name }}</el-row>
+ <el-row>鏈烘瀯鑱旂郴浜猴細{{ row.orgInfo.concatName }}</el-row>
+ <el-row>鏈烘瀯鑱旂郴鏂瑰紡锛歿{ row.orgInfo.mobile }}</el-row>
+ </div>
+ <div v-if="item.value=='operation'">
+ <el-row @click="signup(row)">
+ <el-text v-if="row.signupFlag && userInfo.id">宸叉姤鍚�</el-text>
+ <el-text v-else tag="ins" class="text-primary cursor-p">
+ 鎶ュ悕鑰冭瘯
+ </el-text>
+ </el-row>
+ </div>
</template>
</el-table-column>
</el-table>
@@ -78,12 +126,38 @@
/>
</el-row>
</div>
+
+ <signupDialog
+ v-model="signupDialogVisible"
+ :currentPlan="currentPlan"
+ @signupSuccess="signupSuccessDialogVisible=true"
+ >
+ </signupDialog>
+
+ <signupSuccessDialog
+ v-model="signupSuccessDialogVisible"
+ ></signupSuccessDialog>
+
</div>
</template>
<script>
+import { useLoginStore } from '@/stores/login.js'
+import { useSessionStore } from '@/stores/session.js'
+import { storeToRefs } from 'pinia';
+import signupDialog from '@/views/main/appraisalPlan/components/signupDialog.vue'
+import signupSuccessDialog from '@/views/main/appraisalPlan/components/signupSuccessDialog.vue'
export default {
+ components: {
+ signupDialog,
+ signupSuccessDialog
+ },
+ setup() {
+ const { userInfo } = storeToRefs(useSessionStore())
+ const { loginDialogVisible } = storeToRefs(useLoginStore())
+ return { userInfo, loginDialogVisible }
+ },
data() {
return {
page: 1,
@@ -110,7 +184,7 @@
],
noticeList: [],
headers: [
- { label: '鑱屼笟锛堝伐绉嶏級鍚嶇О', value: 'occupationJob' },
+ { label: '鑱屼笟锛堝伐绉嶏級鍚嶇О', value: 'occupationJob'},
{ label: '绛夌骇', value: 'level' },
{ label: '鑰冪偣', value: 'examAddress' },
{ label: '璇勪环璁″垝鍚嶇О', value: 'planName', width: 150 },
@@ -118,7 +192,36 @@
{ label: '璇勪环鏈烘瀯淇℃伅', value: 'orgInfo' },
{ label: '鎿嶄綔', value: 'operation', align: 'center' },
],
- planList: []
+ planList: [],
+ calendarFlag: true,
+ year: '2025',
+ yearItems: [
+ { label: '2022骞�', value: '2022' },
+ { label: '2023骞�', value: '2023' },
+ { label: '2024骞�', value: '2024' },
+ { label: '2025骞�', value: '2025' },
+ { label: '2026骞�', value: '2026' },
+ ],
+ monthHeaders: [
+ { label: '1鏈�', value: '1' },
+ { label: '2鏈�', value: '2' },
+ { label: '3鏈�', value: '3' },
+ { label: '4鏈�', value: '4' },
+ { label: '5鏈�', value: '5' },
+ { label: '6鏈�', value: '6' },
+ { label: '7鏈�', value: '7' },
+ { label: '8鏈�', value: '8' },
+ { label: '9鏈�', value: '9' },
+ { label: '10鏈�', value: '10' },
+ { label: '11鏈�', value: '11' },
+ { label: '12鏈�', value: '12' },
+ ],
+ monthList: [
+ { 1: false, 2: false, 3: true, 4: true, 5: false, 6: false, 7: true, 8: false, 9: false, 10: true, 11: true, 12: false, }
+ ],
+ signupDialogVisible: false,
+ currentPlan: {},
+ signupSuccessDialogVisible: false
}
},
computed: {
@@ -146,7 +249,8 @@
name: '涓北甯傛妧甯堝闄�',
concatName: '鍚�*瀹�',
mobile: '13424571164'
- }
+ },
+ signupFlag: false
},
{
id: '2',
@@ -160,7 +264,8 @@
name: '涓北甯傛妧甯堝闄�',
concatName: '鍚�*瀹�',
mobile: '13424571164'
- }
+ },
+ signupFlag: true
},
{
id: '3',
@@ -188,7 +293,8 @@
name: '涓北甯傛妧甯堝闄�',
concatName: '鍚�*瀹�',
mobile: '13424571164'
- }
+ },
+ signupFlag: false
},
{
id: '5',
@@ -202,7 +308,8 @@
name: '涓北甯傛妧甯堝闄�',
concatName: '鍚�*瀹�',
mobile: '13424571164'
- }
+ },
+ signupFlag: false
},
{
id: '6',
@@ -216,12 +323,22 @@
name: '涓北甯傛妧甯堝闄�',
concatName: '鍚�*瀹�',
mobile: '13424571164'
- }
+ },
+ signupFlag: false
},
]
this.totalCount = 6
}, 400)
},
+ signup(item) {
+ if (this.userInfo.id) {
+ this.signupDialogVisible = true
+ this.currentPlan = item
+ } else {
+ this.loginDialogVisible = true
+ this.$message.primary('璇峰厛鐧诲綍')
+ }
+ }
}
}
@@ -233,7 +350,7 @@
background-repeat: no-repeat, no-repeat, repeat; /* 鍒嗗埆璁剧疆 */
background-size: cover;
}
-:deep(.el-input__inner) {
+.custom-input :deep(.el-input__inner) {
padding-left: 10px;
font-size: 18px;
}
diff --git a/src/views/main/center/index.vue b/src/views/main/center/index.vue
new file mode 100644
index 0000000..c2c52c9
--- /dev/null
+++ b/src/views/main/center/index.vue
@@ -0,0 +1,176 @@
+<template>
+ <div>
+ <div class="content-bg">
+ <div class="main-content" style="z-index: 10;">
+ <ReturnBtn></ReturnBtn>
+
+ <el-row>
+ <el-text class="text-title">涓汉涓績</el-text>
+ </el-row>
+
+ <el-card shadow="never" class="mt-4" :style="{ height: contentHeight + 'px'}">
+ <el-row style="height: 100%;">
+ <el-col :span="2">
+ <el-row
+ v-for="(tab,index) in tabList"
+ :key="`tab${index}`"
+ style="height: 50%;width: 100%;border-right: 1px solid #e4e7ed;"
+ justify="center"
+ align="middle"
+ class="cursor-p"
+ @click="activeTab=tab.value"
+ :class="{ 'active-tab': tab.value==activeTab }"
+ >
+ <div>
+ <el-row justify="center">
+ <Icon :icon="tab.iconName" width="24" height="24" :style="{color: tab.value==activeTab?'#0069FF':'#333333'}" />
+ </el-row>
+ <el-row class="mt-1 font-medium">{{ tab.label }}</el-row>
+ </div>
+ </el-row>
+ </el-col>
+ <el-col :span="22">
+ <div v-if="activeTab=='toExam'" class="p-4 px-6">
+ <el-row align="middle">
+ <el-text class="font-medium">濮撳悕锛歿{ form.name }}</el-text>
+ <el-button text class="ml-2">
+ <Icon icon="ix:pen-filled" width="18" height="18" style="color: black" />
+ </el-button>
+ </el-row>
+ <el-row align="middle">
+ <el-text class="font-medium">鎬у埆锛歿{ form.gender }}</el-text>
+ <el-button text class="ml-2">
+ <Icon icon="ix:pen-filled" width="18" height="18" style="color: black" />
+ </el-button>
+ </el-row>
+ <el-row align="middle">
+ <el-text class="font-medium">鎵嬫満鍙凤細{{ form.mobilePhone }}</el-text>
+ <el-button text class="ml-2">
+ <Icon icon="ix:pen-filled" width="18" height="18" style="color: black" />
+ </el-button>
+ </el-row>
+ <el-row align="middle">
+ <el-text class="font-medium">韬唤璇佸彿锛歿{ form.idCard }}</el-text>
+ <el-button text class="ml-2">
+ <Icon icon="ix:pen-filled" width="18" height="18" style="color: black" />
+ </el-button>
+ </el-row>
+ <el-row align="middle" class="mt-2">
+ <el-text class="font-medium">韬唤璇佹鍙嶉潰锛�</el-text>
+ </el-row>
+ <el-row>
+ <UploadIdCard v-model="form.idCardFace" :accept="['jpg', 'png']" type="face"></UploadIdCard>
+ <UploadIdCard v-model="form.idCardEmblem" :accept="['jpg', 'png']" type="emblem"></UploadIdCard>
+ </el-row>
+ <el-row align="middle" class="mt-2">
+ <el-text class="font-medium">璇佷功/鍑嗚�冭瘉澶村儚锛�</el-text>
+ </el-row>
+ <UploadBtn v-model="form.certificateAvatar" listType="picture-card" :accept="['jpg', 'png']" ></UploadBtn>
+
+ <el-row class="mt-5">
+ <el-text>缁戝畾寰俊锛氭殏鏈粦瀹氬井淇�</el-text>
+ <el-text tag="ins" class="ml-6 font-medium text-primary">鎵爜缁戝畾</el-text>
+ </el-row>
+ </div>
+ <div v-else-if="activeTab=='alreadyExam'">
+ <mySignup></mySignup>
+ </div>
+ </el-col>
+ </el-row>
+ </el-card>
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import UploadIdCard from '@/views/main/components/UploadIdCard.vue'
+import { useLoginStore } from '@/stores/login.js'
+import { useSessionStore } from '@/stores/session.js'
+import { storeToRefs } from 'pinia';
+import mySignup from '@/views/main/center/mySignup/index.vue'
+export default {
+ components: {
+ mySignup,
+ UploadIdCard,
+ },
+ setup() {
+ const { userInfo } = storeToRefs(useSessionStore())
+ const { loginDialogVisible } = storeToRefs(useLoginStore())
+ return { userInfo, loginDialogVisible }
+ },
+ data() {
+ return {
+ form: {
+ name: '榛勫┓濠�',
+ gender: '濂�',
+ mobilePhone: '13000000000',
+ idCard: '441481155511116622',
+ idCardFace: [],
+ idCardEmblem: [],
+ certificateAvatar: [],
+ },
+ tabList: [
+ { label: '涓汉淇℃伅', iconName: 'mdi:layers-triple', value: 'toExam' },
+ { label: '鎴戠殑鎶ュ悕', iconName: 'ant-design:file-search-outlined', value: 'alreadyExam' },
+ ],
+ activeTab: 'toExam',
+ contentHeight: 580,
+ examList: [],
+ searchKeyword: '',
+ }
+ },
+ computed: {
+
+ },
+ watch: {
+ activeTab: {
+ handler: function() {
+ this.getExamList()
+ },
+ immediate: true
+ }
+ },
+ created() {
+
+ },
+ methods: {
+ getExamList() {
+ if (this.activeTab == 'toExam') {
+ this.examList = [
+
+ ]
+ } else if (this.activeTab == 'alreadyExam') {
+ this.examList = [
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ ]
+ }
+ }
+ }
+}
+
+</script>
+<style scoped>
+.content-bg {
+ height: 240px;
+ background-image: url('@/assets/images/contentBg.png');
+ background-repeat: no-repeat, no-repeat, repeat; /* 鍒嗗埆璁剧疆 */
+ background-size: cover;
+}
+.active-tab {
+ background-color: #EEF5FF;
+ border: 1px solid #0069FF !important;
+ color: #0069FF !important;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/main/center/mySignup/index.vue b/src/views/main/center/mySignup/index.vue
new file mode 100644
index 0000000..8b7d2f9
--- /dev/null
+++ b/src/views/main/center/mySignup/index.vue
@@ -0,0 +1,71 @@
+<template>
+ <div class="p-4 px-2">
+ <el-row class="">
+ <Filtrate :filter="filter" :refresh="getList" :loadingFlag="ListLoadingFlag">
+ <el-row style="width: 100%;">
+ <el-select style="flex: 1;" class="mr-2" v-model="filter.status" placeholder="鍏ㄩ儴鐘舵��">
+ <el-option
+ v-for="item in statusItems"
+ :key="item.status"
+ :label="item.label"
+ :value="item.status"
+ />
+ </el-select>
+ <el-input
+ style="flex: 3;"
+ class="mr-2"
+ v-model="filter.search"
+ placeholder="鎼滅储璇勪环鏈烘瀯鍚嶇О/缁熶竴绀句細淇$敤浠g爜"
+ >
+ <template #prefix>
+ <el-icon class="el-input__icon"><search /></el-icon>
+ </template>
+ </el-input>
+ </el-row>
+ </Filtrate>
+ </el-row>
+ <DataTable
+ v-model:filter="filter"
+ :headers="headers"
+ :list="list"
+ :totalCount="totalCount"
+ ></DataTable>
+
+ </div>
+</template>
+
+<script>
+export default {
+ data() {
+ return {
+ filter: {
+ status: ''
+ },
+ statusItems: [
+ { label: '鍏ㄩ儴鐘舵��', status: '' },
+ { label: '瀹℃牳涓�', status: 'auditing' },
+ { label: '瀹℃牳涓嶉�氳繃', status: 'reject' },
+ { label: '瀹℃牳閫氳繃', status: 'pass' },
+ ],
+ headers: [
+ { label: '璇勪环璁″垝鍚嶇О', value: 'planName' },
+ { label: '鑱屼笟鍚嶇О', value: 'occupationJob' },
+ { label: '绛夌骇', value: 'level' },
+ { label: '鑰冪偣', value: 'address' },
+ { label: '鐘舵��', value: 'status' },
+ { label: '鎿嶄綔', value: 'operation' }
+ ],
+ ListLoadingFlag: false,
+ }
+ },
+ methods: {
+ getList() {
+
+ },
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>
\ No newline at end of file
diff --git a/src/views/main/certificate/index.vue b/src/views/main/certificate/index.vue
new file mode 100644
index 0000000..cf45d45
--- /dev/null
+++ b/src/views/main/certificate/index.vue
@@ -0,0 +1,202 @@
+<template>
+ <div>
+ <div class="content-bg">
+ <div class="main-content">
+ <ReturnBtn></ReturnBtn>
+
+ <el-row class="mt-6">
+ <el-text class="text-title">璇佷功鏌ヨ</el-text>
+ </el-row>
+ </div>
+ </div>
+ <div class="main-content py-4" style="margin-top: -130px;">
+ <el-card shadow="never" class="p-4" style="min-height: 500px;">
+ <el-form-item>
+ <el-input v-model="keyword" placeholder="鎼滅储鍏抽敭瀛�">
+ <template #prefix>
+ <el-icon class="el-input__icon"><search /></el-icon>
+ </template>
+ </el-input>
+ </el-form-item>
+ <el-card
+ v-for="(certificate,index) in certificateList"
+ :key="`certificate${index}`"
+ class="p-4 mb-4"
+ shadow="never"
+ >
+ <el-row justify="space-between" align="middle">
+ <div>
+ <el-row><el-text class="text-lg text-black font-medium">{{ certificate.occupationJob }}</el-text></el-row>
+ <el-row class="mt-2">
+ <el-text>{{ certificate.batch }}</el-text>
+ </el-row>
+ </div>
+ <div>
+ <el-button text style="background-color: #F0F7FF;">
+ <el-row class="mr-1">
+ <Icon icon="flowbite:eye-solid" width="20" height="20" style="color: #007AFF" />
+ </el-row>
+ <el-row class="text-primary">鏌ョ湅鍑嗚�冭瘉</el-row>
+ </el-button>
+ <el-button text style="background-color: #F0F7FF;">
+ <el-row class="mr-1">
+ <Icon icon="material-symbols:download" width="20" height="20" style="color: #007AFF" />
+ </el-row>
+ <el-row class="text-primary">涓嬭浇鍑嗚�冭瘉</el-row>
+ </el-button>
+ </div>
+ </el-row>
+ </el-card>
+ <el-row justify="center" v-if="certificateList.length==0">
+ <el-text>鏆傛棤鏁版嵁~</el-text>
+ </el-row>
+ </el-card>
+ </div>
+ </div>
+</template>
+
+<script>
+import { useLoginStore } from '@/stores/login.js'
+import { useSessionStore } from '@/stores/session.js'
+import { storeToRefs } from 'pinia';
+export default {
+ components: {
+
+ },
+ setup() {
+ const { userInfo } = storeToRefs(useSessionStore())
+ const { loginDialogVisible } = storeToRefs(useLoginStore())
+ return { userInfo, loginDialogVisible }
+ },
+ data() {
+ return {
+ certificateList: [],
+ keyword: '',
+ fieldList: [
+ { label: '濮撳悕', value: 'name' },
+ { label: '韬唤璇佸彿', value: 'idCard' },
+ { label: '鍑嗚�冭瘉鍙�', value: 'examCard' },
+ { label: '鐞嗚鐭ヨ瘑鎴愮哗', value: 'theoryScore' },
+ { label: '鎿嶄綔鎶�鑳芥垚缁�', value: 'operationScore' },
+ { label: '鎴愮哗鐘舵��', value: 'statusText' },
+ ]
+ }
+ },
+ computed: {},
+ watch: {
+ },
+ created() {
+ this.getCertificateList()
+ },
+ methods: {
+ getCertificateList() {
+ this.certificateList = [
+ {
+ id: 1,
+ occupationJob: '鐢靛伐锛堢淮淇數宸ワ級-鍥涚骇',
+ batch: '2025骞�12鏈堝叕鍏辫惀鍏诲笀绗�1鎵�',
+ name: '榛勫┓濠�',
+ idCard: '440203198906302518',
+ examCard: '250610110746092',
+ theoryScore: '--',
+ operationScore: '--',
+ status: 'auditing',
+ statusText: '鎴愮哗瀹℃牳涓�',
+ foldFlag: false
+ },
+ {
+ id: 2,
+ occupationJob: '鐢靛伐锛堢淮淇數宸ワ級-鍥涚骇',
+ batch: '2025骞�12鏈堝叕鍏辫惀鍏诲笀绗�1鎵�',
+ name: '榛勫┓濠�',
+ idCard: '440203198906302518',
+ examCard: '250610110746092',
+ theoryScore: '78鍒嗭紙鍚堟牸锛�',
+ operationScore: '85鍒嗭紙鍚堟牸锛�',
+ status: 'public',
+ statusText: '鎴愮哗鍏ず涓�',
+ foldFlag: true
+ },
+ {
+ id: 3,
+ occupationJob: '鐢靛伐锛堢淮淇數宸ワ級-鍥涚骇',
+ batch: '2025骞�12鏈堝叕鍏辫惀鍏诲笀绗�1鎵�',
+ name: '榛勫┓濠�',
+ idCard: '440203198906302518',
+ examCard: '250610110746092',
+ theoryScore: '78鍒嗭紙鍚堟牸锛�',
+ operationScore: '85鍒嗭紙鍚堟牸锛�',
+ status: 'effectiveness',
+ statusText: '鎴愮哗宸茬敓鏁�',
+ foldFlag: true
+ },
+ {
+ id: 4,
+ occupationJob: '鐢靛伐锛堢淮淇數宸ワ級-鍥涚骇',
+ batch: '2025骞�12鏈堝叕鍏辫惀鍏诲笀绗�1鎵�',
+ name: '榛勫┓濠�',
+ idCard: '440203198906302518',
+ examCard: '250610110746092',
+ theoryScore: '85鍒嗭紙鍚堟牸锛�',
+ operationScore: '78鍒嗭紙鍚堟牸锛�',
+ status: 'cancellation',
+ statusText: '鎴愮哗宸蹭綔搴�',
+ failReason: '杩濊浣滃紛',
+ foldFlag: true
+ },
+ {
+ id: 5,
+ occupationJob: '鐢靛伐锛堢淮淇數宸ワ級-鍥涚骇',
+ batch: '2025骞�12鏈堝叕鍏辫惀鍏诲笀绗�1鎵�',
+ name: '榛勫┓濠�',
+ idCard: '440203198906302518',
+ examCard: '250610110746092',
+ theoryScore: '85鍒嗭紙鍚堟牸锛�',
+ operationScore: '78鍒嗭紙鍚堟牸锛�',
+ status: 'cancellation',
+ statusText: '鎴愮哗宸蹭綔搴�',
+ failReason: '杩濊浣滃紛',
+ foldFlag: true
+ },
+ {
+ id: 6,
+ occupationJob: '鐢靛伐锛堢淮淇數宸ワ級-鍥涚骇',
+ batch: '2025骞�12鏈堝叕鍏辫惀鍏诲笀绗�1鎵�',
+ name: '榛勫┓濠�',
+ idCard: '440203198906302518',
+ examCard: '250610110746092',
+ theoryScore: '85鍒嗭紙鍚堟牸锛�',
+ operationScore: '78鍒嗭紙鍚堟牸锛�',
+ status: 'cancellation',
+ statusText: '鎴愮哗宸蹭綔搴�',
+ failReason: '杩濊浣滃紛',
+ foldFlag: true
+ },
+ ]
+ },
+ getStyle(status) {
+ let obj = {
+ auditing: '#007AFF',
+ public: '#FF9009',
+ effectiveness: '#1BA53A',
+ cancellation: '#FF4040',
+ }
+ return { color: obj[status] }
+ }
+ }
+}
+
+</script>
+<style scoped>
+.content-bg {
+ height: 240px;
+ background-image: url('@/assets/images/contentBg.png');
+ background-repeat: no-repeat, no-repeat, repeat; /* 鍒嗗埆璁剧疆 */
+ background-size: cover;
+}
+.active-tab {
+ background-color: #EEF5FF;
+ border: 1px solid #0069FF !important;
+ color: #0069FF !important;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/main/components/MyHeader.vue b/src/views/main/components/MyHeader.vue
index d3c54d0..4d65e5f 100644
--- a/src/views/main/components/MyHeader.vue
+++ b/src/views/main/components/MyHeader.vue
@@ -10,7 +10,7 @@
</el-row>
<template #dropdown>
<el-dropdown-menu>
- <el-dropdown-item>涓汉涓績</el-dropdown-item>
+ <el-dropdown-item @click="gotoCenter()">涓汉涓績</el-dropdown-item>
<el-dropdown-item @click="logout()">閫�鍑虹櫥褰�</el-dropdown-item>
</el-dropdown-menu>
</template>
@@ -57,6 +57,9 @@
})
}, 1000)
},
+ gotoCenter() {
+ this.$router.push('/main/center')
+ },
logout() {
this.$messageBox.confirm('纭畾瑕侀��鍑虹櫥褰曞悧', '鎻愮ず',
{ confirmButtonText: '纭畾', cancelButtonText: '鍙栨秷', type: 'error' }).then(res => {
diff --git a/src/views/main/components/UploadBtn.vue b/src/views/main/components/UploadBtn.vue
index 42bf5fa..0df0c52 100644
--- a/src/views/main/components/UploadBtn.vue
+++ b/src/views/main/components/UploadBtn.vue
@@ -77,12 +77,14 @@
</template>
<script>
+import { getFileUrlName } from '@/utils/tool.js'
const pdf = 'application/pdf'
const xls = 'application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
const doc = 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document'
const image = 'image/*'
const jpg = 'image/jpeg'
const png = 'image/png'
+const zip = 'application/zip,application/x-zip-compressed'
import { genFileId } from 'element-plus'
export default {
data() {
@@ -101,7 +103,7 @@
accept: {
type: Array,
default: () => {
- return ['pdf', 'xls', 'doc', 'image', 'jpg', 'png']
+ return ['pdf', 'xls', 'doc', 'image', 'jpg', 'png', 'zip']
}
},
limitFileCount: {
@@ -123,19 +125,26 @@
modelValue: {
handler: function() {
this.list = this.modelValue
+ this.list.forEach(ele => {
+ if (!ele.name) {
+ ele.name = getFileUrlName(ele.url)
+ }
+ })
},
+ immediate: true,
deep: true
},
list: {
handler: function(val) {
this.$emit('update:modelValue', val)
},
+ immediate: true,
deep: true
}
},
computed: {
acceptType() {
- let obj = { pdf, xls, doc, image, jpg, png }
+ let obj = { pdf, xls, doc, image, jpg, png, zip }
return this.accept.map(ele => obj[ele]).join(',')
},
tip() {
@@ -145,7 +154,8 @@
doc: 'WORD',
image: '鍥剧墖',
jpg: 'JPEG/JPG',
- png: 'PNG'
+ png: 'PNG',
+ zip: 'ZIP'
}
let tip = this.accept.map(ele => obj[ele]).join('銆�')
return `鏀寔${tip}绫诲瀷鏂囦欢`
diff --git a/src/views/main/components/UploadIdCard.vue b/src/views/main/components/UploadIdCard.vue
new file mode 100644
index 0000000..924684c
--- /dev/null
+++ b/src/views/main/components/UploadIdCard.vue
@@ -0,0 +1,239 @@
+<template>
+ <el-upload
+ ref="upload"
+ class="my-3 mr-4" action="#"
+ v-model:file-list="list"
+ :accept="acceptType"
+ list-type="picture-card"
+ :http-request="uploadRequest"
+ :multiple="true"
+ :limit="limitFileCount"
+ :on-preview="handlePreview"
+ :on-remove="handleRemove"
+ :before-remove="beforeRemove"
+ :on-exceed="handleExceed"
+ :disabled="disabled"
+ :class="{ hideUpload: hideUpload }"
+ >
+ <template #default>
+ <el-image
+ ref="backgroundImg"
+ :src="$getImageUrl(`/uploadBox/${type}.png`)"
+ >
+ </el-image>
+ </template>
+ <template #file="{ file, index }">
+ <el-image
+ ref="previewImg"
+ :src="file.url"
+ :initial-index="initialPreviewImgIndex"
+ :preview-src-list="filterPreviewImgList"
+ >
+ </el-image>
+ <span class="el-upload-list__item-actions">
+ <span @click="previewImage(index)">
+ <el-icon><zoom-in /></el-icon>
+ </span>
+ <!-- <span @click="replaceUpload(index)">
+ <el-icon><upload /></el-icon>
+ </span> -->
+ <span @click="deleteFileItem(index)">
+ <el-icon><delete /></el-icon>
+ </span>
+ </span>
+ </template>
+ </el-upload>
+ <el-dialog v-model="imgPreviewDialogFlag">
+ <img w-full :src="previewUrl" alt="Preview Image" />
+ </el-dialog>
+</template>
+
+<script>
+import { getFileUrlName } from '@/utils/tool.js'
+const pdf = 'application/pdf'
+const xls = 'application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+const doc = 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document'
+const image = 'image/*'
+const jpg = 'image/jpeg'
+const png = 'image/png'
+import { genFileId } from 'element-plus'
+export default {
+ data() {
+ return {
+ list: [],
+ imgPreviewDialogFlag: false,
+ previewUrl: '',
+ initialPreviewImgIndex: 0
+ }
+ },
+ props: {
+ listType: {
+ type: String,
+ default: 'text'
+ },
+ accept: {
+ type: Array,
+ default: () => {
+ return ['image', 'jpg', 'png']
+ }
+ },
+ limitFileCount: {
+ type: Number,
+ default: 1
+ },
+ modelValue: {
+ type: Array,
+ default: () => {
+ return []
+ }
+ },
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ type: {
+ type: String,
+ default: 'face'
+ }
+ },
+ watch: {
+ modelValue: {
+ handler: function() {
+ this.list = this.modelValue
+ this.list.forEach(ele => {
+ if (!ele.name) {
+ ele.name = getFileUrlName(ele.url)
+ }
+ })
+ },
+ immediate: true,
+ deep: true
+ },
+ list: {
+ handler: function(val) {
+ this.$emit('update:modelValue', val)
+ },
+ immediate: true,
+ deep: true
+ }
+ },
+ computed: {
+ acceptType() {
+ let obj = { pdf, xls, doc, image, jpg, png }
+ return this.accept.map(ele => obj[ele]).join(',')
+ },
+ tip() {
+ let obj = {
+ pdf: 'PDF',
+ xls: 'EXCEL',
+ doc: 'WORD',
+ image: '鍥剧墖',
+ jpg: 'JPEG/JPG',
+ png: 'PNG'
+ }
+ let tip = this.accept.map(ele => obj[ele]).join('銆�')
+ return `鏀寔${tip}绫诲瀷鏂囦欢`
+ },
+ againUploadFlag() {
+ return this.limitFileCount == 1 && this.list.length == 1
+ },
+ filterPreviewImgList() {
+ let list = this.list.map(ele => ele.url )
+ return list
+ },
+ hideUpload() {
+ return this.list.length >= this.limitFileCount
+ }
+ },
+ methods: {
+ uploadRequest(UploadRequestOptions) {
+ const data = {
+ file: UploadRequestOptions.file,
+ directory: ''
+ }
+ this.$axios.post('/infra/file/upload', data, {
+ headers: { 'Content-Type': "multipart/form-data" }
+ }).then(res => {
+ let index = this.list.findIndex(ele => ele.uid == data.file.uid)
+ if (res.data.code == 0) {
+ let index = this.list.findIndex(ele => ele.uid == data.file.uid)
+ if (index != -1) {
+ this.list[index].uploadStatus = 'success'
+ this.list[index].url = res.data.data
+ }
+ this.$message.success('涓婁紶鎴愬姛')
+ } else {
+ if (index != -1) {
+ this.list[index].uploadStatus = 'fail'
+ }
+ this.$message.error(res.data.msg || '涓婁紶澶辫触')
+ }
+ })
+ },
+ deleteFileItem(index) {
+ this.list.splice(index, 1)
+ },
+ previewImage(index) {
+ this.initialPreviewImgIndex = index
+ this.$refs.previewImg?.showPreview()
+ },
+ replaceUpload() {
+
+ },
+ handleRemove() {},
+ beforeRemove() {},
+ handlePreview() {},
+ handleExceed(file) {
+ if (this.againUploadFlag) {
+ this.$refs.upload?.clearFiles()
+ let newFile = file[0]
+ newFile.uid = genFileId()
+ this.$refs.upload?.handleStart(newFile)
+ this.$refs.upload?.submit()
+ } else {
+ this.$message.error(`鏈�澶氭敮鎸佷笂浼� ${this.limitFileCount} 涓枃浠禶)
+ }
+ }
+ }
+}
+</script>
+
+<style scoped>
+.hideUpload :deep(.el-upload--picture-card) {
+ display: none !important;
+}
+.file-box {
+ display: flex;
+ color: #007AFF;
+ align-content: center;
+ background-color: #ECF5FF;
+ padding: 8px;
+ font-size: 15px;
+ line-height: 16px;
+}
+
+:deep(.el-upload--picture-card), :deep(.el-upload-list__item) {
+ width: 160px !important;
+ height: 90px !important;
+ padding: 1px 0;
+}
+
+.el-upload-list__item-actions {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.5); /* 鍗婇�忔槑榛戣壊钂欑増 */
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ opacity: 0; /* 榛樿閫忔槑 */
+ transition: opacity .3s; /* 娣诲姞杩囨浮鍔ㄧ敾鏁堟灉 */
+}
+
+/* 榧犳爣鎮仠鏃舵樉绀鸿挋鐗� */
+.el-upload-list__item:hover .el-upload-list__item-actions {
+ opacity: 1;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/main/examTicket/index.vue b/src/views/main/examTicket/index.vue
new file mode 100644
index 0000000..c90f0da
--- /dev/null
+++ b/src/views/main/examTicket/index.vue
@@ -0,0 +1,170 @@
+<template>
+ <div>
+ <div class="content-bg">
+ <div class="main-content" style="z-index: 10;">
+ <ReturnBtn></ReturnBtn>
+
+ <el-row class="mt-6">
+ <el-text class="text-title">鍑嗚�冭瘉鏌ヨ</el-text>
+ </el-row>
+
+ <el-card shadow="never" class="mt-6" :style="{ height: contentHeight + 'px'}">
+ <el-row style="height: 100%;">
+ <el-col :span="2">
+ <el-row
+ v-for="(tab,index) in tabList"
+ :key="`tab${index}`"
+ style="height: 50%;width: 100%;border-right: 1px solid #e4e7ed;"
+ justify="center"
+ align="middle"
+ class="cursor-p"
+ @click="activeTab=tab.value"
+ :class="{ 'active-tab': tab.value==activeTab }"
+ >
+ <div>
+ <el-row justify="center">
+ <Icon :icon="tab.iconName" width="24" height="24" :style="{color: tab.value==activeTab?'#0069FF':'#333333'}" />
+ </el-row>
+ <el-row class="mt-1 font-medium">{{ tab.label }}</el-row>
+ </div>
+ </el-row>
+ </el-col>
+ <el-col :span="22">
+ <el-row class="p-4 text-primary font-medium" justify="space-between">
+ <span>鍏� {{ examList.length }} 涓噯鑰冭瘉</span>
+ <el-form-item class="mb-0">
+ <el-input v-model="searchKeyword" placeholder="鎼滅储鍏抽敭瀛�">
+ <template #append>
+ <el-button>鏌ヨ</el-button>
+ </template>
+ </el-input>
+ </el-form-item>
+ </el-row>
+ <el-divider class="m-0"></el-divider>
+ <el-scrollbar ref="scrollbarRef" class="p-4" :style="{ height: (contentHeight - 70) + 'px'}" always>
+ <el-card
+ v-for="(exam,index) in examList"
+ :key="`exam${index}`"
+ class="p-4 mb-4"
+ shadow="never"
+ >
+ <el-row justify="space-between" align="middle">
+ <div>
+ <el-row><el-text class="text-lg text-black font-medium">{{ exam.occupationJob }}</el-text></el-row>
+ <el-row class="mt-2">
+ <el-text>{{ exam.batch }}</el-text>
+ </el-row>
+ </div>
+ <div>
+ <el-button text style="background-color: #F0F7FF;">
+ <el-row class="mr-1">
+ <Icon icon="flowbite:eye-solid" width="20" height="20" style="color: #007AFF" />
+ </el-row>
+ <el-row class="text-primary">鏌ョ湅鍑嗚�冭瘉</el-row>
+ </el-button>
+ <el-button text style="background-color: #F0F7FF;">
+ <el-row class="mr-1">
+ <Icon icon="material-symbols:download" width="20" height="20" style="color: #007AFF" />
+ </el-row>
+ <el-row class="text-primary">涓嬭浇鍑嗚�冭瘉</el-row>
+ </el-button>
+ </div>
+ </el-row>
+ </el-card>
+ <el-row justify="center" v-if="examList.length==0">
+ <el-text>鏆傛棤鏁版嵁~</el-text>
+ </el-row>
+ </el-scrollbar>
+ </el-col>
+ </el-row>
+
+ </el-card>
+ </div>
+ </div>
+ <div class="main-content py-4">
+
+ </div>
+
+ </div>
+
+</template>
+
+<script>
+import { useLoginStore } from '@/stores/login.js'
+import { useSessionStore } from '@/stores/session.js'
+import { storeToRefs } from 'pinia';
+export default {
+ components: {
+
+ },
+ setup() {
+ const { userInfo } = storeToRefs(useSessionStore())
+ const { loginDialogVisible } = storeToRefs(useLoginStore())
+ return { userInfo, loginDialogVisible }
+ },
+ data() {
+ return {
+ tabList: [
+ { label: '寰呰�冭瘯', iconName: 'gravity-ui:pencil-to-line', value: 'toExam' },
+ { label: '宸茶�冭瘯', iconName: 'ic:round-history', value: 'alreadyExam' },
+ ],
+ activeTab: 'toExam',
+ contentHeight: 530,
+ examList: [],
+ searchKeyword: '',
+ }
+ },
+ computed: {
+
+ },
+ watch: {
+ activeTab: {
+ handler: function() {
+ this.getExamList()
+ },
+ immediate: true
+ }
+ },
+ created() {
+
+ },
+ methods: {
+ getExamList() {
+ if (this.activeTab == 'toExam') {
+ this.examList = [
+
+ ]
+ } else if (this.activeTab == 'alreadyExam') {
+ this.examList = [
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ { occupationJob: '鑱屼笟鍩硅甯�-浜岀骇', batch: '2025骞�12鏈堣亴涓氬煿璁笀绗竴鎵�' },
+ ]
+ }
+ }
+ }
+}
+
+</script>
+<style scoped>
+.content-bg {
+ height: 240px;
+ background-image: url('@/assets/images/contentBg.png');
+ background-repeat: no-repeat, no-repeat, repeat; /* 鍒嗗埆璁剧疆 */
+ background-size: cover;
+}
+.active-tab {
+ background-color: #EEF5FF;
+ border: 1px solid #0069FF !important;
+ color: #0069FF !important;
+}
+</style>
\ No newline at end of file
diff --git a/src/views/main/home/index.vue b/src/views/main/home/index.vue
index 850d37d..2cae64e 100644
--- a/src/views/main/home/index.vue
+++ b/src/views/main/home/index.vue
@@ -54,7 +54,15 @@
</template>
<script>
+import { useLoginStore } from '@/stores/login.js'
+import { useSessionStore } from '@/stores/session.js'
+import { storeToRefs } from 'pinia';
export default {
+ setup() {
+ const { userInfo } = storeToRefs(useSessionStore())
+ const { loginDialogVisible } = storeToRefs(useLoginStore())
+ return { userInfo, loginDialogVisible }
+ },
data() {
return {
operationList: [
@@ -114,6 +122,11 @@
this.$router.push('/main/noticeList')
},
goOperationPage(item) {
+ if (item.value != 'appraisalPlan' && !this.userInfo.id) {
+ this.loginDialogVisible = true
+ this.$message.primary('璇峰厛鐧诲綍')
+ return
+ }
this.$router.push(`/main/${item.value}`)
}
}
diff --git a/src/views/main/notice/list.vue b/src/views/main/notice/list.vue
index 2c1f9d9..dfa8219 100644
--- a/src/views/main/notice/list.vue
+++ b/src/views/main/notice/list.vue
@@ -8,7 +8,7 @@
<el-text class="text-title">閫氱煡鍏憡</el-text>
</el-row>
- <el-row class="mt-5">
+ <el-row class="mt-5 custom-input">
<el-input
v-model="filter.keyword"
style="width: 739px;height: 70px;"
@@ -185,7 +185,7 @@
background-repeat: no-repeat, no-repeat, repeat; /* 鍒嗗埆璁剧疆 */
background-size: cover;
}
-:deep(.el-input__inner) {
+.custom-input :deep(.el-input__inner) {
padding-left: 10px;
font-size: 18px;
}
diff --git a/src/views/main/score/index.vue b/src/views/main/score/index.vue
new file mode 100644
index 0000000..e9d4ebf
--- /dev/null
+++ b/src/views/main/score/index.vue
@@ -0,0 +1,182 @@
+<template>
+ <div>
+ <div class="content-bg">
+ <div class="main-content">
+ <ReturnBtn></ReturnBtn>
+
+ <el-row class="mt-6">
+ <el-text class="text-title">鎴愮哗鏌ヨ</el-text>
+ </el-row>
+ </div>
+ </div>
+ <div class="main-content py-4" style="margin-top: -130px;">
+ <el-card shadow="never" class="p-4" style="min-height: 500px;">
+ <el-form-item>
+ <el-input v-model="keyword" placeholder="鎼滅储鍏抽敭瀛�">
+ <template #prefix>
+ <el-icon class="el-input__icon"><search /></el-icon>
+ </template>
+ </el-input>
+ </el-form-item>
+ <div v-for="(score,index) in scoreList"
+ class="mt-3"
+ :key="`scoreCard${index}`"
+ style="border-radius: 5px;"
+ :style="{ border: `1px solid ${score.foldFlag?'#dcdcdc':'#007aff'}` }"
+ >
+ <el-card shadow="never" class="p-3 cursor-p" style="background: #F7F7F7;border: none;" @click="score.foldFlag=!score.foldFlag">
+ <el-row justify="space-between" align="middle">
+ <div>
+ <el-row><el-text class="text-lg text-black font-medium">{{ score.occupationJob }}</el-text></el-row>
+ <el-row class="mt-1">
+ <el-text>{{ score.batch }}</el-text>
+ </el-row>
+ </div>
+ <Icon v-if="score.foldFlag" icon="mingcute:down-line" width="22" height="22" style="color: #333333" />
+ <Icon v-else icon="mingcute:up-line" width="22" height="22" style="color: #007AFF" />
+ </el-row>
+ </el-card>
+ <div v-if="!score.foldFlag" class="px-4">
+ <el-row v-for="(field,index) in fieldList"
+ style="border-bottom: 1px solid #DCDCDC;"
+ class="py-4"
+ :key="`field${index}`"
+ >
+ <el-text style="width: 170px;color: #666666;" class="font-medium">{{ field.label }}</el-text>
+ <el-text v-if="field.value == 'statusText'" class="font-medium">
+ <div style="display: flex;flex-direction: column;">
+ <el-text :style="getStyle(score.status)" style="align-self: start;">{{ score.statusText }}</el-text>
+ <el-text v-if="score.status=='cancellation'">浣滃簾鍘熷洜锛歿{ score.failReason }}</el-text>
+ </div>
+ </el-text>
+ <el-text v-else class=" text-black font-medium">{{score[field.value]}}</el-text>
+ </el-row>
+ </div>
+ </div>
+ <el-row justify="center" v-if="scoreList.length==0">
+ <el-text>鏆傛棤鏁版嵁~</el-text>
+ </el-row>
+ </el-card>
+ </div>
+ </div>
+</template>
+
+<script>
+import { useLoginStore } from '@/stores/login.js'
+import { useSessionStore } from '@/stores/session.js'
+import { storeToRefs } from 'pinia';
+export default {
+ components: {
+
+ },
+ setup() {
+ const { userInfo } = storeToRefs(useSessionStore())
+ const { loginDialogVisible } = storeToRefs(useLoginStore())
+ return { userInfo, loginDialogVisible }
+ },
+ data() {
+ return {
+ scoreList: [],
+ keyword: '',
+ fieldList: [
+ { label: '濮撳悕', value: 'name' },
+ { label: '韬唤璇佸彿', value: 'idCard' },
+ { label: '鍑嗚�冭瘉鍙�', value: 'examCard' },
+ { label: '鐞嗚鐭ヨ瘑鎴愮哗', value: 'theoryScore' },
+ { label: '鎿嶄綔鎶�鑳芥垚缁�', value: 'operationScore' },
+ { label: '鎴愮哗鐘舵��', value: 'statusText' },
+ ]
+ }
+ },
+ computed: {
+
+ },
+ watch: {
+ },
+ created() {
+ this.getScoreList()
+ },
+ methods: {
+ getScoreList() {
+ this.scoreList = [
+ {
+ id: 1,
+ occupationJob: '鐢靛伐锛堢淮淇數宸ワ級-鍥涚骇',
+ batch: '2025骞�12鏈堝叕鍏辫惀鍏诲笀绗�1鎵�',
+ name: '榛勫┓濠�',
+ idCard: '440203198906302518',
+ examCard: '250610110746092',
+ theoryScore: '--',
+ operationScore: '--',
+ status: 'auditing',
+ statusText: '鎴愮哗瀹℃牳涓�',
+ foldFlag: false
+ },
+ {
+ id: 2,
+ occupationJob: '鐢靛伐锛堢淮淇數宸ワ級-鍥涚骇',
+ batch: '2025骞�12鏈堝叕鍏辫惀鍏诲笀绗�1鎵�',
+ name: '榛勫┓濠�',
+ idCard: '440203198906302518',
+ examCard: '250610110746092',
+ theoryScore: '78鍒嗭紙鍚堟牸锛�',
+ operationScore: '85鍒嗭紙鍚堟牸锛�',
+ status: 'public',
+ statusText: '鎴愮哗鍏ず涓�',
+ foldFlag: true
+ },
+ {
+ id: 3,
+ occupationJob: '鐢靛伐锛堢淮淇數宸ワ級-鍥涚骇',
+ batch: '2025骞�12鏈堝叕鍏辫惀鍏诲笀绗�1鎵�',
+ name: '榛勫┓濠�',
+ idCard: '440203198906302518',
+ examCard: '250610110746092',
+ theoryScore: '78鍒嗭紙鍚堟牸锛�',
+ operationScore: '85鍒嗭紙鍚堟牸锛�',
+ status: 'effectiveness',
+ statusText: '鎴愮哗宸茬敓鏁�',
+ foldFlag: true
+ },
+ {
+ id: 4,
+ occupationJob: '鐢靛伐锛堢淮淇數宸ワ級-鍥涚骇',
+ batch: '2025骞�12鏈堝叕鍏辫惀鍏诲笀绗�1鎵�',
+ name: '榛勫┓濠�',
+ idCard: '440203198906302518',
+ examCard: '250610110746092',
+ theoryScore: '85鍒嗭紙鍚堟牸锛�',
+ operationScore: '78鍒嗭紙鍚堟牸锛�',
+ status: 'cancellation',
+ statusText: '鎴愮哗宸蹭綔搴�',
+ failReason: '杩濊浣滃紛',
+ foldFlag: true
+ },
+ ]
+ },
+ getStyle(status) {
+ let obj = {
+ auditing: '#007AFF',
+ public: '#FF9009',
+ effectiveness: '#1BA53A',
+ cancellation: '#FF4040',
+ }
+ return { color: obj[status] }
+ }
+ }
+}
+
+</script>
+<style scoped>
+.content-bg {
+ height: 240px;
+ background-image: url('@/assets/images/contentBg.png');
+ background-repeat: no-repeat, no-repeat, repeat; /* 鍒嗗埆璁剧疆 */
+ background-size: cover;
+}
+.active-tab {
+ background-color: #EEF5FF;
+ border: 1px solid #0069FF !important;
+ color: #0069FF !important;
+}
+</style>
\ No newline at end of file
--
Gitblit v1.8.0