当前位置: 首页 > news >正文

【商城实战(65)】退换货流程全解析:从前端到后端的技术实现

【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配,乃至运营推广策略,102 章内容层层递进。无论是想深入钻研技术细节,还是探寻商城运营之道,本专栏都能提供从 0 到 1 的系统讲解,助力你打造独具竞争力的电商平台,开启电商实战之旅。

目录

  • 一、引言
  • 二、前端退换货申请页面设计
    • 2.1 uniapp 实现移动前端申请页面
    • 2.2 Element plus 实现 PC 前端申请页面
  • 三、后端退换货处理接口编写
    • 3.1 SpringBoot 搭建后端基础
    • 3.2 Mybatis - plus 操作数据库
    • 3.3 编写退换货处理接口
  • 四、跟踪退换货流程状态
    • 4.1 后端记录流程状态
    • 4.2 前端实时反馈状态
  • 五、总结与展望


一、引言

在电商业务蓬勃发展的当下,用户对于购物体验的要求日益提高。一个完善的电商商城系统,不仅需要具备流畅的购物流程、丰富的商品种类,还需拥有健全的售后服务体系。其中,退换货流程作为售后服务的关键环节,直接影响着用户的购物决策和对商城的信任度。在我们的 “商城实战” 专栏中,此前已深入探讨了从项目基础搭建到核心模块开发,再到性能优化与安全加固等多方面内容,今天我们将聚焦于退换货流程的实现,运用 uniapp、Element plus、SpringBoot 以及 Mybatis-plus 等技术,为大家详细讲解如何构建一个高效、便捷的退换货系统。

二、前端退换货申请页面设计

2.1 uniapp 实现移动前端申请页面

uniapp 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、H5、以及各种小程序(微信 / 支付宝 / 百度 / 头条 / QQ / 钉钉)等多个平台 。在移动前端退换货申请页面的开发中,uniapp 具有显著优势。它能实现一次开发,多端部署,大大提高了开发效率,减少了针对不同平台单独开发的工作量。同时,uniapp 基于 Vue.js,拥有简洁的语法和强大的响应式数据绑定机制,便于开发者进行页面交互逻辑的编写。

以下是使用 uniapp 实现移动前端退换货申请页面的关键代码:

<template>
  <view class="return-apply-page">
    <view class="form-item">
      <label>退换货原因:</label>
      <picker mode="selector" :range="returnReasons" v-model="selectedReasonIndex">
        <view>{{ returnReasons[selectedReasonIndex] }}</view>
      </picker>
    </view>
    <view class="form-item">
      <label>相关描述:</label>
      <textarea v-model="description" placeholder="请简要描述退换货相关情况"></textarea>
    </view>
    <button @click="submitReturnApply">提交申请</button>
  </view>
</template>

<script>
export default {
  data() {
    return {
      returnReasons: ['商品质量问题', '尺码不合适', '不喜欢/不需要', '其他'],
      selectedReasonIndex: 0,
      description: ''
    };
  },
  methods: {
    submitReturnApply() {
      const returnData = {
        reason: this.returnReasons[this.selectedReasonIndex],
        description: this.description
      };
      // 这里使用uni.request发送POST请求到后端
      uni.request({
        url: 'http://your-backend-url/return-apply',
        method: 'POST',
        data: returnData,
        success: res => {
          if (res.statusCode === 200) {
            uni.showToast({
              title: '申请提交成功',
              icon: 'success'
            });
          } else {
            uni.showToast({
              title: '申请提交失败',
              icon: 'none'
            });
          }
        },
        fail: err => {
          uni.showToast({
            title: '网络请求失败',
            icon: 'none'
          });
        }
      });
    }
  }
};
</script>

<style scoped>
.return-apply-page {
  padding: 20px;
}
.form-item {
  margin-bottom: 15px;
}
.form-item label {
  display: block;
  margin-bottom: 5px;
}
textarea {
  width: 100%;
  height: 100px;
  padding: 10px;
  box-sizing: border-box;
}
button {
  width: 100%;
  padding: 10px;
  background-color: #1aad19;
  color: white;
  border: none;
  border-radius: 5px;
}
</style>

