<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
      <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="invitationCode">
        <el-input
          v-model="queryParams.invitationCode"
          placeholder="请输入邀请码"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>

      <el-form-item label="所属部门" prop="deptId">
        <treeselect
          v-model="queryParams.deptId"
          :options="deptOptions"
          :normalizer="normalizer"
          placeholder="选择部门"
          style="width: 250px"
        />
      </el-form-item>

      <el-form-item label="邀请日期" prop="inviteDate">
        <el-date-picker clearable size="small" v-model="queryParams.inviteDate" type="daterange" value-format="yyyy-MM-dd"
          placeholder="选择邀请日期">
        </el-date-picker>
      </el-form-item>

      <el-form-item label="标签" prop="tagIds">
        <div @click="openTagSearchPage"
             style="cursor: pointer; border: 1px solid #e6e6e6; background-color: white; overflow: hidden; flex-grow: 1;width: 250px">
          <div style="min-height: 35px; max-height: 200px; overflow-y: auto;">
            <el-tag type="success"
                closable
                :disable-transitions="false"
                v-for="list in this.tagSearchConfig.selected"
                :key="list.tagId"
                @close="handleCloseTags(list)"
                style="margin: 3px;"
            >{{ list.tagName }}
            </el-tag>
          </div>
        </div>
      </el-form-item>

      <el-form-item label="客服" prop="customerRoles">
        <div @click="openCusSearchPage"
             style="cursor: pointer; border: 1px solid #e6e6e6; background-color: white; overflow: hidden; flex-grow: 1;width: 250px">
          <div style="min-height: 35px; max-height: 200px; overflow-y: auto;">
            <el-tag type="success"
                closable
                :disable-transitions="false"
                v-for="list in this.bindAISearch.selected"
                :key="list.id"
                @close="handleCloseCus(list)"
                style="margin: 3px;"
            >{{ list.roleName }}
            </el-tag>
          </div>
        </div>
      </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"
          v-hasPermi="['app:user:export']"
          @click="handleExport"
        >导出</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          size="mini"
          v-hasPermi="['app:user:bindTag']"
          @click="openBindTagPage(false, 0)"
        > 批量添加标签
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="info"
          plain
          size="mini"
          v-hasPermi="['app:user:unbindTag']"
          @click="openUnbindTagPage(false, 1)"
        >批量移除标签
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          size="mini"
          v-hasPermi="['app:user:bindCustomer']"
          @click="openbindAIPage(false, 0)"
        >批量绑定客服
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          size="mini"
          v-hasPermi="['app:user:batchBindTag']"
          @click="openBindTagPage(true, 0)"
        >批量添加标签(筛选条件)
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="info"
          plain
          size="mini"
          v-hasPermi="['app:user:batchUnbindTag']"
          @click="openUnbindTagPage(true, 1)"
        >批量移除标签(筛选条件)
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          size="mini"
          v-hasPermi="['app:user:batchBindCustomer']"
          @click="openbindAIPage(true, 0)"
        >批量绑定客服(筛选条件)
        </el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table height="660" v-loading="loading" border :data="userList" @selection-change="handleSelectionChange" >
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="用户ID" align="center" prop="userId" width="150px"/>
      <el-table-column label="用户昵称" align="center" prop="nickName" width="150px"/>
      <el-table-column label="用户备注" align="center" prop="remark" 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" min-width="150px"/>
      <el-table-column label="部门 / 公司" align="center" prop="deptName" min-width="150px"/>
      <el-table-column label="用户状态" align="center" prop="status">
         <template slot-scope="scope">
              <dict-tag :options="userOptions" :value="scope.row.status"/>
              <p v-if="scope.row.status == 0 && scope.row.remark">{{scope.row.remark}}</p>
         </template>
      </el-table-column>
      <el-table-column label="注册时间" align="center" prop="createTime" min-width="150px"/>
       <el-table-column label="邀请码" align="center" prop="invitationCode" min-width="150px"/>
       <el-table-column label="邀请时间" align="center" prop="inviteTime" min-width="150px"/>
       <el-table-column label="客服" align="center" min-width="200px" prop="customerRoles">
        <template slot-scope="scope">
          <div v-for="(item, idx) in (scope.row.customerRoles ? scope.row.customerRoles.split(',') : [])" :key="idx" style="display: inline;">
            <el-tag type="primary" style="margin: 3px;">{{item}}</el-tag>
          </div>
        </template>
       </el-table-column>
       <el-table-column label="标签" align="center" min-width="200px" prop="tagsName">
        <template slot-scope="scope">
          <div v-for="(item, idx) in (scope.row.tagsName ? scope.row.tagsName.split(',') : [])" :key="idx" style="display: inline;">
            <el-tag type="success" style="margin: 3px;">{{item}}</el-tag>
          </div>
        </template>
       </el-table-column>

      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="190px">
        <template slot-scope="scope">
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleUpdate(scope.row)"
          >修改</el-button>
          <el-button
            size="mini"
            type="text"
            icon="el-icon-edit"
            @click="handleAIUserInfo(scope.row)"
          >AI获取用户信息</el-button>
          <el-button
            size="mini"
            type="text"
            @click="handledetails(scope.row)"
          >详情</el-button>
          <el-button
            size="mini"
            type="text"
            @click="handleDelete(scope.row)"
          >删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.startIndex"
      :limit.sync="queryParams.pageLimit"
      @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-dialog :title="tagConfig.title" :visible.sync="tagConfig.visible" width="800px" append-to-body>
      <div>搜索标签：
        <el-input v-model="tagConfig.queryParams.groupName" placeholder="请输入标签名称" clearable size="small"
          style="width: 200px;margin-right: 10px"/>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags(false)">搜索</el-button>
        <el-button type="primary" icon="el-icon-refresh" size="mini" @click="cancelSearchTags(false)">重置</el-button>
      </div>
      <div class="dialog-body">
        <div v-for="groupItem in tagConfig.tagGroupList" :key="groupItem.id">
          <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
            <span class="name-background">{{ groupItem.name }}</span>
          </div>
          <div class="tag-container">
            <a
              v-for="tagItem in groupItem.tags"
              class="tag-box"
              @click="tagSelection(tagItem)"
              :class="{ 'tag-selected': tagItem.isSelected }"
            >
              {{ tagItem.name }}
            </a>
          </div>
        </div>
      </div>
      <pagination
        v-show="tagConfig.total > 0"
        :total="tagConfig.total"
        :page.sync="tagConfig.queryParams.pageNum"
        :limit.sync="tagConfig.queryParams.pageSize"
        @pagination="getTagGroupList"
      />
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="bindOrUnbindTagSubmit">确 定</el-button>
        <el-button @click="bindTagCancel">取 消</el-button>
      </div>
    </el-dialog>

    <el-dialog title="搜索标签" :visible.sync="tagSearchConfig.visible" width="800px" append-to-body>
      <div>搜索标签：
        <el-input v-model="tagSearchConfig.queryParams.groupName" placeholder="请输入标签名称" clearable size="small"
          style="width: 200px;margin-right: 10px"/>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearchTags(true)">搜索</el-button>
        <el-button type="primary" icon="el-icon-refresh" size="mini" @click="cancelSearchTags(true)">重置</el-button>
      </div>
      <div class="dialog-body">
        <div v-for="groupItem in tagSearchConfig.tagGroupList" :key="groupItem.id">
          <div style="font-size: 20px;margin-top: 20px;margin-bottom: 20px;">
            <span class="name-background">{{ groupItem.name }}</span>
          </div>
          <div class="tag-container">
            <a
              v-for="tagItem in groupItem.tags"
              class="tag-box"
              @click="searchTagSelection(tagItem)"
              :class="{ 'tag-selected': tagItem.isSelected }"
            >
              {{ tagItem.name }}
            </a>
          </div>
        </div>
      </div>
      <pagination
        v-show="tagSearchConfig.total > 0"
        :total="tagSearchConfig.total"
        :page.sync="tagSearchConfig.queryParams.pageNum"
        :limit.sync="tagSearchConfig.queryParams.pageSize"
        @pagination="getSearchTagGroupList"
      />
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="searchTagSubmit">确 定</el-button>
        <el-button @click="searchTagCancel">取 消</el-button>
      </div>
    </el-dialog>

    <el-drawer
      :with-header="false"
      size="75%"
      :title="show.title"
      :visible.sync="show.open"
    >
      <userDetails  ref="userDetails" />
    </el-drawer>

      <!-- 选择app客服角色 -->
    <el-dialog :title="bindAIConfig.title" :visible.sync="bindAIConfig.visible" width="1000px" append-to-body :close-on-click-modal="false">
      <el-alert
        v-if="bindAIConfig.type === 0"
        type="error"
        :closable="false"
        show-icon
        class="bind-customer-tip"
      >
        <template slot="title">
          <div class="bind-customer-tip-title">一个客户最多只能绑定一个客服，多绑定不生效！！如需换绑请先解绑</div>
        </template>
      </el-alert>
      <CusRoleList
        v-if="bindAIConfig.visible"
        ref="customerBindRef"
        :multiple="false"
        :ids="bindAIConfig.presetIds"
        @confirm="customerSelectedConfirmCallForBind"
        @selectionChange="customerSelectionChangeCallForBind"
        :selected="bindAIConfig.selected"
      />
    </el-dialog>

    <!-- app客服搜索 -->
    <el-dialog title="客服搜索" :visible.sync="bindAISearch.visible" width="1000px" append-to-body>
      <CusRoleList ref="customerSearchRef"
        @confirm="customerSelectedConfirmCall"
        @selectionChange="customerSelectionChangeCall"
        :selected="bindAISearch.selected"
      />
    </el-dialog>

    <!-- ai获取用户信息 -->
    <el-dialog title="AI获取用户信息" :visible.sync="aiUserInfoDialog.visible" width="700px" append-to-body :close-on-click-modal="false">
      <el-form ref="form" :model="aiUserInfoDialog.userInfo" :rules="aiUserInfoDialog.rules" label-width="140px" v-loading="aiUserInfoDialog.loading">
        <div style="height: 500px; overflow: auto;" class="ai-user-info">
          <el-form-item label="姓名" prop="name">
            <el-input v-model="aiUserInfoDialog.userInfo.name" placeholder="请输入姓名" />
          </el-form-item>
          <el-form-item label="性别" prop="sex">
            <el-input v-model="aiUserInfoDialog.userInfo.sex" placeholder="请输入性别" />
          </el-form-item>
          <el-form-item label="年龄" prop="age">
            <el-input v-model="aiUserInfoDialog.userInfo.age" placeholder="请输入年龄" />
          </el-form-item>
          <el-form-item label="地区" prop="address">
            <el-input v-model="aiUserInfoDialog.userInfo.address" placeholder="请输入地区" />
          </el-form-item>
          <el-form-item label="行为习惯" prop="habits">
            <el-input v-model="aiUserInfoDialog.userInfo.habits" placeholder="请输入行为习惯" />
          </el-form-item>
          <el-form-item label="患病时间" prop="illnessTime">
            <el-input v-model="aiUserInfoDialog.userInfo.illnessTime" placeholder="请输入患病时间" />
          </el-form-item>
          <el-form-item label="身体状态" prop="body">
            <el-input v-model="aiUserInfoDialog.userInfo.body" placeholder="请输入身体状态" />
          </el-form-item>
          <el-form-item label="疾病" prop="disease">
            <el-input v-model="aiUserInfoDialog.userInfo.disease" placeholder="请输入疾病" />
          </el-form-item>
          <el-form-item label="提及的家人" prop="family">
            <el-input v-model="aiUserInfoDialog.userInfo.family" placeholder="请输入提及的家人" />
          </el-form-item>
          <el-form-item label="是否线下就诊" prop="isLine">
            <el-input v-model="aiUserInfoDialog.userInfo.isLine" placeholder="是否线下就诊" />
          </el-form-item>
          <el-form-item label="家人的疾病" prop="familyDisease">
            <el-input v-model="aiUserInfoDialog.userInfo.familyDisease" placeholder="请输入家人的疾病" />
          </el-form-item>
          <el-form-item label="用户分类" prop="userType">
          <el-input v-model="aiUserInfoDialog.userInfo.userType" placeholder="用户分类" />
          </el-form-item>
          <el-form-item label="是否本人会诊" prop="isSelf">
            <el-input v-model="aiUserInfoDialog.userInfo.isSelf" placeholder="请输入是否本人会诊" />
          </el-form-item>
          <el-form-item label="什么情况加重或缓解" prop="intensify">
            <el-input v-model="aiUserInfoDialog.userInfo.intensify" placeholder="请输入什么情况加重或缓解" />
          </el-form-item>
          <el-form-item label="是否怕热或者怕冷" prop="isCold">
            <el-input v-model="aiUserInfoDialog.userInfo.isCold" placeholder="请输入是否怕热或者怕冷" />
          </el-form-item>
          <el-form-item label="怕冷或怕热的部位" prop="coldBody">
            <el-input v-model="aiUserInfoDialog.userInfo.coldBody" placeholder="请输入怕冷或怕热的部位" />
          </el-form-item>
          <el-form-item label="出汗情况" prop="sweat">
            <el-input v-model="aiUserInfoDialog.userInfo.sweat" placeholder="请输入出汗情况" />
          </el-form-item>
          <el-form-item label="其他情况" prop="other">
            <el-input v-model="aiUserInfoDialog.userInfo.other" placeholder="请输入其他情况" />
          </el-form-item>
          <el-form-item label="大小便情况" prop="toilet">
            <el-input v-model="aiUserInfoDialog.userInfo.toilet" placeholder="请输入大小便情况" />
          </el-form-item>
          <el-form-item label="饮食情况" prop="eat">
            <el-input v-model="aiUserInfoDialog.userInfo.eat" placeholder="请输入饮食情况" />
          </el-form-item>
          <el-form-item label="经期如何" prop="menses">
            <el-input v-model="aiUserInfoDialog.userInfo.menses" placeholder="请输入经期如何 女 55岁以下" />
          </el-form-item>
          <el-form-item label="现在使用的药品" prop="medicine">
            <el-input v-model="aiUserInfoDialog.userInfo.medicine" placeholder="请输入现在使用的药品" />
          </el-form-item>
          <el-form-item label="体质" prop="constitution">
            <el-input v-model="aiUserInfoDialog.userInfo.constitution" placeholder="请输入体质" />
          </el-form-item>
          <el-form-item label="推荐用药" prop="recommendMedicine">
            <el-input v-model="aiUserInfoDialog.userInfo.recommendMedicine" placeholder="请输入推荐用药" />
          </el-form-item>
          <el-form-item label="咨询产品" prop="consultProduct">
            <el-input v-model="aiUserInfoDialog.userInfo.consultProduct" placeholder="请输入咨询产品" />
          </el-form-item>
          <el-form-item label="是否已经购买产品" prop="isBuy">
            <el-input v-model="aiUserInfoDialog.userInfo.isBuy" placeholder="请输入是否已经购买产品" />
          </el-form-item>
          <el-form-item label="已经购买的产品" prop="buyProduct">
            <el-input v-model="aiUserInfoDialog.userInfo.buyProduct" placeholder="请输入已经购买的产品" />
          </el-form-item>
          <el-form-item label="产品交流" prop="productTalk">
            <el-input v-model="aiUserInfoDialog.userInfo.productTalk" placeholder="请输入产品交流信息" />
          </el-form-item>
          <el-form-item label="疾病交流" prop="diseaseTalk">
            <el-input v-model="aiUserInfoDialog.userInfo.diseaseTalk" placeholder="请输入疾病交流信息" />
          </el-form-item>
          <el-form-item label="渠道类型" prop="channelType">
            <el-input v-model="aiUserInfoDialog.userInfo.channelType" placeholder="请输入渠道类型信息" />
          </el-form-item>
        </div>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitAiUserInfo" :disabled="aiUserInfoDialog.loading">确 定</el-button>
        <el-button @click="closeAIUserInfoDialog">取 消</el-button>
      </div>
    </el-dialog>

  </div>
</template>

<script>
import { getUser, delUser, addUser, updateUser } from "@/api/store/user";
import {
  bindUserCusByIdsV2,
  unbindUserCusByIdsV2,
  listBoundSales,
  listAppUser,
  exportAppUser
} from '@/api/app/user';
import { listTagGroupForUserBindTag } from "@/api/app/tag/tagGroup";
import {
  bindTagV2,
  unbindTagV2,
} from "@/api/app/tag/bindTag";
import { getAIUserInfoByUserId, saveAiUserInfo, } from '@/api/app/user/userInfo';
import { listDept, } from '@/api/system/appDept';

import CusRoleList from '@/views/app/user/CusRoleList.vue';
import userDetails from '@/views/store/components/userDetails.vue';
import Treeselect from '@riophae/vue-treeselect'
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
  name: "UserTag",
  components: { Treeselect, userDetails, CusRoleList},
  data() {
    return {
      show:{
        title:"用户详情",
        open:false,
      },
      userOptions: [],
      // 遮罩层
      loading: false,
      // 导出遮罩层
      exportLoading: false,
      // 选中数组
      ids: [],
      orOptions:[],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 用户表格数据
      userList: [],
      // app部门下拉选项
      deptOptions: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      createTime:null,
      firstLoginTime:null,
      // 查询参数
      queryParams: {
        startIndex: 1,
        pageLimit: 10,
        nickName: null,
        phone: null,
        phoneMk: null,
        status: null,
        invitationCode: null,
        deptId: null,
        inviteDate: null,
        customerRoles: [],
        tagIds: [],
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {
        nickName: [
          { required: true, message: "昵称不能为空", trigger: "blur" }
        ],
        status: [
          { required: true, message: "用户状态不能为空", trigger: "blur" }
        ],
        integral: [
          { required: true, message: "用户积分不能为空", trigger: "blur" }
        ],
      },
      tagConfig: {
        visible: false,//对话框是否展示
        enableFilter: false,//是否开启过滤模式，开启则是引用外部条件，针对外部条件过滤的所有数据做 绑定/解绑 标签，否则根据针对外部勾选的用户做 绑定/解绑 标签操作
        title: null,
        opType: 0,//0-添加，1-移除，2-搜索
        queryParams: {
          groupName: null,
          pageNum: 1,
          pageSize: 10,
        },
        total: 0,
        tagGroupList: [],
        selected: [],
      },
      tagSearchConfig: {
        visible: false,//对话框是否展示
        queryParams: {
          groupName: null,
          pageNum: 1,
          pageSize: 10,
        },
        total: 0,
        tagGroupList: [],
        selected: [],
      },
      bindAIConfig: {
        title: null,
        type: null,
        visible: false,
        enableFilter: false,
        selected: [],
        // 解绑时预填：仅展示这些已绑定销售
        presetIds: [],
      },
      bindAISearch: {
        visible: false,
        selected: [],
        // 缓存子组件实例
        cusRoleListRef: null,
      },
      aiUserInfoDialog: {
        visible: false,
        loading: false,
        rules: {},
        userId: null,
        userInfo: {
          id: null,
          name: null,
          sex: null,
          age: null,
          address: null,
          habits: null,
          illnessTime: null,
          body: null,
          family: null,
          familyDisease: null,
          disease: null,
          isLine: null,
          userType: null,
          isSelf: null,
          intensify: null,
          isCold: null,
          coldBody: null,
          sweat: null,
          other: null,
          toilet: null,
          eat: null,
          menses: null,
          medicine: null,
          constitution: null,
          recommendMedicine: null,
          consultProduct: null,
          isBuy: null,
          buyProduct: null,
          productTalk: null,
          diseaseTalk: null,
          channelType: null,
        },
      },
      userDetails: {
        visible: false,
        rowInfo: null,
        count: 0,
      },
    };
  },
  created() {
    this.getDicts("sys_user_status").then(response => {
      this.userOptions = response.data;
    });
    this.getDicts("sys_company_or").then(response => {
      this.orOptions = response.data;
    });
    this.getDeptList();
  },
  methods: {
    getDeptList() {
      //app个人部门
      listDept().then(response => {
        if (response.code === 200) {
          this.deptOptions = this.handleTree(response.data, "deptId");
        } else {
          this.deptOptions = [];
        }
      }).catch(() => {
        this.deptOptions = [];
      });
    },
    normalizer(node) {
      if (node.children && !node.children.length) {
        delete node.children;
      }
      return {
        id: node.deptId,
        label: node.deptName,
        children: node.children
      };
    },
    handleTree(data, id, parentId, children) {
      id = id || 'id';
      parentId = parentId || 'parentId';
      children = children || 'children';
      var tree = [];
      var map = {};
      data.forEach(function(item) {
        map[item[id]] = item;
      });
      data.forEach(function(item) {
        var parent = map[item[parentId]];
        if (parent) {
          (parent[children] || (parent[children] = [])).push(item);
        } else {
          tree.push(item);
        }
      });
      return tree;
    },
    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;
      }
    },
    changeLoginTime() {
      if (this.firstLoginTime != null) {
        this.queryParams.startLoginTime = this.firstLoginTime[0];
        this.queryParams.endLoginTime = this.firstLoginTime[1];
      } else {
        this.queryParams.startLoginTime = null;
        this.queryParams.endLoginTime = null;
      }
    },
    handledetails(row) {
      this.show.open = true;
      setTimeout(() => {
        this.$refs.userDetails.getDetails(row.userId);
      }, 1);
    },
    /** 查询用户列表 */
    getList() {
      this.loading = true;
      let query = JSON.parse(JSON.stringify(this.queryParams));
      query['tagIds'] = this.tagSearchConfig.selected.map(item => item.tagId);
      query['customerRoles'] = this.bindAISearch.selected.map(item => item.id);
      if (!this.isEmpty(query.inviteDate)) {
        let dateRange = query.inviteDate;
        query['inviteStartDate'] = dateRange[0] + ' 00:00:00';
        query['inviteEndDate'] = dateRange[1] + ' 23:59:59';
        delete query['inviteDate']
      }
      listAppUser(query).then(response => {
        this.userList = response.rows;
        this.total = response.total;
        this.loading = false;
      });
    },
    /**
     * 确认选中回调
     * @param selected
     */
    customerSelectedConfirmCall(selected) {
      this.bindAISearch.visible = false;
    },
    /**
     * 选中元素改变回调
     * @param selected
     */
    customerSelectionChangeCall(config) {
      let selected = config.selected;
      //单行操作
      if (config.mode === 0) {
        let row = config.row;
        if (selected) {
          this.bindAISearch.selected.push(row)
        } else {
          this.bindAISearch.selected = this.bindAISearch.selected.filter(m => m.id != row.id);
        }
      }
      //操作当前页所有行
      else {
        let list = config.rows;
        if (selected) {
          list.map(l => this.bindAISearch.selected.push(l));
        } else {
          list.map(l => {
            for (let i = 0; i < this.bindAISearch.selected.length; i++) {
              if (l.id == this.bindAISearch.selected[i].id) {
                this.bindAISearch.selected.splice(i, 1);
              }
            }
          })
        }
      }
    },
    // 取消按钮
    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.startIndex = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    async resetQuery() {
      this.resetForm("queryForm");
      this.resetTagSearchConfig();
      this.resetCusSearch();
      this.handleQuery();
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.userId)
      this.single = selection.length !== 1
      this.multiple = !selection.length
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.reset();
      this.open = true;
      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)
      });
    },
    /**
     * ai获取用户信息
     */
    handleAIUserInfo(row) {
      this.aiUserInfoDialog.visible = true;
      this.aiUserInfoDialog.userId = row.userId;
      this.getAIUserInfo(row.userId);
    },
    closeAIUserInfoDialog() {
      this.aiUserInfoDialog.visible = false;
      this.resetAIUserInfo();
    },
    /**
     * 重置AI用户信息
     */
    resetAIUserInfo() {
      this.aiUserInfoDialog.userInfo = {
          name: null,
          sex: null,
          age: null,
          address: null,
          habits: null,
          illnessTime: null,
          body: null,
          familyDisease: null,
          disease: null,
          isLine: null,
          userType: null,
          isSelf: null,
          intensify: null,
          isCold: null,
          coldBody: null,
          sweat: null,
          other: null,
          toilet: null,
          eat: null,
          menses: null,
          medicine: null,
          constitution: null,
          recommendMedicine: null,
          consultProduct: null,
          isBuy: null,
          buyProduct: null,
          productTalk: null,
          diseaseTalk: null,
          channelType: null,
        }
    },
    /**
     * 获取ai用户信息
     */
    async getAIUserInfo(userId) {
      this.aiUserInfoDialog.loading = true;
      let userInfo = await getAIUserInfoByUserId(userId);
      let userInfoData = userInfo.data;
      if (userInfoData) {
        this.aiUserInfoDialog.userInfo = userInfoData;
      }
      this.aiUserInfoDialog.loading = false;
    },
    /**
     * 提交ai用户信息
     */
    async submitAiUserInfo() {
      this.aiUserInfoDialog.loading = true;
      let realInfo = JSON.parse(JSON.stringify(this.aiUserInfoDialog.userInfo));
      try {
        for (let key in realInfo) {
          let source = realInfo[key];
          realInfo[key] = this.isEmpty(source) ? null : this.isString(source) ? source.trim() : source;
        }
        realInfo['fsUserId'] = this.aiUserInfoDialog.userId;
        let save = await saveAiUserInfo(realInfo);
        if (save.data) {
          this.msgSuccess("修改成功");
          this.aiUserInfoDialog.visible = false;
          this.resetAIUserInfo();
        } else {
          this.msgError("修改失败");
        }
      } catch (e) {
        console.warn(e);
        this.msgError("修改失败");
      } finally {
        this.aiUserInfoDialog.loading = false;
      }
    },
    isEmpty(value) {
      return value === null || value === undefined || value.length === 0;
    },
    isString(val) {
      return Object.prototype.toString.call(val) === '[object String]';
    },
    /** 提交按钮 */
    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() {
      // 空值保护：深拷贝前先判断
      if (!this.queryParams) return this.$message.warning("查询参数异常");

      const queryParams = JSON.parse(JSON.stringify(this.queryParams));
      delete queryParams['startIndex'];
      delete queryParams['pageLimit'];

      // 空值判断：避免map空数组报错
      queryParams['tagIds'] = this.tagSearchConfig.selected?.map(item => item.tagId) || [];
      queryParams['customerRoles'] = this.bindAISearch.selected?.map(item => item.id) || [];

      // 日期参数空值保护
      if (!this.isEmpty(queryParams.inviteDate)) {
        let dateRange = queryParams.inviteDate;
        queryParams['inviteStartDate'] = dateRange[0] + ' 00:00:00';
        queryParams['inviteEndDate'] = dateRange[1] + ' 23:59:59';
        delete queryParams['inviteDate'];
      } else {
        delete queryParams['inviteDate']; // 空值时直接删除
      }

      this.$confirm('是否确认导出所有用户数据项?', "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        this.exportLoading = true;
        return exportAppUser(queryParams);
      }).then(response => {
        // 接口返回码判断（适配常见的后端返回格式）
        if (response.code === 200) {
          this.download(response.msg);
          this.msgSuccess("导出成功");
        } else {
          this.msgError("导出失败：" + response.msg);
        }
        this.exportLoading = false;
      }).catch(() => {
        this.exportLoading = false; // 取消/失败时重置加载状态
        this.msgError("导出取消或失败");
      });
    },
    openTagSearchPage() {
      this.getSearchTagGroupList();
      this.tagSearchConfig.visible = true;
    },
    openCusSearchPage() {
      this.bindAISearch.visible = true;
    },
    searchTagSubmit() {
      this.tagSearchConfig.visible = false;
    },
    searchTagCancel() {
      this.tagSearchConfig.visible = false;
    },
    async resetTagSearchConfig() {
      this.tagSearchConfig = {
        visible: false,//对话框是否展示
        queryParams: {
          groupName: null,
          pageNum: 1,
          pageSize: 10,
        },
        total: 0,
        tagGroupList: [],
        selected: [],
      }
    },
    async resetCusSearch() {
      this.bindAISearch = {
        visible: false,
        selected: [],
      }
    },
    /**
     * 用户绑定标签页面
     */
    openBindTagPage(enableFilter = false, opType = 0) {
      this.tagConfig.enableFilter = enableFilter;
      this.tagConfig.opType = opType;
      if (!enableFilter && (this.ids === null || this.ids.length === 0)) {
        this.$message.closeAll();
        return this.$message('请选择需要添加标签的用户');
      }
      this.getTagGroupList();
      this.tagConfig.title = '批量添加标签' + (enableFilter ? '(筛选条件)' : '');
      this.tagConfig.visible = true;
    },
    /**
     * 用户解绑标签页面
     */
    openUnbindTagPage(enableFilter = false, opType = 1) {
      this.tagConfig.enableFilter = enableFilter;
      this.tagConfig.opType = opType;
      if (!enableFilter && (this.ids === null || this.ids.length === 0)) {
        this.$message.closeAll();
        return this.$message('请选择需要移除标签的用户');
      }
      this.getTagGroupList();
      this.tagConfig.title = '批量移除标签' + (enableFilter ? '(筛选条件)' : '');
      this.tagConfig.visible = true;
    },
    handleCloseTags(tag) {
      this.tagSearchConfig.selected = this.tagSearchConfig.selected.filter(item => item.tagId != tag.tagId);
    },
    handleCloseCus(cus) {
      this.bindAISearch.selected = this.bindAISearch.selected.filter(item => item.id != cus.id);
    },
    /**
     * 绑定/解绑 标签页面搜索
     */
    handleSearchTags(isSearch = false) {
      if (isSearch) {
        this.tagSearchConfig.queryParams.pageNum = 1;
        this.getSearchTagGroupList();
      } else {
        this.tagConfig.queryParams.pageNum = 1;
        this.getTagGroupList();
      }
    },
    /**
     * 绑定/解绑 标签页面重置
     */
    cancelSearchTags(isSearch = false) {
      if (isSearch) {
        this.tagSearchConfig.queryParams = {
          groupName: null,
          pagenum: 1,
          pagesize: 10,
        }
        this.getSearchTagGroupList();
      } else {
        this.tagConfig.queryParams = {
          groupName: null,
          pagenum: 1,
          pagesize: 10,
        }
        this.getTagGroupList();
      }
    },
    /**
     * 切换选中状态
     * @param row
     */
    tagSelection(row) {
      row.isSelected = !row.isSelected;
      if (row.isSelected) {
        this.tagConfig.selected.push({ tagId: row.id, tagName: row.name });
      }
      //
      else {
        this.tagConfig.selected = this.tagConfig.selected.filter(item => item.tagId !== row.id);
      }
      this.$forceUpdate();
    },
    searchTagSelection(row) {
      row.isSelected = !row.isSelected;
      if (row.isSelected) {
        this.tagSearchConfig.selected.push({ tagId: row.id, tagName: row.name });
      }
      //
      else {
        this.tagSearchConfig.selected = this.tagSearchConfig.selected.filter(item => item.tagId !== row.id);
      }
      this.$forceUpdate();
    },
    /**
     * 重置 绑定/解绑 标签参数
     */
    resetBindTag() {
      this.tagConfig = {
        visible: false,
        enableFilter: false,
        title: null,
        opType: 0,
        queryParams: {
          groupName: null,
          pageNum: 1,
          pagesize: 10,
        },
        total: 0,
        tagGroupList: [],
        selected: [],
      }
    },
    /**
     * 绑定/解绑 标签-提交
     */
    bindOrUnbindTagSubmit() {
      let opType = this.tagConfig.opType;
      let tmpParam = {};
      if (!this.tagConfig.selected || this.tagConfig.selected.length === 0) {
        return this.$message('请选择标签');
      }
      tmpParam['enableFilter'] = this.tagConfig.enableFilter;
      tmpParam['tagId'] = this.tagConfig.selected.map(item => item.tagId);
      tmpParam['userId'] = this.ids;
      const queryParams = JSON.parse(JSON.stringify(this.queryParams));
      delete queryParams['startIndex'];
      delete queryParams['pageLimit'];
      queryParams['tagIds'] = this.tagSearchConfig.selected.map(item => item.tagId);
      queryParams['customerRoles'] = this.bindAISearch.selected.map(item => item.id);
      if (queryParams.inviteDate) {
        let dateRange = queryParams.inviteDate;
        queryParams['inviteStartDate'] = dateRange[0] + ' 00:00:00';
        queryParams['inviteEndDate'] = dateRange[1] + ' 23:59:59';
        delete queryParams['inviteDate']
      }
      tmpParam['fsUserParam'] = queryParams;
      //绑定标签
      if (opType === 0) {
        bindTagV2(tmpParam)
          .then(res => {
            this.tagConfig.visible = false;
            this.resetBindTag();
            this.msgSuccess("正在添加中!");
            setTimeout(() => {
              this.getList();
            }, 500);
          })
          .catch(err => {
            this.msgError("添加标签失败！");
          })
      }
      //解绑标签
      else {
        unbindTagV2(tmpParam)
          .then(res => {
            this.tagConfig.visible = false;
            this.msgSuccess("正在移除中!");
            this.resetBindTag();
            setTimeout(() => {
              this.getList();
            }, 500);
          })
          .catch(err => {
            this.msgError("移除标签失败！");
          })
      }
    },
    /**
     * 绑定/解绑 标签-取消
     */
    bindTagCancel() {
      this.resetBindTag();
    },
    /**
     * 查询标签列表
     */
    getTagGroupList() {
      listTagGroupForUserBindTag(this.tagConfig.queryParams).then(response => {
        this.tagConfig.tagGroupList = response.rows;
        this.tagConfig.total = response.total;
      });
    },
    getSearchTagGroupList() {
      listTagGroupForUserBindTag(this.tagSearchConfig.queryParams).then(response => {
        let tRows = response.rows;
        if (tRows && tRows.length > 0) {
          tRows.forEach(group => {
            group.tags.forEach(tag => {
              if (this.tagSearchConfig.selected.some(item => item.tagId === tag.id)) {
                tag.isSelected = true;
              } else {
                tag.isSelected = false;
              }
            })
          });
        }
        this.tagSearchConfig.tagGroupList = tRows;
        this.tagSearchConfig.total = response.total;
      });
    },
    /**
     * 打开绑定客服页面
     * @param enableFilter 是否开启过滤模式
     * @param type 0-绑定，1-解绑
     */
    async openbindAIPage(enableFilter = false, type = 1) {
      this.bindAIConfig.enableFilter = enableFilter;
      if (!enableFilter && (this.ids === null || this.ids.length === 0)) {
        this.$message.closeAll();
        return this.$message('请选择需要设置客服的用户');
      }
      this.bindAIConfig.title = type == 0 ? '换绑销售' : '解绑客服';
      this.bindAIConfig.type = type;
      this.bindAIConfig.selected = [];
      this.bindAIConfig.presetIds = [];

      // 解绑：预填已绑定销售，便于在弹窗中直接选择
      if (type == 1) {
        let presetIds = [];
        try {
          if (enableFilter) {
            const tmpParam = this.buildBindUnbindQueryParam();
            const res = await listBoundSales(tmpParam);
            presetIds = (res.data || []).map(id => String(id));
          } else {
            const idSet = this.ids.map(String);
            const rows = (this.userList || []).filter(u => idSet.includes(String(u.userId)));
            const salesSet = new Set();
            rows.forEach(row => {
              if (!row.customerRoleIds) {
                return;
              }
              String(row.customerRoleIds).split(',').forEach(id => {
                const trimmed = (id || '').trim();
                if (trimmed) {
                  salesSet.add(trimmed);
                }
              });
            });
            if (salesSet.size === 0) {
              const res = await listBoundSales({
                enableFilter: false,
                userId: this.ids,
              });
              (res.data || []).forEach(id => salesSet.add(String(id)));
            }
            presetIds = Array.from(salesSet);
          }
        } catch (e) {
          this.$message.closeAll();
          return this.$message.error('获取已绑定销售失败');
        }
        if (!presetIds.length) {
          this.$message.closeAll();
          return this.$message.warning('所选用户未绑定客服');
        }
        this.bindAIConfig.presetIds = presetIds;
      }

      this.bindAIConfig.visible = true;
    },
    /**
     * 组装绑定/解绑请求参数（筛选条件）
     */
    buildBindUnbindQueryParam() {
      const tmpParam = {};
      tmpParam['enableFilter'] = this.bindAIConfig.enableFilter;
      tmpParam['userId'] = this.ids;
      const queryParams = JSON.parse(JSON.stringify(this.queryParams));
      delete queryParams['startIndex'];
      delete queryParams['pageLimit'];
      queryParams['tagIds'] = this.tagSearchConfig.selected.map(item => item.tagId);
      queryParams['customerRoles'] = this.bindAISearch.selected.map(item => item.id);
      if (queryParams.inviteDate) {
        let dateRange = queryParams.inviteDate;
        queryParams['inviteStartDate'] = dateRange[0] + ' 00:00:00';
        queryParams['inviteEndDate'] = dateRange[1] + ' 23:59:59';
        delete queryParams['inviteDate']
      }
      tmpParam['fsUserParam'] = queryParams;
      return tmpParam;
    },
    /**
     * 绑定客服页面-选中客服
     */
    customerSelectionChangeCallForBind(config) {
      let selected = config.selected;
      // 单选模式：最多只保留一个客服
      if (config.mode === 0) {
        let row = config.row;
        if (selected) {
          this.bindAIConfig.selected = [row];
        } else {
          this.bindAIConfig.selected = this.bindAIConfig.selected.filter(m => m.id != row.id);
        }
        return;
      }
      // 全选（单选模式下 CusRoleList 已拦截，此处兜底忽略）
    },
    /**
     * 保存绑定的客服
     */
    async customerSelectedConfirmCallForBind() {
      if (!this.bindAIConfig.selected || this.bindAIConfig.selected.length !== 1) {
        this.$message.closeAll();
        return this.$message.warning('请选择一个客服');
      }
      let tmpParam = this.buildBindUnbindQueryParam();
      tmpParam['roleId'] = this.bindAIConfig.selected.map(item => item.id) || [];
      let res;
      if (this.bindAIConfig.type == 0) {
        res = await bindUserCusByIdsV2(tmpParam);
        this.msgSuccess("正在绑定中!");
      } else {
        res = await unbindUserCusByIdsV2(tmpParam);
        this.msgSuccess("正在解绑中!");
      }
      this.getList();
      this.bindAIConfig.visible = false;
      this.bindAIConfig.selected = [];
      this.bindAIConfig.presetIds = [];
    },
  }
};
</script>
<style lang="scss" scoped>
.dialog-body {
  height: 400px;
  overflow: auto;
}

