From 06f22f5674670016808457dbddd1065a180b9fcd Mon Sep 17 00:00:00 2001
From: SjS <email@example.com>
Date: Tue, 8 Apr 2025 16:04:34 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8B=9B=E5=95=86=E5=8A=A0=E7=9B=9F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/api/bst/mchApply.js                       |  57 ++
 src/utils/constants.js                        |   5 +
 .../components/SimpleVerifyDialog.vue         | 105 ++++
 src/views/bst/mchApply/index.vue              | 486 ++++++++++++++++++
 src/views/system/user/UserLink.vue            |  35 ++
 5 files changed, 688 insertions(+)
 create mode 100644 src/api/bst/mchApply.js
 create mode 100644 src/views/bst/mchApply/components/SimpleVerifyDialog.vue
 create mode 100644 src/views/bst/mchApply/index.vue
 create mode 100644 src/views/system/user/UserLink.vue

diff --git a/src/api/bst/mchApply.js b/src/api/bst/mchApply.js
new file mode 100644
index 0000000..95cddcd
--- /dev/null
+++ b/src/api/bst/mchApply.js
@@ -0,0 +1,57 @@
+import request from '@/utils/request'
+
+// 查询招商加盟列表
+export function listMchApply(query) {
+  return request({
+    url: '/bst/mchApply/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询招商加盟详细
+export function getMchApply(applyId) {
+  return request({
+    url: '/bst/mchApply/' + applyId,
+    method: 'get'
+  })
+}
+
+// 新增招商加盟
+export function addMchApply(data) {
+  return request({
+    url: '/bst/mchApply',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改招商加盟
+export function updateMchApply(data) {
+  return request({
+    url: '/bst/mchApply',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除招商加盟
+export function delMchApply(applyId) {
+  return request({
+    url: '/bst/mchApply/' + applyId,
+    method: 'delete'
+  })
+}
+
+// 审核商家合作申请
+export function verifyMchApply(applyId, pass, remark) {
+  return request({
+    url: `/bst/mchApply/${applyId}/verify`,
+    method: 'put',
+    params: {
+      applyId,
+      pass,
+      remark
+    }
+  })
+}
diff --git a/src/utils/constants.js b/src/utils/constants.js
index ad04934..a1e6d59 100644
--- a/src/utils/constants.js
+++ b/src/utils/constants.js
@@ -4,6 +4,11 @@ import { getLastDate, getLastDateTimeEnd, getLastDateTimeStart, getLastMonth, ge
 export const views = {
 }
 
+export const UserType = {
+  ADMIN: "1", // 管理员
+  APP: "2"      // 普通用户
+}
+
 // 日期选择器快捷选项
 export const DatePickerOptions = {
   // 默认
diff --git a/src/views/bst/mchApply/components/SimpleVerifyDialog.vue b/src/views/bst/mchApply/components/SimpleVerifyDialog.vue
new file mode 100644
index 0000000..371732c
--- /dev/null
+++ b/src/views/bst/mchApply/components/SimpleVerifyDialog.vue
@@ -0,0 +1,105 @@
+<template>
+  <el-dialog :title="title" :visible="show" width="500px" center @open="open" @close="close">
+    <el-form :model="form" :rules="rules" ref="form">
+      <el-form-item label="审核意见" prop="remark">
+        <el-input
+          type="textarea"
+          maxlength="200"
+          show-word-limit
+          v-model="form.remark"
+          placeholder="请输入审核意见,该审核意见会反馈给申请用户"
+          :rows="5"
+        />
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <el-button type="success" icon="el-icon-check" plain @click="handlePass">通过</el-button>
+      <el-button type="danger" icon="el-icon-close" plain @click="handleReject">驳回</el-button>
+    </template>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  name: 'SimpleVerifyDialog',
+  props: {
+    title: {
+      type: String,
+      default: '审核',
+    },
+    show: {
+      type: Boolean,
+      default: false,
+    },
+    requiredRemark: {
+      type: Boolean,
+      default: true,
+    },
+    reset: {
+      type: Boolean,
+      default: true,
+    }
+  },
+  data() {
+    return {
+      form: {},
+      rules: {
+        remark: [
+          {required: this.requiredRemark, message: '审核意见不能为空', trigger: 'blur'}
+        ]
+      }
+    }
+  },
+  created() {
+    this.resetForm();
+  },
+  methods: {
+    open() {
+      if (this.reset) {
+        this.resetForm();
+      }
+    },
+    close() {
+      this.$emit('update:show', false);
+    },
+    resetForm() {
+      this.form = {
+        remark: null,
+      }
+    },
+    handleReject() {
+      this.$refs.form.validate((valid) => {
+        if (!valid) {
+          return;
+        }
+        this.$confirm('确认驳回吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning',
+        }).then(() => {
+          this.$emit('reject', this.form);
+        });
+      });
+    },
+    handlePass() {
+      this.$refs.form.validate((valid) => {
+        if (!valid) {
+          return;
+        }
+        this.$confirm('确认通过吗?', '提示', {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning',
+        }).then(() => {
+          this.$emit('pass', this.form);
+        });
+      })
+    },
+  }
+}
+</script>
+
+<style scoped lang="scss">
+
+</style>
diff --git a/src/views/bst/mchApply/index.vue b/src/views/bst/mchApply/index.vue
new file mode 100644
index 0000000..601aaa6
--- /dev/null
+++ b/src/views/bst/mchApply/index.vue
@@ -0,0 +1,486 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="用户名称" prop="userId">
+        <el-input
+          v-model="queryParams.userName"
+          placeholder="请输入用户名称"
+          clearable
+          @change="handleQuery"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="姓名" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入姓名"
+          clearable
+          @change="handleQuery"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="手机号" prop="mobile">
+        <el-input
+          v-model="queryParams.mobile"
+          placeholder="请输入手机号"
+          clearable
+          @change="handleQuery"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="申请状态" prop="status">
+        <el-select v-model="queryParams.status" clearable @change="handleQuery" placeholder="请选择申请状态">
+          <el-option
+            v-for="dict in dict.type.mch_apply_status"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="审核人" prop="verifyName">
+        <el-input
+          v-model="queryParams.verifyName"
+          placeholder="请输入审核人名称"
+          clearable
+          @change="handleQuery"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['bst:mchApply:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['bst:mchApply:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="mchApplyList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="applyId" width="50"/>
+      <el-table-column label="用户名称" align="center" prop="userName" >
+        <template slot-scope="scope">
+          <span>{{ scope.row.userName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="姓名" align="center" prop="name" />
+      <el-table-column label="手机号" align="center" prop="mobile" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="180"/>
+      <el-table-column label="申请状态" align="center" prop="status">
+        <dict-tag slot-scope="d" :value="d.row.status" :options="dict.type.mch_apply_status"/>
+      </el-table-column>
+      <el-table-column label="审核人" align="center" prop="verifyName" />
+      <el-table-column label="审核时间" align="center" prop="verifyTime" width="180"/>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-view"
+            @click="handleView(scope.row)"
+            v-hasPermi="['bst:mchApply:remove']"
+          >查看详情</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+
+    <!-- 在index.vue的template中添加弹窗结构 -->
+    <el-dialog
+      :title="`商户申请详情`"
+      :visible.sync="detailVisible"
+      width="800px"
+      append-to-body>
+
+      <!-- 申请信息区块 -->
+      <div class="info-section">
+        <el-descriptions title="申请信息" :column="2" border>
+          <el-descriptions-item label="申请用户">{{ detailForm.userName }}</el-descriptions-item>
+          <el-descriptions-item label="申请时间">{{ detailForm.createTime }}</el-descriptions-item>
+          <el-descriptions-item label="申请状态">
+            <dict-tag :value="detailForm.status" :options="dict.type.mch_apply_status"/>
+          </el-descriptions-item>
+          <el-descriptions-item label="姓名">{{ detailForm.name }}</el-descriptions-item>
+          <el-descriptions-item label="手机号">{{ detailForm.mobile }}</el-descriptions-item>
+          <el-descriptions-item label="设备情况">
+            <el-tag :type="detailForm.hasDevice ? 'success' : 'danger'" size="small">
+              {{ detailForm.hasDevice ? '已有设备' : '暂无设备' }}
+            </el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item label="经营模式">
+            <dict-tag :value="detailForm.operateMode" :options="dict.type.apply_operate_mode"/>
+          </el-descriptions-item>
+          <el-descriptions-item label="使用场景">
+            {{ detailForm.scenes }}
+          </el-descriptions-item>
+          <!-- 合并后的详细信息 -->
+          <el-descriptions-item label="详细信息" :span="2">
+            <pre class="content-pre">{{ detailForm.content }}</pre>
+          </el-descriptions-item>
+        </el-descriptions>
+      </div>
+
+      <!-- 审核区块 -->
+      <el-divider v-if="isApproving" />
+      <div v-if="isApproving" class="verify-area">
+        <el-input
+          v-model="verifyRemark"
+          type="textarea"
+          :rows="4"
+          placeholder="请输入审核意见"
+          style="margin:20px 0"
+          :disabled="!isApproving"
+        />
+        <div class="dialog-footer" style="display: flex; justify-content: flex-end; gap: 10px;">
+          <el-button
+            type="danger"
+            @click="handleReject"
+            v-hasPermi="['bst:mchApply:verify']"
+          >驳 回</el-button>
+          <el-button
+            type="success"
+          @click="handleApprove"
+          v-hasPermi="['bst:mchApply:verify']"
+          >通 过</el-button>
+<!--          <el-button @click="detailVisible = false">关闭</el-button>-->
+        </div>
+
+      </div>
+
+      <!-- 修改已审核信息展示结构 -->
+      <template v-if="!isApproving">
+        <el-descriptions title="审核信息" :column="1" border style="margin-top:20px">
+          <el-descriptions-item label="审核人" class="text-wrap">{{ detailForm.verifyName }}</el-descriptions-item>
+          <el-descriptions-item label="审核时间" class="text-wrap">{{ detailForm.verifyTime }}</el-descriptions-item>
+          <el-descriptions-item label="审核意见" class="text-wrap">
+            <pre style="white-space: pre-wrap;">{{ detailForm.verifyRemark }}</pre>
+          </el-descriptions-item>
+        </el-descriptions>
+        <div class="dialog-footer" style="margin-top:20px">
+          <el-button @click="detailVisible = false">关 闭</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 添加或修改商家合作申请对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="650px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <!-- 经营模式 -->
+        <el-form-item label="经营模式" prop="operateMode">
+          <el-select
+            v-model="form.operateMode"
+            placeholder="请选择经营模式"
+            clearable
+            style="width: 100%"
+          >
+            <el-option
+              v-for="dict in dict.type.apply_operate_mode"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+
+        <!-- 是否有设备 -->
+        <el-form-item label="是否有设备" prop="hasDevice">
+          <el-radio-group v-model="form.hasDevice">
+            <el-radio :label="1">有设备</el-radio>
+            <el-radio :label="0">无设备</el-radio>
+          </el-radio-group>
+        </el-form-item>
+
+        <!-- 使用场景 -->
+        <el-form-item label="使用场景" prop="scenes">
+          <el-input
+            v-model="form.scenes"
+            placeholder="请输入使用场景"
+            type="textarea"
+            :rows="3"
+          />
+        </el-form-item>
+
+        <!-- 详细信息 -->
+        <el-form-item label="详细信息" prop="content">
+          <el-input
+            v-model="form.content"
+            type="textarea"
+            :rows="5"
+            placeholder="请输入详细信息"
+            show-word-limit
+            maxlength="500"
+          />
+        </el-form-item>
+      </el-form>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listMchApply, getMchApply, delMchApply, addMchApply, updateMchApply ,verifyMchApply} from "@/api/bst/mchApply";
+
+export default {
+  name: "MchApply",
+  components: {},
+  dicts: ['mch_apply_status',"apply_operate_mode"],
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 商家合作申请表格数据
+      mchApplyList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 需要补充以下字段
+      detailVisible: false, // 控制详情弹窗显示
+      detailForm: {},       // 详情数据存储
+      verifyRemark: '',     // 审核意见输入
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 20,
+        userId: null,
+        status: null,
+        name: null,
+        mobile: null,
+        content: null,
+        callback: null,
+        verifyName: null,
+        verifyTime: null,
+        verifyRemark: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        userId: [
+          { required: true, message: "用户id不能为空", trigger: "blur" }
+        ],
+        status: [
+          { required: true, message: "申请状态不能为空", trigger: "change" }
+        ],
+        name: [
+          { required: true, message: "姓名不能为空", trigger: "blur" }
+        ],
+        mobile: [
+          { required: true, message: "手机号不能为空", trigger: "blur" }
+        ],
+        content: [
+          { required: true, message: "详细信息不能为空", trigger: "blur" }
+        ],
+        createTime: [
+          { required: true, message: "创建时间不能为空", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.queryParams = {
+      ...this.queryParams,
+      ...this.$route.query
+    }
+    this.getList();
+  },
+  computed: {
+    isApproving() {
+      return this.detailForm.status === '1' //审核中状态
+    },
+    isView() {
+      return this.title === '查看商家合作申请';
+    }
+  },
+  methods: {
+    // 审核通过
+    handleApprove() {
+      if (!this.verifyRemark) {
+        this.$message.warning('请填写审核意见')
+        return
+      }
+      this.$modal.confirm('确认通过该申请?').then(() => {
+        verifyMchApply(this.detailForm.applyId, true, this.verifyRemark)
+          .then(() => {
+            this.$message.success('审核通过')
+            this.detailVisible = false
+            this.getList() // 刷新列表
+          })
+      })
+    },
+
+    // 审核驳回
+    handleReject() {
+      if (!this.verifyRemark) {
+        this.$message.warning('请填写审核意见')
+        return
+      }
+      this.$modal.confirm('确认驳回该申请?').then(() => {
+        verifyMchApply(this.detailForm.applyId, false, this.verifyRemark)
+          .then(() => {
+            this.$message.success('已驳回')
+            this.detailVisible = false
+            this.getList() // 刷新列表
+          })
+      })
+    },
+    /** 查询商家合作申请列表 */
+    getList() {
+      this.loading = true;
+      listMchApply(this.queryParams).then(response => {
+        this.mchApplyList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        applyId: null,
+        userId: null,
+        status: null,
+        name: null,
+        mobile: null,
+        content: null,
+        remark: null,
+        callback: null,
+        verifyBy: null,
+        verifyTime: null,
+        verifyRemark: null,
+        createTime: null,
+        updateTime: null,
+        deleted: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.applyId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "合作申请";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const applyId = row.applyId || this.ids
+      getMchApply(applyId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改商家合作申请";
+      });
+    },
+    handleView(row) {
+      this.loading = true;
+      getMchApply(row.applyId).then(response => {
+        this.detailForm = response.data;
+        this.detailVisible = true;
+        this.verifyRemark = '';
+      }).finally(() => {
+        this.loading = false;
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.applyId != null) {
+            updateMchApply(this.form).then(response => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addMchApply(this.form).then(response => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const applyIds = row.applyId || this.ids;
+      this.$modal.confirm('是否确认删除商家合作申请编号为"' + applyIds + '"的数据项?').then(function() {
+        return delMchApply(applyIds);
+      }).then(() => {
+        this.getList();
+        this.$modal.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      this.download('ss/mchApply/export', {
+        ...this.queryParams
+      }, `mchApply_${new Date().getTime()}.xlsx`)
+    }
+  }
+};
+</script>
diff --git a/src/views/system/user/UserLink.vue b/src/views/system/user/UserLink.vue
new file mode 100644
index 0000000..ef8bc48
--- /dev/null
+++ b/src/views/system/user/UserLink.vue
@@ -0,0 +1,35 @@
+<template>
+  <el-link v-if="userType === UserType.ADMIN" type="primary" @click="handleClick" :disabled="id == null">{{name | defaultValue}}</el-link>
+  <span v-else >{{name | defaultValue}}</span>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import { UserType } from '@/utils/constants'
+
+export default {
+  name: 'UserLink',
+  props: {
+    id: {
+      type: String,
+      default: null
+    },
+    name: {
+      type: String,
+      default: null,
+    }
+  },
+  computed: {
+    UserType() {
+      return UserType
+    },
+    ...mapGetters(['userType'])
+  },
+  methods: {
+    handleClick() {
+      this.$emit('click');
+      this.$router.push({path: `/smUser/user/${this.id}`})
+    }
+  }
+}
+</script>