在上述代码中,通过组件实现了退换货原因的选择,用于用户输入相关描述。当用户点击 “提交申请” 按钮时,submitReturnApply方法会将用户输入的数据组装成一个对象,然后使用uni.request发送 POST 请求到后端指定的接口。根据后端返回的状态码,使用uni.showToast提示用户申请提交的结果。

2.2 Element plus 实现 PC 前端申请页面

Element plus 是一款基于 Vue 3 的桌面端 UI 组件库,它提供了丰富的组件,如按钮、表单、表格等,能帮助开发者快速构建美观、交互性强的 PC 前端界面 。在 PC 前端退换货申请页面的开发中,Element plus 的组件可以让页面具有更好的视觉效果和用户体验,并且其组件的设计遵循响应式原则,能够适应不同屏幕尺寸的 PC 设备。

以下是使用 Element plus 组件构建 PC 前端退换货申请页面的代码:

<template>
  <el-container class="return-apply-container">
    <el-main>
      <el-form :model="returnForm" :rules="returnRules" ref="returnFormRef">
        <el-form-item label="退换货原因" prop="reason">
          <el-select v-model="returnForm.reason" placeholder="请选择">
            <el-option v-for="(reason, index) in returnReasons" :key="index" :label="reason" :value="reason"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="相关描述" prop="description">
          <el-input type="textarea" v-model="returnForm.description" placeholder="请简要描述退换货相关情况"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitReturnApply">提交申请</el-button>
        </el-form-item>
      </el-form>
    </el-main>
  </el-container>
</template>

<script setup>
import { ref } from 'vue';

const returnReasons = ['商品质量问题', '尺码不合适', '不喜欢/不需要', '其他'];
const returnForm = ref({
  reason: '',
  description: ''
});
const returnRules = {
  reason: [
    { required: true, message: '请选择退换货原因', trigger: 'change' }
  ],
  description: [
    { required: true, message: '请填写相关描述', trigger: 'blur' }
  ]
};

const submitReturnApply = () => {
  const formRef = returnFormRef.value;
  formRef.validate((valid) => {
    if (valid) {
      // 这里使用axios发送POST请求到后端
      import axios from 'axios';
      axios.post('http://your-backend-url/return-apply', returnForm.value)
      .then(res => {
          if (res.status === 200) {
            // 使用Element Plus的Message组件提示用户
            import { ElMessage } from 'element-plus';
            ElMessage.success('申请提交成功');
          } else {
            ElMessage.error('申请提交失败');
          }
        })
      .catch(err => {
          ElMessage.error('网络请求失败');
        });
    } else {
      return false;
    }
  });
};
</script>

<style scoped>
.return-apply-container {
  padding: 20px;
}
</style>

在这段代码中,使用了 Element plus 的el-container、el-main、el-form、el-form-item、el-select、el-option和el-input等组件来构建页面。通过returnRules定义了表单验证规则,确保用户输入了必要的信息。当用户点击 “提交申请” 按钮时,首先会进行表单验证,验证通过后使用axios发送 POST 请求到后端接口。根据后端返回的结果,使用 Element plus 的ElMessage组件提示用户申请提交的状态。

三、后端退换货处理接口编写

3.1 SpringBoot 搭建后端基础

SpringBoot 是整个后端的核心框架,它基于 “约定优于配置” 的原则,极大地简化了 Spring 应用的搭建和开发过程 。在我们的退换货流程实现中,SpringBoot 主要负责创建和管理应用的各种组件,包括处理 HTTP 请求、连接数据库以及整合其他第三方库等。它通过自动配置机制,为我们提供了许多默认的配置,使得我们能够快速搭建起一个可用的后端服务,而无需进行繁琐的配置工作。

