该体育直播体系体系由东莞梦幻网络科技开发,使用 ThinkPHP 作为后端,Vue.js 作为 PC/H5 端框架,Java 和 Objective-C 分别用于安卓和 iOS 开发。
1、前端实现 (Vue.js)
- <template>
- <div class="anchor-certification">
- <div class="header">
- <h1>主播认证</h1>
- </div>
-
- <div class="form-container">
- <el-form :model="form" :rules="rules" ref="form" label-width="120px">
- <!-- 直播信息 -->
- <el-form-item label="直播赛事" prop="liveType">
- <el-checkbox-group v-model="form.liveType">
- <el-checkbox label="足球"></el-checkbox>
- <el-checkbox label="篮球"></el-checkbox>
- <el-checkbox label="电竞"></el-checkbox>
- <el-checkbox label="其他"></el-checkbox>
- </el-checkbox-group>
- </el-form-item>
-
- <el-form-item label="直播经验" prop="experience">
- <el-select v-model="form.experience" placeholder="请选择">
- <el-option label="1个月" value="1"></el-option>
- <el-option label="3个月" value="3"></el-option>
- <el-option label="6个月" value="6"></el-option>
- <el-option label="1年" value="12"></el-option>
- <el-option label="2年" value="24"></el-option>
- <el-option label="3年以上" value="36"></el-option>
- </el-select>
- </el-form-item>
-
- <!-- 个人信息 -->
- <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="idCardPhoto">
- <el-upload
- action="/api/upload/idCard"
- :limit="1"
- :on-success="handleIdCardSuccess"
- :before-upload="beforeIdCardUpload"
- :file-list="idCardFileList">
- <el-button size="small" type="primary">点击上传</el-button>
- <div slot="tip" class="el-upload__tip">请上传身份证正面照片,支持jpg/png格式,大小不超过5MB</div>
- </el-upload>
- </el-form-item>
-
- <!-- 联系方式 -->
- <el-form-item label="联系方式">
- <el-input v-model="form.qq" placeholder="QQ号"></el-input>
- <el-input v-model="form.wechat" placeholder="微信号"></el-input>
- <el-input v-model="form.phone" placeholder="电话号码"></el-input>
- </el-form-item>
-
- <!-- 个人简介 -->
- <el-form-item label="个人简介" prop="introduction">
- <el-input
- type="textarea"
- :rows="5"
- v-model="form.introduction"
- placeholder="请填写您的个人简介,不少于15字"
- :minlength="15">
- </el-input>
- <div class="intro-tips">
- <p>建议包含以下内容:</p>
- <p>1. 主播经验几年</p>
- <p>2. 在哪些平台上担任过主播</p>
- <p>3. 曾经获得过哪些荣誉</p>
- <p>4. 擅长直播哪类赛事(足球、篮球、电竞、娱乐、其他)</p>
- </div>
- </el-form-item>
-
- <!-- 邀请人 -->
- <el-form-item label="邀请人">
- <el-input v-model="form.inviter" placeholder="请输入邀请人(选填)"></el-input>
- <el-input v-model="form.inviterPhone" placeholder="+86 请输入邀请人电话(选填)"></el-input>
- </el-form-item>
-
- <!-- 验证码 -->
- <el-form-item label="验证码" prop="captcha">
- <el-input v-model="form.captcha" placeholder="请输入验证码" style="width: 200px"></el-input>
- <el-button @click="getCaptcha" :disabled="captchaDisabled">
- {{ captchaBtnText }}
- </el-button>
- </el-form-item>
-
- <!-- 协议 -->
- <el-form-item prop="agreed">
- <el-checkbox v-model="form.agreed">
- 我已阅读并同意<a href="/protocol/anchor" target="_blank">《体育直播协议》</a>
- </el-checkbox>
- </el-form-item>
-
- <!-- 提交按钮 -->
- <el-form-item>
- <el-button type="primary" @click="submitForm" :loading="submitting">提交认证</el-button>
- </el-form-item>
- </el-form>
- </div>
-
- <div class="footer">
- <div class="links">
- <a href="#">关于我们</a>
- <a href="#">联系方式</a>
- <a href="#">帮助中心</a>
- </div>
- <div class="copyright">
- Copyright © 2020-2025 龙牙直播 ALL Rights Reserved
- </div>
- </div>
- </div>
- </template>
- <script>
- export default {
- data() {
- return {
- form: {
- liveType: [],
- experience: '',
- realName: '',
- idCard: '',
- idCardPhoto: '',
- qq: '',
- wechat: '',
- phone: '',
- introduction: '',
- inviter: '',
- inviterPhone: '',
- captcha: '',
- agreed: false
- },
- rules: {
- liveType: [
- { type: 'array', required: true, message: '请至少选择一项直播赛事', trigger: 'change' }
- ],
- experience: [
- { required: true, message: '请选择直播经验', trigger: 'change' }
- ],
- realName: [
- { required: true, message: '请输入真实姓名', trigger: 'blur' }
- ],
- idCard: [
- { required: true, message: '请输入身份证号码', trigger: 'blur' },
- { pattern: /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/, message: '身份证号格式不正确' }
- ],
- idCardPhoto: [
- { required: true, message: '请上传身份证照片', trigger: 'blur' }
- ],
- introduction: [
- { required: true, message: '请输入个人简介', trigger: 'blur' },
- { min: 15, message: '个人简介不能少于15个字符', trigger: 'blur' }
- ],
- captcha: [
- { required: true, message: '请输入验证码', trigger: 'blur' }
- ],
- agreed: [
- { validator: (rule, value, callback) => {
- if (!value) {
- callback(new Error('请阅读并同意协议'));
- } else {
- callback();
- }
- }, trigger: 'change' }
- ]
- },
- idCardFileList: [],
- captchaDisabled: false,
- captchaBtnText: '获取验证码',
- countdown: 60,
- submitting: false
- };
- },
- methods: {
- handleIdCardSuccess(response, file) {
- this.form.idCardPhoto = response.data.url;
- },
- beforeIdCardUpload(file) {
- const isJPG = file.type === 'image/jpeg' || file.type === 'image/png';
- const isLt5M = file.size / 1024 / 1024 < 5;
-
- if (!isJPG) {
- this.$message.error('上传头像图片只能是 JPG/PNG 格式!');
- }
- if (!isLt5M) {
- this.$message.error('上传头像图片大小不能超过 5MB!');
- }
- return isJPG && isLt5M;
- },
- getCaptcha() {
- if (!this.form.phone) {
- this.$message.error('请输入手机号码');
- return;
- }
-
- // 调用API获取验证码
- this.$http.post('/api/captcha/sms', { phone: this.form.phone })
- .then(() => {
- this.$message.success('验证码已发送');
- this.startCountdown();
- })
- .catch(error => {
- this.$message.error(error.message || '验证码发送失败');
- });
- },
- startCountdown() {
- this.captchaDisabled = true;
- this.captchaBtnText = `${this.countdown}秒后重新获取`;
-
- const timer = setInterval(() => {
- this.countdown -= 1;
- this.captchaBtnText = `${this.countdown}秒后重新获取`;
-
- if (this.countdown <= 0) {
- clearInterval(timer);
- this.captchaDisabled = false;
- this.captchaBtnText = '获取验证码';
- this.countdown = 60;
- }
- }, 1000);
- },
- submitForm() {
- this.$refs.form.validate(valid => {
- if (valid) {
- this.submitting = true;
-
- this.$http.post('/api/anchor/certification', this.form)
- .then(response => {
- this.$message.success('提交成功,请等待审核');
- this.$router.push('/certification/result');
- })
- .catch(error => {
- this.$message.error(error.message || '提交失败');
- })
- .finally(() => {
- this.submitting = false;
- });
- } else {
- return false;
- }
- });
- }
- }
- };
- </script>
- <style scoped>
- .anchor-certification {
- max-width: 800px;
- margin: 0 auto;
- padding: 20px;
- }
- .header {
- text-align: center;
- margin-bottom: 30px;
- }
- .form-container {
- background: #fff;
- padding: 30px;
- border-radius: 5px;
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
- }
- .intro-tips {
- color: #999;
- font-size: 12px;
- margin-top: 5px;
- }
- .footer {
- margin-top: 30px;
- text-align: center;
- color: #999;
- font-size: 12px;
- }
- .links {
- margin-bottom: 10px;
- }
- .links a {
- margin: 0 10px;
- color: #999;
- text-decoration: none;
- }
- .links a:hover {
- color: #409EFF;
- }
- </style>
复制代码 2、后端实现 (PHP/ThinkPHP)
- <?php
- namespace app\api\controller;
- use think\Controller;
- use think\Request;
- use think\Validate;
- class AnchorCertification extends Controller
- {
- // 提交主播认证
- public function submit()
- {
- $request = Request::instance();
- $data = $request->post();
-
- // 验证规则
- $rules = [
- 'liveType' => 'require|array',
- 'experience' => 'require',
- 'realName' => 'require|chs',
- 'idCard' => 'require|idCard',
- 'idCardPhoto' => 'require|url',
- 'introduction' => 'require|min:15',
- 'captcha' => 'require',
- 'agreed' => 'require|accepted'
- ];
-
- // 验证消息
- $messages = [
- 'liveType.require' => '请选择直播赛事',
- 'experience.require' => '请选择直播经验',
- 'realName.require' => '请输入真实姓名',
- 'realName.chs' => '姓名只能为中文',
- 'idCard.require' => '请输入身份证号码',
- 'idCard.idCard' => '身份证号格式不正确',
- 'idCardPhoto.require' => '请上传身份证照片',
- 'idCardPhoto.url' => '身份证照片URL格式不正确',
- 'introduction.require' => '请输入个人简介',
- 'introduction.min' => '个人简介不能少于15个字符',
- 'captcha.require' => '请输入验证码',
- 'agreed.require' => '请阅读并同意协议',
- 'agreed.accepted' => '请阅读并同意协议'
- ];
-
- $validate = new Validate($rules, $messages);
-
- if (!$validate->check($data)) {
- return json([
- 'code' => 400,
- 'message' => $validate->getError()
- ]);
- }
-
- // 验证验证码
- if (!$this->checkCaptcha($data['phone'], $data['captcha'])) {
- return json([
- 'code' => 400,
- 'message' => '验证码错误或已过期'
- ]);
- }
-
- // 保存认证信息
- $certification = [
- 'user_id' => $request->userId, // 从token中获取的用户ID
- 'live_type' => implode(',', $data['liveType']),
- 'experience' => $data['experience'],
- 'real_name' => $data['realName'],
- 'id_card' => $data['idCard'],
- 'id_card_photo' => $data['idCardPhoto'],
- 'qq' => $data['qq'] ?? '',
- 'wechat' => $data['wechat'] ?? '',
- 'phone' => $data['phone'] ?? '',
- 'introduction' => $data['introduction'],
- 'inviter' => $data['inviter'] ?? '',
- 'inviter_phone' => $data['inviterPhone'] ?? '',
- 'status' => 0, // 0-待审核 1-已通过 2-已拒绝
- 'create_time' => time(),
- 'update_time' => time()
- ];
-
- try {
- $id = db('anchor_certification')->insertGetId($certification);
-
- return json([
- 'code' => 200,
- 'message' => '提交成功,请等待审核',
- 'data' => ['id' => $id]
- ]);
- } catch (\Exception $e) {
- return json([
- 'code' => 500,
- 'message' => '提交失败: ' . $e->getMessage()
- ]);
- }
- }
-
- // 获取验证码
- public function sendCaptcha()
- {
- $request = Request::instance();
- $phone = $request->post('phone');
-
- if (empty($phone)) {
- return json([
- 'code' => 400,
- 'message' => '请输入手机号码'
- ]);
- }
-
- if (!preg_match('/^1[3-9]\d{9}$/', $phone)) {
- return json([
- 'code' => 400,
- 'message' => '手机号码格式不正确'
- ]);
- }
-
- // 生成验证码
- $captcha = mt_rand(100000, 999999);
-
- // 保存验证码到缓存,有效期5分钟
- cache('captcha_' . $phone, $captcha, 300);
-
- // TODO: 实际项目中这里应该调用短信服务发送验证码
- // $this->sendSms($phone, $captcha);
-
- return json([
- 'code' => 200,
- 'message' => '验证码已发送'
- ]);
- }
-
- // 验证验证码
- private function checkCaptcha($phone, $captcha)
- {
- $cacheCaptcha = cache('captcha_' . $phone);
-
- if ($cacheCaptcha && $cacheCaptcha == $captcha) {
- // 验证成功后删除验证码
- cache('captcha_' . $phone, null);
- return true;
- }
-
- return false;
- }
-
- // 上传身份证照片
- public function uploadIdCard()
- {
- $file = request()->file('file');
-
- if (empty($file)) {
- return json([
- 'code' => 400,
- 'message' => '请选择上传文件'
- ]);
- }
-
- // 验证文件类型和大小
- $info = $file->validate([
- 'size' => 5242880, // 5MB
- 'ext' => 'jpg,jpeg,png'
- ])->move(ROOT_PATH . 'public' . DS . 'uploads' . DS . 'idcards');
-
- if ($info) {
- $url = '/uploads/idcards/' . $info->getSaveName();
-
- return json([
- 'code' => 200,
- 'message' => '上传成功',
- 'data' => ['url' => $url]
- ]);
- } else {
- return json([
- 'code' => 400,
- 'message' => $file->getError()
- ]);
- }
- }
- }
复制代码 3、安卓实现 (Java)
- // AnchorCertificationActivity.java
- public class AnchorCertificationActivity extends AppCompatActivity {
- private EditText etRealName, etIdCard, etQQ, etWechat, etPhone, etIntroduction, etInviter, etInviterPhone, etCaptcha;
- private CheckBox cbFootball, cbBasketball, cbEsports, cbOther;
- private Spinner spExperience;
- private ImageView ivIdCard;
- private Button btnGetCaptcha, btnSubmit;
- private CheckBox cbAgree;
-
- private String idCardPhotoUrl;
- private int countdown = 60;
- private boolean isCountdownRunning = false;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_anchor_certification);
-
- initViews();
- setupSpinner();
- }
-
- private void initViews() {
- etRealName = findViewById(R.id.et_real_name);
- etIdCard = findViewById(R.id.et_id_card);
- etQQ = findViewById(R.id.et_qq);
- etWechat = findViewById(R.id.et_wechat);
- etPhone = findViewById(R.id.et_phone);
- etIntroduction = findViewById(R.id.et_introduction);
- etInviter = findViewById(R.id.et_inviter);
- etInviterPhone = findViewById(R.id.et_inviter_phone);
- etCaptcha = findViewById(R.id.et_captcha);
-
- cbFootball = findViewById(R.id.cb_football);
- cbBasketball = findViewById(R.id.cb_basketball);
- cbEsports = findViewById(R.id.cb_esports);
- cbOther = findViewById(R.id.cb_other);
-
- spExperience = findViewById(R.id.sp_experience);
-
- ivIdCard = findViewById(R.id.iv_id_card);
- ivIdCard.setOnClickListener(v -> uploadIdCard());
-
- btnGetCaptcha = findViewById(R.id.btn_get_captcha);
- btnGetCaptcha.setOnClickListener(v -> getCaptcha());
-
- btnSubmit = findViewById(R.id.btn_submit);
- btnSubmit.setOnClickListener(v -> submitCertification());
-
- cbAgree = findViewById(R.id.cb_agree);
- }
-
- private void setupSpinner() {
- ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
- R.array.experience_options, android.R.layout.simple_spinner_item);
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- spExperience.setAdapter(adapter);
- }
-
- private void uploadIdCard() {
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
- intent.setType("image/*");
- startActivityForResult(intent, 1);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
-
- if (requestCode == 1 && resultCode == RESULT_OK && data != null) {
- Uri uri = data.getData();
- try {
- Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
- ivIdCard.setImageBitmap(bitmap);
-
- // 实际上传逻辑
- uploadImageToServer(uri);
- } catch (IOException e) {
- e.printStackTrace();
- Toast.makeText(this, "图片加载失败", Toast.LENGTH_SHORT).show();
- }
- }
- }
-
- private void uploadImageToServer(Uri uri) {
- // 这里实现实际上传逻辑,使用OkHttp或其他网络库
- // 上传成功后保存返回的URL到idCardPhotoUrl
- }
-
- private void getCaptcha() {
- String phone = etPhone.getText().toString().trim();
-
- if (phone.isEmpty()) {
- Toast.makeText(this, "请输入手机号码", Toast.LENGTH_SHORT).show();
- return;
- }
-
- if (!Patterns.PHONE.matcher(phone).matches()) {
- Toast.makeText(this, "手机号码格式不正确", Toast.LENGTH_SHORT).show();
- return;
- }
-
- // 调用API获取验证码
- getCaptchaFromServer(phone);
-
- // 开始倒计时
- startCountdown();
- }
-
- private void getCaptchaFromServer(String phone) {
- // 使用Retrofit或Volley调用API
- // 成功回调后显示提示
- Toast.makeText(this, "验证码已发送", Toast.LENGTH_SHORT).show();
- }
-
- private void startCountdown() {
- isCountdownRunning = true;
- btnGetCaptcha.setEnabled(false);
-
- new CountDownTimer(60000, 1000) {
- @Override
- public void onTick(long millisUntilFinished) {
- btnGetCaptcha.setText(countdown + "秒后重新获取");
- countdown--;
- }
-
- @Override
- public void onFinish() {
- btnGetCaptcha.setEnabled(true);
- btnGetCaptcha.setText("获取验证码");
- countdown = 60;
- isCountdownRunning = false;
- }
- }.start();
- }
-
- private void submitCertification() {
- String realName = etRealName.getText().toString().trim();
- String idCard = etIdCard.getText().toString().trim();
- String introduction = etIntroduction.getText().toString().trim();
- String captcha = etCaptcha.getText().toString().trim();
-
- // 验证必填项
- if (realName.isEmpty()) {
- Toast.makeText(this, "请输入真实姓名", Toast.LENGTH_SHORT).show();
- return;
- }
-
- if (idCard.isEmpty() || !validateIdCard(idCard)) {
- Toast.makeText(this, "请输入正确的身份证号码", Toast.LENGTH_SHORT).show();
- return;
- }
-
- if (idCardPhotoUrl == null || idCardPhotoUrl.isEmpty()) {
- Toast.makeText(this, "请上传身份证照片", Toast.LENGTH_SHORT).show();
- return;
- }
-
- if (introduction.isEmpty() || introduction.length() < 15) {
- Toast.makeText(this, "个人简介不能少于15字", Toast.LENGTH_SHORT).show();
- return;
- }
-
- if (captcha.isEmpty()) {
- Toast.makeText(this, "请输入验证码", Toast.LENGTH_SHORT).show();
- return;
- }
-
- if (!cbAgree.isChecked()) {
- Toast.makeText(this, "请阅读并同意协议", Toast.LENGTH_SHORT).show();
- return;
- }
-
- // 收集直播类型
- List<String> liveTypes = new ArrayList<>();
- if (cbFootball.isChecked()) liveTypes.add("足球");
- if (cbBasketball.isChecked()) liveTypes.add("篮球");
- if (cbEsports.isChecked()) liveTypes.add("电竞");
- if (cbOther.isChecked()) liveTypes.add("其他");
-
- if (liveTypes.isEmpty()) {
- Toast.makeText(this, "请至少选择一项直播赛事", Toast.LENGTH_SHORT).show();
- return;
- }
-
- // 收集其他信息
- String experience = spExperience.getSelectedItem().toString();
- String qq = etQQ.getText().toString().trim();
- String wechat = etWechat.getText().toString().trim();
- String phone = etPhone.getText().toString().trim();
- String inviter = etInviter.getText().toString().trim();
- String inviterPhone = etInviterPhone.getText().toString().trim();
-
- // 提交到服务器
- submitToServer(liveTypes, experience, realName, idCard, idCardPhotoUrl,
- qq, wechat, phone, introduction, inviter, inviterPhone, captcha);
- }
-
- private boolean validateIdCard(String idCard) {
- // 简单的身份证验证
- return idCard.matches("(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$");
- }
-
- private void submitToServer(List<String> liveTypes, String experience, String realName,
- String idCard, String idCardPhoto, String qq, String wechat, String phone,
- String introduction, String inviter, String inviterPhone, String captcha) {
-
- // 使用Retrofit或Volley提交数据
- // 显示加载中
- ProgressDialog progressDialog = new ProgressDialog(this);
- progressDialog.setMessage("提交中...");
- progressDialog.setCancelable(false);
- progressDialog.show();
-
- // 构造请求体
- JSONObject requestBody = new JSONObject();
- try {
- requestBody.put("liveType", new JSONArray(liveTypes));
- requestBody.put("experience", experience);
- requestBody.put("realName", realName);
- requestBody.put("idCard", idCard);
- requestBody.put("idCardPhoto", idCardPhoto);
- requestBody.put("qq", qq);
- requestBody.put("wechat", wechat);
- requestBody.put("phone", phone);
- requestBody.put("introduction", introduction);
- requestBody.put("inviter", inviter);
- requestBody.put("inviterPhone", inviterPhone);
- requestBody.put("captcha", captcha);
- requestBody.put("agreed", true);
- } catch (JSONException e) {
- e.printStackTrace();
- }
-
- // 实际网络请求
- // 成功回调
- progressDialog.dismiss();
- Toast.makeText(this, "提交成功,请等待审核", Toast.LENGTH_SHORT).show();
- finish();
- }
- }
复制代码 4、iOS实现 (Objective-C)
- // AnchorCertificationViewController.h
- #import <UIKit/UIKit.h>
- @interface AnchorCertificationViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>
- @end
- // AnchorCertificationViewController.m
- #import "AnchorCertificationViewController.h"
- @interface AnchorCertificationViewController ()
- @property (weak, nonatomic) IBOutlet UITextField *realNameField;
- @property (weak, nonatomic) IBOutlet UITextField *idCardField;
- @property (weak, nonatomic) IBOutlet UITextField *qqField;
- @property (weak, nonatomic) IBOutlet UITextField *wechatField;
- @property (weak, nonatomic) IBOutlet UITextField *phoneField;
- @property (weak, nonatomic) IBOutlet UITextView *introductionView;
- @property (weak, nonatomic) IBOutlet UITextField *inviterField;
- @property (weak, nonatomic) IBOutlet UITextField *inviterPhoneField;
- @property (weak, nonatomic) IBOutlet UITextField *captchaField;
- @property (weak, nonatomic) IBOutlet UIButton *footballBtn;
- @property (weak, nonatomic) IBOutlet UIButton *basketballBtn;
- @property (weak, nonatomic) IBOutlet UIButton *esportsBtn;
- @property (weak, nonatomic) IBOutlet UIButton *otherBtn;
- @property (weak, nonatomic) IBOutlet UIPickerView *experiencePicker;
- @property (weak, nonatomic) IBOutlet UIImageView *idCardImageView;
- @property (weak, nonatomic) IBOutlet UIButton *getCaptchaBtn;
- @property (weak, nonatomic) IBOutlet UIButton *submitBtn;
- @property (weak, nonatomic) IBOutlet UIButton *agreeBtn;
- @property (strong, nonatomic) NSArray *experienceOptions;
- @property (strong, nonatomic) NSString *idCardPhotoUrl;
- @property (assign, nonatomic) NSInteger countdown;
- @property (strong, nonatomic) NSTimer *countdownTimer;
- @end
- @implementation AnchorCertificationViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
-
- [self setupUI];
- [self setupData];
- }
- - (void)setupUI {
- self.introductionView.layer.borderWidth = 1.0;
- self.introductionView.layer.borderColor = [UIColor lightGrayColor].CGColor;
- self.introductionView.layer.cornerRadius = 5.0;
-
- self.idCardImageView.userInteractionEnabled = YES;
- UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(uploadIdCard)];
- [self.idCardImageView addGestureRecognizer:tap];
-
- self.experiencePicker.delegate = self;
- self.experiencePicker.dataSource = self;
- }
- - (void)setupData {
- self.experienceOptions = @[@"1个月", @"3个月", @"6个月", @"1年", @"2年", @"3年以上"];
- self.countdown = 60;
- }
- - (IBAction)liveTypeSelected:(UIButton *)sender {
- sender.selected = !sender.selected;
- }
- - (IBAction)getCaptchaTapped:(id)sender {
- NSString *phone = self.phoneField.text;
-
- if (phone.length == 0) {
- [self showAlertWithTitle:@"提示" message:@"请输入手机号码"];
- return;
- }
-
- // 简单的手机号验证
- NSString *phoneRegex = @"^1[3-9]\\d{9}$";
- NSPredicate *phoneTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", phoneRegex];
- if (![phoneTest evaluateWithObject:phone]) {
- [self showAlertWithTitle:@"提示" message:@"手机号码格式不正确"];
- return;
- }
-
- [self getCaptchaFromServer:phone];
- [self startCountdown];
- }
- - (void)getCaptchaFromServer:(NSString *)phone {
- // 实际项目中这里应该调用API获取验证码
- [self showAlertWithTitle:@"提示" message:@"验证码已发送"];
- }
- - (void)startCountdown {
- self.getCaptchaBtn.enabled = NO;
- self.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateCountdown) userInfo:nil repeats:YES];
- }
- - (void)updateCountdown {
- if (self.countdown > 0) {
- [self.getCaptchaBtn setTitle:[NSString stringWithFormat:@"%ld秒后重新获取", (long)self.countdown] forState:UIControlStateDisabled];
- self.countdown--;
- } else {
- [self.countdownTimer invalidate];
- self.countdownTimer = nil;
- self.getCaptchaBtn.enabled = YES;
- [self.getCaptchaBtn setTitle:@"获取验证码" forState:UIControlStateNormal];
- self.countdown = 60;
- }
- }
- - (void)uploadIdCard {
- UIImagePickerController *picker = [[UIImagePickerController alloc] init];
- picker.delegate = self;
- picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
- picker.allowsEditing = YES;
- [self presentViewController:picker animated:YES completion:nil];
- }
- - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info {
- UIImage *image = info[UIImagePickerControllerEditedImage] ?: info[UIImagePickerControllerOriginalImage];
- self.idCardImageView.image = image;
-
- // 实际上传逻辑
- [self uploadImageToServer:image];
-
- [picker dismissViewControllerAnimated:YES completion:nil];
- }
- - (void)uploadImageToServer:(UIImage *)image {
- // 这里实现实际上传逻辑,使用AFNetworking或其他网络库
- // 上传成功后保存返回的URL到self.idCardPhotoUrl
- }
- - (IBAction)submitTapped:(id)sender {
- NSString *realName = self.realNameField.text;
- NSString *idCard = self.idCardField.text;
- NSString *introduction = self.introductionView.text;
- NSString *captcha = self.captchaField.text;
-
- // 验证必填项
- if (realName.length == 0) {
- [self showAlertWithTitle:@"提示" message:@"请输入真实姓名"];
- return;
- }
-
- if (idCard.length == 0 || ![self validateIdCard:idCard]) {
- [self showAlertWithTitle:@"提示" message:@"请输入正确的身份证号码"];
- return;
- }
-
- if (self.idCardPhotoUrl.length == 0) {
- [self showAlertWithTitle:@"提示" message:@"请上传身份证照片"];
- return;
- }
-
- if (introduction.length < 15) {
- [self showAlertWithTitle:@"提示" message:@"个人简介不能少于15字"];
- return;
- }
-
- if (captcha.length == 0) {
- [self showAlertWithTitle:@"提示" message:@"请输入验证码"];
- return;
- }
-
- if (!self.agreeBtn.selected) {
- [self showAlertWithTitle:@"提示" message:@"请阅读并同意协议"];
- return;
- }
-
- // 收集直播类型
- NSMutableArray *liveTypes = [NSMutableArray array];
- if (self.footballBtn.selected) [liveTypes addObject:@"足球"];
- if (self.basketballBtn.selected) [liveTypes addObject:@"篮球"];
- if (self.esportsBtn.selected) [liveTypes addObject:@"电竞"];
- if (self.otherBtn.selected) [liveTypes addObject:@"其他"];
-
- if (liveTypes.count == 0) {
- [self showAlertWithTitle:@"提示" message:@"请至少选择一项直播赛事"];
- return;
- }
-
- // 收集其他信息
- NSInteger selectedRow = [self.experiencePicker selectedRowInComponent:0];
- NSString *experience = self.experienceOptions[selectedRow];
- NSString *qq = self.qqField.text;
- NSString *wechat = self.wechatField.text;
- NSString *phone = self.phoneField.text;
- NSString *inviter = self.inviterField.text;
- NSString *inviterPhone = self.inviterPhoneField.text;
-
- // 提交到服务器
- [self submitToServerWithLiveTypes:liveTypes experience:experience realName:realName
- idCard:idCard idCardPhoto:self.idCardPhotoUrl qq:qq
- wechat:wechat phone:phone introduction:introduction
- inviter:inviter inviterPhone:inviterPhone captcha:captcha];
- }
- - (BOOL)validateIdCard:(NSString *)idCard {
- NSString *regex = @"(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$";
- NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
- return [predicate evaluateWithObject:idCard];
- }
- - (void)submitToServerWithLiveTypes:(NSArray *)liveTypes experience:(NSString *)experience
- realName:(NSString *)realName idCard:(NSString *)idCard
- idCardPhoto:(NSString *)idCardPhoto qq:(NSString *)qq
- wechat:(NSString *)wechat phone:(NSString *)phone
- introduction:(NSString *)introduction inviter:(NSString *)inviter
- inviterPhone:(NSString *)inviterPhone captcha:(NSString *)captcha {
-
- // 显示加载中
- UIAlertController *loadingAlert = [UIAlertController alertControllerWithTitle:nil message:@"提交中..." preferredStyle:UIAlertControllerStyleAlert];
- [self presentViewController:loadingAlert animated:YES completion:nil];
-
- // 构造请求参数
- NSDictionary *params = @{
- @"liveType": liveTypes,
- @"experience": experience,
- @"realName": realName,
- @"idCard": idCard,
- @"idCardPhoto": idCardPhoto,
- @"qq": qq ?: @"",
- @"wechat": wechat ?: @"",
- @"phone": phone ?: @"",
- @"introduction": introduction,
- @"inviter": inviter ?: @"",
- @"inviterPhone": inviterPhone ?: @"",
- @"captcha": captcha,
- @"agreed": @YES
- };
-
- // 实际网络请求
- // 使用AFNetworking或NSURLSession
- // 成功回调
- [loadingAlert dismissViewControllerAnimated:YES completion:^{
- [self showAlertWithTitle:@"提示" message:@"提交成功,请等待审核"];
-
复制代码 5、数据库设计 (MySQL)
- CREATE TABLE `anchor_certification` (
- `id` INT PRIMARY KEY AUTO_INCREMENT,
- `name` VARCHAR(50) NOT NULL COMMENT '主播真实姓名',
- `identity_card` VARCHAR(18) NOT NULL COMMENT '身份证号码',
- `identity_photo_front` VARCHAR(255) NOT NULL COMMENT '身份证正面照片路径',
- `identity_photo_back` VARCHAR(255) NOT NULL COMMENT '身份证反面照片路径',
- `identity_photo_handheld` VARCHAR(255) NOT NULL COMMENT '手持身份证照片路径',
- `contact_type` ENUM('QQ', '微信', '电话') DEFAULT NULL COMMENT '联系方式类型',
- `contact_value` VARCHAR(50) DEFAULT NULL COMMENT '联系方式内容',
- `live_experience` ENUM('1个月', '3个月', '1年', '3年', '5年以上') NOT NULL COMMENT '直播经验',
- `live_type` SET('足球', '篮球', '电竞', '娱乐', '其他') NOT NULL COMMENT '擅长的直播类型',
- `personal_intro` TEXT NOT NULL COMMENT '个人简介',
- `invite_code` VARCHAR(20) DEFAULT NULL COMMENT '邀请人邀请码',
- `status` ENUM('待审核', '已通过', '已拒绝') DEFAULT '待审核' COMMENT '审核状态',
- `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
- `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='主播认证信息表';
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |