|
|
@@ -33,6 +33,24 @@
|
|
|
<el-tag :type="authStatusTagType">
|
|
|
{{ authStatusLabel }}
|
|
|
</el-tag>
|
|
|
+ <el-button
|
|
|
+ v-if="userStore.state.authStatus === 'UNAUTHENTICATED'"
|
|
|
+ size="small"
|
|
|
+ type="primary"
|
|
|
+ style="margin-left: 12px"
|
|
|
+ @click="dialogVisible = true"
|
|
|
+ >
|
|
|
+ 提交实名认证
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ v-else-if="userStore.state.authStatus && userStore.state.authStatus !== 'PENDING' && userStore.state.authStatus !== 'AUTHENTICATED'"
|
|
|
+ size="small"
|
|
|
+ type="warning"
|
|
|
+ style="margin-left: 12px"
|
|
|
+ @click="dialogVisible = true"
|
|
|
+ >
|
|
|
+ 重新提交认证
|
|
|
+ </el-button>
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
|
|
|
@@ -43,17 +61,44 @@
|
|
|
<el-button @click="router.push('/profile/password')">修改密码</el-button>
|
|
|
</div>
|
|
|
</el-card>
|
|
|
+
|
|
|
+ <el-dialog v-model="dialogVisible" title="实名认证" width="420px" :close-on-click-modal="false">
|
|
|
+ <el-form label-width="100px">
|
|
|
+ <el-form-item label="校园卡照片">
|
|
|
+ <el-upload
|
|
|
+ ref="uploadRef"
|
|
|
+ v-model:file-list="cardFileList"
|
|
|
+ :auto-upload="false"
|
|
|
+ list-type="picture-card"
|
|
|
+ :limit="1"
|
|
|
+ :on-change="onCardChange"
|
|
|
+ :before-upload="beforeCardUpload"
|
|
|
+ >
|
|
|
+ <el-icon><Plus /></el-icon>
|
|
|
+ </el-upload>
|
|
|
+ <div class="upload-hint">上传校园卡照片用于实名审核</div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="handleCancelAuth">取消</el-button>
|
|
|
+ <el-button type="primary" :loading="submitting" @click="handleSubmitAuth">提交</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { ref, computed } from 'vue'
|
|
|
-import { useRouter } from 'vue-router'
|
|
|
+import { ref, computed, onMounted } from 'vue'
|
|
|
+import { useRouter, useRoute } from 'vue-router'
|
|
|
import { ElMessage } from 'element-plus'
|
|
|
+import { Plus } from '@element-plus/icons-vue'
|
|
|
+import type { UploadFile, UploadRawFile, UploadUserFile } from 'element-plus'
|
|
|
import { useUserStore } from '../store'
|
|
|
import { getUsers } from '../api/endpoints/users'
|
|
|
+import { getAuth } from '../api/endpoints/auth'
|
|
|
|
|
|
const router = useRouter()
|
|
|
+const route = useRoute()
|
|
|
const userStore = useUserStore()
|
|
|
const fileInputRef = ref<HTMLInputElement | null>(null)
|
|
|
const nickname = ref(userStore.state.nickname)
|
|
|
@@ -61,6 +106,11 @@ const signature = ref('')
|
|
|
const avatarFile = ref<File | null>(null)
|
|
|
const saving = ref(false)
|
|
|
|
|
|
+const dialogVisible = ref(false)
|
|
|
+const cardFile = ref<File | null>(null)
|
|
|
+const cardFileList = ref<UploadUserFile[]>([])
|
|
|
+const submitting = ref(false)
|
|
|
+
|
|
|
const authStatusTagType = computed(() => {
|
|
|
const map: Record<string, string> = {
|
|
|
AUTHENTICATED: 'success',
|
|
|
@@ -79,6 +129,52 @@ const authStatusLabel = computed(() => {
|
|
|
return map[userStore.state.authStatus] || userStore.state.authStatus
|
|
|
})
|
|
|
|
|
|
+const onCardChange = (file: UploadFile) => {
|
|
|
+ if (file.raw) cardFile.value = file.raw as UploadRawFile
|
|
|
+}
|
|
|
+
|
|
|
+const beforeCardUpload = (file: UploadRawFile) => {
|
|
|
+ if (!file.type.startsWith('image/')) {
|
|
|
+ ElMessage.error('只能上传图片')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ if (file.size > 10 * 1024 * 1024) {
|
|
|
+ ElMessage.error('图片大小不能超过 10MB')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+const handleCancelAuth = () => {
|
|
|
+ dialogVisible.value = false
|
|
|
+ cardFile.value = null
|
|
|
+ cardFileList.value = []
|
|
|
+}
|
|
|
+
|
|
|
+const handleSubmitAuth = async () => {
|
|
|
+ if (!cardFile.value) {
|
|
|
+ ElMessage.warning('请上传校园卡照片')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ submitting.value = true
|
|
|
+ try {
|
|
|
+ const res = await getAuth().submitAuth({ campusCardImage: cardFile.value })
|
|
|
+ if (res.code === 200) {
|
|
|
+ userStore.updateAuthStatus('PENDING')
|
|
|
+ ElMessage.success('提交成功,等待管理员审核')
|
|
|
+ dialogVisible.value = false
|
|
|
+ cardFile.value = null
|
|
|
+ cardFileList.value = []
|
|
|
+ }
|
|
|
+ } catch (err: unknown) {
|
|
|
+ if (err && typeof err === 'object' && 'message' in err) {
|
|
|
+ ElMessage.error((err as { message: string }).message)
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ submitting.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
const triggerUpload = () => {
|
|
|
fileInputRef.value?.click()
|
|
|
}
|
|
|
@@ -90,6 +186,12 @@ const handleAvatarChange = (event: Event) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+onMounted(() => {
|
|
|
+ if (route.query.verify === '1') {
|
|
|
+ dialogVisible.value = true
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
const handleSave = async () => {
|
|
|
saving.value = true
|
|
|
try {
|
|
|
@@ -139,4 +241,9 @@ const handleSave = async () => {
|
|
|
gap: 12px;
|
|
|
justify-content: center;
|
|
|
}
|
|
|
+.upload-hint {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ margin-top: 8px;
|
|
|
+}
|
|
|
</style>
|