首先,我们需要在项目的pom.xml文件中引入 SpringBoot 相关的依赖,主要包括spring-boot-starter-web用于构建 Web 应用,处理 HTTP 请求;spring-boot-starter-mybatis-plus用于集成 Mybatis-plus,实现数据库操作。以下是部分关键依赖代码:

<dependencies>
    <!-- Spring Boot Web依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Mybatis-Plus依赖 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>最新版本号</version>
    </dependency>
    <!-- 数据库驱动依赖,这里以MySQL为例 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

在引入依赖后,我们还需要配置 SpringBoot 的启动类。启动类通常是项目的入口,通过@SpringBootApplication注解,它会自动扫描并加载应用中的各种组件。示例代码如下:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MallApplication {
    public static void main(String[] args) {
        SpringApplication.run(MallApplication.class, args);
    }
}

同时,我们还需要在application.yml配置文件中配置一些基本信息,如端口号、数据库连接信息等。以 MySQL 数据库为例,配置如下:

server:
  port: 8080 # 应用端口号

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver # 数据库驱动
    url: jdbc:mysql://localhost:3306/your-database-name?useUnicode=true&characterEncoding=utf-8&useSSL=false # 数据库连接URL
    username: your-username # 数据库用户名
    password: your-password # 数据库密码

通过以上配置,我们就完成了 SpringBoot 后端基础的搭建,为后续编写退换货处理接口做好了准备。

3.2 Mybatis - plus 操作数据库

Mybatis - plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生 。它具有无侵入、强大的 CRUD 操作、支持 Lambda 形式调用、支持主键自动生成等诸多优势。在我们的项目中,使用 Mybatis - plus 可以大大简化数据库操作的代码量,提高开发效率。

首先,我们需要配置 Mybatis - plus。在application.yml中添加 Mybatis - plus 的相关配置,指定 Mapper 接口的扫描路径:

mybatis-plus:
  mapper-locations: classpath:/mapper/*.xml # Mapper XML文件路径
  type-aliases-package: com.example.mall.entity # 实体类所在包路径

接下来,设计数据库表结构。为了实现退换货功能,我们至少需要两张表:一张用于存储退换货申请信息的return_apply表,另一张用于存储商品信息的product表(因为退换货可能涉及商品相关信息的查询和更新)。以return_apply表为例,表结构设计如下:

CREATE TABLE `return_apply` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '申请ID',
  `user_id` bigint(20) NOT NULL COMMENT '用户ID',
  `order_id` bigint(20) NOT NULL COMMENT '订单ID',
  `product_id` bigint(20) NOT NULL COMMENT '商品ID',
  `reason` varchar(255) NOT NULL COMMENT '退换货原因',
  `description` text COMMENT '相关描述',
  `status` tinyint(1) DEFAULT 0 COMMENT '申请状态,0:待审核,1:审核通过,2:审核不通过,3:已换货,4:已退款',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '申请时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='退换货申请表';

然后,创建对应的实体类和 Mapper 接口。使用 Lombok 简化实体类的代码编写,以ReturnApply实体类为例:

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.util.Date;

@Data
@TableName("return_apply")
public class ReturnApply {
    private Long id;
    private Long userId;
    private Long orderId;
    private Long productId;
    private String reason;
    private String description;
    private Integer status;
    private Date createTime;
}

Mapper 接口继承自BaseMapper,BaseMapper为我们提供了基本的 CRUD 操作方法。以ReturnApplyMapper接口为例:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mall.entity.ReturnApply;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface ReturnApplyMapper extends BaseMapper<ReturnApply> {
}

通过以上配置和代码编写,我们就完成了 Mybatis - plus 操作数据库的相关设置,能够实现对退换货申请数据的持久化操作。

3.3 编写退换货处理接口

在完成 SpringBoot 和 Mybatis - plus 的基础配置后,我们开始编写退换货处理接口。主要包括审核申请、安排退款或换货的接口。

首先,创建一个ReturnApplyController类来处理前端发送的请求。在该类中,注入ReturnApplyService,通过ReturnApplyService来调用业务逻辑。示例代码如下:

import com.example.mall.entity.ReturnApply;
import com.example.mall.service.ReturnApplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/return-apply")
public class ReturnApplyController {

    @Autowired
    private ReturnApplyService returnApplyService;

    // 审核退换货申请接口
    @PostMapping("/audit")
    public String auditReturnApply(@RequestBody ReturnApply returnApply) {
        boolean result = returnApplyService.auditReturnApply(returnApply);
        if (result) {
            return "审核成功";
        } else {
            return "审核失败";
        }
    }

    // 安排退款接口
    @PostMapping("/refund")
    public String refundReturnApply(@RequestBody ReturnApply returnApply) {
        boolean result = returnApplyService.refundReturnApply(returnApply);
        if (result) {
            return "退款成功";
        } else {
            return "退款失败";
        }
    }

    // 安排换货接口
    @PostMapping("/exchange")
    public String exchangeReturnApply(@RequestBody ReturnApply returnApply) {
        boolean result = returnApplyService.exchangeReturnApply(returnApply);
        if (result) {
            return "换货成功";
        } else {
            return "换货失败";
        }
    }
}

在ReturnApplyService接口中定义审核申请、安排退款和换货的方法:

import com.example.mall.entity.ReturnApply;

public interface ReturnApplyService {
    boolean auditReturnApply(ReturnApply returnApply);
    boolean refundReturnApply(ReturnApply returnApply);
    boolean exchangeReturnApply(ReturnApply returnApply);
}

ReturnApplyServiceImpl实现类中实现上述方法的业务逻辑。以审核申请为例,根据前端传递的ReturnApply对象中的status字段判断审核结果,更新数据库中的申请状态:

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mall.entity.ReturnApply;
import com.example.mall.mapper.ReturnApplyMapper;
import com.example.mall.service.ReturnApplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ReturnApplyServiceImpl implements ReturnApplyService {

    @Autowired
    private ReturnApplyMapper returnApplyMapper;

    @Override
    public boolean auditReturnApply(ReturnApply returnApply) {
        QueryWrapper<ReturnApply> wrapper = new QueryWrapper<>();
        wrapper.eq("id", returnApply.getId());
        returnApply.setStatus(returnApply.getStatus()); // 根据前端传递的status更新审核状态
        int update = returnApplyMapper.update(returnApply, wrapper);
        return update > 0;
    }

    @Override
    public boolean refundReturnApply(ReturnApply returnApply) {
        // 实际业务中可能涉及与支付系统交互进行退款操作
        // 这里简单模拟更新订单状态为已退款
        QueryWrapper<ReturnApply> wrapper = new QueryWrapper<>();
        wrapper.eq("id", returnApply.getId());
        returnApply.setStatus(4); // 已退款状态码
        int update = returnApplyMapper.update(returnApply, wrapper);
        return update > 0;
    }

    @Override
    public boolean exchangeReturnApply(ReturnApply returnApply) {
        // 实际业务中可能涉及库存操作等
        // 这里简单模拟更新订单状态为已换货
        QueryWrapper<ReturnApply> wrapper = new QueryWrapper<>();
        wrapper.eq("id", returnApply.getId());
        returnApply.setStatus(3); // 已换货状态码
        int update = returnApplyMapper.update(returnApply, wrapper);
        return update > 0;
    }
}

以上代码展示了退换货处理接口的编写过程,通过这些接口,前端可以将用户的退换货申请提交到后端进行处理,后端根据不同的业务逻辑进行审核、退款或换货操作,并将结果返回给前端。

四、跟踪退换货流程状态

4.1 后端记录流程状态

在后端,使用 Mybatis - plus 来记录退换货流程状态。在之前设计的return_apply表中,已经有一个status字段来表示退换货申请的状态 。该字段的设计是整个流程跟踪的关键,它通过不同的整数值来区分申请的不同阶段,比如 0 表示待审核,1 表示审核通过,2 表示审核不通过,3 表示已换货,4 表示已退款。

当用户提交退换货申请时,初始状态为 0(待审核)。在ReturnApplyServiceImpl类中,当审核申请接口被调用时,会根据前端传递的ReturnApply对象中的status字段来更新数据库中的状态。以审核申请方法为例:

@Override
public boolean auditReturnApply(ReturnApply returnApply) {
    QueryWrapper<ReturnApply> wrapper = new QueryWrapper<>();
    wrapper.eq("id", returnApply.getId());
    returnApply.setStatus(returnApply.getStatus()); 
    int update = returnApplyMapper.update(returnApply, wrapper);
    return update > 0;
}

上述代码中,首先创建一个QueryWrapper对象,通过eq方法设置条件,根据传入的ReturnApply对象的id来定位要更新的记录。然后将ReturnApply对象中的status字段更新到数据库中。如果更新成功,update的值会大于 0,此时返回true,表示审核成功;否则返回false。

同样,在安排退款和换货的方法中,也会根据业务逻辑更新status字段。例如,在退款方法中:

@Override
public boolean refundReturnApply(ReturnApply returnApply) {
    QueryWrapper<ReturnApply> wrapper = new QueryWrapper<>();
    wrapper.eq("id", returnApply.getId());
    returnApply.setStatus(4); 
    int update = returnApplyMapper.update(returnApply, wrapper);
    return update > 0;
}

这里将status设置为 4,表示已退款,然后更新数据库记录,并返回更新结果。通过这种方式,后端能够准确地记录和跟踪退换货流程的状态变化。

4.2 前端实时反馈状态

在前端,无论是 uniapp 实现的移动前端还是 Element plus 实现的 PC 前端,都需要实时获取并展示退换货流程状态,以便用户能够及时了解自己申请的处理进度。

对于 uniapp 移动前端,可以使用uni.request定时向后端发送请求获取最新的状态信息。在页面的data中定义一个变量来存储状态,例如:

<template>
  <view class="return-status-page">
    <view>退换货申请状态: {{ returnStatus }}</view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      returnStatus: '待审核'
    };
  },
  onLoad() {
    this.getReturnStatus();
    // 每5秒获取一次状态,可根据需求调整时间间隔
    setInterval(() => {
      this.getReturnStatus();
    }, 5000);
  },
  methods: {
    getReturnStatus() {
      uni.request({
        url: 'http://your-backend-url/return-apply/status?id=' + this.returnApplyId,
        method: 'GET',
        success: res => {
          if (res.statusCode === 200) {
            const statusCode = res.data.status;
            if (statusCode === 0) {
              this.returnStatus = '待审核';
            } else if (statusCode === 1) {
              this.returnStatus = '审核通过';
            } else if (statusCode === 2) {
              this.returnStatus = '审核不通过';
            } else if (statusCode === 3) {
              this.returnStatus = '已换货';
            } else if (statusCode === 4) {
              this.returnStatus = '已退款';
            }
          }
        },
        fail: err => {
          console.log('获取状态失败', err);
        }
      });
    }
  }
};
</script>

<style scoped>
.return-status-page {
  padding: 20px;
}
</style>

在上述代码中,onLoad生命周期函数中调用getReturnStatus方法获取初始状态,并设置一个定时器每 5 秒调用一次getReturnStatus方法,实现状态的实时更新。getReturnStatus方法通过uni.request向后端发送 GET 请求,根据后端返回的status字段更新页面上显示的状态。

对于 Element plus 实现的 PC 前端,使用axios进行数据请求。同样在data中定义状态变量,在mounted生命周期函数中发起初始请求并设置定时器:

<template>
  <el-container class="return-status-container">
    <el-main>
      <el-card>
        <div>退换货申请状态: {{ returnStatus }}</div>
      </el-card>
    </el-main>
  </el-container>
</template>

<script setup>
import { ref } from 'vue';
import axios from 'axios';

const returnStatus = ref('待审核');
const returnApplyId = 1; // 假设申请ID为1,实际需要根据具体业务获取

const getReturnStatus = async () => {
  try {
    const response = await axios.get('http://your-backend-url/return-apply/status?id=' + returnApplyId);
    const statusCode = response.data.status;
    if (statusCode === 0) {
      returnStatus.value = '待审核';
    } else if (statusCode === 1) {
      returnStatus.value = '审核通过';
    } else if (statusCode === 2) {
      returnStatus.value = '审核不通过';
    } else if (statusCode === 3) {
      returnStatus.value = '已换货';
    } else if (statusCode === 4) {
      returnStatus.value = '已退款';
    }
  } catch (error) {
    console.log('获取状态失败', error);
  }
};

getReturnStatus();
setInterval(() => {
  getReturnStatus();
}, 5000);
</script>

<style scoped>
.return-status-container {
  padding: 20px;
}
</style>

在这段代码中,通过axios.get方法向后端请求状态信息,根据返回的status字段更新returnStatus的值,从而在页面上实时展示退换货流程状态。通过以上方式,前端能够及时将后端记录的退换货流程状态反馈给用户,提高用户体验。

五、总结与展望

通过本次对商城退换货流程的实现,我们成功运用 uniapp、Element plus、SpringBoot 以及 Mybatis-plus 等技术,构建了一个从前端申请到后端处理,再到流程状态跟踪的完整退换货系统。在前端,uniapp 和 Element plus 分别为移动和 PC 端用户提供了便捷、友好的操作界面,实现了退换货申请信息的快速提交。后端借助 SpringBoot 的强大功能和 Mybatis - plus 对数据库的高效操作,完成了退换货申请的审核、退款和换货等核心业务逻辑的处理 。同时,通过前后端的数据交互,实现了退换货流程状态的实时跟踪与反馈,为用户提供了清晰的进度信息。

展望未来,退换货流程的优化还有很大的发展空间。在技术层面,可以进一步引入人工智能和大数据技术。利用人工智能对退换货原因进行智能分析,自动识别常见问题,提高审核效率;借助大数据分析用户的退换货行为模式,提前预测可能出现的退换货情况,优化库存管理和物流配送。在业务层面,可进一步完善退换货政策,加强与供应商、物流公司的合作,实现全流程的协同优化,提升整体服务质量和用户满意度,为电商商城的持续发展提供更有力的支持。

相关文章:

  • HTML5 SVG:图形绘制的现代标准
  • STL之string
  • Qt的文件操作
  • Linux <(...) 进程替换
  • 【STM32】编写程序控制开发板的RGB LED灯
  • STM32单片机uCOS-Ⅲ系统12 CPU利用率与堆栈检测
  • [plugin:vite:import-analysis] Cannot find module ‘vuex\dist\vuex.esm-bundler
  • 风光互补智慧路灯的灯杆设计有哪些要求?
  • 服务器数据恢复—Raid5热备盘同步中断的数据恢复案例
  • WinSCP使用教程:(SFTP、SCP、FTP 和 WebDAV)
  • CES Asia 2025:科技企业出海的领航灯塔
  • 如何使用VS中的Android Game Development Extension (AGDE) 来查看安卓 Logcat 日志
  • 数据库 第一章 MySql基础(2)
  • STL之map和set
  • Altium Designer——PCB设计(走线与布局前的准备)
  • WebWorkers在项目中的使用案例
  • 状态模式(State Pattern)
  • 识货APP sh-sign sh-ba sh-jt 分析
  • qt QQuaternion详解
  • Arduino、ESP32驱动GUVA-S12SD UV紫外线传感器(光照传感器篇)
  • 山东如意集团及实控人等被出具警示函,此前实控人已被罚十年禁止入市
  • 10家A股农商行去年年报:瑞丰银行营收增速领跑,常熟银行等4家净利增速超11%
  • 山大齐鲁医院通报“子宫肌瘤论文现男性患者”:存在学术不端
  • 侯麦:从莫扎特到贝多芬
  • 让党的理论“飞入寻常百姓家”,他如何做到有新意?
  • 五一假期,新任杭州市委书记刘非到嘉兴南湖瞻仰红船