index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. <template>
  2. <div class="app-container">
  3. <el-row :gutter="20">
  4. <el-col :span="6" :xs="24">
  5. <el-card class="box-card">
  6. <div slot="header" class="clearfix">
  7. <span>个人信息</span>
  8. </div>
  9. <div>
  10. <div class="text-center">
  11. <userAvatar :user="user" />
  12. </div>
  13. <ul class="list-group list-group-striped">
  14. <li class="list-group-item">
  15. <svg-icon icon-class="user" />用户名称
  16. <div class="pull-right">{{ user.userName }}</div>
  17. </li>
  18. <li class="list-group-item">
  19. <svg-icon icon-class="phone" />手机号码
  20. <div class="pull-right">{{ user.phonenumber }}</div>
  21. </li>
  22. <li class="list-group-item">
  23. <svg-icon icon-class="email" />用户邮箱
  24. <div class="pull-right">{{ user.email }}</div>
  25. </li>
  26. <li class="list-group-item">
  27. <svg-icon icon-class="tree" />所属部门
  28. <div class="pull-right" v-if="user.dept">{{ user.dept.deptName }} / {{ postGroup }}</div>
  29. </li>
  30. <li class="list-group-item">
  31. <svg-icon icon-class="peoples" />所属角色
  32. <div class="pull-right">{{ roleGroup }}</div>
  33. </li>
  34. <li class="list-group-item">
  35. <svg-icon icon-class="date" />创建日期
  36. <div class="pull-right">{{ user.createTime }}</div>
  37. </li>
  38. </ul>
  39. <div class="text-center" style="margin-top: 20px;">
  40. <el-button
  41. size="mini"
  42. type="primary"
  43. icon="el-icon-user"
  44. @click="handleBindMember"
  45. v-if="!user.fsUserId"
  46. >绑定会员</el-button>
  47. <div v-if="user.fsUserIdArray && user.fsUserIdArray.length > 0" style="margin-top: 10px;">
  48. <el-tag type="success">已绑定会员</el-tag>
  49. <div style="margin-top: 10px;">
  50. <div
  51. v-for="(fsUserId, index) in user.fsUserIdArray"
  52. :key="index" style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;"
  53. >
  54. <span style="font-size: 12px; color: #666;">会员ID: {{ fsUserId }}</span>
  55. <el-button
  56. size="mini"
  57. type="danger"
  58. icon="el-icon-delete"
  59. @click="handleUnbindSpecificMember(fsUserId)"
  60. >
  61. 解绑
  62. </el-button>
  63. </div>
  64. </div>
  65. </div>
  66. </div>
  67. <div class="text-center" style="margin-top: 20px;" v-if="needWxTemplateMsg">
  68. <div v-if="user.wechatBindStatus">
  69. <el-tag type="success">已绑定服务号通知</el-tag>
  70. </div>
  71. <div v-else>
  72. <el-button type="primary" @click="openWechatBindDialog">
  73. 订阅服务号通知
  74. </el-button>
  75. </div>
  76. </div>
  77. </div>
  78. </el-card>
  79. </el-col>
  80. <el-col :span="18" :xs="24">
  81. <el-card>
  82. <div slot="header" class="clearfix">
  83. <span>基本资料</span>
  84. </div>
  85. <el-tabs v-model="activeTab">
  86. <el-tab-pane label="基本资料" name="userinfo">
  87. <userInfo :user="user" />
  88. </el-tab-pane>
  89. <el-tab-pane label="修改密码" name="resetPwd">
  90. <resetPwd :user="user" />
  91. </el-tab-pane>
  92. </el-tabs>
  93. </el-card>
  94. </el-col>
  95. </el-row>
  96. <!-- 绑定会员对话框 -->
  97. <el-dialog v-if="member && member.hasOwnProperty('title')" :title="member.title" :visible.sync="member.open" width="600px" append-to-body>
  98. <!-- 添加筛选表单 -->
  99. <el-form :model="memberQueryParams" :inline="true" @submit.native.prevent>
  100. <el-form-item label="会员ID">
  101. <el-input
  102. v-model="memberQueryParams.userId"
  103. placeholder="请输入会员ID"
  104. clearable style="width: 160px;"
  105. @keyup.enter.native="handleMemberQuery"
  106. />
  107. </el-form-item>
  108. <el-form-item label="昵称">
  109. <el-input
  110. v-model="memberQueryParams.nickName"
  111. placeholder="请输入昵称"
  112. clearable style="width: 160px;"
  113. @keyup.enter.native="handleMemberQuery"
  114. />
  115. </el-form-item>
  116. <el-form-item label="手机号">
  117. <el-input
  118. v-model="memberQueryParams.phone"
  119. placeholder="请输入手机号"
  120. clearable style="width: 160px;"
  121. @keyup.enter.native="handleMemberQuery"
  122. />
  123. </el-form-item>
  124. <el-form-item>
  125. <el-button icon="el-icon-search" size="mini" @click="handleMemberQuery">搜索</el-button>
  126. <el-button icon="el-icon-refresh" size="mini" @click="resetMemberQuery">重置</el-button>
  127. </el-form-item>
  128. </el-form>
  129. <div style="height: 300px; margin-top: 10px;">
  130. <el-table
  131. :data="memberList"
  132. height="220"
  133. highlight-current-row
  134. @current-change="selectMember"
  135. v-loading="loading"
  136. >
  137. <el-table-column property="userId" label="ID" width="80"></el-table-column>
  138. <el-table-column property="nickName" label="昵称" width="120"></el-table-column>
  139. <el-table-column property="phone" label="手机号" width="120"></el-table-column>
  140. <el-table-column property="status" label="绑定状态" width="100">
  141. <template slot-scope="scope">
  142. <el-tag
  143. :type="scope.row.status === 1 ? 'success' : 'info'"
  144. size="mini">
  145. {{ scope.row.status === 1 ? '已绑定' : '未绑定' }}
  146. </el-tag>
  147. </template>
  148. </el-table-column>
  149. </el-table>
  150. <!-- 分页组件 -->
  151. <pagination
  152. v-show="memberTotal > 0"
  153. :total="memberTotal"
  154. :page.sync="memberQueryParams.pageNum"
  155. :limit.sync="memberQueryParams.pageSize"
  156. @pagination="getMemberList" style="margin-top: 10px; text-align: center;"
  157. />
  158. </div>
  159. <div slot="footer" class="dialog-footer">
  160. <el-button @click="cancelBindMember">取 消</el-button>
  161. <el-button type="primary" @click="confirmBindMember">确 定</el-button>
  162. </div>
  163. </el-dialog>
  164. <el-dialog
  165. title="订阅服务号通知"
  166. :visible.sync="bindDialogVisible"
  167. width="360px"
  168. :close-on-click-modal="false"
  169. >
  170. <div class="text-center">
  171. <img v-if="wechatQrcode" :src="wechatQrcode" style="width: 260px; height: 260px;" />
  172. <p style="margin-top: 10px;">请使用微信扫码绑定服务号通知</p>
  173. </div>
  174. <span slot="footer" class="dialog-footer">
  175. <el-button @click="bindDialogVisible = false">关闭</el-button>
  176. </span>
  177. </el-dialog>
  178. </div>
  179. </template>
  180. <script>
  181. import userAvatar from "./userAvatar";
  182. import userInfo from "./userInfo";
  183. import resetPwd from "./resetPwd";
  184. import { getUserProfile,getSaleBindUserList, bindSaleAndFsUser, unbindSaleAndFsUser } from "@/api/company/companyUser";
  185. import { getWechatBindQrcode, checkWechatBindStatus } from "@/api/wechat";
  186. export default {
  187. name: "Profile",
  188. components: { userAvatar, userInfo, resetPwd },
  189. data() {
  190. return {
  191. user: {},
  192. roleGroup: {},
  193. postGroup: {},
  194. activeTab: "userinfo",
  195. bindDialogVisible: false,
  196. wechatQrcode: "",
  197. wechatBindTimer: null,
  198. needWxTemplateMsg: false,
  199. // 绑定会员相关数据
  200. member: {
  201. open: false,
  202. title: "绑定会员"
  203. },
  204. memberList: [],
  205. selectedMember: null,
  206. currentCompanyId: null,
  207. memberTotal: 0,
  208. loading: false,
  209. // 添加筛选参数
  210. memberQueryParams: {
  211. nickName: null,
  212. phone: null,
  213. userId: null,
  214. pageNum: 1,
  215. pageSize: 10
  216. },
  217. };
  218. },
  219. created() {
  220. if (process.env.VUE_APP_COMPANY_NAME ==="河北红德堂医药连锁有限公司保定第五十七分公司"){
  221. this.needWxTemplateMsg = true
  222. }
  223. this.getUser();
  224. },
  225. methods: {
  226. getUser() {
  227. getUserProfile().then(response => {
  228. this.user = response.data;
  229. this.roleGroup = response.roleGroup;
  230. this.postGroup = response.postGroup;
  231. // 将 fsUserId 字符串拆分为数组
  232. if (this.user.fsUserId) {
  233. this.user.fsUserIdArray = this.user.fsUserId.split(',').map(id => id.trim());
  234. } else {
  235. this.user.fsUserIdArray = [];
  236. }
  237. });
  238. },
  239. /**
  240. * 绑定会员按钮操作
  241. */
  242. handleBindMember() {
  243. // 设置当前用户的ID
  244. this.currentCompanyId = this.user.userId;
  245. // 重置筛选参数
  246. this.memberQueryParams = {
  247. nickName: null,
  248. phone: null,
  249. pageNum: 1, // 重置为第一页
  250. pageSize: 10 // 保持每页数量
  251. };
  252. this.selectedMember = null;
  253. this.member.open = true;
  254. this.getMemberList();
  255. },
  256. /**
  257. * 解绑指定会员
  258. * @param {string} fsUserId - 要解绑的会员ID
  259. */
  260. handleUnbindSpecificMember(fsUserId) {
  261. // 弹出确认框
  262. this.$confirm(`确定要解除与会员 ${fsUserId} 的绑定吗?`, "提示", {
  263. confirmButtonText: "确定",
  264. cancelButtonText: "取消",
  265. type: "warning"
  266. })
  267. .then(() => {
  268. // 构造解绑参数
  269. const unbindData = {
  270. companyUserId: this.user.userId, // 销售ID
  271. userId: fsUserId // 会员ID
  272. };
  273. // 调用解绑接口
  274. unbindSaleAndFsUser(unbindData)
  275. .then(response => {
  276. if (response.code === 200) {
  277. this.$message.success("解绑成功");
  278. // 刷新用户信息
  279. this.getUser();
  280. } else {
  281. this.$message.error(response.msg || "解绑失败");
  282. }
  283. })
  284. .catch(error => {
  285. console.error("解绑失败:", error);
  286. this.$message.error("解绑失败");
  287. });
  288. })
  289. .catch(() => {
  290. this.$message.info("已取消解绑");
  291. });
  292. },
  293. /**
  294. * 获取会员列表
  295. */
  296. getMemberList() {
  297. this.loading = true;
  298. // 调用指定的接口获取会员列表
  299. getSaleBindUserList({
  300. pageNum: this.memberQueryParams.pageNum,
  301. pageSize: this.memberQueryParams.pageSize,
  302. nickName: this.memberQueryParams.nickName,
  303. phone: this.memberQueryParams.phone,
  304. userId: this.memberQueryParams.userId
  305. })
  306. .then(response => {
  307. this.memberList = response.rows || [];
  308. this.memberTotal = response.total || 0;
  309. })
  310. .catch(error => {
  311. console.error('获取会员列表失败:', error);
  312. this.$message.error('获取会员列表失败');
  313. })
  314. .finally(() => {
  315. this.loading = false;
  316. });
  317. },
  318. /**
  319. * 会员搜索按钮操作
  320. // */
  321. handleMemberQuery() {
  322. this.memberQueryParams.pageNum = 1;
  323. this.getMemberList();
  324. },
  325. /**
  326. * 会员重置按钮操作
  327. */
  328. resetMemberQuery() {
  329. this.memberQueryParams = {
  330. nickName: null,
  331. phone: null,
  332. userId: null,
  333. pageNum: 1,
  334. pageSize: 10
  335. };
  336. this.getMemberList();
  337. },
  338. /**
  339. * 选择会员
  340. */
  341. selectMember(member) {
  342. if (member) {
  343. this.selectedMember = member;
  344. }
  345. },
  346. /**
  347. * 确认绑定会员
  348. */
  349. confirmBindMember() {
  350. if (!this.selectedMember) {
  351. this.$message.warning('请选择要绑定的会员');
  352. return;
  353. }
  354. // 这里需要根据实际接口调整参数
  355. const bindData = {
  356. companyUserId: this.currentCompanyId,
  357. userId: this.selectedMember.userId // 使用实际的用户ID字段
  358. };
  359. // 发起绑定请求
  360. bindSaleAndFsUser(bindData).then(response => {
  361. if (response.code === 200) {
  362. this.$message.success('绑定会员成功');
  363. this.cancelBindMember();
  364. // 刷新用户信息
  365. this.getUser();
  366. } else {
  367. this.$message.error(response.msg || '绑定失败');
  368. }
  369. })
  370. .catch(error => {
  371. console.error('绑定会员失败:', error);
  372. this.$message.error('绑定会员失败');
  373. });
  374. },
  375. /**
  376. * 取消绑定会员
  377. */
  378. cancelBindMember() {
  379. this.member.open = false;
  380. this.memberList = [];
  381. this.selectedMember = null;
  382. this.currentCompanyId = null;
  383. this.memberQueryParams = {
  384. nickName: null,
  385. phone: null
  386. };
  387. },
  388. openWechatBindDialog() {
  389. getWechatBindQrcode().then(res => {
  390. console.log(res)
  391. this.wechatQrcode = res.data.qrcodeUrl;
  392. this.bindDialogVisible = true;
  393. this.startCheckWechatBind(res.data.sceneId);
  394. });
  395. },
  396. startCheckWechatBind(sceneId) {
  397. // 清除旧定时器
  398. if (this.wechatBindTimer) clearInterval(this.wechatBindTimer);
  399. this.wechatBindTimer = setInterval(() => {
  400. checkWechatBindStatus(sceneId).then(res => {
  401. if (res.data === true) {
  402. this.$message.success("绑定成功!");
  403. clearInterval(this.wechatBindTimer);
  404. this.bindDialogVisible = false;
  405. this.getUser(); // 刷新绑定状态
  406. }
  407. });
  408. }, 2000);
  409. }
  410. },
  411. beforeDestroy() {
  412. if (this.wechatBindTimer) clearInterval(this.wechatBindTimer);
  413. }
  414. };
  415. </script>