Pārlūkot izejas kodu

1、销售端新增单独的会员展示信息页面

yys 1 nedēļu atpakaļ
vecāks
revīzija
8ba2726a58

+ 16 - 0
src/views/live/live/index.vue

@@ -304,6 +304,12 @@
             <el-radio :label="2">竖屏</el-radio>
           </el-radio-group>
         </el-form-item>
+        <el-form-item label="弹窗位置" prop="popupPosition">
+          <el-radio-group v-model="form.popupPosition" :disabled="isViewOnly">
+            <el-radio :label="1">中间</el-radio>
+            <el-radio :label="2">右下角</el-radio>
+          </el-radio-group>
+        </el-form-item>
         <el-form-item label="直播类型" prop="liveType">
           <el-radio-group v-model="form.liveType" :disabled="isViewOnly">
 <!--            <el-radio :label="1">直播</el-radio>-->
@@ -507,6 +513,9 @@ export default {
         showType: [
           { required: true, message: "不能为空", trigger: "burl" }
         ],
+        popupPosition: [
+          { required: true, message: "不能为空", trigger: "change" }
+        ],
         liveType: [
           { required: true, message: "不能为空", trigger: "burl" }
         ],
@@ -804,6 +813,7 @@ export default {
     reset() {
       this.form = {
         showType: 1,
+        popupPosition: 1,
         liveType: 2,
         isShow: 1,
         isTranscode:0,
@@ -855,6 +865,9 @@ export default {
       const liveId = row.liveId || this.ids
       getLive(liveId).then(response => {
         this.form = response.data;
+        if (this.form.popupPosition == null) {
+          this.form.popupPosition = 1;
+        }
         if(this.form.duration){
           this.form.durationTime = this.secondsToTime(this.form.duration)
         }
@@ -879,6 +892,9 @@ export default {
       const liveId = row.liveId || this.ids
       getLive(liveId).then(response => {
         this.form = response.data;
+        if (this.form.popupPosition == null) {
+          this.form.popupPosition = 1;
+        }
         if(this.form.duration){
           this.form.durationTime = this.secondsToTime(this.form.duration)
         }

+ 223 - 4
src/views/live/liveConfig/task.vue

@@ -98,7 +98,7 @@
       <el-table-column label="任务类型" align="center" prop="taskType" :formatter="taskTypeFormatter" />
       <el-table-column label="触发类型" align="center" prop="triggerType" :formatter="triggerTypeFormatter" />
       <el-table-column label="触发时间" align="center" prop="triggerValue" :formatter="triggerValueFormatter" />
-      <el-table-column label="产品名称" align="center" prop="productName" :formatter="productNameFormatter" />
+      <el-table-column label="关联内容" align="center" prop="productName" :formatter="productNameFormatter" />
       <el-table-column label="状态" align="center" prop="status" :formatter="statusFormatter" />
 <!--      <el-table-column label="完成状态" align="center" prop="finishStatus" :formatter="finishStatusFormatter" />-->
       <el-table-column label="更新时间" align="center" prop="updatedTime" width="180">
@@ -137,8 +137,8 @@
     />
 
     <!-- 添加或修改直播间自动化任务配置对话框 -->
-    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+    <el-dialog :title="title" :visible.sync="open" width="620px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="90px">
         <el-form-item label="直播间ID" prop="liveId">
           <el-input :disabled="liveAbled" v-model="form.liveId" placeholder="请输入直播间ID" />
         </el-form-item>
@@ -230,6 +230,28 @@
             <el-option v-for="i in goodsStatusOptions" :key="i.value" :label="i.label" :value="i.value"></el-option>
           </el-select>
         </el-form-item>
+        <el-form-item label="签到奖励" v-if="form.taskType == 7">
+          <div class="sign-reward-list">
+            <div class="sign-reward-item" v-for="(item, index) in form.rewards" :key="index">
+              <el-select v-model="item.rewardType" placeholder="奖励类型" style="width: 120px; margin-right: 8px;" @change="onSignRewardTypeChange(item, index)">
+                <el-option v-for="i in rewardTypeOptions" :key="i.value" :label="i.label" :value="i.value"></el-option>
+              </el-select>
+              <el-select v-if="item.rewardType == 2" v-model="item.rewardId" placeholder="请选择积分红包" style="width: 180px; margin-right: 8px;">
+                <el-option v-for="i in redOptions" :key="i.value" :label="i.label" :value="i.value"></el-option>
+              </el-select>
+              <template v-else-if="item.rewardType == 5">
+                <el-select v-model="item.rewardId" placeholder="请选择优惠券" style="width: 160px; margin-right: 8px;">
+                  <el-option v-for="i in couponOptions" :key="i.value" :label="i.label" :value="i.value"></el-option>
+                </el-select>
+                <el-input-number v-model="item.couponCount" :min="1" :max="99" controls-position="right" placeholder="数量" style="width: 110px; margin-right: 8px;"></el-input-number>
+                <span style="margin-right: 8px; color: #909399;">张</span>
+              </template>
+              <el-input v-else-if="item.rewardType == 6" v-model="item.amount" placeholder="金额精确到0.1元" style="width: 180px; margin-right: 8px;" @input="onCashAmountInput(item)"></el-input>
+              <el-button type="text" icon="el-icon-delete" @click="removeSignReward(index)" v-if="form.rewards.length > 1">删除</el-button>
+            </div>
+            <el-button type="text" icon="el-icon-plus" @click="addSignReward">添加奖励</el-button>
+          </div>
+        </el-form-item>
         <el-form-item label="触发时间" prop="content">
           <el-time-picker
             default-value="2025-01-01 00:00:00"
@@ -305,8 +327,17 @@ export default {
         {
           value: 6,
           label: "定时商品上下架"
+        },
+        {
+          value: 7,
+          label: "签到任务"
         }
       ],
+      rewardTypeOptions: [
+        { value: 2, label: "积分红包" },
+        { value: 5, label: "优惠券" },
+        { value: 6, label: "金额红包" }
+      ],
       statusOptions:[{
         value: "0",
         label: "禁用"
@@ -470,6 +501,8 @@ export default {
           return "定时优惠券";
         case 6:
           return "定时商品上下架";
+        case 7:
+          return "签到任务";
         default:
           return "--";
       }
@@ -490,6 +523,29 @@ export default {
       if(content.productName) {
         return content.productName
       }
+      if (row.taskType == 7) {
+        const rewards = Array.isArray(content.rewards) ? content.rewards : null;
+        if (rewards && rewards.length) {
+          return rewards.map(r => {
+            if (!r) return '';
+            if (r.rewardType == 2) return (r.reward && r.reward.desc) || '积分红包';
+            if (r.rewardType == 5) {
+              const title = (r.reward && r.reward.title) || '优惠券';
+              const count = r.couponCount > 0 ? r.couponCount : 1;
+              return title + '×' + count;
+            }
+            if (r.rewardType == 6) return '金额红包¥' + (r.amount != null ? r.amount : '--');
+            return '';
+          }).filter(Boolean).join('、') || '--';
+        }
+        if (content.reward) {
+          if (content.rewardType == 2) return content.reward.desc || '--';
+          if (content.rewardType == 5) return content.reward.title || '--';
+        }
+      }
+      if (row.taskType == 2 && content.desc) return content.desc;
+      if (row.taskType == 4 && content.desc) return content.desc;
+      if (row.taskType == 5 && content.title) return content.title;
       return "--";
     },
     triggerValueFormatter(row, column, value) {
@@ -525,6 +581,12 @@ export default {
           pageSize: 10,
           liveId: null
       }
+      this.form.content = null;
+      this.form.goodsId = null;
+      this.form.goodsStatus = null;
+      this.form.rewardType = null;
+      this.form.rewardId = null;
+      this.form.rewards = this.form.taskType == 7 ? [{ rewardType: null, rewardId: null, couponCount: 1, amount: null }] : [];
       if (this.isLoading || !this.hasMore) return;
       this.isLoading = true;
       this.listParams.liveId = this.liveId;
@@ -544,6 +606,8 @@ export default {
           await this.addCouponList();
         }else if(this.form.taskType == 6){
           await this.addGoodsList();
+        }else if(this.form.taskType == 7){
+          await this.preloadAllSignRewardOptions();
         }
       }catch ( err){
         console.error('加载数据失败:', err);
@@ -552,6 +616,66 @@ export default {
       }
 
     },
+    async preloadAllSignRewardOptions() {
+      await this.addRedList();
+      this.listParams.pageNum = 1;
+      this.hasMore = true;
+      await this.addCouponList();
+    },
+    async onSignRewardTypeChange(item) {
+      item.rewardId = null;
+      item.couponCount = 1;
+      item.amount = null;
+      if (!item.rewardType) return;
+      const others = (this.form.rewards || []).filter(r => r !== item);
+      if (item.rewardType == 2 && others.some(r => r.rewardType == 2)) {
+        this.msgError("积分红包只能配置一个");
+        item.rewardType = null;
+        return;
+      }
+      if (item.rewardType == 6 && others.some(r => r.rewardType == 6)) {
+        this.msgError("金额红包只能配置一个");
+        item.rewardType = null;
+        return;
+      }
+      this.listParams = { pageNum: 1, pageSize: 10, liveId: this.liveId };
+      this.hasMore = true;
+      if (item.rewardType == 2) await this.addRedList();
+      else if (item.rewardType == 5) await this.addCouponList();
+    },
+    onCashAmountInput(item) {
+      if (item.amount == null || item.amount === '') return;
+      let val = String(item.amount).replace(/[^\d.]/g, '');
+      const parts = val.split('.');
+      if (parts.length > 2) {
+        val = parts[0] + '.' + parts.slice(1).join('');
+      }
+      // 金额红包精确到 0.1 元(一位小数)
+      if (parts.length === 2) {
+        val = parts[0] + '.' + parts[1].slice(0, 1);
+      }
+      item.amount = val;
+    },
+    addSignReward() {
+      if (!this.form.rewards) this.form.rewards = [];
+      this.form.rewards.push({ rewardType: null, rewardId: null, couponCount: 1, amount: null });
+    },
+    removeSignReward(index) {
+      this.form.rewards.splice(index, 1);
+    },
+    async loadSignRewardOptions(rewardType) {
+      this.hasMore = true;
+      this.listParams = {
+        pageNum: 1,
+        pageSize: 10,
+        liveId: this.liveId
+      }
+      if (rewardType == 2) {
+        await this.addRedList();
+      } else if (rewardType == 5) {
+        await this.addCouponList();
+      }
+    },
     addGoodsList() {
       if(this.haveData.goods) return
       listLiveGoods(this.listParams).then(res => {
@@ -684,6 +808,9 @@ export default {
         content: null,
         goodsId: null,
         goodsStatus: null,
+        rewardType: null,
+        rewardId: null,
+        rewards: [],
         status: 1,
         createdTime: null,
         updatedTime: null
@@ -733,7 +860,7 @@ export default {
         await this.addGoodsList();
       }
       const id = row.id || this.ids
-      getTask(id).then(response => {
+      getTask(id).then(async response => {
         this.form = response.data;
         let content = JSON.parse( response.data.content)
         if (this.form.taskType == 1) {
@@ -747,6 +874,38 @@ export default {
         }else if(this.form.taskType == 6){
           this.form.goodsId = content.goodsId;
           this.form.goodsStatus = content.status;
+        }else if(this.form.taskType == 7){
+          await this.preloadAllSignRewardOptions();
+          const rewards = [];
+          if (Array.isArray(content.rewards) && content.rewards.length) {
+            content.rewards.forEach(r => {
+              let rewardId = r.rewardId;
+              if (rewardId == null && r.reward) {
+                if (r.rewardType == 2) rewardId = r.reward.redId;
+                else if (r.rewardType == 5) rewardId = r.reward.couponId;
+              }
+              rewards.push({
+                rewardType: r.rewardType != null ? Number(r.rewardType) : null,
+                rewardId: rewardId,
+                couponCount: r.couponCount > 0 ? Number(r.couponCount) : 1,
+                amount: r.amount != null ? r.amount : null
+              });
+            });
+          } else if (content.rewardType != null) {
+            // 兼容旧单奖励结构
+            let rewardId = content.rewardId;
+            if (rewardId == null && content.reward) {
+              if (content.rewardType == 2) rewardId = content.reward.redId;
+              else if (content.rewardType == 5) rewardId = content.reward.couponId;
+            }
+            rewards.push({
+              rewardType: Number(content.rewardType),
+              rewardId: rewardId,
+              couponCount: content.couponCount > 0 ? Number(content.couponCount) : 1,
+              amount: content.amount != null ? content.amount : null
+            });
+          }
+          this.form.rewards = rewards.length ? rewards : [{ rewardType: null, rewardId: null, couponCount: 1, amount: null }];
         }
         this.open = true;
         this.title = "修改直播间自动化任务配置";
@@ -770,6 +929,56 @@ export default {
         })
 
       }
+      if(this.form.taskType == 7){
+        const rewards = [];
+        let hasPointRed = false;
+        let hasCashRed = false;
+        for (const r of (this.form.rewards || [])) {
+          if (!r || r.rewardType == null) continue;
+          if (r.rewardType == 2) {
+            if (r.rewardId == null) {
+              this.msgError("请选择积分红包");
+              return;
+            }
+            if (hasPointRed) {
+              this.msgError("积分红包只能配置一个");
+              return;
+            }
+            hasPointRed = true;
+            rewards.push({ rewardType: 2, rewardId: r.rewardId });
+          } else if (r.rewardType == 5) {
+            if (r.rewardId == null) {
+              this.msgError("请选择优惠券");
+              return;
+            }
+            const couponCount = r.couponCount > 0 ? Number(r.couponCount) : 1;
+            rewards.push({ rewardType: 5, rewardId: r.rewardId, couponCount });
+          } else if (r.rewardType == 6) {
+            if (hasCashRed) {
+              this.msgError("金额红包只能配置一个");
+              return;
+            }
+            const amount = Number(r.amount);
+            if (!amount || amount <= 0) {
+              this.msgError("请输入正确的金额红包金额");
+              return;
+            }
+            // 精确到 0.1 元
+            const normalized = Math.round(amount * 10) / 10;
+            if (Math.abs(amount - normalized) > 1e-8) {
+              this.msgError("金额红包需精确到0.1元");
+              return;
+            }
+            hasCashRed = true;
+            rewards.push({ rewardType: 6, amount: normalized.toFixed(1) });
+          }
+        }
+        if (!rewards.length) {
+          this.msgError("请至少配置一个签到奖励");
+          return;
+        }
+        this.form.content = JSON.stringify({ rewards })
+      }
       this.$refs["form"].validate(valid => {
         if (valid) {
           if (this.form.id != null) {
@@ -859,4 +1068,14 @@ export default {
   from { transform: rotate(0deg); }
   to { transform: rotate(360deg); }
 }
+
+.sign-reward-list {
+  width: 100%;
+}
+.sign-reward-item {
+  display: flex;
+  align-items: center;
+  margin-bottom: 8px;
+  flex-wrap: wrap;
+}
 </style>

+ 1 - 85
src/views/store/user/list.vue

@@ -95,16 +95,6 @@
           v-hasPermi="['his:user:export']"
         >导出</el-button>
       </el-col>
-      <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          icon="el-icon-d-arrow-right"
-          size="mini"
-          :disabled="multiple"
-          @click="handleTransfer"
-        >转移直播归属销售</el-button>
-      </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
@@ -222,39 +212,13 @@
       </div>
     </el-dialog>
 
-    <!-- 转移直播归属销售 -->
-    <el-dialog title="转移直播归属销售" :visible.sync="openTransferDialog" width="500px" append-to-body>
-      <el-form ref="transferForm" :model="transferForm" :rules="transferRules" label-width="120px">
-        <el-form-item label="转移至销售" prop="companyUserId">
-          <el-select
-            v-model="transferForm.companyUserId"
-            placeholder="请选择销售"
-            filterable
-            clearable
-            style="width: 100%"
-          >
-            <el-option
-              v-for="item in companyUserList"
-              :key="item.userId"
-              :label="`${item.nickName}-${item.userName}`"
-              :value="item.userId"
-            />
-          </el-select>
-        </el-form-item>
-        <p>确定将选中的 <strong>{{ ids.length }}</strong> 个用户的直播归属销售进行转移吗?</p>
-      </el-form>
-      <div slot="footer" class="dialog-footer">
-        <el-button type="primary" @click="submitTransfer">确 定</el-button>
-        <el-button @click="cancelTransfer">取 消</el-button>
-      </div>
-    </el-dialog>
 
   </div>
 </template>
 
 <script>
 import { listUser, getUser, delUser, addUser, updateUser, exportUser,sendCode,bindPhone } from "@/api/store/user";
-import {getUserList, batchBindCompanyUserId} from "@/api/company/companyUser";
+import {getUserList} from "@/api/company/companyUser";
 import userDetails from '../components/userDetails.vue';
 export default {
   name: "User",
@@ -263,15 +227,6 @@ export default {
     return {
       orOptions:[],
       companyUserList: [],
-      openTransferDialog: false,
-      transferForm: {
-        companyUserId: null
-      },
-      transferRules: {
-        companyUserId: [
-          { required: true, message: "请选择转移至销售", trigger: "change" }
-        ]
-      },
       bindRules: {
         phone: [
           { required: true, message: '请输入手机号', trigger: 'blur' },
@@ -469,45 +424,6 @@ export default {
       this.single = selection.length!==1
       this.multiple = !selection.length
     },
-    /** 转移直播归属销售 */
-    handleTransfer() {
-      if (this.ids.length === 0) {
-        this.$message.warning("请至少选择一个用户进行转移");
-        return;
-      }
-      this.transferForm = {
-        companyUserId: null
-      };
-      this.openTransferDialog = true;
-      this.$nextTick(() => {
-        if (this.$refs.transferForm) {
-          this.$refs.transferForm.clearValidate();
-        }
-      });
-    },
-    cancelTransfer() {
-      this.openTransferDialog = false;
-      this.transferForm = {
-        companyUserId: null
-      };
-    },
-    submitTransfer() {
-      this.$refs["transferForm"].validate(valid => {
-        if (!valid) {
-          return;
-        }
-        batchBindCompanyUserId({
-          companyUserId: this.transferForm.companyUserId,
-          fsUserIds: this.ids
-        }).then(response => {
-          if (response.code === 200) {
-            this.$message.success("转移成功");
-            this.openTransferDialog = false;
-            this.getList();
-          }
-        });
-      });
-    },
     /** 开始倒计时 */
     startCountdown(seconds) {
       this.bindPhone.countdown = seconds;

+ 665 - 0
src/views/store/user/liveBindList.vue

@@ -0,0 +1,665 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="会员ID" prop="userId">
+        <el-input
+          v-model="queryParams.userId"
+          placeholder="请输入会员ID"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="用户昵称" prop="nickName">
+        <el-input
+          v-model="queryParams.nickName"
+          placeholder="请输入用户昵称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="手机号码" prop="phone">
+        <el-input
+          v-model="queryParams.phone"
+          placeholder="请输入手机号码"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="加密号码" prop="phoneMk">
+        <el-input
+          v-model="queryParams.phoneMk"
+          placeholder="请输入手机号码"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="用户状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择用户状态" clearable size="small">
+         <el-option
+                   v-for="dict in userOptions"
+                   :key="dict.dictValue"
+                   :label="dict.dictLabel"
+                   :value="dict.dictValue"
+                 />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="是否购药" prop="isBuy">
+        <el-select v-model="queryParams.isBuy" placeholder="请选择用户状态" clearable size="small">
+         <el-option
+                   v-for="dict in orOptions"
+                   :key="dict.dictValue"
+                   :label="dict.dictLabel"
+                   :value="dict.dictValue"
+                 />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="直播归属销售" prop="bindCompanyUserId" label-width="110px">
+        <el-select
+          v-model="queryParams.bindCompanyUserId"
+          placeholder="请选择直播归属销售"
+          filterable
+          clearable
+          size="small"
+          style="width: 200px"
+        >
+          <el-option
+            v-for="item in companyUserList"
+            :key="item.userId"
+            :label="`${item.nickName}-${item.userName}`"
+            :value="item.userId"
+          />
+        </el-select>
+      </el-form-item>
+       <el-form-item label="注册时间" prop="createTime">
+                 <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"></el-date-picker>
+       </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="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['his:user:export']"
+        >导出</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-d-arrow-right"
+          size="mini"
+          :disabled="multiple"
+          @click="handleTransfer"
+        >转移直播归属销售</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" border :data="userList" @selection-change="handleSelectionChange" >
+      <el-table-column type="selection" width="55" align="center" />
+
+      <el-table-column label="用户昵称" align="center" prop="nickName" width="150px"/>
+      <el-table-column label="用户头像" align="center" prop="avatar" >
+         <template slot-scope="scope">
+                 <el-image v-if="scope.row.avatar!=null"
+                     style="width: 50px;"
+                     :src="scope.row.avatar"
+                    >
+                 </el-image>
+         </template>
+      </el-table-column>
+      <el-table-column label="手机号码" align="center" prop="phone" width="150px" />
+      <el-table-column label="用户积分" align="center" prop="integral" />
+      <el-table-column label="用户状态" align="center" prop="status" >
+         <template slot-scope="scope">
+              <dict-tag :options="userOptions" :value="scope.row.status"/>
+         </template>
+      </el-table-column>
+      <el-table-column label="直播归属销售" align="center" prop="bindCompanyUserNickName" min-width="120" />
+      <el-table-column label="注册时间" align="center" prop="createTime" width="150px" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="150px">
+        <template slot-scope="scope">
+
+          <el-button
+            size="mini"
+            type="text"
+            @click="handledetails(scope.row)"
+          >详情</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleNickName(scope.row)"
+          >修改昵称</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            v-if="scope.row.phone==null || scope.row.phone==''"
+            @click="handleBindPhone(scope.row)"
+          >绑定手机号</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"
+    />
+
+    <!-- 添加或修改用户对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="用户昵称" prop="nickName">
+          <el-input v-model="form.nickName" placeholder="请输入用户昵称" />
+        </el-form-item>
+        <!-- <el-form-item label="用户状态" prop="status">
+            <el-select v-model="form.status" placeholder="请选择状态" clearable size="small">
+                  <el-option
+                    v-for="dict in userOptions"
+                    :key="dict.dictValue"
+                    :label="dict.dictLabel"
+                    :value="dict.dictValue"
+                  />
+                </el-select>
+        </el-form-item>
+        <el-form-item label="用户备注" prop="remark" >
+          <el-input v-model="form.remark" placeholder="请输入用户备注" type="textarea"/>
+        </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>
+
+    <el-drawer
+           :with-header="false"
+            size="75%"
+             :title="show.title" :visible.sync="show.open">
+         <userDetails  ref="userDetails" />
+       </el-drawer>
+
+    <!-- 绑定用户手机号 -->
+    <el-dialog :title="bindPhone.title" :visible.sync="bindPhone.open" width="500px" append-to-body>
+      <el-form ref="bindPhoneForm" :model="bindPhoneForm"  :rules="bindRules" label-width="80px">
+        <el-form-item label="用户昵称" prop="nickName" label-width="100px">
+          <el-input v-model="bindPhoneForm.nickName" placeholder="请输入用户昵称" :disabled="true"/>
+        </el-form-item>
+        <el-form-item label="用户手机号" prop="phone" label-width="100px">
+          <el-input v-model="bindPhoneForm.phone" placeholder="请输入用户手机号">
+            <el-button
+              slot="append"
+              @click="sendCode"
+              :disabled="bindPhone.isCountingDown || bindPhone.countdown > 120"
+              :loading="bindPhone.sendCodeLoading"
+            >
+              {{ countdownText }}
+            </el-button>
+          </el-input>
+        </el-form-item>
+        <el-form-item label="验证码" prop="code" label-width="100px">
+          <el-input v-model="bindPhoneForm.code" placeholder="请输入验证码"/>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitBindPhoneForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 转移直播归属销售 -->
+    <el-dialog title="转移直播归属销售" :visible.sync="openTransferDialog" width="500px" append-to-body>
+      <el-form ref="transferForm" :model="transferForm" :rules="transferRules" label-width="120px">
+        <el-form-item label="转移至销售" prop="companyUserId">
+          <el-select
+            v-model="transferForm.companyUserId"
+            placeholder="请选择销售"
+            filterable
+            clearable
+            style="width: 100%"
+          >
+            <el-option
+              v-for="item in companyUserList"
+              :key="item.userId"
+              :label="`${item.nickName}-${item.userName}`"
+              :value="item.userId"
+            />
+          </el-select>
+        </el-form-item>
+        <p>确定将选中的 <strong>{{ ids.length }}</strong> 个用户的直播归属销售进行转移吗?</p>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitTransfer">确 定</el-button>
+        <el-button @click="cancelTransfer">取 消</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+import { listUser, getUser, delUser, addUser, updateUser, exportUser,sendCode,bindPhone } from "@/api/store/user";
+import {getUserList, batchBindCompanyUserId} from "@/api/company/companyUser";
+import userDetails from '../components/userDetails.vue';
+export default {
+  name: "LiveBindUser",
+  components: {userDetails},
+  data() {
+    return {
+      orOptions:[],
+      companyUserList: [],
+      openTransferDialog: false,
+      transferForm: {
+        companyUserId: null
+      },
+      transferRules: {
+        companyUserId: [
+          { required: true, message: "请选择转移至销售", trigger: "change" }
+        ]
+      },
+      bindRules: {
+        phone: [
+          { required: true, message: '请输入手机号', trigger: 'blur' },
+          { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
+        ],
+        code: [
+          { required: true, message: '请输入验证码', trigger: 'blur' }
+        ]
+      },
+      bindPhoneForm:{
+        nickName: '',
+        userId: null,
+        phone: '',
+        code: ''
+      },
+      bindPhone:{
+        // 弹出层标题
+        title: "",
+        // 是否显示弹出层
+        open: false,
+        // 发送验证码相关
+        countdown: 0,           // 当前倒计时秒数
+        isCountingDown: false,  // 是否正在倒计时
+        sendCodeLoading: false, // 发送中loading
+        countdownTimer: null,   // 定时器引用
+      },
+      show:{
+              title:"用户详情",
+              open:false,
+            },
+      userOptions: [],
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 用户表格数据
+      userList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      createTime:null,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        nickName: null,
+        avatar: null,
+        phone: null,
+        phoneMk: null,
+        integral: null,
+        status: null,
+        tuiUserId: null,
+        tuiTime: null,
+        tuiUserCount: null,
+        maOpenId: null,
+        mpOpenId: null,
+        unionId: null,
+        isDel: null,
+        userCode: null,
+        lastIp: null,
+        balance: null,
+        sTime:null,
+        eTime:null,
+        isBuy:null,
+        bindCompanyUserId: null,
+        // 仅展示有直播归属销售的用户
+        hasBindCompanyUser: 1,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        nickName: [
+          { required: true, message: "昵称不能为空", trigger: "blur" }
+        ],
+        status: [
+          { required: true, message: "用户状态不能为空", trigger: "blur" }
+        ],
+        integral: [
+          { required: true, message: "用户积分不能为空", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  computed: {
+    // 倒计时按钮文字
+    countdownText() {
+      if (this.bindPhone.sendCodeLoading) {
+        return '发送中...';
+      }
+      if (this.bindPhone.isCountingDown) {
+        return `${this.bindPhone.countdown}s后重发`;
+      }
+      return '发送验证码';
+    }
+  },
+  // 页面销毁时清除定时器
+  beforeDestroy() {
+    this.clearCountdown();
+  },
+  created() {
+    getUserList().then(res => {
+      if (res.code === 200) {
+        this.companyUserList = res.data;
+      }
+    });
+    this.getList();
+    this.getDicts("sys_user_status").then(response => {
+      this.userOptions = response.data;
+    });
+    this.getDicts("sys_company_or").then(response => {
+          this.orOptions = response.data;
+    });
+  },
+  methods: {
+    change(){
+          if(this.createTime!=null){
+            this.queryParams.sTime=this.createTime[0];
+            this.queryParams.eTime=this.createTime[1];
+          }else{
+            this.queryParams.sTime=null;
+            this.queryParams.eTime=null;
+          }
+        },
+    handledetails(row){
+            this.show.open=true;
+            setTimeout(() => {
+                 this.$refs.userDetails.getDetails(row.userId);
+            }, 1);
+     },
+    /** 查询用户列表 */
+    getList() {
+      this.loading = true;
+      listUser(this.queryParams).then(response => {
+        this.userList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        userId: null,
+        nickName: null,
+        avatar: null,
+        phone: null,
+        integral: null,
+        status: null,
+        tuiUserId: null,
+        tuiTime: null,
+        tuiUserCount: null,
+        maOpenId: null,
+        mpOpenId: null,
+        unionId: null,
+        isDel: null,
+        userCode: null,
+        remark: null,
+        createTime: null,
+        updateTime: null,
+        lastIp: null,
+        balance: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+       this.createTime=null;
+      this.queryParams.sTime=null;
+      this.queryParams.eTime=null;
+      this.queryParams.hasBindCompanyUser = 1;
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.userId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 转移直播归属销售 */
+    handleTransfer() {
+      if (this.ids.length === 0) {
+        this.$message.warning("请至少选择一个用户进行转移");
+        return;
+      }
+      this.transferForm = {
+        companyUserId: null
+      };
+      this.openTransferDialog = true;
+      this.$nextTick(() => {
+        if (this.$refs.transferForm) {
+          this.$refs.transferForm.clearValidate();
+        }
+      });
+    },
+    cancelTransfer() {
+      this.openTransferDialog = false;
+      this.transferForm = {
+        companyUserId: null
+      };
+    },
+    submitTransfer() {
+      this.$refs["transferForm"].validate(valid => {
+        if (!valid) {
+          return;
+        }
+        batchBindCompanyUserId({
+          companyUserId: this.transferForm.companyUserId,
+          fsUserIds: this.ids
+        }).then(response => {
+          if (response.code === 200) {
+            this.$message.success("转移成功");
+            this.openTransferDialog = false;
+            this.getList();
+          }
+        });
+      });
+    },
+    /** 开始倒计时 */
+    startCountdown(seconds) {
+      this.bindPhone.countdown = seconds;
+      this.bindPhone.isCountingDown = true;
+
+      this.clearCountdown();
+      this.bindPhone.countdownTimer = setInterval(() => {
+        this.bindPhone.countdown--;
+        if (this.bindPhone.countdown <= 0) {
+          this.clearCountdown();
+        }
+      }, 1000);
+    },
+
+    /** 清除倒计时 */
+    clearCountdown() {
+      if (this.bindPhone.countdownTimer) {
+        clearInterval(this.bindPhone.countdownTimer);
+        this.bindPhone.countdownTimer = null;
+      }
+      if (this.bindPhone.countdown <= 0) {
+        this.bindPhone.isCountingDown = false;
+        this.bindPhone.countdown = 0;
+      }
+    },
+    /** 发送验证码 */
+    sendCode(){
+      const phone = this.bindPhoneForm.phone
+      if (phone === null || phone === "") {
+        this.$message.error("请输入正确手机号");
+      }
+      console.log("-----------------",phone);
+      // 60秒内不能重复点击(倒计时 > 120 时禁止,即180-60=120)
+      if (this.bindPhone.countdown > 120) {
+        this.$message.warning(`请${this.bindPhone.countdown - 120}秒后再试`);
+        return;
+      }
+
+      // 表单验证
+      this.$refs.bindPhoneForm.validateField('phone', (errorMessage) => {
+        if (errorMessage) {
+          return;
+        }
+
+        const phone = this.bindPhoneForm.phone;
+        this.sendCodeLoading = true;
+
+        sendCode(phone).then(response => {
+          this.sendCodeLoading = false;
+          if (response.code === 200) {
+            this.$message.success('验证码已发送,有效期180秒');
+            // 开始180秒倒计时
+            this.startCountdown(180);
+          } else {
+            this.$message.error(response.msg || '发送失败');
+          }
+        }).catch(() => {
+          this.sendCodeLoading = false;
+        });
+      });
+    },
+    /** 绑定手机按钮操作 */
+    handleBindPhone(row){
+      this.bindPhoneForm.nickName = row.nickName;
+      this.bindPhoneForm.userId = row.userId;
+      this.bindPhone.title = "绑定用户手机";
+      this.bindPhone.open = true;
+    },
+    /** 新增按钮操作 */
+    handleNickName(row) {
+      this.reset();
+      this.open = true;
+      this.form.nickName = row.nickname;
+      this.form.userId = row.userId;
+      this.title = "修改用户昵称";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const userId = row.userId || this.ids
+      getUser(userId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改用户";
+        this.form.status = String(this.form.status)
+      });
+    },
+    submitBindPhoneForm(){
+      this.$refs["bindPhoneForm"].validate(valid => {
+        if (valid) {
+          bindPhone(this.bindPhoneForm).then(response => {
+            this.msgSuccess("绑定成功");
+            this.bindPhone.open = false;
+            this.clearCountdown();
+            this.bindPhone.open = false;
+            this.getList();
+            });
+          }
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.userId != null) {
+            updateUser(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addUser(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const userIds = row.userId || this.ids;
+      this.$confirm('是否确认删除用户编号为"' + userIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delUser(userIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有用户数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportUser(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    }
+  }
+};
+</script>