体育直播平台专家认证身份审核逻辑功能技术实现,涵盖前后端各个模块

简介: 体育直播系统引入“专家认证”机制,确保内容专业性和可信度。用户申请成为解说嘉宾、分析师或主播需经过严格身份审核。通过认证的专家可发布赛事预测(收费)、动态、视频等内容,并享有专属权限。系统包含数据库设计、PHP管理端实现、Java Android客户端及Vue.js网页端开发,支持多端操作与自动化审核流程,提升管理效率和用户体验。

一、功能概述

为保障体育直播平台内容的专业性与可信度,“东莞梦幻网络科技” 体育直播系统引入“专家认证”机制,对申请成为解说嘉宾、分析师或主播的用户进行严格身份审核。通过认证的专家将获得“专家标识”并享有专属权限,如发布赛事预测方案(可设置收费)、专家动态、专家视频、发起专家资讯等。
专家申请-–-1.png

二、数据库设计 (MySQL)

-- 用户基础表
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(255) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    phone VARCHAR(20),
    avatar VARCHAR(255),
    status TINYINT DEFAULT 1 COMMENT '1-正常, 0-禁用',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- 专家申请表
CREATE TABLE expert_applications (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    real_name VARCHAR(50) NOT NULL,
    id_card VARCHAR(20) NOT NULL,
    id_card_front VARCHAR(255) NOT NULL COMMENT '身份证正面照片URL',
    id_card_back VARCHAR(255) NOT NULL COMMENT '身份证反面照片URL',
    qualification_cert VARCHAR(255) COMMENT '专业资质证明URL',
    work_proof VARCHAR(255) COMMENT '工作经历证明URL',
    introduction TEXT COMMENT '个人简介',
    status TINYINT DEFAULT 0 COMMENT '0-待审核, 1-初审通过, 2-复审通过, 3-驳回',
    reject_reason VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

-- 专家信息表
CREATE TABLE experts (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    expert_level TINYINT DEFAULT 1 COMMENT '专家等级',
    hit_rate DECIMAL(5,2) DEFAULT 0 COMMENT '预测命中率',
    follower_count INT DEFAULT 0 COMMENT '粉丝数',
    is_featured BOOLEAN DEFAULT FALSE COMMENT '是否推荐专家',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

-- 专家内容表
CREATE TABLE expert_contents (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    expert_id BIGINT NOT NULL,
    content_type TINYINT NOT NULL COMMENT '1-赛事预测, 2-分析文章, 3-短视频, 4-动态',
    title VARCHAR(255) NOT NULL,
    content TEXT,
    video_url VARCHAR(255),
    images TEXT COMMENT '图片URL, 多个用逗号分隔',
    is_paid BOOLEAN DEFAULT FALSE,
    price DECIMAL(10,2) DEFAULT 0,
    view_count INT DEFAULT 0,
    like_count INT DEFAULT 0,
    comment_count INT DEFAULT 0,
    is_verified BOOLEAN DEFAULT FALSE COMMENT '是否审核通过',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (expert_id) REFERENCES experts(id)
);

-- 审核日志表
CREATE TABLE audit_logs (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    application_id BIGINT NOT NULL,
    operator_id BIGINT COMMENT '操作人ID',
    operation_type TINYINT NOT NULL COMMENT '1-初审通过, 2-复审通过, 3-驳回',
    remark VARCHAR(255),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (application_id) REFERENCES expert_applications(id)
);

三、PHP 管理端实现

1、专家审核控制器

<?php
namespace app\admin\controller;

use think\Controller;
use think\Request;
use app\admin\model\ExpertApplication;
use app\admin\model\AuditLog;
use app\admin\service\ExpertService;

class ExpertAudit extends Controller
{
   
    // 初审列表
    public function initialList()
    {
   
        $status = input('status', 0);
        $list = ExpertApplication::where('status', $status)
            ->order('created_at', 'desc')
            ->paginate(10);
        return view('initial_list', ['list' => $list]);
    }

    // 复审列表
    public function reviewList()
    {
   
        $list = ExpertApplication::where('status', 1)
            ->order('created_at', 'desc')
            ->paginate(10);
        return view('review_list', ['list' => $list]);
    }

    // 初审操作
    public function initialAudit()
    {
   
        $id = input('id');
        $action = input('action'); // pass/reject
        $reason = input('reason', '');

        $application = ExpertApplication::get($id);
        if (!$application) {
   
            return json(['code' => 404, 'msg' => '申请不存在']);
        }

        if ($action == 'pass') {
   
            $application->status = 1;
            $application->save();

            // 记录审核日志
            AuditLog::create([
                'application_id' => $id,
                'operator_id' => session('admin_id'),
                'operation_type' => 1,
                'remark' => '初审通过'
            ]);

            return json(['code' => 200, 'msg' => '初审通过成功']);
        } else {
   
            $application->status = 3;
            $application->reject_reason = $reason;
            $application->save();

            AuditLog::create([
                'application_id' => $id,
                'operator_id' => session('admin_id'),
                'operation_type' => 3,
                'remark' => $reason
            ]);

            // TODO: 发送通知给用户
            return json(['code' => 200, 'msg' => '已驳回申请']);
        }
    }

    // 复审操作
    public function reviewAudit()
    {
   
        $id = input('id');
        $action = input('action'); // pass/reject
        $reason = input('reason', '');

        $application = ExpertApplication::get($id);
        if (!$application || $application->status != 1) {
   
            return json(['code' => 400, 'msg' => '申请状态不正确']);
        }

        if ($action == 'pass') {
   
            // 调用专家服务处理认证通过逻辑
            $service = new ExpertService();
            $result = $service->approveExpert($application);

            if ($result) {
   
                AuditLog::create([
                    'application_id' => $id,
                    'operator_id' => session('admin_id'),
                    'operation_type' => 2,
                    'remark' => '复审通过,专家认证成功'
                ]);
                return json(['code' => 200, 'msg' => '专家认证成功']);
            } else {
   
                return json(['code' => 500, 'msg' => '专家认证失败']);
            }
        } else {
   
            $application->status = 3;
            $application->reject_reason = $reason;
            $application->save();

            AuditLog::create([
                'application_id' => $id,
                'operator_id' => session('admin_id'),
                'operation_type' => 3,
                'remark' => $reason
            ]);

            // TODO: 发送通知给用户
            return json(['code' => 200, 'msg' => '已驳回申请']);
        }
    }

    // 专家管理列表
    public function expertList()
    {
   
        $list = Expert::with('user')
            ->order('created_at', 'desc')
            ->paginate(10);
        return view('expert_list', ['list' => $list]);
    }

    // 撤销专家资格
    public function revokeExpert()
    {
   
        $id = input('id');
        $reason = input('reason', '');

        $service = new ExpertService();
        $result = $service->revokeExpert($id, $reason);

        if ($result) {
   
            return json(['code' => 200, 'msg' => '撤销专家资格成功']);
        } else {
   
            return json(['code' => 500, 'msg' => '撤销专家资格失败']);
        }
    }
}

2、专家服务类

<?php
namespace app\admin\service;

use think\Db;
use app\admin\model\ExpertApplication;
use app\admin\model\Expert;
use app\admin\model\User;

class ExpertService
{
   
    // 批准专家申请
    public function approveExpert(ExpertApplication $application)
    {
   
        Db::startTrans();
        try {
   
            // 更新用户角色为专家
            User::where('id', $application->user_id)
                ->update(['role' => 'expert']);

            // 创建专家记录
            Expert::create([
                'user_id' => $application->user_id,
                'created_at' => time()
            ]);

            // 更新申请状态
            $application->status = 2; // 复审通过
            $application->save();

            // TODO: 发送专家认证通过通知
            // $this->sendExpertApprovedNotification($application->user_id);

            Db::commit();
            return true;
        } catch (\Exception $e) {
   
            Db::rollback();
            return false;
        }
    }

    // 撤销专家资格
    public function revokeExpert($expertId, $reason)
    {
   
        Db::startTrans();
        try {
   
            // 获取专家信息
            $expert = Expert::get($expertId);
            if (!$expert) {
   
                throw new \Exception('专家不存在');
            }

            // 更新用户角色
            User::where('id', $expert->user_id)
                ->update(['role' => 'user']);

            // 删除专家记录
            $expert->delete();

            // TODO: 发送撤销通知
            // $this->sendExpertRevokedNotification($expert->user_id, $reason);

            Db::commit();
            return true;
        } catch (\Exception $e) {
   
            Db::rollback();
            return false;
        }
    }

    // 自动初审逻辑
    public function autoInitialReview($applicationId)
    {
   
        $application = ExpertApplication::get($applicationId);
        if (!$application) {
   
            return false;
        }

        // 调用实名认证接口
        $realNameVerified = $this->verifyRealName(
            $application->real_name,
            $application->id_card
        );

        // 检查材料完整性
        $materialsComplete = $this->checkMaterialsComplete($application);

        // 检查违规内容
        $noViolation = $this->checkViolation($application);

        if ($realNameVerified && $materialsComplete && $noViolation) {
   
            $application->status = 1; // 初审通过
            $application->save();

            AuditLog::create([
                'application_id' => $applicationId,
                'operation_type' => 1,
                'remark' => '系统自动初审通过'
            ]);

            return true;
        } else {
   
            $application->status = 3; // 驳回
            $application->reject_reason = '自动审核未通过';
            $application->save();

            AuditLog::create([
                'application_id' => $applicationId,
                'operation_type' => 3,
                'remark' => '系统自动初审驳回'
            ]);

            return false;
        }
    }

    // 实名认证接口调用
    private function verifyRealName($name, $idCard)
    {
   
        // TODO: 调用第三方实名认证接口
        // 这里简化处理,实际应调用公安部门接口
        return true;
    }

    // 检查材料完整性
    private function checkMaterialsComplete($application)
    {
   
        return !empty($application->id_card_front) 
            && !empty($application->id_card_back)
            && (!empty($application->qualification_cert) || !empty($application->work_proof));
    }

    // 检查违规内容
    private function checkViolation($application)
    {
   
        // TODO: 使用关键词过滤和图片识别技术
        // 这里简化处理
        $bannedWords = ['赌博', '诈骗', '色情'];
        foreach ($bannedWords as $word) {
   
            if (strpos($application->introduction, $word) !== false) {
   
                return false;
            }
        }
        return true;
    }
}

四、Java Android 客户端实现

1、专家认证API接口

// ExpertApiService.java
public interface ExpertApiService {
   
    // 提交专家申请
    @Multipart
    @POST("expert/apply")
    Call<BaseResponse> submitExpertApplication(
        @Part("real_name") RequestBody realName,
        @Part("id_card") RequestBody idCard,
        @Part MultipartBody.Part idCardFront,
        @Part MultipartBody.Part idCardBack,
        @Part MultipartBody.Part qualificationCert,
        @Part MultipartBody.Part workProof,
        @Part("introduction") RequestBody introduction
    );

    // 获取申请状态
    @GET("expert/application/status")
    Call<BaseResponse<ExpertApplicationStatus>> getApplicationStatus();

    // 获取专家主页信息
    @GET("expert/profile/{expertId}")
    Call<BaseResponse<ExpertProfile>> getExpertProfile(
        @Path("expertId") long expertId
    );

    // 获取专家内容列表
    @GET("expert/contents")
    Call<BaseResponse<List<ExpertContent>>> getExpertContents(
        @Query("expertId") long expertId,
        @Query("type") int type,
        @Query("page") int page,
        @Query("size") int size
    );
}

// 数据模型
public class ExpertApplicationStatus {
   
    private int status; // 0-待审核, 1-初审通过, 2-复审通过, 3-驳回
    private String rejectReason;
    private Date applyTime;
    // getters & setters
}

public class ExpertProfile {
   
    private long expertId;
    private String nickname;
    private String avatar;
    private String title;
    private String introduction;
    private int followerCount;
    private double hitRate;
    private boolean isFollowed;
    // getters & setters
}

public class ExpertContent {
   
    private long id;
    private int type; // 1-赛事预测, 2-分析文章, 3-短视频, 4-动态
    private String title;
    private String summary;
    private String coverImage;
    private boolean isPaid;
    private double price;
    private int viewCount;
    private Date createTime;
    // getters & setters
}

2、专家申请Activity

// ExpertApplyActivity.java
public class ExpertApplyActivity extends AppCompatActivity {
   
    private static final int REQUEST_PICK_ID_FRONT = 1;
    private static final int REQUEST_PICK_ID_BACK = 2;
    private static final int REQUEST_PICK_QUALIFICATION = 3;
    private static final int REQUEST_PICK_WORK_PROOF = 4;

    private EditText etRealName, etIdCard, etIntroduction;
    private ImageView ivIdCardFront, ivIdCardBack, ivQualification, ivWorkProof;
    private Button btnSubmit;
    private Uri idCardFrontUri, idCardBackUri, qualificationUri, workProofUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_expert_apply);

        initViews();
        setupListeners();
    }

    private void initViews() {
   
        etRealName = findViewById(R.id.et_real_name);
        etIdCard = findViewById(R.id.et_id_card);
        etIntroduction = findViewById(R.id.et_introduction);
        ivIdCardFront = findViewById(R.id.iv_id_card_front);
        ivIdCardBack = findViewById(R.id.iv_id_card_back);
        ivQualification = findViewById(R.id.iv_qualification);
        ivWorkProof = findViewById(R.id.iv_work_proof);
        btnSubmit = findViewById(R.id.btn_submit);
    }

    private void setupListeners() {
   
        ivIdCardFront.setOnClickListener(v -> pickImage(REQUEST_PICK_ID_FRONT));
        ivIdCardBack.setOnClickListener(v -> pickImage(REQUEST_PICK_ID_BACK));
        ivQualification.setOnClickListener(v -> pickImage(REQUEST_PICK_QUALIFICATION));
        ivWorkProof.setOnClickListener(v -> pickImage(REQUEST_PICK_WORK_PROOF));

        btnSubmit.setOnClickListener(v -> submitApplication());
    }

    private void pickImage(int requestCode) {
   
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, requestCode);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && data != null) {
   
            Uri uri = data.getData();
            switch (requestCode) {
   
                case REQUEST_PICK_ID_FRONT:
                    idCardFrontUri = uri;
                    ivIdCardFront.setImageURI(uri);
                    break;
                case REQUEST_PICK_ID_BACK:
                    idCardBackUri = uri;
                    ivIdCardBack.setImageURI(uri);
                    break;
                case REQUEST_PICK_QUALIFICATION:
                    qualificationUri = uri;
                    ivQualification.setImageURI(uri);
                    break;
                case REQUEST_PICK_WORK_PROOF:
                    workProofUri = uri;
                    ivWorkProof.setImageURI(uri);
                    break;
            }
        }
    }

    private void submitApplication() {
   
        String realName = etRealName.getText().toString().trim();
        String idCard = etIdCard.getText().toString().trim();
        String introduction = etIntroduction.getText().toString().trim();

        if (realName.isEmpty() || idCard.isEmpty() || idCardFrontUri == null || idCardBackUri == null) {
   
            Toast.makeText(this, "请填写完整信息并上传身份证正反面", Toast.LENGTH_SHORT).show();
            return;
        }

        if (qualificationUri == null && workProofUri == null) {
   
            Toast.makeText(this, "请至少上传一种资质证明或工作证明", Toast.LENGTH_SHORT).show();
            return;
        }

        // 创建请求体
        RequestBody realNameBody = RequestBody.create(realName, MediaType.parse("text/plain"));
        RequestBody idCardBody = RequestBody.create(idCard, MediaType.parse("text/plain"));
        RequestBody introBody = RequestBody.create(introduction, MediaType.parse("text/plain"));

        MultipartBody.Part frontPart = prepareFilePart("id_card_front", idCardFrontUri);
        MultipartBody.Part backPart = prepareFilePart("id_card_back", idCardBackUri);
        MultipartBody.Part qualPart = qualificationUri != null ? 
            prepareFilePart("qualification_cert", qualificationUri) : null;
        MultipartBody.Part workPart = workProofUri != null ? 
            prepareFilePart("work_proof", workProofUri) : null;

        // 显示加载对话框
        ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("提交中...");
        progressDialog.setCancelable(false);
        progressDialog.show();

        // 调用API
        ExpertApiService apiService = RetrofitClient.getInstance().create(ExpertApiService.class);
        Call<BaseResponse> call = apiService.submitExpertApplication(
            realNameBody, idCardBody, frontPart, backPart, qualPart, workPart, introBody
        );

        call.enqueue(new Callback<BaseResponse>() {
   
            @Override
            public void onResponse(Call<BaseResponse> call, Response<BaseResponse> response) {
   
                progressDialog.dismiss();
                if (response.isSuccessful() && response.body() != null) {
   
                    if (response.body().isSuccess()) {
   
                        Toast.makeText(ExpertApplyActivity.this, "提交成功,请等待审核", Toast.LENGTH_SHORT).show();
                        finish();
                    } else {
   
                        Toast.makeText(ExpertApplyActivity.this, response.body().getMessage(), Toast.LENGTH_SHORT).show();
                    }
                } else {
   
                    Toast.makeText(ExpertApplyActivity.this, "提交失败", Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<BaseResponse> call, Throwable t) {
   
                progressDialog.dismiss();
                Toast.makeText(ExpertApplyActivity.this, "网络错误: " + t.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }

    private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) {
   
        File file = new File(getRealPathFromURI(fileUri));
        RequestBody requestFile = RequestBody.create(file, MediaType.parse("image/*"));
        return MultipartBody.Part.createFormData(partName, file.getName(), requestFile);
    }

    private String getRealPathFromURI(Uri contentUri) {
   
        String[] proj = {
   MediaStore.Images.Media.DATA};
        Cursor cursor = getContentResolver().query(contentUri, proj, null, null, null);
        if (cursor == null) return null;
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String path = cursor.getString(column_index);
        cursor.close();
        return path;
    }
}

五、Vue.js PC网页端实现

1、专家认证组件

<template>
  <div class="expert-apply-container">
    <el-card class="box-card">
      <div slot="header" class="clearfix">
        <h2>专家认证申请</h2>
      </div>

      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
        <el-form-item label="真实姓名" prop="realName">
          <el-input v-model="form.realName" placeholder="请输入真实姓名"></el-input>
        </el-form-item>

        <el-form-item label="身份证号" prop="idCard">
          <el-input v-model="form.idCard" placeholder="请输入身份证号码"></el-input>
        </el-form-item>

        <el-form-item label="身份证正面" prop="idCardFront">
          <el-upload
            action="#"
            :auto-upload="false"
            :on-change="handleIdCardFrontChange"
            :show-file-list="false"
            accept="image/*">
            <img v-if="form.idCardFront" :src="form.idCardFront" class="id-card-img">
            <el-button v-else size="small" type="primary">点击上传</el-button>
          </el-upload>
        </el-form-item>

        <el-form-item label="身份证反面" prop="idCardBack">
          <el-upload
            action="#"
            :auto-upload="false"
            :on-change="handleIdCardBackChange"
            :show-file-list="false"
            accept="image/*">
            <img v-if="form.idCardBack" :src="form.idCardBack" class="id-card-img">
            <el-button v-else size="small" type="primary">点击上传</el-button>
          </el-upload>
        </el-form-item>

        <el-form-item label="专业资质证明">
          <el-upload
            action="#"
            :auto-upload="false"
            :on-change="handleQualificationChange"
            :show-file-list="false"
            accept="image/*">
            <img v-if="form.qualification" :src="form.qualification" class="id-card-img">
            <el-button v-else size="small" type="primary">点击上传</el-button>
          </el-upload>
          <p class="tip">如体育从业证书、解说资格证书等</p>
        </el-form-item>

        <el-form-item label="工作经历证明">
          <el-upload
            action="#"
            :auto-upload="false"
            :on-change="handleWorkProofChange"
            :show-file-list="false"
            accept="image/*">
            <img v-if="form.workProof" :src="form.workProof" class="id-card-img">
            <el-button v-else size="small" type="primary">点击上传</el-button>
          </el-upload>
          <p class="tip">如工作证明、往期解说截图等</p>
        </el-form-item>

        <el-form-item label="个人简介" prop="introduction">
          <el-input
            type="textarea"
            :rows="5"
            v-model="form.introduction"
            placeholder="请简要介绍您的专业背景、解说经验等">
          </el-input>
        </el-form-item>

        <el-form-item>
          <el-button type="primary" @click="submitForm" :loading="submitting">提交申请</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script>
import {
     submitExpertApplication } from '@/api/expert';
import {
     uploadImage } from '@/api/upload';

export default {
    
  name: 'ExpertApply',
  data() {
    
    return {
    
      submitting: false,
      form: {
    
        realName: '',
        idCard: '',
        idCardFront: '',
        idCardBack: '',
        qualification: '',
        workProof: '',
        introduction: ''
      },
      rules: {
    
        realName: [
          {
     required: true, message: '请输入真实姓名', trigger: 'blur' }
        ],
        idCard: [
          {
     required: true, message: '请输入身份证号码', trigger: 'blur' },
          {
     pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, message: '身份证格式不正确' }
        ],
        idCardFront: [
          {
     required: true, message: '请上传身份证正面照片', trigger: 'change' }
        ],
        idCardBack: [
          {
     required: true, message: '请上传身份证反面照片', trigger: 'change' }
        ],
        introduction: [
          {
     required: true, message: '请输入个人简介', trigger: 'blur' },
          {
     min: 50, message: '至少输入50个字符', trigger: 'blur' }
        ]
      }
    };
  },
  methods: {
    
    handleIdCardFrontChange(file) {
    
      this.getBase64(file.raw).then(base64 => {
    
        this.form.idCardFront = base64;
      });
    },
    handleIdCardBackChange(file) {
    
      this.getBase64(file.raw).then(base64 => {
    
        this.form.idCardBack = base64;
      });
    },
    handleQualificationChange(file) {
    
      this.getBase64(file.raw).then(base64 => {
    
        this.form.qualification = base64;
      });
    },
    handleWorkProofChange(file) {
    
      this.getBase64(file.raw).then(base64 => {
    
        this.form.workProof = base64;
      });
    },
    getBase64(file) {
    
      return new Promise((resolve, reject) => {
    
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result);
        reader.onerror = error => reject(error);
      });
    },
    async submitForm() {
    
      this.$refs.form.validate(async valid => {
    
        if (!valid) {
    
          return false;
        }

        if (!this.form.qualification && !this.form.workProof) {
    
          this.$message.warning('请至少上传一种资质证明或工作证明');
          return;
        }

        this.submitting = true;
        try {
    
          // 上传图片并获取URL
          const uploadTasks = [];
          if (this.form.idCardFront) {
    
            uploadTasks.push(uploadImage(this.form.idCardFront).then(url => {
    
              this.form.idCardFront = url;
            }));
          }
          if (this.form.idCardBack) {
    
            uploadTasks.push(uploadImage(this.form.idCardBack).then(url => {
    
              this.form.idCardBack = url;
            }));
          }
          if (this.form.qualification) {
    
            uploadTasks.push(uploadImage(this.form.qualification).then(url => {
    
              this.form.qualification = url;
            }));
          }
          if (this.form.workProof) {
    
            uploadTasks.push(uploadImage(this.form.workProof).then(url => {
    
              this.form.workProof = url;
            }));
          }

          await Promise.all(uploadTasks);

          // 提交申请
          const response = await submitExpertApplication({
    
            real_name: this.form.realName,
            id_card: this.form.idCard,
            id_card_front: this.form.idCardFront,
            id_card_back: this.form.idCardBack,
            qualification_cert: this.form.qualification,
            work_proof: this.form.workProof,
            introduction: this.form.introduction
          });

          if (response.code === 200) {
    
            this.$message.success('提交成功,请等待审核');
            this.$router.push('/user/center');
          } else {
    
            this.$message.error(response.message || '提交失败');
          }
        } catch (error) {
    
          console.error('提交失败:', error);
          this.$message.error('提交失败');
        } finally {
    
          this.submitting = false;
        }
      });
    }
  }
};
</script>

<style scoped>
.expert-apply-container {
    
  max-width: 800px;
  margin: 20px auto;
}

.id-card-img {
    
  max-width: 300px;
  max-height: 200px;
  display: block;
  margin-bottom: 10px;
}

.tip {
    
  font-size: 12px;
  color: #999;
  margin-top: 5px;
}
</style>

专家待审核-–-1.png

相关文章
|
1月前
|
前端开发 JavaScript 安全
7.6K Star Shadcn Admin:颜值与实力并存的后台管理系统,前端开发者的新宠!
"基于 Shadcn UI 和 Vite 打造的现代化管理后台,开箱即用的响应式设计 + 无障碍访问,让后台开发从未如此优雅!" —— 来自 GitHub 7.6K 星认证
305 26
|
1月前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
166 1
|
2月前
|
Kubernetes 数据可视化 Java
SAE 实现应用发布全过程可观测
本文聚焦阿里云Serverless应用引擎(SAE)用户在发布过程中的痛点,如“发布效率低、实例启动过程不透明”等问题。通过分步骤可视化解决方案,帮助用户明确问题、理解原因并最终解决,提升SAE平台使用体验。文章详细剖析了发布过程慢、信息透出不足及实例启动黑盒等痛点,并提出通过可观测、可解释和可优化的策略解决问题,同时展示了具体实现效果与后续优化规划。
360 68
|
1月前
|
API Python
飞桨x昇腾生态适配方案:13_API离线推理
ais_bench 提供了基于昇腾硬件的 Python API,用于离线模型(.om模型)推理。支持静态与动态API场景,如单个或多个OM模型推理。通过 `InferSession` 类加载模型并执行推理,可灵活处理输入输出形状转换。示例代码涵盖图片读取、形状调整、多模型串联推理及资源释放等操作,满足多样化推理需求。
109 26
|
1月前
|
人工智能 自然语言处理 数据库
云上玩转Qwen3系列之二:PAI-LangStudio搭建联网搜索和RAG增强问答应用
本文详细介绍了如何使用 PAI-LangStudio 和 Qwen3 构建基于 RAG 和联网搜索 的 AI 智能问答应用。该应用通过将 RAG、web search 等技术和阿里最新的推理模型 Qwen3 编排在一个应用流中,为大模型提供了额外的联网搜索和特定领域知识库检索的能力,提升了智能回答的效果,减少了幻觉。开发者可以基于该模板进行灵活扩展和二次开发,以满足特定场景的需求。
|
1月前
|
安全 网络协议 搜索推荐
远控安全金标准,ToDesk、向日葵、网易UU安全功能盘点,是否能攻破防线
本文对ToDesk、向日葵和网易UU三款主流远程控制软件进行了安全性评测。远程控制技术虽带来便利,但也存在安全隐患。文章从设备授权管理、远程连接与数据传输、隐私安全机制及主动防诈保护四个方面展开分析。ToDesk在二次验证、金融窗口保护等方面表现突出;向日葵基础安全功能完善但缺乏创新;网易UU侧重基础功能,安全机制尚待完善。最终通过星级表对比,ToDesk综合表现最佳,向日葵次之,网易UU适合低风险场景。未来远控软件需向体系化、智能化方向发展以应对不断演变的威胁。
|
1月前
|
人工智能 城市大脑 运维
2025数字中国建设峰会:阿里云+AI深入千行百业
近日,第八届数字中国建设峰会在福州召开。峰会期间,阿里云及通义大模型服务政企的一批领先成果被重点展示。
247 1
|
1月前
|
编解码 人工智能 JSON
飞桨x昇腾生态适配方案:10_ONNX转OM
本章节主要介绍如何将ONNX模型转化为昇腾AI处理器支持的OM模型,并进行离线推理。通过昇腾张量编译器(ATC),可实现静态OM、动态BatchSize、动态分辨率、动态维度及动态shape等多种模型转换。文中详细说明了ATC工具的使用方法、参数配置、命令格式以及常见问题解决方法,同时提供了具体示例和可视化工具辅助输入参数确认,帮助用户高效完成模型转换与部署。
158 0
|
10月前
|
jenkins 持续交付 开发工具
jenkins学习笔记之一:流水线基础语法
jenkins学习笔记之一:流水线基础语法
|
6月前
|
机器学习/深度学习 存储 并行计算
Differential Transformer: 通过差分注意力机制提升大语言模型性能
《Differential Transformer》论文提出了一种新的差分注意力机制,旨在解决传统Transformer模型过分关注不相关信息的问题。该机制通过计算两个独立的注意力图谱之差来消除注意力噪声,提高模型性能。实验结果显示,DIFF Transformer在减少参数量和训练token数量的同时,显著提升了多目标检索任务的准确率。
290 11
Differential Transformer: 通过差分注意力机制提升大语言模型性能