.tag-container {
  display: flex;
  flex-wrap: wrap; /* 超出宽度时自动换行 */
  gap: 8px; /* 设置标签之间的间距 */
}

.name-background {
  display: inline-block;
  background-color: #abece6; /* 背景颜色 */
  padding: 4px 8px; /* 调整内边距，让背景包裹文字 */
  border-radius: 4px; /* 可选：设置圆角 */
}

.tag-box {
  padding: 8px 12px;
  border: 1px solid #989797;
  border-radius: 4px;
  cursor: pointer;
  display: inline-block;
}

.tag-selected {
  background-color: #00bc98;
  color: #fff;
  border-color: #00bc98;
}

.el-tag + .el-tag {
  margin-left: 10px;
}

::v-deep  .ai-user-info .el-form-item__label {
  text-align: right !important;
}

.bind-customer-tip {
  margin-bottom: 16px;
  padding: 18px 20px !important;
  border: 2px solid #f56c6c !important;
  border-radius: 6px;
  background-color: #fef0f0 !important;
}
.bind-customer-tip-title {
  font-size: 20px;
  font-weight: 700;
  line-height: 1.6;
  color: #f56c6c;
  letter-spacing: 1px;
}
::v-deep .bind-customer-tip .el-alert__icon {
  font-size: 28px;
  width: 28px;
}
</style>
